Convirtiendo Tensorflow Graph para usar Estimator, obtenga ‘TypeError: tipo de datos no entendido’ en función de pérdida usando `sampled_softmax_loss` o` nce_loss`

Estoy tratando de convertir la implementación de word2vec básica oficial de Tensorflow para usar tf.Estimator. El problema es que la función de pérdida ( sampled_softmax_loss o nce_loss ) da un error cuando se utilizan estimadores de Tensorflow. Funciona perfectamente bien en la implementación original.

Aquí está la implementación básica oficial de word2vec de Tensorflow:

https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/word2vec/word2vec_basic.py

Aquí está el cuaderno de Google Colab donde implementé este código, que está funcionando.

https://colab.research.google.com/drive/1nTX77dRBHmXx6PEF5pmYpkIVxj_TqT5I

Aquí está el cuaderno de Google Colab donde modifiqué el código para que use Tensorflow Estimator, que no está funcionando.

https://colab.research.google.com/drive/1IVDqGwMx6BK5-Bgrw190jqHU6tt3ZR3e

Para su comodidad, aquí está el código exacto de la versión de Estimator anterior donde defino model_fn

 batch_size = 128 embedding_size = 128 # Dimension of the embedding vector. skip_window = 1 # How many words to consider left and right. num_skips = 2 # How many times to reuse an input to generate a label. num_sampled = 64 # Number of negative examples to sample. def my_model( features, labels, mode, params): with tf.name_scope('inputs'): train_inputs = features train_labels = labels with tf.name_scope('embeddings'): embeddings = tf.Variable( tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0)) embed = tf.nn.embedding_lookup(embeddings, train_inputs) with tf.name_scope('weights'): nce_weights = tf.Variable( tf.truncated_normal( [vocabulary_size, embedding_size], stddev=1.0 / math.sqrt(embedding_size))) with tf.name_scope('biases'): nce_biases = tf.Variable(tf.zeros([vocabulary_size])) with tf.name_scope('loss'): loss = tf.reduce_mean( tf.nn.nce_loss( weights=nce_weights, biases=nce_biases, labels=train_labels, inputs=embed, num_sampled=num_sampled, num_classes=vocabulary_size)) tf.summary.scalar('loss', loss) if mode == "train": with tf.name_scope('optimizer'): optimizer = tf.train.GradientDescentOptimizer(1.0).minimize(loss) return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=optimizer) 

Y aquí es donde llamo al estimador y al entrenamiento.

 word2vecEstimator = tf.estimator.Estimator( model_fn=my_model, params={ 'batch_size': 16, 'embedding_size': 10, 'num_inputs': 3, 'num_sampled': 128, 'batch_size': 16 }) word2vecEstimator.train( input_fn=generate_batch, steps=10) 

Y este es el mensaje de error que recibo cuando llamo a la capacitación de Estimator:

 INFO:tensorflow:Calling model_fn. --------------------------------------------------------------------------- TypeError Traceback (most recent call last)  in () 1 word2vecEstimator.train( 2 input_fn=generate_batch, ----> 3 steps=10) /usr/local/lib/python3.6/dist-packages/tensorflow/python/estimator/estimator.py in train(self, input_fn, hooks, steps, max_steps, saving_listeners) 352 353 saving_listeners = _check_listeners_type(saving_listeners) --> 354 loss = self._train_model(input_fn, hooks, saving_listeners) 355 logging.info('Loss for final step: %s.', loss) 356 return self /usr/local/lib/python3.6/dist-packages/tensorflow/python/estimator/estimator.py in _train_model(self, input_fn, hooks, saving_listeners) 1205 return self._train_model_distributed(input_fn, hooks, saving_listeners) 1206 else: -> 1207 return self._train_model_default(input_fn, hooks, saving_listeners) 1208 1209 def _train_model_default(self, input_fn, hooks, saving_listeners): /usr/local/lib/python3.6/dist-packages/tensorflow/python/estimator/estimator.py in _train_model_default(self, input_fn, hooks, saving_listeners) 1235 worker_hooks.extend(input_hooks) 1236 estimator_spec = self._call_model_fn( -> 1237 features, labels, model_fn_lib.ModeKeys.TRAIN, self.config) 1238 global_step_tensor = training_util.get_global_step(g) 1239 return self._train_with_estimator_spec(estimator_spec, worker_hooks, /usr/local/lib/python3.6/dist-packages/tensorflow/python/estimator/estimator.py in _call_model_fn(self, features, labels, mode, config) 1193 1194 logging.info('Calling model_fn.') -> 1195 model_fn_results = self._model_fn(features=features, **kwargs) 1196 logging.info('Done calling model_fn.') 1197  in my_model(features, labels, mode, params) 33 inputs=embed, 34 num_sampled=num_sampled, ---> 35 num_classes=vocabulary_size)) 36 37 # Add the loss value as a scalar to summary. /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/nn_impl.py in nce_loss(weights, biases, labels, inputs, num_sampled, num_classes, num_true, sampled_values, remove_accidental_hits, partition_strategy, name) 1246 remove_accidental_hits=remove_accidental_hits, 1247 partition_strategy=partition_strategy, -> 1248 name=name) 1249 sampled_losses = sigmoid_cross_entropy_with_logits( 1250 labels=labels, logits=logits, name="sampled_losses") /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/nn_impl.py in _compute_sampled_logits(weights, biases, labels, inputs, num_sampled, num_classes, num_true, sampled_values, subtract_log_q, remove_accidental_hits, partition_strategy, name, seed) 1029 with ops.name_scope(name, "compute_sampled_logits", 1030 weights + [biases, inputs, labels]): -> 1031 if labels.dtype != dtypes.int64: 1032 labels = math_ops.cast(labels, dtypes.int64) 1033 labels_flat = array_ops.reshape(labels, [-1]) TypeError: data type not understood 

