11

Moje pytanie i problem znajduje się poniżej dwóch bloków kodu.TensorFlow: Wykonywanie tego obliczenia strat


funkcja straty

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] 

wykorzystywane w

Próbowałem spłaszczyć mój kod tak, że wszystko dzieje się w jednym miejscu. Daj mi znać, jeśli pojawią się literówki/punkty dezorientacji.

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}) 

Mój problem

Kwestia jest taka, że ​​jest to powrót błąd:

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> 

więc zakładam, że jest to TensorFlow skarży, że nie można obliczyć gradienty moja strata, ponieważ strata jest wykonywana przez numpy, poza zakresem TF.

Tak naturalnie to naprawić, spróbuję to zaimplementować w TensorFlow. Problem polega na tym, że moje logit_lengths i label_lengths są obydwoma tensorami, więc gdy spróbuję uzyskać dostęp do pojedynczego elementu, otrzymuję Tensor kształtu []. Jest to problem, gdy próbuję użyć tf.nn.top_k(), która pobiera Int dla jego parametru.

Innym problemem z tym jest mój label_lengths jest zastępczy, a ponieważ moja wartość loss muszą być zdefiniowane przed wywołaniem optimizer.minimize(loss), ja też się błąd, który mówi, wartość musi być przekazany do zastępczy.

Zastanawiam się, jak mógłbym spróbować zrealizować tę funkcję straty. Lub jeśli brakuje mi czegoś oczywistego.


Edit: Po pewnym further reading widzę, że zazwyczaj straty, takie jak ta, którą opisują stosowane są w walidacji i szkolenia, który minimalizuje straty zastępczą w tym samym miejscu jak prawdziwa strata jest używany. Czy ktokolwiek wie, jakie straty zastępcze są używane w scenariuszu opartym na odległości, jak na przykład mój?

+0

w '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) ' Jaki jest Twój 'feed_dict'? Nie powinieneś mieć elementów zastępczych na liście pobierania dla session.run. –

+0

@TheMyth The feed_dict w rzeczywistości przechowuje wartości zastępcze. Jest to z pewnością redundancja, ale myślę, że zrobiłem to, aby kod był bardziej zwięzły dla SO. –

Odpowiedz

1

Pierwszą rzeczą, którą zrobiłbym, aby obliczyć stratę używając tensorflow zamiast numpy. Dzięki temu tensorflow będzie mógł obliczać gradienty dla ciebie, dzięki czemu będziesz mógł propagować wstecz, co oznacza, że ​​możesz zminimalizować straty.

Jest tf.edit_distance (https://www.tensorflow.org/api_docs/python/tf/edit_distance) funkcja w bibliotece rdzenia.

So naturally to fix that I would try and implement this in TensorFlow. The issue is, my logit_lengths and label_lengths are both Tensors, so when I try and access a single element, I'm returned a Tensor of shape []. This is an issue when I'm trying to use tf.nn.top_k() which takes an Int for its k parameter.

Czy możesz podać trochę więcej szczegółów, dlaczego jest to problem?