2017-08-25 86 views
1

下面的网络代码应该是您的经典简单LSTM语言模型,在一段时间后开始输出nan损失...在我的训练集上需要几个小时,我无法复制它很容易在较小的数据集上。但它总是在严肃的训练中发生。NaN在张量流中的损失LSTM模型

Sparse_softmax_with_cross_entropy应该在数值上是稳定的,所以它不可能是原因...但除此之外,我没有看到任何其他可能导致图形问题的节点。可能是什么问题呢?

class MyLM(): 
    def __init__(self, batch_size, embedding_size, hidden_size, vocab_size): 
     self.x = tf.placeholder(tf.int32, [batch_size, None]) # [batch_size, seq-len] 
     self.lengths = tf.placeholder(tf.int32, [batch_size]) # [batch_size] 

     # remove padding. [batch_size * seq_len] -> [batch_size * sum(lengths)] 
     mask = tf.sequence_mask(self.lengths) # [batch_size, seq_len] 
     mask = tf.cast(mask, tf.int32) # [batch_size, seq_len] 
     mask = tf.reshape(mask, [-1]) # [batch_size * seq_len] 

     # remove padding + last token. [batch_size * seq_len] -> [batch_size * sum(lengths-1)] 
     mask_m1 = tf.cast(tf.sequence_mask(self.lengths - 1, maxlen=tf.reduce_max(self.lengths)), tf.int32) # [batch_size, seq_len] 
     mask_m1 = tf.reshape(mask_m1, [-1]) # [batch_size * seq_len] 

     # remove padding + first token. [batch_size * seq_len] -> [batch_size * sum(lengths-1)] 
     m1_mask = tf.cast(tf.sequence_mask(self.lengths - 1), tf.int32) # [batch_size, seq_len-1] 
     m1_mask = tf.concat([tf.cast(tf.zeros([batch_size, 1]), tf.int32), m1_mask], axis=1) # [batch_size, seq_len] 
     m1_mask = tf.reshape(m1_mask, [-1]) # [batch_size * seq_len] 

     embedding = tf.get_variable("TokenEmbedding", shape=[vocab_size, embedding_size]) 
     x_embed = tf.nn.embedding_lookup(embedding, self.x) # [batch_size, seq_len, embedding_size] 

     lstm = tf.nn.rnn_cell.LSTMCell(hidden_size, use_peepholes=True) 

     # outputs shape: [batch_size, seq_len, hidden_size] 
     outputs, final_state = tf.nn.dynamic_rnn(lstm, x_embed, dtype=tf.float32, 
               sequence_length=self.lengths) 
     outputs = tf.reshape(outputs, [-1, hidden_size]) # [batch_size * seq_len, hidden_size] 

     w = tf.get_variable("w_out", shape=[hidden_size, vocab_size]) 
     b = tf.get_variable("b_out", shape=[vocab_size]) 
     logits_padded = tf.matmul(outputs, w) + b # [batch_size * seq_len, vocab_size] 
     self.logits = tf.dynamic_partition(logits_padded, mask_m1, 2)[1] # [batch_size * sum(lengths-1), vocab_size] 

     predict = tf.argmax(logits_padded, axis=1) # [batch_size * seq_len] 
     self.predict = tf.dynamic_partition(predict, mask, 2)[1] # [batch_size * sum(lengths)] 

     flat_y = tf.dynamic_partition(tf.reshape(self.x, [-1]), m1_mask, 2)[1] # [batch_size * sum(lengths-1)] 

     self.cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=self.logits, labels=flat_y) 
     self.cost = tf.reduce_mean(self.cross_entropy) 
     self.train_step = tf.train.AdamOptimizer(learning_rate=0.01).minimize(self.cost) 
+0

它是否直接从合理的损失值到所有突然变为NaN或者损失逐渐增加直至最终失控? – Aaron

+0

损失徘徊在2左右,然后突然变成NaN。 –

+0

在过去调试这类事情时所做的一些事情是确保在第一个NaN发生时立即退出训练循环。然后查看上一个小批量中的任何数据,看看是否有任何异常。例如,可能有一个长度为零的序列,正在搞砸事情。 – Aaron

回答

1

这可能是exploding gradients,其中梯度可以在LSTMs反向传播期间发生爆炸的情况下,得到的数字溢出。处理爆炸梯度的常用技术是执行Gradient Clipping