2016-10-13 3 views
0

장난감 분류 문제에 대해 Tensorflow (r0.10, python 3.5)를 사용하여 반복적 인 신경망을 학습하려고하지만 혼란스러운 결과가 나타납니다.tensorflow RNN이 장난감 데이터를 학습하지 않는 이유 이해

0과 1의 시퀀스를 RNN에 입력하고 시퀀스의 주어진 요소에 대한 대상 클래스를 시퀀스의 현재 값과 이전 값으로 나타내는 숫자로, 이진수로 처리해야합니다. 번호. 예를 들어 :

input sequence: [0,  0,  1,  0,  1,  1] 
binary digits : [-, [0,0], [0,1], [1,0], [0,1], [1,1]] 
target class : [-,  0,  1,  2,  1,  3] 

이이 RNN은 아주 쉽게 배울 수 있어야 뭔가 것 같다, 대신 나의 모델은 [1,3]에서 클래스 [0,2]를 구별 할 수 있습니다. 즉, 현재 숫자가 0 인 클래스를 현재 숫자가 1 인 클래스와 구별 할 수 있습니다. 이로 인해 RNN 모델이 시퀀스의 이전 값을 제대로 볼 수 없다는 것을 알게되었습니다 .

어떻게 구축하고 tensorflow에서 재발 성 신경 회로망 (RNNs)를 사용하여 보여 몇 가지 자습서 및 예제 ([1], [2], [3])가 있지만 그것들을 공부 한 후에 나는 아직도 내 문제를 볼 수 없습니다 (모든 예제가 원본 데이터로 텍스트를 사용하는 데 도움이되지 않습니다).

길이가 Ttf.nn.rnn()의 데이터를 [batch_size x input_size] 시퀀스로 입력하고 있습니다. 내 시퀀스가 ​​1 차원이기 때문에 input_size은 1과 동일하므로 본질적으로 길이가 batch_size 인 시퀀스 목록을 입력한다고 생각합니다 (documentation은 어떤 차원이 시간 차원으로 취급되는지에 대해 명확하지 않습니다). 그 이해가 맞습니까? 그렇다면 RNN 모델이 올바르게 학습되지 않는 이유를 이해할 수 없습니다.

import tensorflow as tf 
import numpy as np 

input_size = 1 
batch_size = 50 
T = 2 
lstm_size = 5 
lstm_layers = 2 
num_classes = 4 
learning_rate = 0.1 

lstm = tf.nn.rnn_cell.BasicLSTMCell(lstm_size, state_is_tuple=True) 
lstm = tf.nn.rnn_cell.MultiRNNCell([lstm] * lstm_layers, state_is_tuple=True) 

x = tf.placeholder(tf.float32, [T, batch_size, input_size]) 
y = tf.placeholder(tf.int32, [T * batch_size * input_size]) 

init_state = lstm.zero_state(batch_size, tf.float32) 

inputs = [tf.squeeze(input_, [0]) for input_ in tf.split(0,T,x)] 
outputs, final_state = tf.nn.rnn(lstm, inputs, initial_state=init_state) 

w = tf.Variable(tf.truncated_normal([lstm_size, num_classes]), name='softmax_w') 
b = tf.Variable(tf.truncated_normal([num_classes]), name='softmax_b') 

output = tf.concat(0, outputs) 

logits = tf.matmul(output, w) + b 

probs = tf.nn.softmax(logits) 

cost = tf.reduce_mean(tf.nn.seq2seq.sequence_loss_by_example(
    [logits], [y], [tf.ones_like(y, dtype=tf.float32)] 
)) 

optimizer = tf.train.GradientDescentOptimizer(learning_rate) 
tvars = tf.trainable_variables() 
grads, _ = tf.clip_by_global_norm(tf.gradients(cost, tvars), 
            10.0) 
train_op = optimizer.apply_gradients(zip(grads, tvars)) 

init = tf.initialize_all_variables() 

with tf.Session() as sess: 
    sess.run(init) 
    curr_state = sess.run(init_state) 
    for i in range(3000): 
     # Create toy data where the true class is the value represented 
     # by the current and previous value treated as binary, i.e. 
     train_x = np.random.randint(0,2,(T * batch_size * input_size)) 
     train_y = train_x + np.concatenate(([0], (train_x[:-1] * 2))) 

     # Reshape into T x batch_size x input_size 
     train_x = np.reshape(train_x, (T, batch_size, input_size)) 

     feed_dict = { 
      x: train_x, y: train_y 
     } 
     for j, (c, h) in enumerate(init_state): 
      feed_dict[c] = curr_state[j].c 
      feed_dict[h] = curr_state[j].h 

     fetch_dict = { 
      'cost': cost, 'final_state': final_state, 'train_op': train_op 
     } 

     # Evaluate the graph 
     fetches = sess.run(fetch_dict, feed_dict=feed_dict) 

     curr_state = fetches['final_state'] 

     if i % 300 == 0: 
      print('step {}, train cost: {}'.format(i, fetches['cost'])) 

    # Test 
    test_x = np.array([[0],[0],[1],[0],[1],[1]]*(T*batch_size*input_size)) 
    test_x = test_x[:(T*batch_size*input_size),:] 
    probs_out = sess.run(probs, feed_dict={ 
      x: np.reshape(test_x, [T, batch_size, input_size]), 
      init_state: curr_state 
     }) 
    # Get the softmax outputs for the points in the sequence 
    # that have [0, 0], [0, 1], [1, 0], [1, 1] as their 
    # last two values. 
    for i in [1, 2, 3, 5]: 
     print('{}: [{:.4f} {:.4f} {:.4f} {:.4f}]'.format(
       [1, 2, 3, 5].index(i), *list(probs_out[i,:])) 
      ) 

