순환신경망(RNN) 정리
다음의 출처를 참고했습니다.
순차 데이터
순차 데이터는 순서에 의미가 있으며, 순서가 달라질 경우 의미가 손상되는 데이터입니다.
시간적 의미가 있는 경우 Temporal Sequence라고 하며, 일정한 시간차라면 Time Series라고 합니다.
순환 신경망(RNN)
순환 신경망은 순차 데이터와 같이 시간의 흐름에 따라 변화하는 데이터를 학습하기 위한 인공신경망입니다.
따라서, 과거의 출력 데이터를 재귀적으로 참조합니다.
순환되는 고리가 있는 신경망입니다.
위의 그림을 보면 은닉층의 노드에서 나온 결과값이 출력층 방향으로도 보내지고,
다시 은닉층 노드의 다음 계산을 위한 입력으로도 보내지는 특징이 있습니다.
그러므로, 결과값 O(t)는 결과값 O(t-1)에 대한 정보가 어느정도 포함(기억)되고,
O(t+1)은 O(t)와 O(t-1)의 정보가 어느정도 포함(기억)된다고 할 수 있습니다.
이렇게 이전의 계산에서 나온 출력값을 다시 다음 단계 계산에서 사용하는 하나의 사이클을 Time Step이라고 합니다.
- 셀 : 은닉층에서 결과를 두 뱡향(출력층과 다음 연산)으로 내보내는 노드를 메모리 셀 혹은 셀이라고 합니다.
완전 연결층에서 출력되는 값은 활성화 출력, 합성곱 층에서 출력되는 값은 특성 맵이라고 하듯이,
셀에서 출력하는 값은 은닉 상태(Hidden State)라고 합니다.
또한, RNN에서는 입력층/출력층을 입력벡터/출력벡터 라고 합니다.
RNN 수식 이해하기
-
ht : 현재 타임 스텝 t에서의 은닉 상태값
-
wx : 입력 벡터의 입력값과 곱해질 가중치
-
wh : 이전 타임 스텝 t-1에서의 은닉 상태값 ht-1과 곱해질 가중치
따라서 ht를 계산하는 수식은 다음과 같습니다.
-
ht = activation_function((wh * ht-1) + (wx * xt) + b)
-
yt = activation_function((wy * ht) + b)
RNN에서도 역시 활성화 함수를 사용하는데, 보통 tanh함수를 많이 사용합니다.(relu를 사용하기도)
(tanh도 역시 S자 모양으로 -1 ~ 1값을 가지기 때문에 시그모이드라고 불리기도 합니다.)
RNN은 이렇게 각 타임 스텝마다 wx와 wh를 동일하게 사용합니다.
이런 부분을 보았을 때, RNN은 타임 스텝에 따라서 가중치를 공유하며 모델의 파라미터를 효율적으로 사용할 수 있습니다.
순환 신경망의 입력과 출력
RNN층은 (batch_size, timesteps, input_dim) 형태의 3D 텐서를 입력받습니다.
-
batch_size는 한번에 RNN이 학습하는 데이터의 양을 의미합니다.
-
timesteps는 입력 시퀀스의 크기입니다. input_length와 동일합니다.
-
input_dim은 입력의 크기입니다.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import SimpleRNN
model = Sequential()
model.add(SimpleRNN(3, input_shape=(2, 10)))
# batch_size=8, timesteps=2, input_dim=10
model.summary()
Model: "sequential_3" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= simple_rnn_3 (SimpleRNN) (8, 3) 42 ================================================================= Total params: 42 Trainable params: 42 Non-trainable params: 0 _________________________________________________________________
RNN의 출력값은 (batch_size, output_dim)형태로 출력됩니다.
units는 RNN층의 은닉층의 갯수를 의미하고, output_dim은 은닉층의 갯수(units)가 됩니다.
위와 같이 (2, 10)형태의 2D 텐선을 입력하면 units는 3이고, batch_size는 알 수 없으므로 (None, 3)이 출력됩니다.
model = Sequential()
model.add(SimpleRNN(3, batch_input_shape=(8, 2, 10)))
# RNN층의 units = 3, batch_size=8, timesteps=2, input_dim=10
model.summary()
Model: "sequential_4" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= simple_rnn_4 (SimpleRNN) (8, 3) 42 ================================================================= Total params: 42 Trainable params: 42 Non-trainable params: 0 _________________________________________________________________
batch_size를 기재하면 입력은 3D 텐서이고, 출력값으로 (batch_size, output_dim)이 리턴됩니다.
하지만, return_sequences 매개 변수를 True로 지정해주면 (batch_size, timesteps, output_dim)크기의
3D 텐서를 리턴할 수 있습니다.
return_sequences
셀의 각 시점(time step)의 은닉 상태값들을 모아서 전체 시퀀스를 리턴하려면 return_sequences=True를 설정하면
됩니다.
위의 그림은 time step가 3일 때, return_sequences=True로 설정했을 때와 아닐 때의 차이를 보여줍니다.
return_sequences=True로 설정하면 셀의 모든 시점(time step)에 대한 은닉 상태값을 출력하고,
return_sequences=False일 경우에 셀은 하나의 마지막 시점의 은닉 상태값만 출력합니다.
model = Sequential()
model.add(SimpleRNN(3, batch_input_shape=(8, 2, 10), return_sequences=True))
# RNN층의 units = 3, batch_size=8, timesteps=2, input_dim=10
model.summary()
Model: "sequential_5" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= simple_rnn_5 (SimpleRNN) (8, 2, 3) 42 ================================================================= Total params: 42 Trainable params: 42 Non-trainable params: 0 _________________________________________________________________
return_sequences=True를 설정하면 출력값으로 (batch_size, timesteps, output_dim) 크기의
3D 텐서가 출력되는 것을 확인할 수 있습니다.
RNN의 활용
RNN은 입력과 출력의 길이가 고정되어 있지 않습니다. 그러므로, 설계에 따라 다양한 용도로 신경망을 사용할 수 있습니다.
일대다 모델
- 하나의 이미지 입력에 대해서 사진의 제목을 출력하는 이미지 캡셔닝(Image Captioning)작업에 사용할 수 있습니다.
사진의 제목은 단어들의 나열이므로 시퀀스 출력입니다.
다대일 모델
-
입력 문서가 긍정적인지 부정적인지 판별하는 감성 분류(sentiment classification)
-
메일이 정상 메일인지 스팸 메일인지 판별하는 스팸 메일 분류(spam detection)등에 사용할 수 있습니다.
다대다 모델
-
사용자가 문장을 입력하면 대답 문장을 출력하는 챗봇
-
입력 문장으로부터 번역된 문장을 출력하는 번역기 등이 있습니다.
양방향 순환 신경망
양방향 RNN은 이전과 이후의 시점 모두를 고려해서 현재 시점의 예측을 더욱 정확하게 할 수 있도록 고안된 방법입니다.
기본적으로 두 개의 메모리 셀을 사용합니다.
첫번째 셀은 기존과 동일하게 앞 시점의 은닉 상태를 전달받아 현재의 은닉 상태를 계산합니다.
두번째 셀은 뒤 시점의 은닉상태를 전달 받아 현재의 은닉 상태를 계산합니다.(입력 시퀀스를 반대 방향으로 읽습니다.)
이처럼 앞, 뒤 2개의 시점을 이용하여 현재 시점의 은닉 상태를 출력합니다.
from tensorflow.keras.layers import Bidirectional
model = Sequential()
model.add(Bidirectional(SimpleRNN(3, return_sequences=True), input_shape=(2, 10)))
model.summary()
Model: "sequential_7" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= bidirectional_1 (Bidirectio (None, 2, 6) 84 nal) ================================================================= Total params: 84 Trainable params: 84 Non-trainable params: 0 _________________________________________________________________
댓글남기기