본문 바로가기

DeepLearning Specialization(Andrew Ng)/Sequence Models

[코세라] [Week 1] 1. Recurrent Neural Networks

728x90
Recurrent Neural Networks
1. Why sequence models?
2. Notation
3. Recurrent Neural Networks
4. Backpropagation through time
5. Different types of RNNs
6. Language model and sequence generation
7. Sampling novel sequences
8. Vanishing gradients with RNNs
9. Gated Recurrent Unit
10. Long Short Term Memory(LSTM) 
11. Bidirectional RNN
12. Deep RNNs

1. Why sequence models?

'Sequence' 가 있는 data의 예들이다.

이걸 왜 쓰냐? 기존 NN은 입력층과 출력층이 고정되어 있어 시퀀스 데이터를 처리하는데 한계가 있기 때문. 

"Sequence data" 는 그 데이터의 특성 상 이전의 정보가 다음의 정보에 영향을 끼치며 이를 통해 맥락을 파악해야함.

그런데 기존 NN은 그런 '순서'적인 성격이 약하다. 그리고 시퀀스의 길이에 따라 모델의 모양과 파라미터가 계속 달라지게 되므로 일률적으로 적용할 수 있는 모델을 만들기 힘들다.

RNN은 그런 약점들을 보완할 수 있다. 뒤에 설명하지만 Waa, Wax, Wya 는 입력 시퀀스의 길이가 길어져도 공유되는 매개변수들이므로 시퀀스의 길이에 제약이 없다. 그리고 RNN 의 구조적 특성상 이전의 정보가 다음 정보에 영향을 끼치기 때문에 시퀀스 데이터 분석에 적합하다. 순서를 갖는 데이터를 순차적으로 RNN에 input하고 원하는 길이 만큼의 시퀀스를 output할 수 있다. 

  • 정확히 말하면 시퀀스가 뒤죽박죽이어도 만능은 아니다. 프레임워크의 특성상 분석하고자 하는 데이터에 따라 특정 시퀀스 길이를 맞춰주어야 하기 때문. 
  • 예를 들어, 문장을 인풋해서 1~5점의 선호도 평가를 한다고 했을 때 훈련데이터의 문장마다 길이가 다를 것이다. 이럴 경우 max(len(X, key = len))을 이용해서 최대 길이의 문장을 기준으로 인풋데이터를 padding( 공백은 0으로) 하는 과정이 필요하다. 
  • 하지만 뒤에서 language modelling나 기계번역을 하는 경우, <EOS>가 등장하는 시점에 맞게 output이 조절될 것이다.

dreamgonfly.github.io/blog/understanding-rnn/

 

Recurrent Neural Network (RNN) 이해하기 | Dreamgonfly's blog

Recurrent Neural Network (RNN) 이해하기# 음악, 동영상, 에세이, 시, 소스 코드, 주가 차트. 이것들의 공통점은 무엇일까요? 바로 시퀀스라는 점입니다. 음악은 음계들의 시퀀스, 동영상은 이미지의 시퀀

dreamgonfly.github.io


2. Notation

  • Tx와 Ty 는 각각 x와 y의 시퀀스 길이를 의미한다. 두개가 같을 경우도 있지만 다를 때도 있다. 
  • 위으 예는 i번째 training example이며 해당 example의 Tx = Ty = 9이다.
  • y는 input x에서 '이름'을 의미하는 경우 1, 아니면 0을 매핑한 것.

문장이 주어지고 문장 안에서 '이름'을 의미하는 단어의 위치를 알고자 함. 뉴스 등에서 이름 인덱스를 알고자할 때 유용.

  • 자연어처리(NLP)를 한다고 했을 때, 시퀀스의 개별 단어를 어떻게 표현해야 할까? 답은 Vocabulary 를 만드는 것
  • 위의 예에서 1만개의 단어가 들어있는 사전이 있다고 하자. 그렇다면 x는 위와 같이 one-hot encoding으로 표현할 수 있다.
  • 그러고 나서는 x와 y를 묶어 지도학습을 수행

3. Recurrent Neural Networks

우리가 one-hot encoding으로 만들어놓고 x<t> 를 그냥 냅다 NN에 쳐넣으면 문제가 있다.

 

