2017-12-19 41 views
0

짧은 시퀀스를 예측하기 위해 아주 사소한 LSTM을 만들었지 만, 예상치 못한 방식으로 과부하가되지 않고 0의 손실에 접근합니다.왜 사소한 LSTM이 과장되지 않습니까?

대신이 시퀀스를 그대로 배울 수있는 충분한 자유도가 있더라도 약 1.5의 손실로 수렴합니다.

import tensorflow as tf 
import time 

tf.logging.set_verbosity(tf.logging.DEBUG) 

# 
# Training data, just a single sequence 
# 
train_input = [[0, 1, 2, 3, 4, 5, 0, 6, 7, 0]] 
train_output = [[1, 2, 3, 4, 5, 0, 6, 7, 8, 0]] 

# 
# Training metadata 
# 
batch_size = 1 
sequence_length = 10 
n_classes = 9 

# Network size 
rnn_cell_size = 10 
rnn_layers = 2 
embedding_rank = 3 

# 
# Training hyperparameters 
# 
epochs = 100 
n_batches = 100 
learning_rate = 0.01 

# 
# Model 
# 
features = tf.placeholder(tf.int32, [None, sequence_length], name="features") 
embeddings = tf.Variable(tf.random_uniform([n_classes, embedding_rank], -1.0, 1.0)) 
embed = tf.nn.embedding_lookup(embeddings, features) 
cell = tf.contrib.rnn.MultiRNNCell([tf.contrib.rnn.LSTMCell(rnn_cell_size) for i in range(rnn_layers)]) 
initial_state = cell.zero_state(batch_size, tf.float32) 
cell, _ = tf.nn.dynamic_rnn(cell, embed, initial_state=initial_state) 
# Convert sequences x batches x outputs to (sequences * batches) x outputs 
flat_lstm_output = tf.reshape(cell, [-1, rnn_cell_size]) 
output = tf.contrib.layers.fully_connected(inputs=flat_lstm_output, num_outputs=n_classes) 
softmax = tf.nn.softmax(output) 

# 
# Training 
# 
targets = tf.placeholder(tf.int32, [None, sequence_length]) 
# Convert sequences x batches x targets to (sequences * batches) x targets 
flat_targets = tf.reshape(targets, [-1]) 
loss = tf.losses.sparse_softmax_cross_entropy(flat_targets, softmax) 
train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) 

with tf.Session() as sess: 
    sess.run(tf.global_variables_initializer()) 
    for i in range(epochs): 
     loss_sum = 0 
     epoch_start = time.time() 
     for j in range(n_batches): 
      _, step_loss = sess.run([train_op, loss], { 
        features: train_input, 
        targets: train_output, 
      }) 
      loss_sum = loss_sum + step_loss 
     print('avg_loss', loss_sum/n_batches, 'avg_time', (time.time() - epoch_start)/n_batches) 

여기에 기본적인 느낌이 들지 않습니다. 내가 뭘 잘못하고있는 걸까요?

편집

나는 더를 단순화하기 위해 노력하고, 지금은 (도 수렴하지 않는) 다음과 같은 더 사소한 예를 아래로 해요 :

import tensorflow as tf 
import time 

tf.logging.set_verbosity(tf.logging.DEBUG) 

# 
# Training data, just a single sequence 
# 
train_input = [0, 1, 2, 3, 4] 
train_output = [1, 2, 3, 4, 5] 

# 
# Training metadata 
# 
batch_size = 1 
sequence_length = 5 
n_classes = 6 

# 
# Training hyperparameters 
# 
epochs = 100 
n_batches = 100 
learning_rate = 0.01 

# 
# Model 
# 
features = tf.placeholder(tf.int32, [None]) 
one_hot = tf.contrib.layers.one_hot_encoding(features, n_classes) 
output = tf.contrib.layers.fully_connected(inputs=one_hot, num_outputs=10) 
output = tf.contrib.layers.fully_connected(inputs=output, num_outputs=n_classes) 

# 
# Training 
# 
targets = tf.placeholder(tf.int32, [None]) 
one_hot_targets = tf.one_hot(targets, depth=n_classes) 
loss = tf.losses.softmax_cross_entropy(one_hot_targets, output) 
train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) 

with tf.Session() as sess: 
    sess.run(tf.global_variables_initializer()) 
    for i in range(epochs): 
     loss_sum = 0 
     epoch_start = time.time() 
     for j in range(n_batches): 
      _, step_loss = sess.run([train_op, loss], { 
        features: train_input, 
        targets: train_output, 
      }) 
      loss_sum = loss_sum + step_loss 
     print('avg_loss', loss_sum/n_batches, 'avg_time', (time.time() - epoch_start)/n_batches) 

