본문 바로가기
개발 Tools/파이썬_Deep learning & ML

딥러닝 RNN의 모든 것이었으면 좋겠다 ( Bidirectional RNN, Deep RNN, Seq2seq, Attention Mechanism )

by 전컴반 2022. 6. 9.
반응형
RNN ( Recurrent Neural Network )

 

RNN이란 번역하면 순환 신경망이다. 순차적으로 뭔가를 처리하고자 만든 모델이다. 번역기나 음성인식, 주식 시세, 문장, 유전자 배열, 심전도 신호 등, 여러 곳에서 많이 사용된다. 순차적이고 동적이며 가변의 길이를 가지고 상호 의존성을 가진다.

 

동적이며 가변적이기 때문에 기존에 알던 CNN, DNN으로는 한계가 있다. CNN과 DNN은 이미지나 입력이 고정된 크기로 정해지기 때문이다. 그래서 나온 것이 RNN이다. 간단히 말해, 연속적이며 흐름이 있는 뭔가를 분석하기 위해 필요한 모델이다. 진짜 초간단하게 말하면 과거의 입력에 영향을 받는 모델이다.

 


 

기본 꼴은 아래와 같다. 출력과 은닉층에서도 정보를 주고받는다. 즉, 은닉층이 순환 에지를 가진다.

이렇게 돼야 과거의 입력이 현재의 출력에 영향을 주는 구조로 바뀐다. 

 

https://wikidocs.net/22886

 

위 그림을 단순화하면 아래 그림처럼 나타낼 수 있다. 현재의 상태는 과거의 상태와 현재의 입력을 받아서 나타낼 수 있다. 

 

 

그렇다면 Hidden state는 어떤 역학을 할까??

Hidden state는 lossy summary라는 이름으로 불리기도 하는데 요약을 해준다는 의미다. 조금 다르게 말하면 여러 입력을  하나의 고정된 크기로 정리하여 요약해준다는 의미다. 그 요약본에 필요한 정보만 담겠다는 게 hidden state의 역할이다.

예를 들면 언어 모델링과 같은 곳에서 사용할 수 있는데. 빈칸을 맞추기 위해 앞 단어들의 정보를 요약한다는 것이다

 


 

현재의 상태는 아래와 같은 식으로 표현될 수 있는데 이때 함수 f는 입력과 이전의 상태에 어떤 W를 곱해서 현재의 상태를 나타내는 함수다. 보통 tanh를 사용한다. 이유는 sigmoid에 비해 기울기 소실 문제를 예방할 수 있는데 미분 값이 상대적으로 크기 때문이다.

 

 

 

그리고 출력을 나가는 W와 현재의 상태를 활성 함수의 입력으로 집어넣으면 출력이 나온다.

 

 

 

RNN Weight

 

RNN에는 Weight가 3가지가 존재하는데

 

1. 입력에 곱해주는 Whx

2. 이전 상태에서 넘어올 때 곱해주는 Whh

3. 출력으로 나갈 때 곱해주는 Wyh가 있다.

 

세 W는 모든 time에서 동일한 값으로 적용된다. x0, x1, x2에서 곱해주는 Whx가 똑같고, h0, h1, h2에서 곱해주는 Whh가 똑같고 출력에서 나가는 Wyh도 모두 동일한 값으로 적용된다. 이렇게 해서 연산량을 줄일 수 있다.

 

 

 

RNN 종류

 

RNN의 모델 종류에는 여러 가지가 있다.

쉽게 말해 입력과 출력의 조합이 여러 개가 될 수 있다는 말이다. 아래서 빨간색은 입력, 초록색은 은닉층, 파란색은 출력에 해당한다. 

 

 

 

RNN Train

 

처음 시작했을 때, h(0)를 0으로 시작해서 입력을 하나하나 받기 시작한다. 예를 들어 many to many라고 가정했을 때. 그림은 아래와 같이 된다.

 

이때 정답과 예측의 에러를 모두 다 더해서 전체 lossy를 구해서 경사 하강법을 이용하여 업데이트한다. 이렇게 모든 시간에 대해서 에러를 구하고 업데이트해주는 걸 BPTT ( BackProp Through Time )이라 한다. 

 

만약 many to one이라면 하나면 구해주면 된다.

 

 

하지만 BPTT에서 입력이 너무 길어지면 시간도 많이 걸리고 하니까 chunk로 잘라서 업데이트해주는 방법을 Truncated BPTT라고 한다. 다시 말해, 한 번에 다 업데이트하는 것이 아니라, 일정 부분 진행하고 업데이트하고 또 다른 부분 업데이트한다는 의미다. 

 

다만, 시간에 따라서 hidden state의 입력은 계속 forward 해야 한다. 예를 들면, 전체가 하나의 문장인데 조금씩 끊어서 업데이트하면 연결성이 사라지기 때문에 끊어서 업데이트하더라도 이전 state정보는 계속 forward 돼야 한다.

 

문장이 끝나야만 h(0)를 0으로 넣을 수 있다.

 

 


 

하지만 실제로 train을 시키는데 어려움이 있는데 가장 큰 문제는 기울기의 소실이다. 

우리는 이전 상태들에 똑같은 W를 곱해서 현재 상태를 도출하는데 만약 W가 1보다 크다면 점진적으로 커지면서 기울기가  계속 커지는 상황이 생긴다.

