Dans une question précédente le but et la structure du serving_input_receiver_fn
Sont explorés et dans la réponse :
def serving_input_receiver_fn():
"""For the sake of the example, let's assume your input to the network will be a 28x28 grayscale image that you'll then preprocess as needed"""
input_images = tf.placeholder(dtype=tf.uint8,
shape=[None, 28, 28, 1],
name='input_images')
# here you do all the operations you need on the images before they can be fed to the net (e.g., normalizing, reshaping, etc). Let's assume "images" is the resulting tensor.
features = {'input_data' : images} # this is the dict that is then passed as "features" parameter to your model_fn
receiver_tensors = {'input_data': input_images} # As far as I understand this is needed to map the input to a name you can retrieve later
return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)
l'auteur de réponse déclare (en ce qui concerne receiver_tensors
):
Pour autant que je sache, cela est nécessaire pour mapper l'entrée à un nom que vous pourrez récupérer plus tard
Cette distinction n'est pas claire pour moi. En pratique, (voir ceci colab ), le même dictionnaire peut être passé à la fois features
et receiver_tensors
.
À partir de code source de @estimator_export('estimator.export.ServingInputReceiver')
(ou ServingInputReceiver docs :
- caractéristiques : A
Tensor
,SparseTensor
, ou dict de chaîne àTensor
ouSparseTensor
, spécifiant les fonctions à transmettre au modèle. Remarque: sifeatures
passé n'est pas un dict, il sera encapsulé dans un dict avec une seule entrée, en utilisant 'feature' comme clé. Par conséquent, le modèle doit accepter un dict de fonction de la forme {'feature': tensor}. Vous pouvez utiliserTensorServingInputReceiver
si vous souhaitez que le tenseur soit transmis tel quel.- receiver_tensors : A
Tensor
,SparseTensor
, ou dict de chaîne àTensor
ouSparseTensor
, spécifiant les nœuds d'entrée où ce récepteur s'attend à être alimenté par défaut. En règle générale, il s'agit d'un espace réservé unique qui attend des protos sérialiséstf.Example
.
Après lecture, il est clair pour moi quels sont les objectifs de features
. features
est un dictionnaire d'entrées que j'envoie ensuite via le graphique. De nombreux modèles courants n'ont qu'une seule entrée, mais vous pouvez ou bien sûr en avoir plus.
Ainsi, la déclaration concernant receiver_tensors
Qui "En général, il s'agit d'un espace réservé unique qui attend des protos tf.Example
Sérialisés.", Pour moi, suggère que receiver_tensors
Veut un espace réservé en lots unique pour (Sequence)Example
Est analysé à partir de TF Record
s.
Pourquoi? Si le TF Record
s est entièrement prétraité, cela est-il redondant? s'il n'est pas entièrement prétraité, pourquoi le passerait-on? Les clés des dictionnaires features
et receiver_tensors
Doivent-elles être identiques?
Quelqu'un peut-il me donner un exemple plus concret de la différence et de ce qui se passe où, comme maintenant
input_tensors = tf.placeholder(tf.float32, <shape>, name="input_tensors")
features = receiver_tensors = {'input_tensors': input_tensors}
fonctionne ... (même si cela ne devrait peut-être pas ...)
Si vous effectuez le prétraitement à l'intérieur de TensorServingInputReceiver que receiver_tensors et les fonctionnalités seraient différentes. les fonctionnalités seront transmises au modèle une fois le prétraitement à l'intérieur de TensorServingInputReceiver effectué. receiver_tensors sont l'entrée du TensorServingInputReceiver et ils peuvent être au format tf.