답변

0

당신이를 확인 했 학습률 (예 : 0.001 또는 0.0001)에 대한 낮은 값?

0

데이터가 충분하지 않아 네트워크가 적합하지 않습니다. LSTM에는 하나의 시퀀스 만 있고 MLP에는 5 개의 데이터 포인트가 있습니다.

추정 할 매개 변수의 수와 이것을 비교하십시오. MLP에 120 개의 매개 변수가 있습니다 (올바르게 계산하는 경우). 당신이 아주 운이 좋으면 않는 한 당신은 단 5 datapoints로 모든 이들을 견적 할 수있는 방법이 없습니다. (시퀀스를 작은 배치로 분할하여 수렴 가능성을 높일 수 있지만 그다지 수렴하지는 않습니다).

요약하면 신경망은 사용하기에 알맞은 양의 데이터가 필요합니다.

0

대답은 세 배였습니다.

1) 완전히 연결된 레이어 (relu)에서 tanh로 기본 활성화를 바꾸면 RNN이없는 예가 수렴됩니다.

이것은 relu가 많은 입력을 무시하고 (0 이하의 모든 것) 그라데이션을 제공하지 않기 때문인 것으로 보입니다. 입력이 많을수록 효과가있을 수 있습니다.

2) RNN이있는 예는 완전히 연결되지 않은 마지막 레이어 (softmax 이전)에서 활성화를 완전히 제거해야합니다. None을 사용하면 완전히 활성화되지 않습니다 (대부분의 조합에서). 소프트 맥스 앞에 완전히 연결된 층.

3) RNN 예제에서는 명시 적 softmax를 제거해야합니다. sparse_softmax_cross_entropy는 이미 softmax를 적용하기 때문입니다.

import tensorflow as tf 
import time 

tf.logging.set_verbosity(tf.logging.DEBUG) 

# 
# Training data, just a single sequence 
# 
train_input = [[0, 1, 2, 3, 4, 5, 0, 6, 7, 0]] 
train_output = [[1, 2, 3, 4, 5, 0, 6, 7, 8, 0]] 

# 
# Training metadata 
# 
batch_size = 1 
sequence_length = 10 
n_classes = 9 

# Network size 
rnn_cell_size = 10 
rnn_layers = 2 
embedding_rank = 3 

# 
# Training hyperparameters 
# 
epochs = 100 
n_batches = 100 
learning_rate = 0.01 

# 
# Model 
# 
features = tf.placeholder(tf.int32, [None, sequence_length], name="features") 
embeddings = tf.Variable(tf.random_uniform([n_classes, embedding_rank], -1.0, 1.0)) 
embed = tf.nn.embedding_lookup(embeddings, features) 
cell = tf.contrib.rnn.MultiRNNCell([tf.contrib.rnn.LSTMCell(rnn_cell_size) for i in range(rnn_layers)]) 
initial_state = cell.zero_state(batch_size, tf.float32) 
cell, _ = tf.nn.dynamic_rnn(cell, embed, initial_state=initial_state) 
# Convert [batche_size, sequence_length, rnn_cell_size] to [(batch_size * sequence_length), rnn_cell_size] 
flat_lstm_output = tf.reshape(cell, [-1, rnn_cell_size]) 
output = tf.contrib.layers.fully_connected(inputs=flat_lstm_output, num_outputs=n_classes, activation_fn=None) 

# 
# Training 
# 
targets = tf.placeholder(tf.int32, [None, sequence_length]) 
# Convert [batch_size, sequence_length] to [batch_size * sequence_length] 
flat_targets = tf.reshape(targets, [-1]) 
loss = tf.losses.sparse_softmax_cross_entropy(flat_targets, output) 
train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) 

with tf.Session() as sess: 
    sess.run(tf.global_variables_initializer()) 
    for i in range(epochs): 
     loss_sum = 0 
     epoch_start = time.time() 
     for j in range(n_batches): 
      _, step_loss = sess.run([train_op, loss], { 
        features: train_input, 
        targets: train_output, 
      }) 
      loss_sum = loss_sum + step_loss 
     print('avg_loss', loss_sum/n_batches, 'avg_time', (time.time() - epoch_start)/n_batches) 
:

마지막으로 코드를 작업