1) 일단 매 문장마다 문장 길이가 다르므로 x<Tx>와 y<Ty>가 달라진다.

2) CNN에서 하던 것처럼 feature sharing을 할 수가 없다. 우리는 모델이 문장의 맥락을 보면서 해당 단어가 이름인지 여부를 알고싶기 때문이다. 

3) 그리고 헷갈릴 수 있지만 x<t> 는 하나하나가 다 1만차원의 벡터이다(tx = 10,000 일 때). 따라서 입력계층이 9x10000 차원으로 늘어나 parameter가 너무 많아진다. 마치 FC와 CNN의 차이점이랄까?

 

  • 그래서 우리는 위와 같은 RNN을 사용한다.
  • 계산 방식은 a<0> 벡터를 input하고
  • RNN의 핵심은 y<3> 을 예측하기 위해 x<1>, x<2>, x<3> 의 정보를 모두 활용한다는 것.
  • 그리고 그 과정에서 Waa, Wax, Wya를 parameter로 설정하여 나중에 update 하겠지.
  • Wax 는 산출값이 a이고 연산에 들어가는 값이 x일 때의 매개변수이다. 나머지도 똑같.
  • 이 모델의 문제점은 구조상 earlier information 밖에 사용하지 못한다는 것이다. 예를 들어 위와 같은 두 문장이 있을 때, y<3>(Teddy가 이름인지 여부) 를 예측하기 위해서 He, said 두 단어를 활용하는데 이 두 단어만으로는 두 문장에서 차이를 발견할 수 없다. 뒤에서 해당 문제를 해결하는 비기를 알려준다고 한다.

  • 보기 좋게 도식화하면 위와 같다. 
  • a<t>와 y<t>는 위와 같은 연산으로 산출되며, Waa와 Wya, Wax는 모든 층에 있어 같은 값으로 공유된다.

  • 같은 식이지만 조금 더 단순한 표기법이다.
  • Waa와 Wax를 가로로 이어붙이고(=Wa), a<t-1>과 x<t>를 세로로 이어붙인 후(=[a<t-1>, x<t>]) 둘을 곱하면 같은 연산결과가 나온다.
  • 차원은 이어붙인만큼 길어지겠지

4. Backpropagation through time

  • Wa, ba, Wy, by 는 위와 같이 다 공유된다. 생각해보면 당연한거다. 결국 x<t> 각각은 input의 한 요소들인데 그 요소들에게 공통적인 weight를 취해줘야겠지. 일반적인 NN과 동일한 것.
  • Loss는 교차 엔트로피로 저렇게 하고 모든 t에 대해서 더해준다. 

5. Different types of RNNs

  • 아까 봤던 것처럼 Tx 가 Ty가 다른 경우가 많다. 

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

  • many to many(tx = ty) : Name entity. 앞서 이름 인식한거.
  • many to many(tx ? ty) : 불어-> 영어 번역. 단어 수가 꼭 같을 수는 없겠지?
  • one to many : 음악만들기. 장르를 선택하거나 아니면 아예 아무것도 입력안했을 때 음악 만드는 RNN.
  • many to one : Movie review text를 보고 이게 긍정적인 리뷰인지 여부를 판단. 혹은 1~5점 중 판단. 

Music generation, translation의 예.

 

  • Summary


6. Language model and sequence generation

Speech Recognition을 한다고 했을 때, y<t> 는 각각 인식한 단어가 된다. 다 모으면 한 문장.

이 때 Speech recognition을 통해 나온 문장이 실제로 일상생활에서 쓰일 확률이 P(sentence)이다.

Language Model 의 목적은 '빈칸 채우기' 라고 생각하면 된다.

RNN을 위해서는 우선 tokenize를 해야한다. 일반적으로 단어단위로 쪼개며 문장 끝에는 <EOS(end of sentence)> 라는 토큰을 추가하여 문장이 끝났음을 알린다.

만약 우리가 준비한 10000개 짜리 Dictionary에 없는 단어가 등장한다면 UNK(unknown)라는 토큰으로 처리한다.

