AI/Fundamental

RNN(Recurrent Neural Network) 순환신경망 공부하기

방황하는 데이터불도저 2023. 6. 14. 21:25

08-01 순환 신경망(Recurrent Neural Network, RNN) - 딥 러닝을 이용한 자연어 처리 입문 글을 참고하여 공부한 내용을 정리하였습니다. 

 

순서를 가지는 Sequence 데이터를 입력값과 출력값으로 가지는 경우 Sequential Model을 사용할 수 있다. 그 중 가장 처음 고안된 신경망 모델이 바로 RNN이다. 데이터 시퀀스를 처리하는 모델로 각 시간 단계를 독립적인 레이어로 처리할 수 있게 구성되어 RNN unrolling technique라는 용어가 사용된다. (참고논문)

 

LSTM이나 GRU도 근본적으로는 RNN을 기반으로 발전된 모델들이다. 시퀀스 모델은 기계번역, 문서 요약 등의 자연어 처리 모델에서 주로 활용된다. 

 

RNN모델의 architecture 구성을 자세히 살펴보자.

벡터의 차원은 더 아래의 그림에서 확인해보자.

 

먼저, 그림에서 Layer에 대해 설명해보면 (①)

[Input Layer=입력층]에는 입력벡터 xt,

[Hidden Layer=은닉층]에는 [hidden state=은닉상태]를 저장하는 [RNN cell=메모리셀],

[Output Layer=출력층]에는 출력벡터 yt 가 존재하게 된다. 

 

* Feed Forward Neural Network에서는 neuron 뉴런 단위를 사용했으나, RNN에서는 뉴런보다는 벡터 단위를 사용한다.

이해를 위해 벡터를 뉴런으로 시각화해보면 위의 사진의 ②그림 예시처럼 한 벡터안에 여러개의 뉴런으로 구성되고, 이는 입력한 데이터, 설정하는 하이퍼 파라미터에 따라서 뉴런수는 달라진다.

* 뉴런수에 따라서 벡터의 차원수가 결정된다.

 

위에서 설명한 Layer 구조는 위의 사진의 ③그림처럼 시퀀스에 따라 Layer 구조 통째로 계속 반복되게 된다.

이때, 입력데이터에 따라서 c (cell)의 은닉상태를 계산하여 업데이트하게 된다.

 

해당 내용을 수식으로는 어떻게 되는지 알아보자.

수식을 정리한 그림
두 시점의 연산 과정

예를 들어 Happy Birthday라는 문장이 들어갔을 때,

입력값x의 t-1시점은 Happy라는 단어의 벡터이고, t시점은 Birthday라고 가정해보자.

 

입력층 → 은닉층

Birthday라는 단어를 단어 임베딩(word embedding) 벡터값으로 치환하고, batch size가 1일 때, 해당 벡터의 성분의 개수를 벡터의 차원수=뉴런수라고 할 수 있다. 이 입력 벡터는 그림의 오른쪽의 수식으로 계산되어 t시점의 hidden state인 h_t를 구하여 cell에 업데이트 시키게 된다. 

활성화 함수에는 tanh가 주로 사용되고, 결과적으로 아래와 같이 계산된다. 

 

은닉층 → 출력층

위에서 계산된 ht는 현재시점 t의 출력벡터 y를 계산하는데에 아래와 같이 사용된다.

마지막 시점(t)의 hidden state의 벡터가 문장 임베딩 벡터(sentence embedding vector)이고, 해당 모델의 결과물이 된다.

위에서 설명한 과정은 Feed Forward를 수행하는 RNN으로 향후 Encoder가 된다.

 

잠시 활성화 함수에 대해 이야기하자면,

이진 분류의 문제일 경우에는 로지스틱 회귀를 활용하는 시그모이드 함수

다중 분류의 문제일 경우에는 소프트맥스 회귀를 활용하는 소프트맥스 함수가 자주 사용된다.

추후 Decoder RNN을 다룰 때, 어떤 단어가 출력될 확률에 대해서 소프트맥스 함수를 사용해줄 수 있다.

 

그리고 RNN을 적용하는 방식은 아래와 같이 다양하고, 어떤 문제에 적용하느냐에 따라서 형태가 달라질 수 있다.

 

여기까지가 수식계산에 대한 설명이었고, 이어서 코드로 어떻게 RNN을 구현하고, 계산하는지 살펴보자.

 

Keras 구현함수 예시

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import SimpleRNN

# 빈 모델 선언
model = Sequential()

# 모델에 Layer추가
#방법 1
#model.add(SimpleRNN(hidden_units, input_shape=(timesteps,input_dim)))
#방법 2
model.add(SimpleRNN(hidden_units=3, input_length=2, input_dim=10))
# 모델내부 확인
model.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
simple_rnn_1 (SimpleRNN)     (None, 3)                 42        
=================================================================
Total params: 42
Trainable params: 42
Non-trainable params: 0
_________________________________________________________________
  • W_x.shape = (3, 10)
  • x_t.shape = (10, 1)
  • W_h.shape = (3,3)
  • h_t-1.shape = (3,1)
  • b.shape = (3,1)
  • h_t.shape = (3,1)

W_x, W_h, b의 성분 개수의 합이 총 파라미터 수가 된다.

따라서, 3*10 + 3*3 + 3*1 = 42 가 된다.

 

** RNN을 구현코드 : Github


정리 요약 

  • 위의 내용은 아주 기본적인 RNN 구조로 Simple RNN 또는 Vanilla RNN이라고 한다.
  • Input값과 Output값을 Sequence 단위로 끊어서 처리하는 Sequence Model 이다.
  • 은닉층(Hidden Layer)에서 출력된 값이 그대로 출력층(Output Layer)으로 가는 보편적인 Feed Forward Neural Network와 달리 RNN은 활성화함수를 거친 결과는 출력층으로 가면서, 또한 다음 은닉층 노드의 입력으로도 보내진다. (출력층의 값은 다음 은닉층의 값으로 보내지지 않는다.)
  • 마지막 은닉층에서 나온 hidden state(h_t)가 문장 임베딩 벡터가 된다.

다음 글 : https://kyull-it.tistory.com/157

 

LSTM (Long Short-Term Memory) 장단기 메모리; 공부하기

이 글을 읽기 전에 해당 내용은 08-02 장단기 메모리(Long Short-Term Memory, LSTM) - 딥 러닝을 이용한 자연어 처리 입문 을 보고 공부한 내용입니다. 잘못된 부분이 있다면 댓글 부탁드립니다. 아래의 내

kyull-it.tistory.com