RNN(Recurrent Neural Network)
시퀀스(Sequence) 모델로, 입력과 출력을 시퀀스 단위로 처리하는 모델임
피드 포워드 신경망과(Feed Forward Neural Network) 달리 은닉층의 노드에서 활성화 함수를 통해 나온 결과값을 출력층 방향으로도 보내면서, 다시 은닉층 노드의 다음 계산의 입력으로 보내는 특징 가짐
- 피드 포워드 신경망 : 은닉층에서 활성화 함수를 지난 값이 오직 출력층 방향으로만 향하는 신경망
- x : 입력층의 입력 벡터
- y : 출력층의 출력 벡터
- b : 편향 (그림에서는 생략됨)
- t : 현재 시점
- cell : 은닉층에서 활성화 함수를 통해 결과를 내보내는 역할을 하는 노드. 메모리 셀 또는 RNN 셀이라고도 표현함
- 은닉층의 메모리 셀은 각각의 시점(time step)에서 바로 이전 시점에서의 은닉층의 메모리 셀에서 나온 값을 자신의 입력으로 사용 = 재귀적 활동
- 위의 그림은 입력 벡터의 차원이 4, 은닉 상태의 크기가 2, 출력층의 출력 벡터의 차원이 2인 RNN이 시점이 2일 때의 모습
- 뉴런 단위로 해석하면, 입력층의 뉴런 수는 4, 은닉층의 뉴런 수는 2, 출력층의 뉴런 수는 2
은닉 상태(hidden state)
메모리 셀이 출력층 방향으로 또는 다음 시점 t+1의 자신에게 보내는 값
t 시점의 메모리 셀은 t-1 시점의 메모리 셀이 보낸 은닉 상태값을 t 시점의 은닉 상태 계산을 위한 입력값으로 사용함
RNN의 종류
RNN은 입력과 출력의 길이를 다르게 설정 가능함
- 일 대 다 :하나의 입력에 대해 여러 개의 출력 ex) 이미지 캡셔닝
- 다 대 일 : 단어 시퀀스에 대해 하나의 출력 ex) 감성 분류, 스팸 메일 분류
- 다 대 다 : 입력 문장으로부터 대답 문장 출력 ex) 챗봇, 번역기, 품사 태깅
RNN 수식
- h_t : 현 시점 t에서의 은닉 상태값
- W_x : 입력층에서 입력 값을 위한 가중치
- W_h : 이전 시점 t-1의 은닉 상태값인 h_t-1을 위한 가중치
- h_t 계산을 위한 활성화 함수로 주로 tanh가 많이 사용되지만, ReLU로 바꿔 사용하는 시도도 존재함
- y_t 계산을 위한 활성화 함수로는 이진 분류의 경우 시그모이드 함수를, 다양한 카테고리 중 선택하는 문제라면 소프트 맥스함수를 사용
RNN에서의 입력 x_t는 대부분의 경우 단어 벡터로 간주할 수 있는데, 단어 벡터의 차원을 d, 은닉 상태의 크기를 D_h라고 하면 각 벡터와 행렬 크기는 다음과 같다.
파이썬 pseudocode
메모리 셀에서 은닉 상태를 계산하는 식 구현
hidden_state_t = 0 # 초기 은닉 상태를 0(벡터)로 초기화
for input_t in input_length: # 각 시점마다 입력을 받는다.
output_t = tanh(input_t, hidden_state_t) # 각 시점에 대해서 입력과 은닉 상태를 가지고 연산
hidden_state_t = output_t # 계산 결과는 현재 시점의 은닉 상태가 된다.
- hidden_state_t : t시점의 은닉 상태
- input_length : 입력 데이터의 길이. 이 경우 입력 데이터는 총 시점의 수(timesteps)이 됨
- input_t : t 시점의 입력값
각 메모리 셀은 각 시점마다 input_t와 hidden_state_t(이전 상태의 은닉 상태)를 입력으로 활성화 함수인 tanh를 통해 현 시점의 hidden_state_t를 계산한다.
양방향 RNN
RNN이 과거 시점(time step)의 데이터들을 참고해서, 찾고자하는 정답을 예측하지만 실제 문제에서는 과거 시점의 데이터만 고려하는 것이 아니라 향후 시점의 데이터에 힌트가 있는 경우도 많음
-> 이전 시점의 데이터뿐만 아니라, 이후 시점의 데이터도 힌트로 활용하기 위해서 고안된 것이 양방향 RNN
양방향 RNN은 하나의 출력값을 예측하기 위해 기본적으로 두 개의 메모리 셀을 사용함
- 첫 번째 메모리 셀 : 앞 시점의 은닉 상태를 전달받아 현재의 은닉 상태 계산 (주황색)
- 두 번째 메모리 셀 : 뒤 시점의 은닉 상태를 전달받아 현재의 은닉 상태 계산 (초록색)
이 두 개 모두가 출력층에서 출력값을 예측하기 위해 사용됨
- 양방향 RNN을 구현할 땐 nn.RNN()의 인자 bidirectional = True로 설정하면 됨
LSTM (Long Short-Term Memory)
바닐라 RNN의 장기 의존성 문제 (the problem of Long-Term Dependencies)
바닐라 RNN은 출력 결과가 이전의 계산 결과에 의존함
하지만 바닐라 RNN은 비교적 짧은 시퀀스에 대해서만 효과를 보인다는 단점이 존재함
= time step이 길어질 수록 앞의 정보가 뒤로 충분히 전달되지 못하는 현상이 발생
= 시점이 지날수록 x_1의 정보량이 손실되고, 시점이 충분히 긴 상황에서는 x_1의 전체 정보에 대한 영향력은 거의 의미가 없어질 수도 있음
LSTM (Long Short-Term Memory)
은닉층의 메모리 셀에 입력 게이트, 망각 게이트, 출력 게이트를 추가하여 불필요한 기억을 지우고, 기억해야할 것들을 정함
=> LSTM은 은닉 상태(hidden state)를 계산하는 식이 전통적인 RNN보다 조금 더 복잡해짐 & 셀 상태(cell state)라는 값 추가됨
- C_t : t 시점의 셀 상태 (셀 상태 : 아래 그림에서 왼쪽에서 오른쪽으로 가는 굵은 선)
은닉 상태값과 셀 상태값을 구하기 위해 새로 추가 된 3개의 게이트 사용함
- 각 게이트는 입력 게이트, 삭제 게이트, 출력 게이트라고 부르며 이 3개의 게이트에는 공통적으로 시그모이드 함수가 존재
- 시그모이드 함수를 지나면 0과 1사이의 값이 나오게 되는데 이 값들을 가지고 게이트를 조절함
- 이하 식에서 sigma는 시그모이드 함수 의미, tanh는 하이퍼볼릭탄젠트 함수 의미
- W들은 각 게이트에서 사용되는 가중치들 의미
- b들은 각 게이트에서 사용되는 편향 의미
(1) 입력 게이트 : 현재 정보를 기억하기 위한 게이트
- i_t : 현재 시점 t의 x값과 입력 게이트로 이어지는 가중치 W_xi를 곱한 값과 이전 시점 t-1의 은닉 상태가 입력 게이트로 이어지는 가중치 W_hi를 곱한 값을 더해 시그모이드 함수를 지남
- g_t : 현재 시점 t의 x값과 입력 게이트로 이어지는 가중치 W_xi를 곱한 값과 이전 시점 t-1의 은닉 상태가 입력 게이트로 이어지는 가중치 W_hg를 곱한 값을 더해 하이퍼볼릭탄젠트 함수를 지남
시그모이드 함수를 지나 0과 1 사이의 값과 하이퍼볼릭 탄젠트 함수를 지나 -1과 1 사이의 값 두 개가 나옴
(2) 삭제 게이트 : 기억을 삭제하기 위한 게이트
현재 시점 t의 x값과 이전 시점 t-1의 은닉 상태가 시그모이드 함수를 지나고, 0과 1 사이의 값이 나오게 됨
-> 이 값이 곧 삭제 과정을 거친 정보의 양이 됨
- 0에 가까울수록 정보가 많이 삭제된 것이고, 1에 가까울수록 정보를 온전히 기억한 것
- 이를 이용해 셀 상태를 구하게 됨
(3) 셀 상태(장기 상태)
- 셀 상태 C_t를 LSTM에서는 장기 상태라고 부르기도 함
입력 게이트에서 구한 i_t, g_t 두 개의 값에 대해 원소별 곱을 진행함
- 원소별 곱( ∘ ): 같은 크기의 두 행렬이 있을 때 같은 위치의 성분끼리 곱하는 것
-> 입력 게이트에서 선택된 기억을 삭제 게이트의 결과값과 더함(= 시점 t의 셀 상태). 이 값은 다음 t+1 시점의 LSTM 셀로 넘겨짐
- 삭제 게이트의 출력값인 f_t가 0 -> 이전 시점의 셀 상태값인 C_t-1은 현재 시점의 셀 상태값을 결정하기 위한 영향력이 0이 됨 -> 오직 입력 게이트의 결과만이 현재 시점의 셀 상태값 C_t을 결정할 수 있음
- => 삭제 게이트가 완전히 닫히고 입력 게이트를 연 상태 의미
- 입력 게이트의 i_t값이 0 -> 현재 시점의 셀 상태값 C_t는 오직 이전 시점의 셀 상태값 C_t-1의 값에만 의미
- => 입력 게이트를 완전히 닫고 삭제 게이트만을 연 상태 의미
즉, 삭제 게이트는 이전 시점의 입력을 얼마나 반영할지를 의미하고, 입력 게이트는 현재 시점의 입력을 얼마나 반영할지를 결정함
(4) 출력 게이트와 은닉 상태(단기 상태)
출력 게이트는 현재 시점 t의 x값과 이전 시점 t-1의 은닉 상태가 시그모이드 함수를 지난 값임
해당 값은 현재 시점 t의 은닉 상태를 결정하는 일에 쓰임
은닉 상태를 단기 상태라고 하기도 하는데, 은닉 상태는 장기 상태의 값이 하이퍼볼릭탄젠트 함수를 지난 -1과 1 사이의 값을 의미함. 해당 값은 출력 게이트의 값과 연산되면서, 값이 걸러지는 효과가 발생함
파이토치의 nn.LSTM()
LSTM을 파이토치에서 사용하는 방법은 아래와 같음
nn.LSTM(input_dim, hidden_size, batch_fisrt=True)
게이트 순환 유닛 (Gated Recurrent Unit, GRU)
LSTM의 장기 의존성 문제에 대한 해결책을 유지하면서, 은닉 상태를 업데이트하는 계산을 줄인 것
-> GRU는 성능은 LSTM과 유사하면서 복잡했던 LSTM의 구조를 간단화 시킨 모델임
- LSTM에서는 3개의 게이트가 존재했는데, GRU에서는 업데이트 게이트와 리셋 게이트 두 가지 게이트만 존재함
- LSTM보다 학습 속도가 빠르지만 여러 평가에서 GRU는 LSTM과 비슷한 성능을 보인다고 알려져있음
GRU와 LSTM 중 어떤 것이 모델의 성능면에서 더 낫다라고 단정지어 말할 수 없으며, 기존에 LSTM을 사용하면서 최적의 하이퍼파라미터를 찾아낸 상황이라면 굳이 GRU로 바꿔서 사용할 필요는 없음
- 경험적으로 데이터 양이 적을 때는 매개 변수의 양이 적은 GRU가 조금 더 낫고, 데이터 양이 더 많으면 LSTM이 더 낫다고도함
- GRU보다 LSTM에 대한 연구나 사용량이 더 많은데, 이는 LSTM이 더 먼저 나온 구조이기 때문이라고 함
'AI > PyTorch로 시작하는 딥러닝' 카테고리의 다른 글
[PyTorch] Chapter 10 (0) | 2024.07.16 |
---|---|
[PyTorch] Chapter 3 (0) | 2024.07.16 |
[PyTorch] Functional API (0) | 2024.03.21 |
[PyTorch] Sequential API - tokenizer(), Sequential(), Dense() (0) | 2024.03.21 |
[PyTorch] 과적합(Overfitting) 방지 - Dropout (0) | 2024.03.21 |