85个纪元后,我的模型(具有3个LSTM层的RNN)的损失(余弦距离)变为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,因为每个时期的最后一批较小,并且每个批次的最大序列长度都发生变化。 / p>
x和y经过嵌入查找并变为[批大小,最大序列长度,嵌入大小]形状,填充字的嵌入为0的向量。
动态rnn会获取每个序列的长度(代码中的序列,形状为[批处理大小]),因此它将仅对每个序列的确切长度进行预测,而其余输出将被填充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()
答案 0 :(得分:4)
变为NaN
的每一层的权重可能表明您的模型正在经历exploding gradient problem。
我认为随着历元数的增加,图层中的权重值可能会变得太大。我建议您实施某种渐变裁剪或权重正则化(请检查链接)。