트랜스포머 : 2017년 구글이 발표한 논문인 "Attention is all you need"에서 나온 모델로 기존의 seq2seq의 구조인 인코더-디코더를 따르면서도, 논문의 이름처럼 어텐션(Attention)만으로 구현한 모델. RNN을 사용하지 않음. 성능은 RNN보다 우수하다
Attention : 특정 정보에 좀 더 주의를 기울이는 것
인코더의 입력 = 임베딩 벡터 + 포지셔널 인코딩 값
포지셔널 인코딩?
pos : 입력 문장에서의 임베딩 벡터의 위치 (단어의 위치)
i : 임베딩 벡터 내의 차원의 인덱스
dmodel : 트랜스포머 모든 층의 출력 차원 (그림에서는 4 실제 논문에서는 512)
주기가 10000^(2i/dmodel)*2π인 삼각 함수
단어 순서대로 정수 값(1, 2, 3, 4)으로 인코딩하는 경우
상대적 거리(1)는 표시할 수 있지만 두번째 문장과 같이 문장의 길이가 매우 큰 경우는 토큰 값이 매우 커짐 -> 원래의 임베딩 벡터의 값에 영향을 줌 -> 범위 안에서 인코딩함
“어머님 나 는 별 하나 에 아름다운 말 한마디 씩 불러 봅니다”
“소학교 때 책상 을 같이 했 던 아이 들 의 이름 과 패 경 옥 이런 이국 소녀 들 의 이름 과 벌써 애기 어머니 된 계집애 들 의 이름 과 가난 한 이웃 사람 들 의 이름 과 비둘기 강아지 토끼 노새 노루 프란시스 쟘 라이너 마리아 릴케 이런 시인 의 이름 을 불러 봅니다”
1: ‘어머님’, 2: ‘나’, 3: ‘는’, 4: ‘별’, 5: ‘하나’, 6: ‘에’, 7: ‘아름다운’, 8: ‘말’, 9: ‘한마디’, 10: ‘씩’, 11: ‘불러’, 12: ‘봅니다’
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: ‘과’, 32: ‘가난’, 33: ‘한’, 34: ‘이웃’, 35: ‘사람’, 36: ‘들’, 37: ‘의’, 38: ‘이름’, 39: ‘과’, 40: ‘비둘기’, 41: ‘강아지’, 42: ‘토끼’, 43: ‘노새’, 44: ‘노루’, 45: ‘프란시스’, 46: ‘쟘’, 47: ‘라이너’, 48: ‘마리아’, 49: ‘릴케’, 50: ‘이런’, 51: ‘시인’, 52: ‘의’, 53: ‘이름’, 54: ‘을’, 55: ‘불러’, 56: ‘봅니다’
- 0: ‘어머님’, 0.091: ‘나’, 0.182: ‘는’, 0.273: ‘별’, 0.364: ‘하나’, 0.455: ‘에’, 0.545: ‘아름다운’, 0.636: ‘말’, 0.727: ‘한마디’, 0.818: ‘씩’, 0.909: ‘불러’, 1: ‘봅니다’
- 0: ‘소학교’, 0.018: ‘때’, 0.036: ‘책상’, 0.055: ‘을’, 0.073: ‘같이’, 0.091: ‘했’, 0.109: ‘던’, 0.127: ‘아이’, 0.145: ‘들’, 0.164: ‘의’, 0.182: ‘이름’, 0.2: ‘과’, 0.218: ‘패’, 0.236: ‘경’, 0.255: ‘옥’, 0.273: ‘이런’, 0.291: ‘이국’, 0.309: ‘소녀’, 0.327: ‘들’, 0.345: ‘의’, 0.364: ‘이름’, 0.382: ‘과’, 0.4: ‘벌써’, 0.418: ‘애기’, 0.436: ‘어머니’, 0.455: ‘된’, 0.473: ‘계집애’, 0.491: ‘들’, 0.509: ‘의’, 0.527: ‘이름’, 0.545: ‘과’, 0.564: ‘가난’, 0.582: ‘한’, 0.6: ‘이웃’, 0.618: ‘사람’, 0.636: ‘들’, 0.655: ‘의’, 0.673: ‘이름’, 0.691: ‘과’, 0.709: ‘비둘기’, 0.727: ‘강아지’, 0.745: ‘토끼’, 0.764: ‘노새’, 0.782: ‘노루’, 0.8: ‘프란시스’, 0.818: ‘쟘’, 0.836: ‘라이너’, 0.855: ‘마리아’, 0.873: ‘릴케’, 0.891: ‘이런’, 0.909: ‘시인’, 0.927: ‘의’, 0.945: ‘이름’, 0.964: ‘을’, 0.982: ‘불러’, 1: ‘봅니다’
<첫 번째 서브층>
셀프어텐션
Q : 입력 문장의 모든 단어 벡터들
K : 입력 문장의 모든 단어 벡터들
V : 입력 문장의 모든 단어 벡터들
<The animal didn't cross the street because it was too tired.> = <그 동물은 길은 건너지 않았다. 왜냐하면 그것은 너무 피곤하였기 때문이다.>
1️⃣ 단어 'I' 에 대한 Q 벡터가 모든 K 벡터에 대해서 어텐션 스코어를 구하는 과정.
2️⃣ 어텐션분포를 구함(소프트맥스) 3️⃣ 각 V벡터와 가중합하여 어텐션 값(컨텍스트 벡터)을 구함
2️⃣ 어텐션 스코어 구하기
3️⃣ 어텐션 분포 / 어텐션 값 구함
입력 문장의 길이 : sep_len
문장 행렬의 크기 : (sep_len, dmodel)
Q 벡터, K 벡터 : dk -> Q 행렬, K 행렬 : (sep_len, dk)
V 벡터 : dv -> V 행렬 : (sep_len, dv)
가중치 행렬 WQ, WK : (dmodel, dk)
WV : (dmode, dv)
어텐션 값 행렬 : (seq_len, dv) (Q, K전치, V 곱함)
어텐션 헤드를 모두 연결한 행렬에 가중치 행렬 Wo를 곱해준다 : 최종 결과물
가중치
패드가 포함된 입력 문장의 셀프 어텐션
실질적 의미가 없는 <PAD>를 유사도를 구하는 과정에서 제외하기 위해서 Masking해줌
(소프트맥스 함수를 지난 후를 가정)
<두 번째 서브층>
x : 멀티 헤드 에텐션의 결과 (seq_len, dmodel)
W1 : 가중치 행렬 (dmodel, dff) (dff는 2048로 설정)
Add & Norm = 잔차 연결과 층 정규화
1️⃣ 평균과 분산을 통한 정규화 : 평균과 분산을 통해 벡터 xi를 정규화
벡터 xi의 k차원의 값이 평균과 분산에 의해 정규화
2️⃣ 감마와 베타를 도입
디코더도 인코더와 마찬가지
문제 :
룩 어헤드 마스크를 도입
인코더의 첫번째 서브층 : Query = Key = Value
디코더의 첫번째 서브층 : Query = Key = Value
디코더의 두번째 서브층 : Query : 디코더 행렬 / Key = Value : 인코더 행렬