-
Chapter 16 Natural Language Processing with RNNs and AttentionML/딥러닝 2020. 6. 18. 19:43반응형
- 자연어 처리 태스크의 가장 흔한 접근방법은 RNN을 사용하는 것
- 문장에서 다음 문자를 예측하는 character RNN
- 텍스트의 나머지 정보 없이, 매 iteration마다 텍스트의 랜덤한 비율만 학습하는 stateless RNN
- 그다음은 stateful RNN, 학습하는 iteration들 사이에 hidden state를 보존하고 오른쪽으로 차례로 읽는
- Sentiment analysis를 생성하는 RNN (영화 리뷰를 읽고 평가자의 감정을 추출하는)
- Encoder-Decoder 구조를 사용해 NMT
- 두번째 파트로 attention mechanisms
- Attention을 사용하는 RNN-based Encoder-Decoder 구조
- Transformer
- GPT-2 and BERT
Generating Shakespearean Text Using a Character RNN
- 셰익스피어의 작품을 학습한 Char-RNN으로 만들어진 샘플들
- 단어, 문법, 정확한 발음 등을 학습해 단순히 다음 문자를 예측하는 모델
Creating the Training Dataset
- 데이터를 다운 받고
- 토크나이저를 만든다.
- character -> integer
- 1부터 출발하는 정수
- 토크나이저는 디폴트로 소문자로 바꾼다.
How to Split a Sequential Dataset
- 당연히 training set, validation set, test set이 겹치면 안된다.
- 간단하게는 training set 90% validation set 그다음 5%, test set은 나머지 5%로 하면 안겹친다.
- time series 데이터를 다룰때 2000-2012는 training set, 2013-2015는 validation set, 2016-2018은 test set으로 나눌 수 있지만 다른 dimension을 사용할 수도 있다.
- 만약 10000개의 회사의 2000-2018 데이터를 회사별로 나눈다면, training set과 test set의 correlation이 높아져서 test set이 쓸모 없어 질 수도 있다. 경제상황으로 보면 회사들 데이터가 시간에 따라 비슷할 수 있다.
- 그래서 안전하게는 시간으로 나누는 것이 좋다. 그러나 이는 가정한다. 과거에서 RNN이 학습한 패턴들이 현재에도 존재한다고.
- 다른말로는 time series가 stationary하다.
- 화학 반응은 가정에 합당한데, 주식시장은 아니다..
- time series가 stationary한지 확인하기 위해 validation set의 모델 에러를 시간에 따라 plot해보면 된다.
- 만약 모델이 validation set의 첫번째 파트가 과거 파트보다 성능이 좋다면 이 데이터는 stationary하지 않다.
- 결론적으로는 셰익스피어 데이터셋은 그냥 앞 90%를 training set으로 쓴다.
Chopping the Sequential Dataset into Multiple Windows
- 현재 training set이 수백 문자로 이루어진 하나의 시퀀스라 바로 학습시킬 수 없고 잘라야 한다.
- window()라는 메서드를 쓰는데 이는 문자들의 긴 시퀀스를 작고 많은 window들로 나눈다.
- dataset의 모든 인스턴스들은 전체 텍스트의 substring이고 RNN은 이 substring의 길이만큼 unroll될 것이다.
- 이것은 truncated backpropagation through time이라고 한다.
- 디폴트로는 overlap이 없지만 shift=1로 설정하여 더욱 많은 training set을 만들 수 있다.
- 길이도 전부 101이라 따로 패딩할 필요도 없다.
- drop_remainder=True로 마지막에 101이 안되는 문자들은 버린다.
- window() 메서드로 list의 list인 nested dataset으로 만든다.
- 모델의 인풋은 tensor여야하므로 바로 사용할 수 없다. 그래서 flat_map() 메서드를 사용해야 한다.
- 인풋은 0-100, 타겟은 1-101
- 데이터는 전부 one-hot이다.
Building and Training the Char-RNN Model
- 이전 100 문자들로부터 다음 문자를 예측하기 위해
- 128 units인 2 GRU layer
- input과 hidden states에 20% dropout
- timedistributed
- 39개의 출력이고 원하면 probability로 변환 가능. softmax
Using the Char-RNN Model
- how are yo 다음에 u를 예측했다.
Generating Fake Shakespearean Text
- Char-RNN model을 사용해 새로운 텍스트를 만들기 위해서는 약간의 텍스트를 입력해야한다.
- 이렇게 새로운 문장을 계속 만들다보면 실제로는 계속 같은 단어가 반복된다.
- 그래서 tf.random.categorical을 사용해서 주어진 logits을 기반으로 class indice를 생성한다.
- 그냥 확률이 max인 라벨을 클래스로 사용하는 것이 아니라 다시 생성
- 더 다양한 문장을 만들 수 있다.
Stateful RNN
- 지금까지 써온 RNN은 stateless다. 매 iteration마다 hidden state가 0으로 시작하는
- 만약 batch training 한 후 final state를 다음 batch에서 초기값으로 쓸 수 있다면?
- 이러한 방법은 모델이 짧은 시퀀스에 대해 backpropa함에도 불구하고 long-term 패턴을 학습할 수 있다.
- 이게 바로 stateful RNN
- 첫번째로 기억해야하는 것은 데이터가 시퀀설하게 들어가야하고 overlap이 없어야 한다.
- 데이터셋을 만들 때 shift를 window_length만큼 해야한다. 셔플도 하면 안된다.
- batch 단위로 학습 시킬 때 이제 문제가 되는데 그냥 batch를 1쓰면 된다.
- 매 에포크마다 state를 reset 해줘야 한다.
Sentiment Analysis
- 컴퓨터 비전에 MNIST가 있다면, 자연어 처리에는 IMDb가 있다.
- 25000 training set, 25000 test set으로 총 50000개의 영화 리뷰가 있다. 라벨로는 negative 0, positive 1이다.
- 케라스에 이미 numpy의 integer ndarray로 전처리 되어있다.
- index는 frequency 기준으로 나열되어 있음.
- 0은 padding token, 1은 start-of-sequence token, 2는 unknown token
- 리뷰중에 앞에 300글자만 남겨둔다. 속도도 빨라지고 성능에도 큰 영향 없다.
- 불필요한 문자들도 없앤다.
- 스페이스 기준으로 나눈다.
- <pad> token으로 패딩하여 길이를 모두 맞춘다.
- vocabulary를 만들어야한다. 모든 데이터를 전체 검사하며 단어가 몇번 나왔는지 체크한다.
- 모든 단어를 사용할 필요는 없다. 자주 나온 10000만 사용하자.
- 룩업 테이블 만들고
- preprocessing하며 데이터셋을 만든다.
- 임베딩하고 GRU 2개 지나고 dense layer 지나면 끝
- 임베딩 레이어의 입력은 [batch size, time steps], 출력은 [batch size, time steps, embedding size]
- 첫번째 GRU layer는 출력 시퀀스를 리턴하고, 두번째 GRU layer는 마지막 time step의 출력만 리턴한다.
- 마지막은 하나의 sigmoid로 결정된다. 0-1로 왜냐면 라벨이 0이 negative, 1이 positive
Masking
- 모델은 padding token들을 무시하고 학습해야한다.
- Embedding layer를 만들 때 mask_zero=True로 하면 무시된다.
- 들어온 입력이 0이냐 아니냐 boolean tensor를 만들어서 간단하게 마스킹한다.
Reusing Pretrained Embeddings
- TenforFlow Hub에 들어가면 미리 학습되어 있는 embedding layer가 많다.
- 쉽게 다운로드해서 쓸 수 있다.
- 디폴트로는 학습이 안되는데 trainable=True로 바꿔서 학습시킬 수도 있다.
An Encoder-Decoder Network for Neural Machine Translation
- 영어를 프랑스어로 번역하는 모델
- 인코더의 입력으로 영어가 들어가고 디코더의 출력으로 프랑스어가 나온다.
- 디코더의 입력으로 한칸씩 쉬프트된 프랑스어 번역이 사용된다. 이전 스텝의 출력이 현재 스텝의 입력으로 (실제 출력이 아닐지라도)
- 첫번째는 start-of-sentence token, 마지막에는 end-of-sentence token
- 영어가 입력으로 들어갈 때 문장의 순서와 반대로 들어간다. 번역에 필요한 디코더의 첫번째 요소가 영어에서는 가장 첫 단어일테니
- 단어별로 ID를 가지며 임베딩 레이어를 통과해 얻은 값들이 인코더 디코더의 입력으로 들어간다.
- 디코더의 출력은 각 단어의 점수를 출력하고 소프트맥스를 거쳐 확률로 바뀐다. 가장 큰 확률인 단어를 고르면 된다. 일반적인 classification task처럼
- crossentropy loss를 사용할 수 있다.
- 이와 같이 이전 스텝의 출력을 현재 스텝의 입력으로 사용한다.
- 인풋 시퀀스의 길이가 같다고 가정을 했다.
- 하지만 문장의 길이는 모두 다르다.
- 텐서는 고정된 shape을 사용해야해서 마스킹을 통해 문장의 길이가 다른 문제를 해결했다.
- 하지만 길이가 너무 다르다면, 감정 분석때 하던 것처럼 간단히 자를수도 없다. (번역문제이기 때문)
- 대신에 비슷한 길이들을 하나의 bucket에 담을 수 있다.
- 예를 들어 1-6 단어 문장 버킷, 7-12 단어 문장 버킷
- 버킷을 사용하는 이유는 학습속도 증가
- EOS token 다음의 출력은 무시되어야 한다. loss에 더해지면 안된다. 마스킹 되어야 한다.
- 예를 들어 "Je bois du lait <eos> oui."에서 oui는 무시
- 만약 출력 단어의 수가 매우 많다면, 각각 모든 가능한 단어의 확률을 구하는 것은 매우 느리다.
- 만약 50000 프랑스어 단어가 존재한다면, 디코더의 출력은 50000-dimension의 벡터가 되어야 한다.
- 이를 피하기 위한 하나의 솔루션은 옳은 단어와 옳지 않은 단어중 랜덤으로 샘플링된 logits 출력만을 보는 것
- 이 서브셋의 logits로부터 loss의 추정값을 계산한다. sampled softmax
- 학습할 때만 사용하고 테스트할 때는 원래 softmax 사용
- 중간에 TrainingSampler()라고 있는데 Scheduled sampling의 기능을 함. 벤지오 논문
- 다른 말로는 teacher forcing
- 디코더에서 이전 스텝의 출력을 현재 스텝의 입력으로 사용하는데 학습 초기에는 이전 스텝의 출력이 엉망임.
- 그래서 선생님이 가르쳐준다는 의미로, 일정 확률로 이전 스텝의 출력이 아닌 이전 스텝의 정답을 현재 스텝의 입력으로 넣음.
- 학습이 진행될수록 러닝 레이트를 decay하며 적용하듯이 선생님이 가르쳐줄 확률을 낮춰감.
Bidirectional RNNs
- 기존 RNN은 과거에서 현재 순으로 입력이 들어간다. 한마디로 causal하다. 미래를 보지 않는다.
- time series를 예측할 때는 기존 RNN의 방식이 맞아보이지만, 기계번역같은 NLP task에서는 주어진 단어가 인코딩 되기 전에 다음 단어를 보는 것이 선호된다.
- 예를 들어 the queen of hearts와 같은 단어구를 번역하려면 뒤에 단어를 봐야한다.
- 이를 구현하기 위해서는 그냥 간단하게 같은 입력을 왼쪽에서 오른쪽으로 통과시키는 layer, 오른쪽에서 왼쪽으로 통과시키는 layer를 만들면 된다.
- 그다음 출력을 같은 시간에 맞게 연결하기만 하면된다. 입력이 10이면 출력이 20이 된다.
Beam Search
- Comment vas-tu라는 문장을 번역하면 how are you로 번역하길 원하지만 how will you로 번역된다.
- 이는 train set에 commnet vas의 정답으로 how will이 많기 때문이다.
- 이러한 문제를 막기 위해서 모델은 뒤로 다시 돌아가서 고칠 수 없다.
- 그러므로 최대한 문장을 잘 만들 노력을 해야한다.
- 매 스탭마다 제일 확률 높은 단어를 출력하는 것은 suboptimal한 번역을 한다.
- 어떻게 모델이 뒤로 가서 다시 고칠 수 있는 기회를 줄 수 있을까? beam search
- 매 스텝마다 가장 좋은 문장을 약속하는 top k 개의 list를 계속 가져간다.
- k는 beam width
- 예시 문장 Comment vas-tu, k는 3
- 첫 스텝 how 75%, what 3%, you 1%
- 모델 3개를 복사한다.
- 처음 모델은 how 다음에 will 36%, are 32%, do 16%의 확률을 출력한다.
- 두번째 모델은 what 다음에 are 50%
- 두 스텝에 대해 경우에 따라 확률이 구해졌으면 확률들을 곱해 조건부 확률을 만든다.
- how will 75% * 36% = 27%
- how are 24%
- how do 12%
- 확률은 how will이 제일 높지만 how are은 제거되지 않는다.
- 이 과정을 반복하면
- how are you 10%
- how do you 8%
- how will you 2%
- 다음 스텝까지 하면
- how do you do 7%
- how are you <eos> 6%
- how are you doing 3%
- 합리적인 번역을 위해 3개만 가지고 있기 때문에 how will은 제거된다.
Attention Mechanisms
- milk가 lait으로 번역되는 과정이 너무 길다!
- 제일 먼저 인코딩되었던 단어가 디코딩되어 번역되기 전까지 매우 많은 스텝을 거쳐야 한다.
- 디코더가 매 스텝마다 인코더의 정확한 단어에 집중할 수 있는 방법이 제안되었다.
- 왼쪽에 인코더 디코더가 있는데 바뀐 점은 인코더의 마지막 state를 디코더로 넘기는 것 대신에 인코더들의 출력을 디코더로 보낸다.
- 매 스텝마다 디코더는 모든 인코더의 출력의 weighted sum을 계산한다. 어떠한 단어에 집중할지를 결정하는
- weight a(t, i)는 t 디코더 스텝의 i 인코더 출력
- 만약 weight a(3, 2)가 weight a(3, 0)와 weight a(3, 1)보다 크다면, 디코더는 "milk"에 더 집중할 것이다.
- weight a는 alignment model(attention layer)라는 작은 모델에서 생성된다.
- single neuron의 TimeDistributed dense layer에서 인코더의 모든 아웃풋과 디코더의 이전 스테이트를 concatenate해서 dense layer를 통과한다. attention score
- 이 score는 얼마나 잘 각 출력이 디코더의 이전 히든 스테이트와 함께 정렬되었는지를 말한다.
- 마지막으로 소프트맥스를 통과하여 인코더의 출력과 weighted sum해서 입력으로 들어간다.
- Bahdanau attention 또는 concatenative attention이라고 불린다.
- 그 다음 제안된 것은 인코더의 출력과 디코더의 이전 히든 스테이트간에 similarity를 측정하는 것을 목표하였다.
- concatenate 대신 dot product를 해서 score를 구함.
- Luong attention 또는 multiplicative attention
Visual Attention
- 어텐션 메커니즘이 NMT 말고 이미지 캡션을 만들 때도 사용될 수 있다.
- 이미지를 CNN으로 통과시키고 어텐션 기반의 decoder RNN으로 캡션을 만들 수 있다.
- A woman is throwing a frisbee in a park.
Attention Is All You Need: The Transformer Architecture
- Transformer
- RNN과 CNN을 사용하지 않고 어텐션만 이용해서 성능을 높임.
- 학습도 빠르고 병렬화 하기도 쉽다
- 왼쪽에는 인코더부분
- 인코더 input으로 [batch size, max input sentence length]
- 인코더 output으로 [batch size, max input sentence length, 512]
- N개만큼 인코더가 쌓이고, N은 논문에서 6 사용
- 오른쪽에는 디코더부분
- 학습하는 동안 디코더 input으로 1 time step 쉬프트된 타겟 문장
- 인코더의 output도 입력으로 받음
- 디코더도 N개만큼 쌓임
- N개의 인코더 출력이 각각 N개의 디코더 입력으로 들어감
- 출력은 다음 단어에 대한 확률 [batch size, max output sentence length, vocabulary length]
- inference 동안 디코터는 타겟들을 입력으로 넣어줄 수 없다. 그래서 이전 출력 단어를 입력으로 사용한다.
- 2 embedding layers
- 5 * N skip connections (+ layer normalization layer)
- 2 * N feed forward (2 dense layer, first ReLU, second none)
- 1 dense layer, 1 softmax function
- all layers time distributed
- 새로운 요소1
- 인코더의 Multi-Head Attention layer는 같은 문장 안에 모든 다른 단어에 대해 각 단어의 관계를 인코딩한다.
- 예를 들어 "They welcomed the Queen of the United Kingdom"라는 문장 안에 "Queen"에 대한 이 layer의 출력은 문장 안에 모든 단어에 의존한다
- 하지만 그것은 "They" 또는 "welcomed"보다는 "United"와 "Kingdom"에 어텐션을 더 줄 것이다.
- 이 어텐션 메카니즘은 "self-attention"이라고 불린다.
- 디코더의 Masked Multi-Head Attention layer도 같은 동작을 한다. 그러나 각 단어는 오직 그 단어 이전에 위치한 단어에만 참석하는 것을 허락한다.
- 두번째 Multi-Head Attention layer에서 드디어 input sequence에 어텐션을 준다.
- 새로운 요소2
- Positional embeddings는 간단하게는 문장에서 단어의 위치를 나타내는 dense vector들이다. (word embeddings 같은)
- nth positional embedding은 각 문장에 nth word의 word embedding이 더해진다.
- 이것은 모델이 각 단어의 위치에 접근하게 한다. 왜냐하면 Multi-Head Attention layer들은 단어들의 순서나 위치를 고려하지 않기 때문에. 오직 관계만 쳐다본다.
- RNN은 시간적 연속성을 보장해줬다.
Positional embeddings
- 만약 위치의 정보를 단순하게 1, 2, 3, 4 이런식으로 부여하면 큰 숫자가 모델의 입력으로 사용되고 이것은 좋지 않은 영향을 끼친다.
- 그래서 모델 학습에 방해가 되지 않으면서 위치 정보를 부여할 수 있는 방법을 생각.
- ith positional embedding은 간단하게 ith word embedding에 더해진다.
- 그림 16-9를 보면 word position p에 따라 단어의 위치에 따라 PE (positional embedding)의 값이 바뀌고 이는 위치에 따라 유니크하다.
- 또한 값이 -1 ~ 1로 존재해 모델 학습에 안 좋은 영향을 끼치지 않는다. sine, cosine과 같은 oscillating functions은 모델이 상대적인 위치를 학습하는 것을 가능하게 해준다.
- 또한 문장의 길이가 길어져도 확장이 가능하다.
- 그림 16-9에서 22번과 60번 위치를 보자. i가 100, 101일 때 PE 값이 같지만 전체의 PE를 보면 유니크하다.
Multi-Head Attention
- 먼저 Scaled Dot-Product Attention layer를 이해해야 한다.
- 번역을 하기 위해서는 인코더가 인풋 시퀀스를 분석해야한다. "They played chess," -> {"subject": "They", "verb": "played", ...} 이렇게 인코더가 분석을 해야한다. they는 주어 played는 동사.
- 디코더는 이미 주어를 번역했고 다음으로 동사가 번역되어야 한다고 생각한다. 그러면 인풋에서 동사가 어디 있나 찾아야 한다.
- 디코더는 verb라는 key를 보고 이해하면 된다. 하지만 모델은 이렇게 discrete한 token들을 가지고 있지 않다. vector로 표현된 key를 가지고 있고 이를 query라고 한다.
- look up에 사용될 key(query)는 딕셔너리에 정확히 일치하지 않는다. 그래서 query와 딕셔너리의 key의 similarity를 구한다. 그다음 소프트맥스 함수를 사용해서 similarity score를 합 1로 바꿔준다.
- 모델은 다시 similarity와 value의 weighted sum을 구한다.
- Transformer 모델에서 사용되는 similarity measure는 그냥 dot product다. (scaling factor만 추가된)
- Q는 query다. [n_queries, d_keys]
- K는 key다. [n_keys, d_keys]
- V는 value다. [n_keys, d_values]
- QK^T는 [n_queries, n_keys] 모양이고, 각 query와 key의 similarity score. 소프트맥스 함수를 거치기 때문에 각 query마다 합이 1이고 최종 출력은 [n_queries, d_values]. 행은 각 query의 결과
- Scaling factor는 그레디언트를 작게 만드는 소프트맥스 함수의 saturation을 피하기 위해 사용한다.
- 소프트맥스 지나기 전에 Similarity score에 매우 큰 음수를 더함으로써 마스킹할 수 있다. Masked Multi-Head Attention layer.
- 인코더에서 이 식에서 Q, K, V는 모두 인풋 시퀀스의 단어 리스트다. (그래서 문장에 각 단어들은 본인 문장에 모든 단어들과의 관계를 학습하게 된다. 본인 단어 포함)
- 비슷하게 디코더의 마스킹된 어텐션 레이어는 Q, K, V는 모두 타겟 시퀀스의 단어 리스트다. 그런데 inference를 할 때는 미래의 출력이 없기 때문에 학습할 때 마찬가지로 미래의 타겟 시퀀스는 마스킹 된 상태로 학습되어야한다.
- 디코더에서 위에 있는 어텐션 레이어의 K와 V는 인코더에서 만들어진 word encodings이다. (인코더의 출력)
- Q는 디코더에서 만들어진 word encodings이다.
- Mulit-Head Attention layer는 단순히 scaled dot-product attention layer를 겹쳐 놓은 것이다.
- 입력을 linear transform하고 출력을 합쳐서 다시 linear transform
- 왜 그럴까?
- 인코더는 똑똑해서 단어에서 다양한 특성을 포함한다.
- 품사
- position
- 등등
- 만약 multi가 아니라 single로 attention layer를 사용한다면 하나의 특성만 query할 것이다. (요청?)
- 그래서 다양한 linear transform을 통해 다양한 subspace들로 projection해서 모델이 적용할 수 있다. word의 특성의 서브셋에 집중한 subspace
- 인코더는 똑똑해서 단어에서 다양한 특성을 포함한다.
- 모델 구조 다시 한번 보고 끝내자.
반응형'ML > 딥러닝' 카테고리의 다른 글
[AutoGPTQ] KoAlpaca 양자화하기 (2) 2023.08.18 TRAINING NEURAL AUDIO CLASSIFIERS WITH FEW DATA 논문 리뷰 (0) 2020.11.02 Chapter 9 Unsupervised Learning Techniques (0) 2020.05.07 Chapter 7 Ensemble Learning and Random Forests (0) 2020.04.13