마침표, 물음표 등도 토큰으로 처리할 수 있지만, 안할거면 다 같이 하지 않는다.

  • 이 슬라이드가 핵심이다.

  • RNN으로 여러가지 output을 만들 수 있지만, 저런 식으로 하는게 Language Modelling 인듯.

  • 매커니즘은 다음과 같다.

1. 먼저 a<0>과 x<0>를 영벡터로 초기화한 후, 문장의 첫 단어로 어떤 단어가 올지 확률을 예측하고 이걸 y_hat<1> 이라 한다. 이 단계에서는 어떠한 맥락도 파악할 수 없다. 단지 우리가 갖고 있는 10000개의 단어들이 처음 등장할 확률을 벡터화 한 것이 y_hat<1> 이다.
  cf) y_hat<1> =( p(a), p(aa), ......, p(cats), ..., p(zelu) ) 와 같은 벡터의 형태일 것. 10000 + 2(Unk, Eos) 개의 소프트맥스가 될 것.

2. 그리고 나서 x<2> =y<1> 을 input 한다. 여기서 y<1>은 실제로 문장의 첫번째 단어를 one-hot encoding한 벡터이다. 그리고 y_hat<2> 는 실제 y<1>을 알려주고 그렇다면 두번째 단어는 무엇이 올지에 대한 소프트맥스 산출값이다.
  cf) y_hat<2> = ( p(a|cats), p(aa|'cats'), p(average|'cats'), ... , p(zelu|'cats')

3. 그 이후로 같은 과정 반복하며 마지막은 EOS가 마무리.

 

  • Loss 함수는 교차엔트로피로 정의하며(근본적으로 softmax이기 때문), y_hat<t>과 y<t>는 벡터이므로 모든 차원에 대해서 다 더해준다. 그리고 마지막으로 전체 Loss는 모든 time step의 loss를 더해주는 것으로 정의한다.

  • 결과적으로 우리가 language modelling을 통해 구하려는 P(sentence)는 아래와 같이 구한다.

    • P(sentence) = P(y<1>, y<2>, ... ) = P(y<1>) * P(y<2> | y<1>) * P(y<3> | y<1>, y<2>) * ...

    • 즉, (첫단어로 y<1>이 나올 확률) x (y<1>이 첫단어일 때 다음 단어로 y<2>가 나올 확률) x ...

    • 단순한 확률문제이다.

Q. 이게 어떻게 여러 문장에 적용되는지는 아직 이해가 안된다. 문장1 훈련 후 문장 2, 3 쭉쭉 나아가는 것인지 아님 한꺼번에 하는건지.

 


7. Sampling novel sequences

1) Sampling

  • 그래서 우리가 지금까지 무엇을 했느냐~. 우리는 방금 한 문장을 학습했지만 RNN을 통해 수많은 문장들을 학습시켜 time step에서 어떠한 input word가 있을 때, 그 다음에 올 수 있는 가장 적절한 단어(혹은 문자)를 찾아줄 수 있는 모델을 만들었다. 

  • 이 모델로 소설을 쓰기 위해서는 어떻게 해야할까? parameter를 유지한 채로 y_hat이 다음 time step의 input이 되게하면된다.

  • 이제 우리는 정답데이터가 없으므로 가장 높은 확률을 가진 단어를 one-hot encoding하여 다음 time step에 이것이 정답인 것처럼 알려주는 것이다. 이 과정이 반복되어 하나의 문장이 완성된다.

2) Character-level language model

  • 원래는 Voca에 단어들 쎄리 넣어서 동작시키는 반면에 character-level은 알파벳을 비롯한 기호들 몇개 넣어놓고 동작시킨다. 기본원리는 걍 똑같다. 단지 그 본질적 특성에서 기인하는 장점과 단점이 있다.

  • 장점 : Unk 토큰을 신경쓸 필요가 없다. word-level과는 다르게 어떠한 단어라도 조합할 수 있음. 

  • 단점 : 아무래도 문자 하나하나가 time step이니 sequence의 길이가 엄청 길어진다. 당연하겠지? 문장 하나를 구성하는 수는 단어보다 문자가 월등히 많을테니. 시퀀스가 길어짐에 따라 time step 간의 사이가 멀어지는 경우 종속성이 작아져 말이 안되는 시퀀스가 나올 수 있다. 그리고 당연히 연산도 많아지니 계산효율도 저하됨. 

  •  우리가 뉴스를 기반으로 훈련시켰다면 후에 자동으로 소설을 쓸 경우에도 뉴스처럼 문장이 완성될 것이고 shakespeare의 소설을 train시켰다면 shakespeare의 문체와 비슷한 문장을 완성할 것이다. 


