이전의 "hi hello" 문자열이나 LONG SEQUENCE RNN에서 사용했던 긴 문자열과는 달리, 사용자로부터 직접 데이터(문자열)을 입력받는 것을 DYNAMIC RNN이라고 합니다.
이것은 데이터에 이미 정해진 문자열 길이가 아닌 가변적인 문자열 길이를 사용한다는 의미입니다.
예로 3개의 문자열 'hello', 'eolll', 'lleel'이 있다고 가정합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | import tensorflow as tf import numpy as np import pprint pp = pprint.PrettyPrinter(indent=4) sess = tf.InteractiveSession() h = [1, 0, 0, 0] e = [0, 1, 0, 0] l = [0, 0, 1, 0] o = [0, 0, 0, 1] x_data = np.array([[h, e, l, l, o], [e, o, l, l, l], [l, l, e, e, l]] ,dtype=np.float32) | cs |
우리가 지금까지 사용했던 sequence_length는 데이터의 길이 값 = len(x_data)이었던 것과는 달리, DYNAMIC RNN은 다음과 같이 구성합니다
1 2 3 4 5 6 7 8 9 | hidden_size = 2 with tf.variable_scope('3batch') as scope: cell = tf.contrib.rnn.BasicRNNCell(num_units=hidden_size) outputs, _states = tf.nn.dynamic_rnn( cell, x_data, sequence_length=[5, 3, 4], dtype=tf.float32) sess.run(tf.global_variables_initializer()) pp.pprint(outputs.eval()) | cs |
이 속성은 3개의 문자열에서 각각 5개, 3개, 4개의 문자의 대한 output을 출력합니다.
[사용된 문자열]
hello -> hello
eolll -> eol
lleel -> llee
[output]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | array([[[-0.61227953, 0.5256336 ], # h [-0.51040757, -0.1740599 ], # e [ 0.26046374, 0.21115965], # l [ 0.4724385 , -0.26186004], # l [ 0.43014514, 0.2979847 ]], # o [[-0.217902 , 0.14853615], # e [ 0.10625201, 0.09534559], # o [ 0.43874428, -0.13767782], # l [ 0. , 0. ], [ 0. , 0. ]], [[ 0.41703776, -0.0360325 ], # l [ 0.55141526, -0.08852454], # l [ 0.01884381, 0.11428992], # e [-0.22966114, 0.04843425], # e [ 0. , 0. ]]], dtype=float32) | cs |
마지막으로는 Time Series Data를 사용하는 RNN이 있습니다. 이 데이터의 유형은 아래의 그림 및 텍스트를 참고하세요.
[그림]
[텍스트]
1 2 3 4 5 6 7 8 9 10 11 | # http://finance.yahoo.com/quote/GOOG/history?ltr=1 # Open,High,Low,Volume,Close 828.659973,833.450012,828.349976,1247700,831.659973 823.02002,828.070007,821.655029,1597800,828.070007 819.929993,824.400024,818.97998,1281700,824.159973 819.359985,823,818.469971,1304000,818.97998 819,823,816,1053600,820.450012 816,820.958984,815.48999,1198100,819.23999 811.700012,815.25,809.780029,1129100,813.669983 ... ... | cs |
이번 RNN에서는 위의 주식형 텍스트 데이터를 사용합니다. 해당 데이터는 여기에서 다운받을 수 있습니다.
우리는 마지막 Close 값 예측을 목표로 합니다. 따라서 구성하는 RNN의 구조는 다음과 같습니다.
INPUT : 5 (Open, High, Low, Volume, Close)
SEQUENCE : 7 (7일까지의 데이터만 사용)
OUTPUT : 1 (Close)
먼저 데이터 값이 복잡하므로 MinMaxScaler 및 hyper_parameter을 미리 정의합니다.
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 | import tensorflow as tf import numpy as np import matplotlib import os #for graph import matplotlib.pyplot as plt def MinMaxScaler(data): ''' Min Max Normalization Parameters ---------- data : numpy.ndarray input data to be normalized shape: [Batch size, dimension] Returns ---------- data : numpy.ndarry normalized data shape: [Batch size, dimension] References ---------- .. [1] http://sebastianraschka.com/Articles/2014_about_feature_scaling.html ''' numerator = data - np.min(data, 0) denominator = np.max(data, 0) - np.min(data, 0) # noise term prevents the zero division return numerator / (denominator + 1e-7) # train Parameters input_dim = 5 #input sequence_length = 7 #sequence output_dim = 1 #output hidden_size = 10 #user default learning_rate = 0.01 iterations = 500 #learning count | cs |
이제 데이터를 읽고 지정하는데, 아래와 같이 읽어온 데이터를 시간순으로 배열합니다.
1 2 3 | # Open, High, Low, Volume, Close xy = np.loadtxt('data-02-stock-daily.csv', delimiter=',') xy = xy[::-1] # reverse order (chronically ordered) | cs |
기본적으로 학습은 총 데이터의 0.7, 나머지는 테스트용으로 사용합니다. 따라서 데이터를 다음과 같이 나눌 수 있습니다.
동시에 MinMaxScaler를 적용합니다.
1 2 3 4 5 6 7 8 | # train/test split train_size = int(len(xy) * 0.7) train_set = xy[0:train_size] test_set = xy[train_size - sequence_length:] # Index from [train_size - sequence_length] to utilize past sequence # Scale each train_set = MinMaxScaler(train_set) test_set = MinMaxScaler(test_set) | cs |
test_set은 총 데이터의 30퍼센트 이외로 과거 시퀸스 7개를 더 포함하고 있습니다. 이렇게 과거의 시퀸스를 이용하면 더 높은 정확도를 얻을 수 있습니다.
이제 편리하게 함수를 이용해 dataX와 dataY를 구축합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # build datasets def build_dataset(time_series, sequence_length): dataX = [] dataY = [] for i in range(0, len(time_series) - sequence_length): _x = time_series[i:i + sequence_length, :] _y = time_series[i + sequence_length, [-1]] # Next close price print(_x, "->", _y) dataX.append(_x) dataY.append(_y) return np.array(dataX), np.array(dataY) trainX, trainY = build_dataset(train_set, sequence_length) testX, testY = build_dataset(test_set, sequence_length) | cs |
마지막으로 RNN을 구성해야 하는데, 우리는 output이 1이므로 이를 고려해서 FCLayer를 추가합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # input place holders X = tf.placeholder(tf.float32, [None, sequence_length, input_dim]) Y = tf.placeholder(tf.float32, [None, 1]) # build a LSTM network cell = tf.contrib.rnn.BasicLSTMCell( num_units=hidden_size, state_is_tuple=True, activation=tf.tanh) outputs, _states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32) Y_pred = tf.contrib.layers.fully_connected( outputs[:, -1], output_dim, activation_fn=None) # We use the last cell's output # cost/loss loss = tf.reduce_sum(tf.square(Y_pred - Y)) # sum of the squares # optimizer optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss) | cs |
이 속성은 기본적인 파이썬 슬라이싱 방법으로, 도출된 수많은 output 중에서 마지막 한개만을 가져옵니다.
이 속성은 활성 함수(activation function)을 지정합니다. 여기서 적절한 활성 함수를 지정하면 더 높은 정확도를 얻을 수 있습니다. (reLU, tanh, ...)
이제 학습 후 테스트, 그리고 matplotlib를 이용해 테스트 결과를 그래프로 표시합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) # Training step for i in range(iterations): _, step_loss = sess.run([train, loss], feed_dict={ X: trainX, Y: trainY}) print("[step: {}] loss: {}".format(i, step_loss)) # Test step test_predict = sess.run(Y_pred, feed_dict={X: testX}) # Plot predictions plt.plot(testY) plt.plot(test_predict) plt.xlabel("Time Period") plt.ylabel("Stock Price") plt.show() | cs |
[output]
그래프에서 보다시피 예측값과 실제값이 비교적 정확하게 일치하는 것을 알 수 있습니다.
RNN 모델은 이렇게 다양한 데이터 형식에 적용될 수 있는데, 아래의 그림과 같이 대표적으로 4개의 모델이 있습니다.
ONE TO ONE : Vanila RNN
ONE TO MANY : Image Captioning (이미지를 설명하는 문장 만들기)
MANY TO ONE : Sentiment Classification (문장에서 각 단어를 입력받아 감정적 표현으로 나타내기 - 슬픔, 기쁨, 감동 ...)
MANY TO MANY (1) : Machine Translation (문장 번역)
MNAY TO MANY (2) : Video Classification on frame level (여러 프레임을 입력받아 프레임 별 설명을 출력 - Captioning)
'파이썬 > 머신러닝' 카테고리의 다른 글
[#E20] Recurrent Neural Network (RNN - PART 2/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 |