python - neural - tensorflow tutorial
TensorFlow: realizando este cálculo de pérdida (1)
Lo primero que haría es calcular la pérdida usando tensorflow en lugar de numpy. Eso permitirá que tensorflow calcule gradientes para usted, de modo que podrá propagar hacia atrás, lo que significa que puede minimizar la pérdida.
Existe la función tf.edit_distance ( https://www.tensorflow.org/api_docs/python/tf/edit_distance ) en la biblioteca central.
Así que, naturalmente, para solucionarlo, trataría de implementar esto en TensorFlow. El problema es que mis logit_lengths y label_lengths son ambos Tensors, así que cuando intento acceder a un solo elemento, me devuelven un Tensor de forma []. Este es un problema cuando intento usar tf.nn.top_k () que toma un int para su parámetro k.
¿Podría darnos un poco más de detalles sobre por qué es un problema?
Mi pregunta y problema se establece debajo de los dos bloques de código.
Función de pérdida
def loss(labels, logits, sequence_lengths, label_lengths, logit_lengths):
scores = []
for i in xrange(runner.batch_size):
sequence_length = sequence_lengths[i]
for j in xrange(length):
label_length = label_lengths[i, j]
logit_length = logit_lengths[i, j]
# get top k indices <==> argmax_k(labels[i, j, 0, :], label_length)
top_labels = np.argpartition(labels[i, j, 0, :], -label_length)[-label_length:]
top_logits = np.argpartition(logits[i, j, 0, :], -logit_length)[-logit_length:]
scores.append(edit_distance(top_labels, top_logits))
return np.mean(scores)
# Levenshtein distance
def edit_distance(s, t):
n = s.size
m = t.size
d = np.zeros((n+1, m+1))
d[:, 0] = np.arrange(n+1)
d[0, :] = np.arrange(n+1)
for j in xrange(1, m+1):
for i in xrange(1, n+1):
if s[i] == t[j]:
d[i, j] = d[i-1, j-1]
else:
d[i, j] = min(d[i-1, j] + 1,
d[i, j-1] + 1,
d[i-1, j-1] + 1)
return d[m, n]
Ser utilizado en
Intenté aplanar mi código para que todo esté sucediendo en un solo lugar. Avísame si hay errores de tipeo / puntos de confusión.
sequence_lengths_placeholder = tf.placeholder(tf.int64, shape=(batch_size))
labels_placeholder = tf.placeholder(tf.float32, shape=(batch_size, max_feature_length, label_size))
label_lengths_placeholder = tf.placeholder(tf.int64, shape=(batch_size, max_feature_length))
loss_placeholder = tf.placeholder(tf.float32, shape=(1))
logit_W = tf.Variable(tf.zeros([lstm_units, label_size]))
logit_b = tf.Variable(tf.zeros([label_size]))
length_W = tf.Variable(tf.zeros([lstm_units, max_length]))
length_b = tf.Variable(tf.zeros([max_length]))
lstm = rnn_cell.BasicLSTMCell(lstm_units)
stacked_lstm = rnn_cell.MultiRNNCell([lstm] * layer_count)
rnn_out, state = rnn.rnn(stacked_lstm, features, dtype=tf.float32, sequence_length=sequence_lengths_placeholder)
logits = tf.concat(1, [tf.reshape(tf.matmul(t, logit_W) + logit_b, [batch_size, 1, 2, label_size]) for t in rnn_out])
logit_lengths = tf.concat(1, [tf.reshape(tf.matmul(t, length_W) + length_b, [batch_size, 1, max_length]) for t in rnn_out])
optimizer = tf.train.AdamOptimizer(learning_rate)
global_step = tf.Variable(0, name=''global_step'', trainable=False)
train_op = optimizer.minimize(loss_placeholder, global_step=global_step)
...
...
# Inside training loop
np_labels, np_logits, sequence_lengths, label_lengths, logit_lengths = sess.run([labels_placeholder, logits, sequence_lengths_placeholder, label_lengths_placeholder, logit_lengths], feed_dict=feed_dict)
loss = loss(np_labels, np_logits, sequence_lengths, label_lengths, logit_lengths)
_ = sess.run([train_op], feed_dict={loss_placeholder: loss})
Mi problema
El problema es que esto está devolviendo el error:
File "runner.py", line 63, in <module>
train_op = optimizer.minimize(loss_placeholder, global_step=global_step)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/training/optimizer.py", line 188, in minimize
name=name)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/training/optimizer.py", line 277, in apply_gradients
(grads_and_vars,))
ValueError: No gradients provided for any variable: <all my variables>
Así que supongo que esto es TensorFlow quejándose de que no puede calcular los gradientes de mi pérdida porque la pérdida se realiza por numpy, fuera del alcance de TF.
Así que, naturalmente, para solucionarlo, trataría de implementar esto en TensorFlow. El problema es que mis logit_lengths
y label_lengths
son ambos Tensors, así que cuando intento acceder a un solo elemento, me devuelven un Tensor de forma []. Este es un problema cuando intento usar tf.nn.top_k()
que toma un Int
para su parámetro k
.
Otro problema es que mi label_lengths
es un Placeholder y dado que mi valor de loss
debe definirse antes de la llamada optimizer.minimize(loss)
, también aparece un error que indica que se debe pasar un valor para el marcador de posición.
Me pregunto cómo podría tratar de implementar esta función de pérdida. O si me falta algo obvio.
Editar: Después de leer un poco más veo que usualmente las pérdidas como la que describo se utilizan en la validación y en el entrenamiento una pérdida sustituta que se minimiza en el mismo lugar donde se usa la pérdida real. ¿Alguien sabe qué pérdida indirecta se utiliza para un escenario basado en la distancia de edición como el mío?