8. Vanishing gradients with RNNs

  • 일반 NN에서 layer가 너무 많아질 때 발생하는 gradient vanishing 문제와 동일하게 RNN에서 time step 이 많아지면 같은 문제가 발생한다.

  • 즉, y_hat<Ty>를 Back P하여 초반 time step에 대한 미분값을 구하려고 해도, 초반 time step의 결과값에대한 영향력이 매우 미미해져서 gradient vanishing 문제가 발생할 수 있다.

  • 그래서 y_hat<t>는 그 근처의 earlier information에만 큰 영향을 받고, 멀어지면 그 종속성이 매우 떨어진다. 물론 Deep NN에서와 마찬가지 이유로 gradient exploding문제도 발생할 수 있다. 

  • exploding문제는 변수들의 값이 폭발적으로 증가하므로 포착하기 쉬우나 vanishing은 그렇지 않고 쉽게 해결할 수 없어 문제가 심각

 cf) 참고로 exploding은 clipping으로 해결하라. 이게 뭔지는 그냥 구글링하자.

 

  • 즉, cat-was, cat-were의 예시를 성공적으로 달성하기 쉽지 않다. 이상적이라면 위의 예시에서 단어끼리 떨어져 있더라도 cat이면 was, cats면 were을 사용해야하는데, 기초적인 RNN은 그런 문제를 잘 해결할 수 없다. 

증말 좋은 블로그다.

aikorea.org/blog/rnn-tutorial-3/

 

RNN Tutorial Part 3 - BPTT와 Vanishing Gradient 문제

WildML의 세 번째 RNN 튜토리얼입니다. RNN 모델을 학습하는데 사용되는 핵심 알고리즘은 Backpropagation Through Time (BPTT)와, 기본 RNN 모델에서 발생하는 vanishing gradient 문제에 대해 조금 더 심도있게 다

aikorea.org


9. Gated Recurrent Unit (GRU)

  • 기존의 RNN 에서 하나의 time step 을 도식화한 것.

1) GRU 원리 

  • GRU를 적용했을 때 RNN unit 의 모습이다.

  • C 는 메모리 셀로서 c<t> = a<t> 이다. GRU에서는 큰 의미가 없으나 뒤에 LSTM과의 일관성을 위해 c를 사용.

  • C_tilde<t> 는 기존 RNN에서 a<t>가 될 값이다. 그러나 GRU에서는 a<t> 후보가 되는 벡터라고 이해하자.

  • 왜 c_tilde <t>가 후보냐면, 감마u 와의 곱을 통해 c_tilde<t>를 구성하는 일부 원소들만 c<t>로 넘어갈 것이기 때문이다. 

  • 그럼 감마u는 무엇이냐? 감마u는 Wu, bu라는 새로운 parameter matrix와의 연산 결과에 sigmoid를 적용한 값으로서 sigmoid의 특성상 거의 0 혹은 1에 가까운 원소로 이루어진 벡터이다. 

  • 따라서 C<t> 는 감마u와 c_tilde<t>와의 element-wise 결과로서 감마u의 원소가 0이면 x<t>가 반영되지 않은 c<t-1> 의 원소가 넘어가고, 반대로 감마 u의 원소가 1이면 x<t>가 반영된 c_tilde<t>의 원소가 넘어갈 것이다.

  • 예시 문장에서 모델은 was/were 위치에서 cat 다음에 올 단어에 대한 확률을 y_hat 으로 산출할 수 있다.

2) 효과 

  • 마치 ResNet 처럼 Gradient Vanishing&Exploding 문제를 해결할 수 있다.

  • 즉, 긴 종속성을 유지시킬 수 있음.

  • "Therefore allow NN to learn even very long range of dependency, even if 'cat' and 'was' are seperated by a lot of words in middle"

