Почему выходные данные моей модели тензорного потока становятся NaN после x эпох?

После 85 эпох потери (косинусное расстояние) моей модели (RNN с 3 слоями LSTM) стали NaN. Почему это происходит и как это исправить? Выходы моей модели также становятся NaN.

Моя модель:

tf.reset_default_graph()

seqlen = tf.placeholder(tf.int32, [None])
x_id = tf.placeholder(tf.int32, [None, None])
y_id = tf.placeholder(tf.int32, [None, None])

embeddings_matrix = tf.placeholder(np.float32, [vocabulary_size, embedding_size])
x_emb = tf.nn.embedding_lookup(embeddings_matrix, x_id)
y_emb = tf.nn.embedding_lookup(embeddings_matrix, y_id)

cells = [tf.contrib.rnn.LSTMCell(s, activation=a) for s, a in [(400, tf.nn.relu), (400, tf.nn.relu), (400, tf.nn.tanh)]]
cell = tf.contrib.rnn.MultiRNNCell(cells)

outputs, _ = tf.nn.dynamic_rnn(cell, x_emb, dtype=tf.float32, sequence_length=seqlen)

loss = tf.losses.cosine_distance(tf.nn.l2_normalize(outputs, 2), tf.nn.l2_normalize(y_emb, 2), 1)
tf.summary.scalar('loss', loss)
opt = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
merged = tf.summary.merge_all()

Результат обучения:

Epoch 80/100
    Time : 499 s    Loss : 0.972911523852701    Val Loss : 0.9729658
Epoch 81/100
    Time : 499 s    Loss : 0.9723407568655597   Val Loss : 0.9718646
Epoch 82/100
    Time : 499 s    Loss : 0.9718870568505438   Val Loss : 0.971976
Epoch 83/100
    Time : 499 s    Loss : 0.9913996352643445   Val Loss : 0.990693
Epoch 84/100
    Time : 499 s    Loss : 0.9901496524596137   Val Loss : 0.98957264
Epoch 85/100
    Time : 499 s    Loss : nan  Val Loss : nan
Epoch 86/100
    Time : 498 s    Loss : nan  Val Loss : nan
Epoch 87/100
    Time : 498 s    Loss : nan  Val Loss : nan
Epoch 88/100
    Time : 499 s    Loss : nan  Val Loss : nan
Epoch 89/100
    Time : 498 s    Loss : nan  Val Loss : nan
Epoch 90/100
    Time : 498 s    Loss : nan  Val Loss : nan

А вот изгиб петель на протяжении всего обучения:  Потеря

Синяя кривая - это потеря обучающих данных, а оранжевая - потеря данных проверки.

Скорость обучения, используемая для ADAM, составляет 0,001.

Мои координаты x и y имеют следующую форму: [размер пакета, максимальная длина последовательности], они оба установлены на None, потому что последний пакет каждой эпохи меньше, а максимальная длина последовательности изменяется в каждом пакете.

x и y проходят поиск встраивания и приобретают форму [размер пакета, максимальная длина последовательности, размер встраивания], встраивание для слова-заполнителя представляет собой вектор 0.

Динамический rnn принимает длину каждой последовательности (seqlen в коде с формой [размер пакета]), поэтому он будет делать прогнозы только для точной длины каждой последовательности, а остальная часть вывода будет дополнена векторами с нулем. , что касается y.

Я предполагаю, что значения вывода становятся настолько близкими к нулю, что, как только они возведены в квадрат для вычисления косинусного расстояния, они становятся 0, что приводит к делению на ноль.

Формула косинусного расстояния:
 косинусное расстояние

Не знаю, прав ли я, и как это предотвратить.

РЕДАКТИРОВАТЬ:
Я только что проверил веса каждого слоя, и все они NaN

РЕШЕНО:
Использование регуляризации l2 сработало.

tf.reset_default_graph()

seqlen = tf.placeholder(tf.int32, [None])
x_id = tf.placeholder(tf.int32, [None, None])
y_id = tf.placeholder(tf.int32, [None, None])

embeddings_matrix = tf.placeholder(np.float32, [vocabulary_size, embedding_size])
x_emb = tf.nn.embedding_lookup(embeddings_matrix, x_id)
y_emb = tf.nn.embedding_lookup(embeddings_matrix, y_id)

cells = [tf.contrib.rnn.LSTMCell(s, activation=a) for s, a in [(400, tf.nn.relu), (400, tf.nn.relu), (400, tf.nn.tanh)]]
cell = tf.contrib.rnn.MultiRNNCell(cells)

outputs, _ = tf.nn.dynamic_rnn(cell, x_emb, dtype=tf.float32, sequence_length=seqlen)

regularizer = tf.reduce_sum([tf.nn.l2_loss(v) for v in tf.trainable_variables()])
cos_distance = tf.losses.cosine_distance(tf.nn.l2_normalize(outputs, 2), tf.nn.l2_normalize(y_emb, 2), 1)
loss = cos_distance + beta * regularizer

opt = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)

tf.summary.scalar('loss', loss)
tf.summary.scalar('regularizer', regularizer)
tf.summary.scalar('cos_distance', cos_distance)
merged = tf.summary.merge_all()

person François MENTEC    schedule 26.06.2018    source источник
comment
Значения активации элементов в ваших слоях также становятся NaN после 85-й эпохи?   -  person Anshul Rai    schedule 26.06.2018
comment
@ a_r41 idk, когда я пытаюсь получить вывод любого уровня, я получаю эту ошибку: слой lstm_cell_x не имеет входящих узлов. Я использую следующий код: sessions.run (cells [x] .output, feed_dict = {...})   -  person François MENTEC    schedule 26.06.2018
comment
Все веса - NaN, поэтому выходные данные каждого слоя тоже должны быть NaN.   -  person François MENTEC    schedule 26.06.2018


Ответы (1)


Вес каждого слоя становится NaN может быть сигналом того, что ваша модель испытывает взрывной градиент. проблема.

Я думаю, что по мере увеличения количества эпох значения веса в ваших слоях могут стать слишком большими. Я предлагаю вам реализовать что-то вроде отсечения градиента или регуляризации веса (проверьте ссылку в приложении).

person Anshul Rai    schedule 26.06.2018
comment
Я собираюсь попробовать l2-регуляризацию, обучение моей модели займет несколько часов, завтра я обновлю пост с результатами. - person François MENTEC; 26.06.2018