저번 [#E20 : Recurrent Neural Network (RNN - PART 1/3)] 포스트에서는 Long Sequence RNN를 직접 구현했습니다.
그러나 우리가 구현한 RNN은 테스트 시 좋은 성능을 내지 못하는데, 그 이유는 다음과 같습니다.
1. 셀의 크기가 너무 작다.
solution : 셀을 wide & deep 하게 구성한다. (use Deep Learning - Stacked RNN)
이것은 텐서플로우에서 제공하는 MultiRNNCell 메소드를 이용하여 쉽게 해결할 수 있습니다.
1 2 3 4 5 6 | # 기존 1개의 Cell cell = tf.contrib.rnn.BasicLSTMCell(hidden_size, state_is_tuple=True) # 2개의 Cell cell = tf.contrib.rnn.BasicLSTMCell(hidden_size, state_is_tuple=True) cell = tf.contrib.rnn.MultiRNNCell([cell]*2, state_is_tuple=True) | cs |
다음과 같이 기본 Cell을 구성하고, 구성한 Cell을 몇 개 쌓을 것인지만 임의의 숫자로 설정해주면 됩니다.
2. 가공되지 않은 output을 직접 사용한다.
solution : output을 SoftMax 가공한다. (use SoftMax Layer - FCLayer)
CNN (Convolution Neural Network) 를 사용하여 MNIST 데이터를 분류할 때 최종적으로 나온 3136개의 데이터를 FCLayer에 연결 및 학습했습니다.
이와 동일하게 RNN에서도 도출된 output을 FCLayer에 연결하여 사용할 수 있는데, 이것을 그림으로 표현하면 다음과 같습니다.
즉 RNN으로 도출된 output을 Softmax 함수가 이용할 수 있는 형태로 reshape한 후, Softmax 가공 후 다시 데이터를 펼치는 Reshape를 진행합니다.
각각의 과정은 다음과 같이 코드로 나타낼 수 있습니다.
1 2 3 4 5 6 7 8 9 10 | # reshape(1) X_for_softmax = tf.reshape(outputs, [-1, hidden_size]) # softmax (hidden_size -> num_classes) softmax_w = tf.get_variable("softmax_w", [hidden_size, num_classes]) softmax_b = tf.get_variable("softmax_b", [num_classes]) outputs = tf.matmul(X_for_softmax, softmax_w) + softmax_b # reshape(2) -> expend the data (revive the batches) outputs = tf.reshape(outputs, [batch_size, sequence_length, num_classes]) | cs |
Softmax 함수를 이용하기 위해서 H(x) = W*x + B의 형태를 구성합니다. W의 shape에서 입력값은 RNN output의 출력값과 같으므로 hidden_size입니다.
출력값 또한 RNN output의 출력값과 같아야 하므로 마찬가지로 hidden_size입니다.
(num_classes = hidden_size)
이외의 것은 저번의 RNN 구성과 동일합니다.
SOURCE CODE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | import tensorflow as tf import numpy as np sentence = ("if you want to build a ship, don't drum up people together to " "collect wood and don't assign them tasks and work, but rather " "teach them to long for the endless immensity of the sea.") idx2char = list(set(sentence)) char2idx = {w: i for i, w in enumerate(idx2char)} data_dim = len(idx2char) hidden_size = len(idx2char) num_classes = len(idx2char) sequence_length = 10 # Any arbitrary number learning_rate = 0.1 dataX = [] dataY = [] for i in range(0, len(sentence) - sequence_length): x_str = sentence[i:i + sequence_length] y_str = sentence[i + 1: i + sequence_length + 1] print(i, x_str, '->', y_str) x = [char2idx[c] for c in x_str] # x str to index y = [char2idx[c] for c in y_str] # y str to index dataX.append(x) dataY.append(y) batch_size = len(dataX) X = tf.placeholder(tf.int32, [None, sequence_length]) Y = tf.placeholder(tf.int32, [None, sequence_length]) # One-hot encoding X_one_hot = tf.one_hot(X, num_classes) print(X_one_hot) # check out the shape cell = tf.contrib.rnn.BasicLSTMCell(hidden_size, state_is_tuple=True) cell = tf.contrib.rnn.MultiRNNCell([cell]*30, state_is_tuple=True) initial_state = cell.zero_state(batch_size, tf.float32) outputs, _states = tf.nn.dynamic_rnn( cell, X_one_hot, initial_state=initial_state, dtype=tf.float32) # reshape(1) X_for_softmax = tf.reshape(outputs, [-1, hidden_size]) # softmax (hidden_size -> num_classes) softmax_w = tf.get_variable("softmax_w", [hidden_size, num_classes]) softmax_b = tf.get_variable("softmax_b", [num_classes]) outputs = tf.matmul(X_for_softmax, softmax_w) + softmax_b # reshape(2) -> expend the data (revive the batches) outputs = tf.reshape(outputs, [batch_size, sequence_length, num_classes]) weights = tf.ones([batch_size, sequence_length]) sequence_loss = tf.contrib.seq2seq.sequence_loss( logits=outputs, targets=Y, weights=weights) loss = tf.reduce_mean(sequence_loss) train = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss) sess = tf.Session() sess.run(tf.global_variables_initializer()) #learning for i in range(500): _, l, results = sess.run( [train, loss, outputs], feed_dict={X: dataX, Y: dataY}) for j, result in enumerate(results): index = np.argmax(result, axis=1) print(i, j, ''.join([idx2char[t] for t in index]), l) # Let's print the last char of each result to check it works results = sess.run(outputs, feed_dict={X: dataX}) for j, result in enumerate(results): index = np.argmax(result, axis=1) if j is 0: # print all for the first result to make a sentence print(''.join([idx2char[t] for t in index]), end='') else: print(idx2char[index[-1]], end='') # get last index | cs |
'파이썬 > 머신러닝' 카테고리의 다른 글
[#E21] Recurrent Neural Network (RNN - PART 3/3) (0) | 2018.12.18 |
---|---|
[#E19] Recurrent Neural Network (RNN - PART 1/3) (0) | 2018.12.16 |
[#E18] CNN을 이용한 MNIST 데이터 분류 (0) | 2018.12.14 |
[#E17] Convolution Neural Network (CNN - 실전편) (0) | 2018.12.14 |
[#E16] Convolution Neural Network (CNN - 준비편) (0) | 2018.12.14 |