Edición: si se solicita, esto es lo que parece una salida típica para input_fn

print(generate_batch(batch_size=8, num_skips=2, skip_window=1))

 (array([3081, 3081, 12, 12, 6, 6, 195, 195], dtype=int32), array([[5234], [ 12], [ 6], [3081], [ 12], [ 195], [ 6], [ 2]], dtype=int32)) 

Usted utiliza generate_batch como una variable aquí:

 word2vecEstimator.train( input_fn=generate_batch, steps=10) 

Llame a la función con generate_batch() . Pero creo que debes pasar algunos valores a la función.

Puede ser que los tensores y las operaciones deban estar en el input_fn , no en el ‘model_fn’

Encontré este problema # 4026 que resolvió mi problema … Tal vez solo sea que sea estúpido, pero sería genial si mencionara que los tensores y las operaciones deben estar dentro de input_fn en algún lugar de la documentación.

Debe llamar a read_batch_examples desde algún lugar dentro de input_fn para que los tensores que crea estén en la gráfica que el Estimator crea en fit ().

https://github.com/tensorflow/tensorflow/issues/8042

¡Oh, me siento como un idiota! He estado creando la operación fuera del scope del gráfico. Funciona ahora, no puedo creer que no pensé en intentarlo. ¡Muchas gracias! Esto no es un problema y se ha resuelto

https://github.com/tensorflow/tensorflow/issues/4026

Sin embargo, todavía no hay suficiente información sobre lo que está causando el problema. Esto es sólo una ventaja.

Encontré la respuesta

El error indica claramente que tiene un tipo no válido para las tags.

Estás intentando pasar una matriz numpy en lugar de Tensor. A veces, Tensorflow realiza una conversión implícita de ndarray a Tensor debajo del capó (por lo que su código funciona fuera de Estimator), pero en este caso no lo hace.

.

No, impl. Oficial. alimenta datos de un marcador de posición. El marcador de posición es siempre un tensor, por lo que no depende de cosas implícitas.

Pero si llama directamente a la función de pérdida con una matriz numpy como entrada (Aviso: llame durante la fase de construcción del gráfico, para que el contenido del argumento se incruste en el gráfico), PUEDE funcionar (sin embargo, no lo verifiqué).

Este código:

nce_loss (labels = [1,2,3]) se llamará solo UNA VEZ durante la construcción del gráfico. Las tags se incorporarán estáticamente en el gráfico como una constante y potencialmente pueden ser de cualquier tipo compatible con Tensor (lista, ndarray, etc.)

Este código: “ `Python def model (label_input): nce_loss (labels = label_input)

estimator (model_fun = model) .train () “ `no puede incrustar tags de forma estática, porque el contenido no se define durante la construcción del gráfico. Por lo tanto, si alimenta algo que no sea el Tensor, se producirá un error.

Desde

https://www.reddit.com/r/MachineLearning/comments/a39pef/r_tensorflow_estimators_managing_simplicity_vs/

Así que usé labels=tf.dtypes.cast( train_labels, tf.int64) y funcionó