Q. 벡터의 일부원소만 유지시킨다고 해서 종속성을 유지시킬 수 있는가?

뇌피셜) 설명을 들으면 그럴듯하지만 사실 GRU의 개념이 머릿속에 완전히 잡히지는 않은 것 같다. 내가 이해한 바로는 GRU를 사용하면 일부원소에만 해당 timestep에서의 x input이 반영된다. 그리고 GRU 구조도 결국 Learning Algorithm 이므로 y_hat<t> 의 예측과 관련된 원소를 보존할지 바꿀지 결정하는 감마u라는 parameter를 추가하고 지속적으로 update함으로써 종국에는 긴 의존성을 갖는 원소들은 보존되고 중간의 word 에 대한 y_hat 값을 y값과 비슷하게 update 하기 위한 원소들은 값이 바뀔 것이다. 
 즉, C 값을 유지할 수 있는 루트를 열어둔 것. 

 

3) Full GRU

  • 정리하자면 위와 같이 된다.

  • 감마 r은 relevance와 관련된 행렬인데, 그냥 여러 연구자들이 해보니 저걸 추가하는게 낫단다. 그냥 그러려니 하자.


10. Long Short Term Memory (LSTM)

  • LSTM 도 원리는 GRU와 같다. 참고로 LSTM이 먼저 개발되고 GRU가 후에 발표되었다. GRU는 gate가 2개이므로 좀 더 간소화된 버전이라고 이해하면 될 듯.

  • GRU에서는 1-감마u 로 update gate와 forget gate를 표현했으나 LSTM은 아예 다른 gate로 정의한다. 거기다가 output gate를 만들어서 최종적으로 a<t>를 산출할 때, 감마o를 사용한다. 

  • 참고로 

The last line should be:

 

  • 도식화하면 위와 같다. 

  • GRU와는 다르게 c<t>와 a<t>가 다르며 c<t>가 지나가는 빨간 라인을 통해 c<t>값이 보존된다.

cf) peephole connections

 모든 gate의 연산에 c<t-1> 을 참여시키는 방법이다. 이를 통해 좀 더 맥락을 고려하게 된다고 한다. 이 때 c<t-1> 은 당연히 n차원의 벡터인데, 교수님이 c<t-1>의 i번째 원소의 변화는 gate의 i번째 원소에만 영향을 끼친다고 한다. 근데 이건 진짜 이해가 안된다. 


11.Bidirectional RNN

  • 기존 RNN의 경우 이전 정보만을 통해 다음 정보를 예측하는데, 다음 정보를 모르는 상황에서 한계가 있을 수 밖에 없다. 그래서 Bidirectional RNN 이라는 기법을 사용한다.

  • 대충 예상했듯이 RNN의 같은 과정을 거꾸로 수행하면 된다. 순방향과 역방향에서 산출된 a 값을 모두 엮어서 기존 y_hat 을 계산하는 수식에 쳐넣으면 된다. 

  • Bidirectional RNN은  BRNN은 양방향의 맥락을 고려하여 뚫려있는 빈칸을 채우는 알고리즘이라고 이해하면 된다. 따라서 소설쓰기, 음성인식과 같은 모델을 만드려면 좀 더 복잡한 구조가 필요하다. 원래 기존 Language Model RNN으로 earlier info로는 다음 빈칸을 채우기만 하면 되지만, BRNN은 양쪽 정보가 모두 필요하기에 전체 시퀀스를 우선적으로 파악해야한다. 자세한 알고리즘은 안알려주네.


12. Deep RNNs

  • 지금까지는 layer = 1 짜리만 본 것이고 위의 도식은 layer = 3 짜리이다. 

  • 화살표로 연결된 방향으로 선형연산이 이루어지고 있으며, parameter는 저기 작게 써놓은 것이다.

  • RNN 구조는 계산비용이 엄청나기 때문에 아무리 깊어도 100 층을 안넘어간다고 한다.

  • 그리고 저기 위에 중간에 수평적으로 연결안된건 그냥 Deep RNN의 한 종류이다. 

비판과 비난은 언제나 환영입니다. 많이 꾸짖어주세요.

 

 

728x90