반대로 W가 1보다 작으면 계속 곱해져 나갈 때마다 점점 0에 가까운 값을 가져가면서 기울기의 소실이 생긴다. 그러면 경사 하강법을 사용할 수 없어서 업데이트가 안 된다. 

 

왼쪽 : 기본 RNN / 오른쪽 : LSTM

 

예를 들어 아래 글과 같은 것이다 1번에서 빈칸에 들어갈 말을 예측하는 것은 쉬운 일이다. 이유는 문장의 길이가 짧기 때문에 Jane이라는 정보에 영향이 클 것이다.

 

하지만 2번에서의 빈칸을 예측하기엔 문장의 길이가 너무 멀다. 빈칸에는 Jane이 들어갈지 everyone이 들어갈지 모르지만 Jane이 가지고 있는 정보의 연관성이 큼에도 불구하고 많이 사라졌을 것이다.  

 

 

이런 기울기의 소실 문제를 해결하고자 나온 방법이 LSTM과 GRU라는 방법이다. 간단히 말해서 선택적으로 정보의 의미를 전달받겠다는 의미다. 이때 선택을 특정 Gate들로 한다고 하여 Gate RNN이라고도 불린다.

 

LSTM에 대해서는 아래를 참조하면 좋을 것 같다.

 

2021.10.22 - [내가 하는 프로그래밍/파이썬_Deep learning & ML] - 딥러닝 LSTM (Long Short-Term Memory)

 

딥러닝 LSTM (Long Short-Term Memory)

LSTM 의미 있는 데이터와 의미 없는 데이터를 구분하고, 정보가 많아지면 기울기의 소실이 생기는데 이를 막기 위해 나온 개념이다. 기본 RNN에서 Cells이라는 개념이 추가된다. Cells란 정보를 임시

wpaud16.tistory.com

 

 

Bidirectional RNN

 

그 전에는 과거로부터 현재를 추정했다면 Bidrection RNN은 후 상황, 즉 미래를 고려한 모델이다.

"g"라는 state를 만들어서 미래의 입력을 받아서 과거로 영향을 준다. 단, 기존보다 2배의 파라미터를 더 사용한다는 단점이 있다.

 

 

 

Deep RNN

 

층을 쌓으면 실제로 성능이 좋아지기도 하는데 어떻게 해야 층을 쌓을 수 있을까??

3가지 방법이 있다.

 

 

a) 계층적으로 RNN위에 RNN을 쌓는 방법

b) 들어가기 전 중간에 unit을 추가하는 방법

c) 위 2개를 혼용하는 방법

 

사실 a)를 대부분 사용한다 b)와 c)는 성능의 큰 효과가 없다.

 

 

Seq2seq ( sequence to sequence )

 

입력 길이가 다르게 사용될 수 있는 many to many 모델에 대해 알아보자. many to one과 one to many 모델을 섞은 모델이다. 번역기나 음성인식과 같은 부분에서 많이 사용된다. 

 

many to one은 여러 입력을 받아서 하나의 정보로 출력을 내놓는다. ( encoder / reader / input ) 역할을 수행하고,

one to many는 하나의 입력을 여러 출력으로 내보내는 ( decoder / writer / output ) 역할을 한다.

 

 

하지만 요즘은 사용하지 않는다. 이유는 입력 문장이 굉장히 길다면 이 긴 문장을 하나로 요약하기엔 너무 정보가 부족하고 C의 길이가 작다. 그래서 나온 방법이 Attention Mechanism이 나왔다.

 

 

Attention Mechanism

 

C의 크기를 크게 만드는 방법이다. C라 함은 하나의 encoder가 하나의 출력을 내놓는데 그 출력을 말한다. 크기를 출력단의 개수만큼 가지게 된다. C의 집합이 생긴다는 의미다. 

 

예를 들면 아래와 같은 그림으로 볼 수 있다.

원래는 제일 마지막에 있는 h 하나만 decoder로 전달됐지만 이번 모델에서는 모든 단에서 C를 내보내고 decoder의 입력으로 주어진다.

 

 

번역기와 같은 모델에서는 같은 의미를 갖는 짝이 있을 것이다. 예를 들면 "I"와 "나"처럼 의미가 같은 애들은 짝을 지어줘야 된다. 즉, 하나의 단어에게 의미가 비슷한 단어를 집중하라고 ( Attention ) 지정해서 매핑해준다. 

 

알파라는 Attention value를 만드는데 hidden 층의 출력과 decoder에서 그 전 단의 값을 입력으로 받아 추가적인 neural net layer를 통해 생성한다.

 

위 그림을 예를 들면, input에서 "you"의 h(3)과  output에서 "wau"로부터 넘어온 s(3)를 비교한다. 그래서 비슷한 역학을 한다고 하면 Attention을 높게 준다.

그리고 softmax를 통과시켜서 확률의 합이 1이 되게 만든 다음에 다시 hidden 층과 곱하는 동작을 반복하여 모든 값을 더하면 C가 나온다. ( t는 프랑스어, t'은 영어라고 가정할 수 있다 )

 

왼쪽 : C을 구하는 수식 / 중앙 : 알파를 구하는 수식 / 오른쪽 : 새로운 neural net을 추가하여 구하는 수식

 

아래 그림에서 알파 값을 매트릭스로 보면 밝을수록 비슷한 의미를 가진다는 의미다.

 

 

반응형

댓글