Writer: Harim Kang
해당 포스팅은 '시작하세요! 텐서플로 2.0 프로그래밍'책의 흐름을 따라가면서, 책 이외에 검색 및 다양한 자료들을 통해 공부하면서 정리한 내용의 포스팅입니다. 해당 내용은 RNN, LSTM, GRU에 대한 내용을 담고 있습니다. 사용 라이브러리는 Tensorflow 2.0 with keras, sklearn입니다.
return_sequences
RNN 계산 과정에 있는 hidden state를 출력할 것인지에 대한 값을 의미합니다.
해당 값은 다층으로 이루어진 RNN 또는 one-to-many, many-to-many 출력을 위해서 사용됩니다.
위의 그림과 같이 False의 경우, 마지막 출력값 하나를 출력합니다. True의 경우, 모든 과정의 출력 값을 출력합니다.
return_state
activation
tf.keras.layers.SimpleRNN에서 import가 가능합니다.
model = tf.keras.Sequential([
tf.keras.layers.SimpleRNN(units=1,
activation='tanh',
return_sequences=True,
return_state=True)
])
SimpleRNN 네트워크 예제
[0.0 0.1 0.2 0.3]이라는 0.1씩 늘어나는 수열을 줄 때, 이후의 값들도 예측을 하는 네트워크를 만들어보겠습니다.
Test 환경
X = []
Y = []
for i in range(6):
lst = list(range(i,i+4))
X.append(list(map(lambda c: [c/10], lst)))
Y.append((i+4)/10)
X = np.array(X)
Y = np.array(Y)
print(X)
print(Y)
X에 0, 0.1, 0.2, 0.3 같은 수열들을 0.1씩 증가하면서 나열해줍니다. 해당 수열의 답인 Y는 0.4부터 0.1씩 증가하면서 들어가게 됩니다.
모델 만들기 & 학습
model = tf.keras.Sequential([
tf.keras.layers.SimpleRNN(units=10,
return_sequences=False,
input_shape=[4,1]),
tf.keras.layers.Dense(1)
])
model.compile(optimizer='adam', loss='mse')
history = model.fit(X, Y, epochs=100, verbose=0)
모델은 Sequential에 SimpleRNN과 Dense레이어를 하나씩 추가해 주었고, input_shape는 4 time-step마다 하나의 답이라서 [4,1]을 선언하였습니다.
위와 같은 학습을 반복하여서 MSE값을 낮추는 훈련을 하게 됩니다.
예측
print(model.predict(X))
기존의 훈련 데이터 세트를 넣어서 예측을 해보겠습니다.
위와 같이, 답에 가깝게 예측이 되는 것이 확인이 됩니다. 이제는 새로운 데이터를 넣어서 예측해봅시다.
X_test = np.array([[[0.8],[0.9],[1.0],[1.1]]])
print(model.predict(X_test))
위의 데이터를 넣어서 원하는 결과는 1.2에 가까운 수입니다.
그러나 위와 같은 결과를 얻었습니다. 훈련 데이터를 증가시켜서 해당 결과를 개선시킬 수 있습니다.
간단한 RNN의 구조로는 위와 같은 장기 의존성 문제가 발생합니다. 이를 해결하기위해서 제안된 RNN의 변형 구조가 바로 LSTM입니다.
활성화 함수는 두 가지로 아래와 같습니다.
좀 더 자세히 살펴보겠습니다.
위의 그림처럼 LSTM 레이어는 Input Gate, Forget Gate, Output Gate라는 c(cell state)의 값을 제어하는 게이트들이 존재합니다. 각 게이트들은 sigmoid layer와 pointwise곱 연산을 통해서 값을 제어합니다.
각각의 게이트들은 cell state를 보호하고 제어하는 역할을 합니다.
Input gate layer
Forget gate layer
Output gate layer
model = tf.keras.Sequential([
tf.keras.layers.LSTM(units=30,
return_sequences=True,
input_shape=[100,2]),
tf.keras.layers.LSTM(units=30),
tf.keras.layers.Dense(1)
])
model.compile(optimizer='adam', loss='mse')
history = model.fit(X, Y, epochs=100, verbose=0)
제가 전공 프로젝트를 했던 LSTM을 이용한 청바지 가격 예측 프로젝트입니다.
https://davinci-ai.tistory.com/11?category=907787
GRU는 LSTM과 비슷한 역할을 하지만, 더 간단한 구조로 이루어져 있어서 계산상으로 효율적입니다. 이것은 기존의 LSTM에서 사용되는 셀 상태 계산(은닉 상태 업데이트)을 줄였습니다. 또한 특정 문제에서는 LSTM보다 더 적합한 레이어입니다.
좀 더 자세히 살펴보겠습니다.
위의 그림처럼 GRU레이어는 Reset Gate, Update Gate들로 이루어져 있습니다. 각 게이트들은 sigmoid layer와 pointwise곱 연산을 통해서 값을 제어합니다.
Reset Gate
Update Gate
데이터 선정
출력 값 계산
model = tf.keras.Sequential([
tf.keras.layers.GRU(units=30,
return_sequences=True,
input_shape=[100,2]),
tf.keras.layers.GRU(units=30),
tf.keras.layers.Dense(1)
])
model.compile(optimizer='adam', loss='mse')
history = model.fit(X, Y, epochs=100, verbose=0)
임베딩 레이어는 주로 자연어 처리에서 사용되며, 자연어를 수치화된 정보로 바꾸기 위한 레이어입니다.
RNN은 자연어 처리에 좋은 신경망입니다. 하지만, 신경망은 기본적으로 숫자로 이루어진 가중치와 편향들로 구성되어있습니다. 이를 위해 우리는 자연어를 의미가 있는 숫자 벡터로 바꾸어주어야 합니다.
tf.keras.preprocessing.text.Tokenizer()
토큰화와 정수 인코딩을 위해서 제공되는 클래스입니다.
t = tf.keras.preprocessing.text.Tokenizer()
fit_text = "I love Deep Learning"
t.fit_on_texts([fit_text])
test_text = "I like Deep Learning"
sequences = t.texts_to_sequences([test_text])[0]
print("sequences : ",sequences) # great는 단어 집합(vocabulary)에 없으므로 출력되지 않는다.
print("word_index : ",t.word_index) # 단어 집합(vocabulary) 출력
위와 같이 'I love Deep Learning'이라는 문장을 토크 나이저에 적용시키고 'I like Deep Learning'이라는 문장을 sequence로 변환시키면 아래와 같은 결과가 나옵니다.
해당 토크 나이저는 i-1, love-2, deep-3, learning-4로 index가 지정되었고, 두 번째 문장에서는 1, 3, 4에 해당되는 단어들만 찾은 것을 알 수 있습니다.
tensorflow.keras.preprocessing.sequence.pad_sequence()
데이터 세트에서 문장들의 길이는 서로 다를 가능성이 높습니다. 또한 각 문장마다 단어의 수는 다를 확률이 큽니다.
모델을 학습시키기 위해서는 모든 데이터의 길이가 동일하여야 하는 경우가 많습니다. 이를 맞추기 위하여 패딩(padding) 작업을 합니다. 0을 넣어서 크기를 유지해 줍니다.
tf.keras.preprocessing.sequence.pad_sequences([[1, 2, 3], [3, 4, 5, 6], [7, 8]], maxlen=3, padding='pre')
maxlen: 맞추고자 하는 길이를 의미합니다.
padding: 'pre'는 앞쪽에 패딩을 0으로 넣는 것을 의미하고, 'post'는 뒤쪽에 패딩을 0으로 넣는 것을 의미합니다.
위와 같이 text to sequence 작업을 마친 데이터 3개를 넣으면 아래와 같은 패딩 작업이 이루어집니다.
model = tf.keras.Sequential([
tf.keras.layers.Embedding(2000, 128, input_length=X.shape[1]),
tf.keras.layers.SpatialDropout1D(0.4),
tf.keras.layers.LSTM(196, dropout=0.2, recurrent_dropout=0.2),
tf.keras.layers.Dense(2, activation='softmax')
])
model.compile(loss = 'categorical_crossentropy', optimizer='adam',metrics = ['accuracy'])
model.summary()
위와 같이, tf.keras.layers.Embedding클래스를 사용하여 선언할 수 있습니다.
https://www.tensorflow.org/tutorials/keras/text_classification
https://github.com/wikibook/tf2/blob/master/Chapter7.ipynb
https://www.kaggle.com/crowdflower/first-gop-debate-twitter-sentiment
https://github.com/harimkang/tensorflow2_deeplearning/blob/master/RNN_kaggle.ipynb
그림들은 대부분 다양한 정보를 바탕으로 직접 작성한 그림들입니다.
LSTM: http://colah.github.io/posts/2015-08-Understanding-LSTMs/
GRU: https://yjjo.tistory.com/18
Embedding: https://www.tensorflow.org/api_docs/python/tf/keras/layers/Embedding
https://wikidocs.net/32105
딥러닝 (9) - [RL2] 신경망 네트워크를 이용한 MountainCar 해결 (3) | 2020.03.25 |
---|---|
딥러닝 (8) - [RL1] 강화학습(Reinforcement Learning)이란? (0) | 2020.03.22 |
딥러닝 (6) - CNN (Convolutional Neural Network) (2) | 2020.02.24 |
딥러닝 (5) - 분류(Classification) 네트워크 (1) | 2020.02.24 |
딥러닝 (4) - 회귀(Regression) 네트워크 만들기 (0) | 2020.02.12 |