최종 출력을 여기 :

그것은 내 전체 RNN를 통해 실행할 수있는 코드의 작은 집합을 얻기 어렵다, 이것은 내가 (이 대부분 the char-rnn model herethe PTB model here에서 적응하고) 할 수있는 최고입니다

0: [0.4899 0.0007 0.5080 0.0014] 
1: [0.0003 0.5155 0.0009 0.4833] 
2: [0.5078 0.0011 0.4889 0.0021] 
3: [0.0003 0.5052 0.0009 0.4936] 

이는 [1,3]과 [0,2]를 구별하는 것을 배우고 있음을 나타냅니다. 이 모델이 시퀀스의 이전 값을 사용하는 방법을 배우지 않는 이유는 무엇입니까?

답변

2

this blog post (입력 텐서의 훌륭한 다이어그램이 있습니다)의 도움으로 그것을 알아 냈습니다.

시퀀스 수를 가정 해 봅시다. 각 시퀀스의 크기는 input_size이고 길이는 T입니다 (이 이름은 tf.nn.rnn()here의 설명서와 일치하도록 선택되었습니다). 그런 다음 입력 내용을 각 요소의 모양이 batch_size x input_sizeT 길이 목록으로 분할해야합니다. 즉, 인접 시퀀스가 ​​목록의 요소에 걸쳐 펼쳐질 것입니다. 인접한 시퀀스가 ​​함께 유지되어리스트 inputs의 각 요소가 하나의 시퀀스의 예가 될 것이라고 생각했습니다.

우리는 각 단계를 시퀀스를 통해 병렬 처리하기를 원하므로 각 시퀀스의 첫 번째 단계 (목록의 첫 번째 요소)를 실행하고 각 시퀀스의 두 번째 단계 (두 번째 요소는 등 목록), 코드의 버전 근무

:

import tensorflow as tf 
import numpy as np 

sequence_size = 50 
batch_size = 7 
num_features = 1 
lstm_size = 5 
lstm_layers = 2 
num_classes = 4 
learning_rate = 0.1 

lstm = tf.nn.rnn_cell.BasicLSTMCell(lstm_size, state_is_tuple=True) 
lstm = tf.nn.rnn_cell.MultiRNNCell([lstm] * lstm_layers, state_is_tuple=True) 

x = tf.placeholder(tf.float32, [batch_size, sequence_size, num_features]) 
y = tf.placeholder(tf.int32, [batch_size * sequence_size * num_features]) 

init_state = lstm.zero_state(batch_size, tf.float32) 

inputs = [tf.squeeze(input_, [1]) for input_ in tf.split(1,sequence_size,x)] 
outputs, final_state = tf.nn.rnn(lstm, inputs, initial_state=init_state) 

w = tf.Variable(tf.truncated_normal([lstm_size, num_classes]), name='softmax_w') 
b = tf.Variable(tf.truncated_normal([num_classes]), name='softmax_b') 

output = tf.reshape(tf.concat(1, outputs), [-1, lstm_size]) 

logits = tf.matmul(output, w) + b 

probs = tf.nn.softmax(logits) 

cost = tf.reduce_mean(tf.nn.seq2seq.sequence_loss_by_example(
    [logits], [y], [tf.ones_like(y, dtype=tf.float32)] 
)) 

# Now optimize on that cost 
optimizer = tf.train.GradientDescentOptimizer(learning_rate) 
tvars = tf.trainable_variables() 
grads, _ = tf.clip_by_global_norm(tf.gradients(cost, tvars), 
            10.0) 
train_op = optimizer.apply_gradients(zip(grads, tvars)) 

init = tf.initialize_all_variables() 

with tf.Session() as sess: 
    sess.run(init) 
    curr_state = sess.run(init_state) 
    for i in range(3000): 
     # Create toy data where the true class is the value represented 
     # by the current and previous value treated as binary, i.e. 

     train_x = np.random.randint(0,2,(batch_size * sequence_size * num_features)) 
     train_y = train_x + np.concatenate(([0], (train_x[:-1] * 2))) 

     # Reshape into T x batch_size x sequence_size 
     train_x = np.reshape(train_x, [batch_size, sequence_size, num_features]) 

     feed_dict = { 
      x: train_x, y: train_y 
     } 
     for j, (c, h) in enumerate(init_state): 
      feed_dict[c] = curr_state[j].c 
      feed_dict[h] = curr_state[j].h 

     fetch_dict = { 
      'cost': cost, 'final_state': final_state, 'train_op': train_op 
     } 

     # Evaluate the graph 
     fetches = sess.run(fetch_dict, feed_dict=feed_dict) 

     curr_state = fetches['final_state'] 

     if i % 300 == 0: 
      print('step {}, train cost: {}'.format(i, fetches['cost'])) 

    # Test 
    test_x = np.array([[0],[0],[1],[0],[1],[1]]*(batch_size * sequence_size * num_features)) 
    test_x = test_x[:(batch_size * sequence_size * num_features),:] 
    probs_out = sess.run(probs, feed_dict={ 
      x: np.reshape(test_x, [batch_size, sequence_size, num_features]), 
      init_state: curr_state 
     }) 
    # Get the softmax outputs for the points in the sequence 
    # that have [0, 0], [0, 1], [1, 0], [1, 1] as their 
    # last two values. 
    for i in [1, 2, 3, 5]: 
     print('{}: [{:.4f} {:.4f} {:.4f} {:.4f}]'.format(
       [1, 2, 3, 5].index(i), *list(probs_out[i,:])) 
      ) 
관련 문제