https://arxiv.org/abs/1409.3215
(+2020기준 가장 좋은 모델은 s2s가 아닌 transformer기반이다.)
Sequence to Sequence Learning with Neural Networks
Deep Neural Networks (DNNs) are powerful models that have achieved excellent performance on difficult learning tasks. Although DNNs work well whenever large labeled training sets are available, they cannot be used to map sequences to sequences. In this pap
arxiv.org
이전 단어를 보고 다음 단어를 예측하는게 기본 루트
1
전통적 언어모델 : 카운트 기법을 주로 사용
3개의 단어가 하나의 문장 (1,2,3)이라고 하면,
1번 단어가 나올 확률 * 1번단어가나왔을때 2번단어가 나올확률 * 1번단어와 2번단어가 나왔을때 3번 단어가 나올 확률 이다.
여기서 seq2seq가
2
기존 RNN
입력과 출력의 크기가 동일(하나넣고 하나나옴)
한글과 영어의 차이등의 고려가 힘들다 (한글: 주어,목적어,동사 / 영어: 주어/동사/목적어)
(이 경우 한글->영어로 한개씩 출혁하므로 주어->주어 목적어->동사 목적어->동사로 나온다)
h가 고정?
3
rnn기반의 seq2seq
문맥벡터(context vector)를 추출한다.
여기서 특이점은 인코더의 마지막 hiddenstate만을 문맥벡터로 사용한다.
인코더와 디코더는 다른 파라미터를 사용한다.
입력과 출력의 길이가 달라도 상관없다. (문맥벡터를 거치기에)
자세히 :
등장 빈도수가 많은 단어(ex 20000개)를 원핫(20000차원)으로 표현
-> 1000~2000차원정도로 줄이는 임베딩 레이어를 거친다 (딥러닝에서 종종거침)
-> 그 값을 입력으로하고 h를 같이 받아서 rnn과 같은 레이어가 처리하도록 한다.(인코딩)
-> 이렇게 나온 h는 다음 인코더에 들어가도록 한다.
-> h를 계속 갱신하며 최종 h를 고정된 크기의 문맥벡터로 사용한다.
->입력을 임베딩 - 디코더 - hudden state(St) - linear layer - 아웃풋
-> 입력차원은 인코더와 디코더의 입력이 다를수 있다. 언어가 다르므로.
-> 시퀀스 시작을 알리기 위해 <start of sequence>, 끝<end of sequence>를 토큰으로 넣어 알리는게 일반적.
-> 종료시점은 가 나오면 번역이 끝났다
- 입력이 고정된 벡터로 변형되기 때문에 입력과 출력시의 문장 길이가 너무 다르면 특징을 잘 추출하지 못한 상태이므로 성능이 낮아질 수 있다. (이후 논문에서 해결)
성능 개선
1.LSTM
2.입력 문장 뒤집기(앞쪽 단어가 연관성이 커서, 뒤집으면 맨뒤로 가므로 앞쪽 단어 정보가 더 잘 담기기 때문)
[논문 읽기]
해당 시기는 기계번역과 딥러닝이 혼용하는 과도기적 시기 (그래서 논문에서 SMT와 LSTM을 같이 진행하는 실험도 진행해보는 모습을 보임)
역전파로 진행을 하면 복잡한 함수도 잘 찾아줌
해당 시점에서는 입력과 출력이 대부분 픽스 되어있음 -> 이경우 한계. 출력이 가변적으로 바뀌는 경우도 많고.
LSTM만으로 s2s해결을 잘함. 인코딩을 통해 큰그기의 고정된차원의 백터를 뽑고 또다른 LSTM을 통해 (디코더)출력을 뽑아냄
앙상블로 성능을 더 높게 만듬
문장이 길어도 잘 진행해냄
모델
인풋은 단어(x)들 T개를 차원으로 변형 (16만개단어로 고정한다면, 인풋 단어는 모두 이 16만개중 하나이다.)
현재단어 hidden state : 이전까지의 h정보와 현재단어에 대한 정보를 조합해서 sigmoid
현재h의 linear한 레이어를 통해 실제출력이 나옴
하지만 이 RNN을 쓰면 입력과 출력의 길이(단어)가 다르면 사용이 어렵다.
그래서 고정된 vector를 만드는거고. 인코더와 디코더(각기다른). 근데 이때 너무 문장이길면 해석이 잘 안돼서 LSTM을 사용.
실제론 디코더 들어갈때 SOS가 있지만 논문엔 우선 EOS만 작성해둠
실제모델은 1. 인코더와 디코더의 파라미터가 다르다.
2. LSTM 레이어는 4개
3. 문장 순서를 바꾸면 훨씬 잘됨 (첫번쨰 단어 중요도가 높은걸 반영 위해)
디코더에 소스넣으면 1대1매칭되는 타겟을 출력. 로그를 붙인 이유는 이 확률값이 높아지도록 하기 위해. -> 일반적인 NN에서 사용되는 트레이닝 오브젝트 식이다. (학습식)
학습이 완료되면 sentence가 주어질때마다 가장 높은 확률을 가지는 타겟을 결과값으로 리턴한다. (테스트식)
자연어 처리에서 많이 사용되는 bean search도 사용. 단순히 매번 그리디하게 가장 확률이 높은것을 석택하는것이 아닌, 특정 깊이만큼 들어가볼수 있도록 만들어서 결과적으로 출력문장이 더 높은 확률을 뱉도록 한다.
디테일
워드임베딩 : 1000차원으로 임베딩
LSTM : 레이어 4개 중첩, 셀의 크기는 1000
LSTM 파라미터 : -0.08~0.08을 따르도록 유니폼 분포를 따름
모멘텀없이 stochastic 경사하강 진행, 학습과정에서 learning rate를 줄임
배치사이즈 128 (학습 과정에서 모델의 포워드를 할때 사용하는 문장의 개수가 128개)
랜덤하게 128개 배치 문장을 뽑으면, 긴 문장이 껴있을때 다른 문장도 그에 맞게 패딩을 해야하므로 계산적 낭비. 그래서 같은 미니배치마다의 문장 길이들은 비슷하게 구성해서 패딩이 적게 들어가게 만들어서 학습속도를 높인다.
결과가 지금까지중 가장 높진 않지만, 거의 높으며 딥러닝의 문을 열수 있게한다.
LSTM hidden state를 PCA를 써서 2차원에 뽑은것 : 확인하면 비슷한 애들끼리 잘 클러스터링 되어있다.
[코드]
spaCy라이브러리 : 문장을 토큰화, 태깅등을 진행해주는 보편적 파이썬 라이브러리
field 라이브러리 : 데이터에대해 자세한 전처리를 명시해줄수 있다. 여기서 사용은 <sos>와 <eos>토큰을 넣고, 모든 단어를 소문자로 명시.
field의 build_vocab : 실제로 유의미한 단어가 몇개인지 구하기. 2번 이상 등장한 단어만 선택.
사전을 구성하게되면 없는단어:0, 패딩:1, sos:2, eos:3
bucket iterater : 유사한 단어길이들을 하나의 배치로 넣기 위해
-> train iterater, valid iterater, test iterater를 각각 초기화. 간단히 반복문으로 train iterater에서 첫번째 배치만 확인해보기 (첫번쨰 돌면 바로 종료). 각각의 배치는 소스문장과 타겟문장으로 구성. 배치의 쉐입을 출력하면 [단어의 길이, 배치사이즈]가 나옴. 현재 배치에 있는 모든 문장은 30개의 토큰으로 구성되도록 전처리를 해줬다. 현재 배치에 있는 하나의(첫번째) 문장을 뽑아보면 {인덱스0:sos(2) 13:eos(3) 이후는 패딩(1)(길이를 맞추기 위한)}.
인코더와 디코더 (거의 유사. 디코더에 fully connected 레이어가 추가된게 다름)
인코더
LSTM을 사용. 입력과 출력에 있어서 hidden과 cell state 을 둘다 사용. 여기서 cell은 일반적으로 RNN에서 수행되는 hidden state와 유사한 기능을 수행한다고 보면 됨.
하이퍼파라미터 : imput_dim-전체 단어의 개수 / embed_dim-해당단어를 특정크기의 임베딩으로 압축할때 그 임베딩의 키기 / hidden_dim-히든상태의 차원 / n_layers-중첩레이어 개수 / dropout_ratio-정규화효과를 위해. 일반적으로 0.5를 사용
임베딩레이어, LSTM레이어 두가지로 구성.
소스가 2차원 리스트로 들어옴. [단어개수, 배치크기] 이때 각 단어의 인덱스 정보가 담김. (ex. Apple라는 단어는 5)
임베딩을 통해 각각의 단어를 특정 크기의 임베딩으로 바꿀수 있도록 함.
결과적으로 그러한 소스 문장이 RNN에 들어가서 output, hidden, cell을 출력함.
인코더에서 output은 사용되지 않음.
전체 단어의 문맥정보가 포함된 히든상태가 context vextor로 사용되기 때문에 히든과 셀만 반환.
마지막 단어를 넣었을때 그때 반환되는 히든과 셀을 문맥벡터로 그대로 사용
디코더
인코더와 아주 유사
문맥벡터를 특정 타겟 문장으로 디코딩.
나머지는 기본적으로 동일하되, 별도로 FC레이어가 추가.
이때 히든디멘전을 통해 실제로 아웃풋과,
즉 번역 결과를 내보내기 위해 FC레이어를 초기화해주고 이를 이용한다.
디코더의 포워드는 하나의 단어를 입력받아 그때마다 출력단어와 현재까지 출력했던 단어에 대한 정보값을 리턴. 즉 여기선 단어를 하나씩 넣는다.
현재 인풋을 임베딩 -> 구해진 임베딩벡터가 있을때, 현재단어와 지금까지 단어의 정보를 같이 넣어서 매번 아웃풋을 뽑는다 -> 이 아웃풋이 번역결과가 될 수 있도록 하나를 리턴.
실제 s2s는 이 디코더의 포워드를 여러번 호출하는 방식으로 전체 번역결과를 구한다.
추가로 teacher forcing 사용 : 모델이 내뱉은 결과와 실제 결과를 비교하며 모델이 업데이트되는데, 디코더 예측이 한번 틀리면 뒷부분도 부적절한 결과를 내뱉기 때문에 학습이 별로가 됨. 그러므로 디코더의 예측을 다음 입력으로 쓰지 않고 실제 목표 출력을 다음 입력으로 사용한다.
모델 s2s
하나의 인코더와 디코더 객체로 초기화
학습을 진행할때 티처포싱을 0.5확률로 진행.
소스문장이 즐어오면 인코더 거쳐서 하나의 문맥벡터 뽑음
이제 디코더를 여러번 거쳐 전체 번역 결과를 뽑음. 디코더를 거쳐 나오는 모든 단어를 합쳐 최종 결과로 담기 위해 하나의 텐서 객체를 초기화. 그래서 학습을 진행할때 타겟 단어의 개수만큼 반복해서 매번 디코더에 포워딩할 수 있도록 한다. 즉 디코더를 여러번 실행. 타겟 단어의 개수만큼 반복을 할때마다 매번 현재 단어 그리고 지금까지 출력했던 단어에 대한 정보 벡터들을 모두 조합해서 출력할 번역결과를 뽑고 히든 스테이트 값을 갱신. 이때 매번 FC를 거쳐서 나온 출력단어정보 그 확률값이 있을때 거기서 가장 확률값이 높은 단어의 인덱스를 추출하여 실제 결과를 뽑는다.
파라미터 설정
입력차원, 출력차원은 데이터에 따라 결정
임베딩차원 256
히든상태차원 512
각 LSTM 레이어 2번씩 중첩
s2s 객체 초기화
가장 먼저 모델에 포함된 모든 파라미터 값을 초기화 (출력해서 확인 가능)
실제학습
아담 옵티마이저
손실값 계산시 뒤의 패딩 값 무시
트레인 이터레이터를 통해 매번 배치 단위로 각각의 학습 데이터를 확인하며
모델의 데이터를 포워딩
결과로 나온 아웃풋과 실제정답(타겟)을 비교해 크로스 엔트로피 로스를 구해서 학습을 진행
출력 단어중 인덱스 0은 사용하지 않는다. 아웃풋차원은 고정하고 앞쪽의 차원을 출력 단어의 개수-1 * 배치사이즈로 바꿔준다. 타겟도 동일하게.
이제 크로스 엔트로피구하기
역전파
기울기에 대해 gradient clipping 진행 (논문과 마찬가지로)
이후 파라미터 업데이트 반복 -> 전체 모델(인코더와 디코더에 포함된) 파라미터를 다 업데이트
모델 평가할땐 파라미터 업데이트는 제외하고 손실값만 계산해서 리턴
에폭: 20, 트레인데이터로 학습(train함수), 벨리데이션데이터(eval함수->파라미터업뎃코드빼고 손실만 리턴) 함께 진행
valid로스가 가장 낮을때 별도로 모델 파일 저장하도록 (일반적)
모델파일 다운
모델파일 불러와서 evaluate로 테스트데이터 넣으면 PPL(perplexity:테스트데이터확률의 역수.)지수 확인.
데이터 넣을때 토큰화로 순서바꾸고 sos, eos넣고 인덱스로 바꾸고.
인코더 거치면 문맥벡터 출력
문맥벡터와 sos를 디코더에 반복적으로 넣는다. (번역결과로 뽑을 문장의 최대 길이만큼 반복)
출력 결과로 나온 확률분포중 가장 확률값이 큰걸 리스트에 넣는다.
eos를 만나면 반복문 끝
리스트를 실제 문자열로 변경(itos-인덱스 투 스트링)
해당 결과 추출
'AI > Model (Paper)' 카테고리의 다른 글
NIC : 이미지 문장 번역 (0) | 2021.08.09 |
---|---|
Attention : NEURAL MACHINE TRANSLATIONBY JOINTLY LEARNING TO ALIGN AND TRANSLATE (0) | 2021.06.28 |
[코드] 오토인코더 - Training Deep AutoEncoders for Collaborative Filtering (0) | 2021.03.02 |
[논문] 오토인코더 - Training Deep AutoEncoders for Collaborative Filtering (0) | 2021.02.26 |
(진행중)Transformer : Attention Is All You Need 리뷰 (0) | 2021.01.18 |