1. RNN
(1) RNN의 구조
Sequence data란 현재 state가 그 다음 state에 영향을 미치는 데이터이다. 아래 그림과 같이, x라는 입력을 넣으면 RNN에서 출력으로 나오는 state가 다시 RNN의 입력이 된다. 또한 각각 RNN 셀에서 y값을 뽑아낼 수가 있다.
RNN을 계산할 때 state를 먼저 계산한 후 y를 구한다. state를 계산할 때 중요한 것은 tiem step 이전의 state가 입력으로 사용된다는 것이다. 즉 입력값은 2개로 [1] x, [2] 이전 RNN 셀에서의 state이다. 또한 RNN의 셀은 여러 개지만, 위의 그림처럼 구조를 표현하는 이유는 셀들마다 동일한 fW를 사용하기 때문이다.
(2) Vanilla RNN
RNN의 가장 기본적인 형태다. 시퀀스 데이터에 대해 작동하며, 이전 시간의 출력을 현재 시간의 입력으로 사용한다. Vanilla RNN은 타임 스텝마다 동일한 가중치를 사용한다. 즉, 모델이 모든 타임 스텝에서 동일한 연산을 수행하도록 한다. 이 모델은 짧은 시간 내의 의존성을 모델링하는데 적합하므로, 장기 의존성을 적절하게 다루긴 어렵다.
WX를 사용할 것이다. 입력이 2개이므로, 입력마다 각각의 가중치를 만들어준다. 그다음 tanh 함수에 넣어 현재의 ht를 계산한다. yt는 계산된 현재 state에 또다른 가중치를 곱한 값이다. y가 몇 개 나올지는 Why의 형태에 달려 있다. 즉 Why가 어떤 형태의 벡터냐에 따라서 y 개수가 결정된다.
(3) RNN의 활용
다양한 분야에서 RNN이 활용된다.
Image Captioning이란 이미지를 제공받고 '나는 모자를 쓰고 있다'와 같은 글자를 출력하는 것이다. Sentiment Classification은 문장을 입력받고 하나의 출력 '이 문장은 슬프다' 만을 출력하는 것이다. Machine Translation은 문자열을 입력받고 문자열을 출력하는 방식으로 사용된다. 마지막으로 Video classification on frame level은 여러 개의 프레임을 입력받아 출력하는 것이다.
2. LSTM
RNN의 단점 : 긴 기간의 의존성이 존재한다. 여러 문장, 많은 문맥 속 마지막 단어를 학습하고자 할 때엔 필요한 정보를 얻기 위한 시간 격차가 커질 수 밖에 없다. 이렇게 격차가 늘수록 RNN은 학습하는 정보를 계속 이어나가기 힘들어한다. 긴 시퀀스에서 정보를 전달하는 과정에서 Vanishing Gradient, Exploding Gradient와 같은 문제들이 발생한다.
(1) LSTM의 구조
LSTM은 RNN의 한 종류로, explicit하게 설계되었다. LSTM 역시 RNN과 동일하게 NN 모듈을 반복시키는 체인 같은 형태를 지닌다. 그러나 각 반복 모듈이 다르게 설계되었다. NN 한 층이 존재하는 대신에, 4개의 layer가 서로 정보를 주고 받도록 설계되었다.
아래 링크에서 설명이 무척 잘 되어 있으니 참고하면 좋을 것 같다.
3. RNN in Tensorflow
(1) 기본 구조
#cell = tf.contrib.rnn.BasicRNNCell(num_units=hidden_size)
cell = tf.contrib.rnn.BasicLSTMCell(num_units=hidden_size)
outputs, _states = tf.nn.dynamic_rnn(cell, x_data, dtype = tf.float32)
-> cell을 만들 땐 hidden size, 즉 출력의 크기를 정해주어야 한다.
-> cell, 원하는 입력 데이터를 입력으로 넣으면 dynamic_rnn은 출력, 마지막 state를 출력한다.
(2) one-hot encoding
one-hot encoding이란 데이터 변환 방법 중 하나로, 주로 이산적인(discrete) 카테고리를 다룰 때 사용된다. 입력데이터를 이진 벡터로 표현하는 기술이다. 예시를 들어보자. [1] 카테고리(사과, 바나나, 오렌지) 각각에 고유한 인덱스를 할당한다. [2] 각 데이터 포인트는 카테고리 인덱스에 대응하는 위치를 제외하곤 모두 0으로 채워진 벡터이다. [3] 데이터 포인트가 특정 카테고리에 속하면 해당 인덱스 위치 값은 1로 설정된다. 다른 위치 값은 모두 0이다.
-> hidden_size
hello를 one-hot encoding으로 표현해보다. h, e, l, o 총 4개의 값이 필요하므로 아래 코드와 같이 나타낼 수 있다. 이들을 입력으로 주면, 입력의 dimension은 4가 된다. shape의 마지막 요소가 4임을 알 수 있다.
#cell = tf.contrib.rnn.BasicRNNCell(num_units=hidden_size)
cell = tf.contrib.rnn.BasicLSTMCell(num_units=hidden_size)
outputs, _states = tf.nn.dynamic_rnn(cell, x_data, dtype = tf.float32)
output dimension은 우리의 마음대로다. hidden size를 무엇으로 정했느냐에 따라서 이 값이 결정된다. 아래 그림에선 hidden_size가 2이므로 출력의 shape이 (1,1,2)다. output, _states의 값을 각각 확인하려면 해당 링크를 참고하자.
-> sequance_length
shape의 중간에 위치한 값은 sequance_length로, 한 번에 몇 개의 serial data를 받을 것인가를 의미하는 값이다. 출력 시 입력과 동일한 sequance length 값을 출력한다.
x_data = np.array([[h, e, l, l, o]], dtype=np.float32)
-> batch_size
문자열을 하나씩 학습시키는 것은 꽤 비효율적이다. batch_size는 문자열 여러 개를 한번에 입력하는 것이다.
# 3 batches 'hello', 'eolll', 'lleel'
x_data = np.array([[h, e, l, l, o],
[e, o, l, l, l],
[l, l, e, e, l]], dtype=np.float32)
-> 최종 코드 그림
왼쪽 그림에서 shape = (3, 5, 4)일 때 4가 input dimension이다. 또한 shape = (1,5,2)에서 2가 hidden size이다. batch_size와 sequance_length는 3, 5로 입력에 넣어준 값 그대로 출력에 나온다.
오른쪽 그림에서 ... 얘는 입력의 shape = (1,5,4)와 출력의 shape = (1,5,2)인 것 같다. 문자열 'hello'를 학습시킬 때 문자열이 한 줄이므로 batch_size = 1, 글자가 총 5개이므로 sequance_length = 5이다.
4. LSTM in Tensorflow
(1) Character-level language model
hell을 입력하면 hello를 출력하는 형식의 모델이다. 즉 현재 글씨가 있을 때 그다음 글씨를 추측하는 모델이다. [1] 입력을 벡터로 표현한다. one-hot encoding을 사용하여 각각에 해당하는, 총 4개의 벡터로 표현한다. h, e, l, o를 서로 다른 multi label이라 생각하면 된다. [2] 첫번째 은닉층엔 ht-1가 없으므로 ht-1를 0으로 가정하고 W_xh를 곱하여 은닉층을 구한다. 두번째 은닉층부턴 W_hh와 W_xh를 사용하여 그다음 은닉층을 구하는 방식으로 계산이 진행된다. [3] y를 출력할 때엔 은닉층에 W_hy를 곱하여 결과를 바로 도출한다. softmax를 취하여 가장 큰 값을 도출한다.
(2) 코드 전문
import numpy as np
import tensorflow as tf
idx2char = ['h', 'i', 'e', 'l', 'o']
# hello를 학습시키자.
# hihell를 입력하면 ihello를 출력하는 형태다.
# x_data = [[0, 1, 0, 2, 3, 3]] # hihell
y_data = [[1, 0, 2, 3, 3, 4]] # ihello
num_classes = 5 #5개의 classification
input_dim = 5 # one-hot size, same as hidden_size to directly predict one-hot
sequence_length = 6 # |ihello|의 길이이므로 6.
learning_rate = 0.1 #학습률
x_one_hot = np.array([[[1, 0, 0, 0, 0], # h 0
[0, 1, 0, 0, 0], # i 1
[1, 0, 0, 0, 0], # h 0
[0, 0, 1, 0, 0], # e 2
[0, 0, 0, 1, 0], # l 3
[0, 0, 0, 1, 0]]], # l 3
dtype=np.float32)
y_one_hot = tf.keras.utils.to_categorical(y_data, num_classes=num_classes)
print(x_one_hot.shape)
print(y_one_hot.shape)
tf.model = tf.keras.Sequential()
# make cell and add it to RNN layer
# input_shape = (1,6,5) => number of sequence (batch), length of sequence, size of input dim
cell = tf.keras.layers.LSTMCell(units=num_classes, input_shape=(sequence_length, input_dim))
#lstm으로 5개의 classification에 대해, 6행 5열로 input data를 정렬해주는 것을 의미.
tf.model.add(tf.keras.layers.RNN(cell=cell, return_sequences=True))
#RNN으로 LSTM의 cell을 지정해주고, Sequences=True라는 명령어로, Time sequential한 데이터임을 선언한다.
# single LSTM layer can be used as well instead of creating LSTMCell
# tf.model.add(tf.keras.layers.LSTM(units=num_classes, input_shape=(sequence_length, input_dim), return_sequences=True))
# fully connected layer
tf.model.add(tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(units=num_classes, activation='softmax')))
#모델의 layer를 설명해주는 부분, TimeDistributed를 추가시켜줌.
#classification을 5개로 선언, activation function은 sofrmax를 사용함.
#lstm은 과거의 값을 끊임없이, 재귀로 사용한다. 그래서 -1~1 사이로 normalizing이 필요하다.
#But ReLU의 경우 0 이상의 값에선 y=x로 나온다. 발산할 확률이 아주아주.. 높아져.. 대부분 발산한다.
tf.model.compile(loss='categorical_crossentropy', optimizer=tf.keras.optimizers.Adam(lr=learning_rate),
metrics=['accuracy'])
# train
tf.model.fit(x_one_hot, y_one_hot, epochs=100)
tf.model.summary()
predictions = tf.model.predict(x_one_hot)
for i, prediction in enumerate(predictions):
print(prediction)
# print char using argmax, dict
result_str = [idx2char[c] for c in np.argmax(prediction, axis=1)]
print("\tPrediction str: ", ''.join(result_str))
RNN 개념 출처: https://www.youtube.com/watch?v=-SHPG_KMUkQ
LSTM 개념 출처: https://dgkim5360.tistory.com/entry/understanding-long-short-term-memory-lstm-kr
LSTM 코드 출처: https://limitsinx.tistory.com/62#google_vignette
'LAB > AI' 카테고리의 다른 글
딥러닝(3) 파이썬, 텐서플로 : 코드 위주 (0) | 2024.01.17 |
---|---|
딥러닝(2) 인공신경망의 구조와 연산 : 이론 위주 (0) | 2024.01.17 |
딥러닝(1) 인공지능의 분류, 지도 학습 구현 기법 (2) | 2024.01.17 |
딥러닝(6) 실습: RNN image classification 코드 (0) | 2023.09.07 |
딥러닝(4) ANN, DNN, CNN, RNN 개념과 차이 (0) | 2023.08.18 |