일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- iTerm2
- python
- Residual Connection
- Inception V1
- sigmoid
- Vanilla RNN
- GCN
- DL
- RNN
- ResNet
- version
- Generative
- virtualenv
- Skip Connection
- Linear
- GoogLeNet
- AI
- Bottleneck Layer
- Optimizer
- jupyter
- Manager
- DCGAN
- cnn
- classification
- Regression
- Inception Module
- Skip Connectioin
- Peephole Connection
- vim-plug
- Gated Skip Connection
- Today
- Total
IT Repository
(2) Basic of RNN - Vanilla RNN 본문
RNN (Recurrent Neaural Network)¶
RNN은 시퀀스 데이터를 다루기 위해 고안된 구조입니다.
따라서, 데이터의 순서를 고려할 수 있도록 디자인되었습니다.
제가 예전에 했었던 프로젝트를 예시로 들면서 이를 설명하겠습니다.
프로젝트의 목표는 카카오톡 메시지를 통해 사람의 호감도 추이를 파악해서 현재의 감정 정도를 Regression하는 것이었습니다.
우리가 어떤 사람과 주고 받은 메시지는 매일매일 혹은 매 시간마다의 타임 스텝을 갖고 있는 시퀀스 데이터입니다.
따라서 메시지로 파악하는 호감도 역시 제로 베이스가 아니라, 이전 스텝의 호감도 정보가 반영된다고 생각했습니다.
RNN은 시퀀스의 특징을 고려할 수 있는 네트워크 구조를 갖기 위해서
현재 타임스텝의 인풋을 처리할 때에 이전 타임스텝의 아웃풋을 함께 처리합니다.
자, 이제부터 RNN을 이해해봅시다!
Understanding of RNN Structure¶
RNN을 한번이라도 들어보신 분들은 아래와 같은 그림을 많이 보셨을 것입니다.
대부분의 RNN에 대한 설명을 위 그림 하나로 끝내는데에 비해 저는 이해가 정말 안되었습니다.
저와 같이 "그래서 RNN이 정확하게 어떻게 돌아간다는거야?" 라고 느끼셨을 분들을 위해서
실제로 RNN이 작동하는 방법에 대해서 하나씩 설명 하겠습니다.
How to Merge New Input and Previous Output¶
아래는 이전 타임스텝의 아웃풋과 지금 타임스텝의 인풋을 어떻게 반영하는지에 대해서
그림과 함꼐 Work Flow를 설명하였습니다.
(죄송합니다. 이미지를 더 보기좋게 편집하려 했으나, 이미지 편집툴이 계속 다운되는 바람에 최대한 빠르게 다시 수정하겠습니다.)
현재 타임스텝이 t 지점이라고 할 떄
- $X_t$ : 현재 타임스텝에서의 인풋 데이터
- $h_{t-1}$ : 이전 타임스텝의 히든 스테이트
- $u_{t}$ : $X_t$에 대한 모델 U(초록색 사다리꼴)의 아웃풋
- $h'_{t-1}$ : $h_{t-1}$를 현재 스텝에 알맞게 사용하기 위해 가공한 상태 ($W$와의 dot product)
- $W$: 이전 타임스텝의 히든 스테이트를 Linear transformation하기 위한 가중치 행렬(파란색 마름모)
Work Flow to Merge Input & Output
(1)
모델 U의 아웃풋 $u_t$를 만듭니다.
현재 타임스텝의 인풋 $X_t$를 모델 U에 넣어 아웃풋 $u_t$를 만듭니다.
모델 U는 MLP와 같은 구조를 통해 Feature를 추출합니다.
(2)
히든 스테이트를 가공한 $h'_{t-1}$을 만듭니다.
이전까지의 결과들을 현재 스텝에 맞도록 가공하기 위해 히든 스테이트 $h_{t-1}$과 $W$를 행렬곱해서 $h'_{t-1}$을 만듭니다.
이 $h'_{t-1}$은 기존의 $h_{t-1}$과 같은 shape을 가져야 합니다.
예를 들어, $h_{t-1}$이 1x100의 벡터일떄 $W$가 100x100 행렬이면 결과는 $h_{t-1}$과 동일한 1x100이 됩니다.
(3)
$u_t$와 $h'_{t-1}$을 element-wise하게 합연산하고 Non-linear Activation 합니다.
RNN에서 Non-linear function은 주로 sigmoid, tanh 를 사용합니다.
(이 이유로 인해 Gradient Vanishing 문제가 발생하고, Cell state를 통해 이 문제를 다시 해결합니다.)
(4)
다음 스텝에 $h_t$를 넘겨주고 (1) ~ (3)을 반복합니다.
Applications to the Types of RNN Task¶
RNN은 위와 같은 프로시져를 통해서 Recurrent하게 현재 스텝 t까지 인풋과 히든 스테이트를 반영하여 작동하게 됩니다.
이제부터는 이전에 소개했던 RNN Task를 어떠한 방법으로 최종 아웃풋까지 도달하는지 확인하겠습니다.
(이전에 소개했던 순서와 관계없이 더 설명하기 쉬운 순서대로 진행합니다.)
Many to One¶
그냥 마지막 h에 원하는 모델을 Attach 합니다.
예를 들어 Classifier나 Regressor 등을 Attach하면 되겠죠.
Many to Many (Type B)¶
각 타임스텝 마다의 h에 원하는 모델을 Attach 합니다.
중요한 것은 Attach하는 모델의 파라미터가 공유된다는 점입니다.
Many to Many (Type A)¶
Translation과 같은 문제는 위의 두 가지와는 경우가 조금 다릅니다.
Encoder 파트와 Decoder 파트를 각각 만들어서 하나의 모델로 활용하기 때문입니다.
우선 방법에 대해 간략하게 설명하자면 마지막 h에 Attach한 모델의 아웃풋을 y라고 할 때, 다음 스텝의 x를 y로 간주하고 진행하는 것입니다.
아래 사진을 보겠습니다.
아래의 초록색 부분이 Encoder이고, 노란색 부분이 Decoder입니다.
Encoder는 시퀀스를 Feature vector로 Compress하는 역할을 합니다.
Decoder는 Feature vector를 y로 Decompress하는 역할을 합니다.
영한 번역 문제를 생각했을 때에
영단어가 Feature vector로 향하는 매핑을 배우는 게 인코더이고
Feature vector가 한글로 향하는 매핑을 배우는 게 디코더입니다.
따라서, 일반적으로 인코더와 디코더는 파라미터를 공유하지 않는 서로 다른 모델입니다.
예) Translation
Input: I have apple (word level)
Time step | t | t+1 | t+2 | t+3 | t+4 |
---|---|---|---|---|---|
x | I | have | apple | 나는 | 갖는다 |
h | O | O | O | O | O |
y | 나는 | 갖는다 | 사과 |
One to Many¶
CNN을 통과한 이미지 벡터를 인풋으로 하고, 다음 스텝의 인풋은 Attach한 모델의 아웃풋 y로 합니다.
이전의 Translation 문제에서 인코더가 RNN이었다면,
이 경우에는 CNN이 인코더를 담당하고 디코더는 RNN + Attached model 이 담당합니다.
Formularization of RNN¶
위에서 길게 설명한 RNN의 작동방법은 결국 아래의 2개의 식으로 요약할 수 있습니다.
위 설명을 이해하셨다면 아래의 수식도 큰 어려움없이 이해하실 수 있을 것입니다.
Calculate Loss & Update Parameters¶
하나의 시퀀스를 끝까지 진행(Forward)하고 난 후에는 파라미터를 업데이트하기 위해 Loss를 계산하게 됩니다.
한 개의 시퀀스의 Loss는 아래와 같이 계산될 것입니다.
$\array{ Loss(\theta) = & \dfrac{\sum_t loss(y\_true, y\_pred)}{t} \\ & (t\text{ : the number of time steps}) }$
물론 $loss(y\_true, y\_pred)$는 Classification이라면 CrossEntropy를 Regression이라면 MSE 혹은 MAE 등을 사용할 수 있겠네요.
이와 같이 하나의 시퀀스의 Loss를 구할 수 있다면 각 시퀀스마다의 Loss를 구할 수 있습니다.
각 시퀀스의 Loss를 모두 더한 후에 시퀀스의 개수만큼 나눠주면 모델의 평균 손실값이 계산될 것입니다.
이제 이를 통해 Gradient를 계산하고 Optimizer가 파라미터를 업데이트하면 되겠네요.
Questions to Understand RNN Structure¶
Q. Sequence 길이가 다르면 어떻게 처리하는지 (arbitrary input)
1. Max Sequence Length를 정하고, 그에 맞추어 Pre-process (이 과정에서 Interpolation을 사용할 수도 있음)
2. 서로 다른 길이의 각 Sequence가 처리가 끝날 때마다 결과 집합에 추가
Q. 출력값의 길이가 다른 경우는 어떻게 처리하는지 (arbitrary output)
1. max sequence length를 정하고, 그에 맞추어 post-process
2. 2개의 토큰(begin of sentence, end of sentence)을 데이터셋에 모두 추가해서 학습하면, 디코딩 중에 문장이 종결된다고 판단했을 때에 eos 토큰을 반환하게 됨
Q. 가중치 행렬 $W$는 매 타임스텝마다 각각 존재하는지
노. 매 타임스텝마다 같은 $W$가 파라미터 쉐어링을 하고 있음
To Solve Gradient Vanishing Problem¶
지금까지 기본형 RNN, 즉 Vanilla RNN에 대해서 학습했습니다.
Vanilla RNN은 기존 MLP 방식보다 시퀀스를 처리하는 데에 유리하도록 설계되었습니다.
그러나 이번에도 역시 문제점이 발생했습니다.
시퀀스가 길어질 수록 Gradient가 소실되어 타임스텝의 간격이 서로 먼 곳으로 반영이 되지 않는 것입니다.
영문장이 있다고 생각해봅시다.
"Adam Smith did (중략). His idea was absolutely incredable at that time."
중략된 공간에 단어의 길이가 길면 길수록 타임스텝이 멀리 떨어져 있다는 것이고,
결국 길어질 수록 His가 Adam Smith임을 거의 학습하지 못하게 된다는 것입니다.
이를 해결하기 위해서 사람들은 아래의 두 가지 방법을 사용했습니다.
우리는 이 중에서 우선 LSTM과 GRU에 대해 알아보겠습니다.
- LSTM, GRU
- Attension
'RNN > Study' 카테고리의 다른 글
(4) GRU (0) | 2020.01.17 |
---|---|
(3) LSTM (0) | 2020.01.17 |
(1) Basic of RNN - Sequence Data (0) | 2020.01.16 |
(0) Overview of RNN (0) | 2020.01.14 |