기계번역 과제#
- 인코더: 입력 문장의 표현 방법 학습
- 디코더: 인코더에서 학습한 표현 결과를 입력받아 사용자가 원하는 문장 생성
Encoder#
Self Attention#
- 임베딩: 각각의 단어를 표현하는 벡터값, [문장 길이 x 임베딩 차원]
- 쿼리(Q), 키(K), 밸류(V) > 각각의 가중치 행렬을 입력 행렬에 곱해 Q, K, V 행렬 생성
- Q, K, V의 차원 [문장 길이 x 벡터의 차원]
- 1단계: Q와 K^T 행렬의 내적 연산, 쿼리 벡터(I)와 키 벡터(I, am, good) 사이의 유사도 계산
- 2단계: QK^T 행렬을 키 벡터 차원의 제곱근값($\sqrt{d_k}$)으로 나눈 것, 안정적인 gradient 얻음
- 3단계: 소프트맥스 함수를 사용해 비정규화된 형태의 유사도 값을 정규화 (score 행렬)
- 4단계: 스코어 행렬에 V 행렬을 곱해 어텐션(Z) 행렬 계산, 어텐션 행렬은 문장의 각 단어와 벡터값 가짐
(단어 I의 셀프 어텐션은 각 밸류 벡터값의 가중치 합으로 계산, 단어가 문장 내에 있는 다른 단어와의 연관성)
Multi-Head Attention#
- 문장 내에서 모호한 의미를 가진 단어(it)가 있을 경우,
문장의 의미가 잘못 해석될 수 있기 때문에 멀티 헤드 어텐션을 사용한 후 그 결괏값을 더함 - 다수의 어텐션 행렬을 구하기 위해 서로 다른 가중치 행렬을 입력 행렬에 곱해 Q, K, V 생성
- 다수의 어텐션 행렬을 concatenate하고 새로운 가중치 행렬을 곱해 멀티 헤드 어텐션 결과 도출
(concatenate 시 [어텐션 헤드 x h] 크기가 되기 때문에 원래 크기로 만들기 위해 가중치 행렬 곱함)
Positional Encoding#
- 트랜스포머는 문장 안에 있는 모든 단어를 병렬 형태로 입력
- 단어의 순서 정보를 제공하기 위해 문장에서 단어의 위치를 나타내는 인코딩 제공
- 위치 인코딩은 사인파 함수를 사용
- 입력 임베딩 결과에 위치 인코딩을 합한 후 멀티 헤드 어텐션에 입력
Feed Forward Network#
- 2개의 전결합층(Dense)과 ReLU 활성화 함수로 구성
- add와 norm을 추가해 서브레이어에서 멀티 헤드 어텐션의 입력값과 출력값을 서로 연결
- add와 norm은 레이어 정규화(각 레이어 값이 크게 변화하는 것을 방지해 모델 학습 빠르게)와 잔차 연결
인코더 순서#
- 입력값은 입력 임베딩으로 변환한 다음 위치 인코딩 추가, 가장 아래 있는 인코더 1의 입력값으로 공급
- 인코더 1은 입력값을 받아 멀티 헤드 어텐션의 서브레이어에 값을 보냄, 어텐션 행렬을 결괏값으로 출력
- 어텐션 행렬의 값을 다음 서브레이어인 피드포워드 네트워크에 입력, 결괏값 출력
- 인코더 1의 출력값을 그 위에 있는 인코더 2에 입력값으로 제공
- 인코더 2에서 이전과 동일한 방법 수행, 주어진 문장에 대한 인코더 표현 결과를 출력으로 제공
Decoder#
- 이전 디코더의 입력값과 인코더의 표현(인코더의 출력값), 2개를 입력 데이터로 받음
- t=1에서 디코더의 입력값은 문장의 시작을 알리는 를 입력 > 타깃 문장의 첫 번째 단어(Je) 생성
- t=2에서 t-1 디코더에서 생성한 단어(, Je)를 추가해 문장의 다음 단어 생성
- t=3에서도 동일하게 (, Je, vais)를 입력받아 다음 단어 생성
- 디코더에서 토큰을 생성할 때 타깃 문장의 생성이 완료
- 디코더도 입력값을 바로 입력하지 않고 위치 인코딩을 추가한 값을 출력 임베딩에 더해 입력값으로 사용
Masked Multi-Head Attention#
- 디코더에서 문장을 생성할 때 이전 단계에서 생성한 단어만 입력으로 넣기 때문에,
아직 예측하지 않은 오른쪽의 모든 단어를 마스킹해 학습을 진행 - 소프트맥스 함수를 적용한 정규화 작업 전에 오른쪽의 모든 단어를 $-{\infty}$로 마스킹 수행
($-{\infty}$는 학습 도중 발산하는 경우가 있기 때문에 실제로는 작은 값 $e^{-9}$으로 지정)
Encoder-Decoder Attention Layer#
- 디코더의 멀티 헤드 어텐션의 입력으로 인코더의 표현값 R과 마스크된 멀티 헤드 어텐션의 결과 M을 받을 때 상호작용 발생
- 쿼리, 키, 밸류 행렬을 생성할 때, M을 사용해 Q를 생성, R을 활용해 K, V를 생성
(쿼리 행렬은 타깃 문장의 표현을 포함하기 때문에 M을 참조, 키와 밸류 행렬은 입력 문장의 표현을 참조) - 쿼리, 키 행렬 간의 내적 시 타깃 단어 가 입력 문장의 모든 단어(I, am, good)와 얼마나 유사한지 계산
(두 번째 행에서 Je에 대해, 나머지 행에서도 동일한 방법을 적용해 유사도 계산)
Linear and Sofmax Layer#
- 최상위 디코더에서 얻은 출력 값을 선형 및 소프트맥스 레이어에 전달
- 선형 레이어는 vocab 크기와 같은 logit 형태
- logit 값을 확률값으로 변환하고, 디코더에서 가장 높은 확률값을 갖는 인덱스의 단어로 출력
디코더 순서#
- 디코더에 대한 입력 문장을 임베딩 행렬로 변환하고 위치 인코딩 정보를 추가해 디코더 1에 입력
- 입력을 가져와서 마스크된 멀티 헤드 어텐션 레이어에 보내고, 출력으로 어텐션 행렬 M 반환
- 어텐션 행렬 M, 인코딩 표현 R을 입력받아 멀티 헤드 어텐션 레이어에 값을 입력, 새로운 어텐션 행렬 생성
- 인코더-디코더 어텐션 레이어에서 출력한 어텐션 행렬을 피드포워드 네트워크에 입력, 디코더의 표현으로 값 출력
- 디코더 1의 출력값을 다음 디코더 2의 입력값으로 사용
- 디코더 2는 이전과 동일한 방법 수행, 타깃 문장에 대한 디코더 표현 반환
- 타깃 문장의 디코더 표현을 선형 및 소프트맥스 레이어에 입력해 최종으로 예측된 단어 얻음
- 손실 함수로 cross-entropy를 사용해 분포의 차이를 확인
- 옵티마이저로 Adam 사용
- 과적합을 방지하기 위해 각 서브레이어 출력에 dropout 적용 (임베딩 및 위치 인코딩 합을 구할 때도 포함)
BERT#
- Word2Vec: 문맥 독립 임베딩, BERT: 문맥 기반 임베딩
- BERT는 인코더-디코더가 있는 트랜스포머 모델에서 인코더만 사용
- BERT-base: L(인코더 레이어)=12, A(어텐션 헤드)=12, H(은닉 유닛)=768
- BERT-large: L=24, A=16, H=1024
- BERT-tiny(L=2, A=2, H=128), BERT-mini(L=4, A=4, H=256) 등
사전 학습#
- 대규모 데이터셋으로 학습된 가중치를 활용해 새로운 태스크에 적용 (find-tuning)
- BERT는 MLM과 NSP 태스크를 이용해 거대한 말뭉치를 기반으로 사전 학습
Token Embedding#
- 첫 번째 문장의 시작 부분에 [CLS] 토큰 추가
- 모든 문장 끝에 [SEP] 토큰 추가
Segment Embedding#
- 두 문장을 구별하는데 사용
- [SEP] 토큰과 별도로 두 문장을 구분하기 위해 입력 토큰($E_A,E_B$) 제공
Position Embedding#
입력 데이터#
- 토큰 임베딩 + 세그먼트 임베딩 + 위치 임베딩 으로 표현
WordPiece Tokenizer#
- 하위 단어 토큰화 알고리즘 기반
- Let us start pretraining the model >
[let, us, start, pre, ##train, ##ing, the, model]
- 단어가 어휘 사전에 있으면 토큰으로 사용, 없으면 하위 단어로 분할해 하위 단어가 어휘 사전에 있는지 확인 (OOV 처리에 효과적)
Language Modeling#
- 임의의 문장이 주어지고 단어를 순서대로 보면서 다음 단어를 예측하도록 모델 학습
- 자동 회귀 언어 모델링: 전방(좌>우) 예측, 후방(좌<우) 예측, 각 방향(단방향)으로 공백까지 모든 단어를 읽음
- 자동 인코딩 언어 모델링: 예측하면서 양방향으로 문장을 읽음
Masked Language Modeling (MLM)#
- 주어진 입력 문장에서 전체 단어의 15%를 무작위로 마스킹, 마스크된 단어를 예측 (빈칸 채우기 태스크)
- [MASK] 토큰을 사전 학습시킬 경우 파인 튜닝 시 입력에 [MASK] 토큰이 없어 불일치가 발생
- 15% 토큰에 대해 80%만 [MASK] 토큰으로 교체, 10%는 임의의 토큰(단어)로 교체, 10%는 변경하지 않음
(사전 학습과 파인 튜닝 태스크의 차이를 줄이기 위한 일종의 정규화 작업) - 역전파를 통한 반복 학습을 거치며 최적의 가중치 학습
Whole Word Masking (WWM)#
- WWM 방법에서는 하위 단어가 마스킹되면 해당 하위 단어와 관련된 모든 단어를 마스킹
- 하위 단어와 관련된 모든 단어의 마스크 비율이 15%를 초과하면 다른 단어의 마스킹을 무시
Next Sentence Prediction (NSP)#
- BERT에 두 문장을 입력하고 두 번째 문장이 첫 번째 문장의 다음 문장인지 예측
- B 문장이 A 문장에 이어지만
isNext
를 반환하고, 그렇지 않으면 notNext
를 반환 - 두 문장 사이의 관계를 파악해 질문-응답 및 유사문장탐지와 같은 downstream 태스크에서 유용
- 한 문서에서 연속된 두 문장을
isNext
로 표시하고, 두 문서에서 각각 문장을 가져와 notNext
로 표시 - [CLS] 토큰 표현에 소프트맥스 함수를 사용하고 피드포워드 네트워크에 입력해 두 클래스에 대한 확률값 반환
- [CLS] 토큰은 모든 토큰의 집계 표현을 보유하고 있기 때문에 문장 전체에 대한 표현을 담고 있음
사전 학습 절차#
- lr = 1e-4, b1 = 0.9, b2 = 0.999
초기 모델의 큰 변화를 유도하기 위해 웜업으로 1만 스텝 학습
(0에서 1e-4로 선형적으로 학습률 증가, 1만 스탭 후 수렴에 가까워짐에 따라 학습률을 선형적으로 감소) - dropout 0.1, GELU(가우시안 오차 선형 유닛) 활성화 함수 사용
하위 단어 토큰화 알고리즘#
Byte Pair Encoding (BPE)#
- 모든 단어를 문자로 나누고 문자 시퀀스로 만듦
- 우선 문자 시퀀스에 있는 고유 문자를 어휘 사전에 추가
- 어휘 사전 크기에 도달할 때까지 가장 빈도수가 큰 기호 쌍을 반복적으로 병합해 어휘 사전에 추가
- 토큰화 시 어휘 사전에 존재하지 않는 단어는 하위 단어로 나눔, 사전에 없는 개별 문자는 토큰으로 교체
Byte-Level Byte Pair Encoding (BBPE)#
- 문자 수준 시퀀스 대신 바이트 수준 시퀀스를 사용
- 유니코드 문자가 바이트로 변환되어 단일 문자 크기는 1~4 바이트가 됨
- 바이트 수준에서 빈번한 쌍을 구분해 어휘 사전을 구축
- 다국어 설정에서 유용, OOV 단어 처리에 효과적
WordPiece#
- BPE랑 다르게 빈도수 대신 likelihood를 기준으로 기호 쌍을 병합
- 모든 기호 쌍에 대해 언어 모델의 가능도를 확인, 가능도가 가장 높은 기호 쌍을 병합