머신러닝 2022. 2. 17. 11:13

BERT는 트랜스포머를 이용하여 구현되었으며, 위키피디아와 BooksCorpus와 같은 레이블이 없는 텍스트 데이터로 사전 훈련된 언어 모델이다. BERT는 이미 기 학습된 사전 훈련 모델에 레이블이 있는 레이어 층을 하나 쌓아서 훈련해 파이미터를 재조정하여 다른 작업(task)에서도 좋은 성능을 낼 수 있다. 이러한 다른 작업을 위해 레이어를 쌓은 후 훈련하여 파라미터를 재 조정하는 과정을 파인튜닝(fine-tuning)이라고한다.

 

언어 모델(Language Model, LM)
언어 모델이란 단어들의 시퀀스에 대한 확률 분포다. 간단히 말하면 단어들의 모음이 있을 때 해당 단어의 모임이 
어떤 확률로 등장할지를 나태나는 값이라 생각하면 된다. 예를 들면, Word2vec 모델 중 CBOW 모델은 주변 
단어들을 통한 중앙 단어 예측이 학습의 목적이다. 즉, 문장 시퀀스 중 t번째 단어를 예측하기 위해 해당 단어의
앞,뒤 c개의 단어를 사용하는데, 앞뒤로 총 2c개의 단어 모음이 있을 때 t번째 위치에 올 단어에 대한 확률 분포를
찾는 언어 모델이고, 언어 모델의 성능은 이 확률을 최대화 하는 것이다.

 

BERT의 크기

 

버트는 트랜스포머의 인코더-디코더의 구조를 따라가는 것은 아니고, 인코더만 여러 레이어로 쌓아 올린 구조이다. Base 버전에서는 총 12개, Large 버전에서는 총 24개의 인코더 레이어를 쌓았다. 그리고 각 버전은 모델의 차원수도 차이가 있고, 셀프어텐션 헤드수도 다르기때문에 아래와 같은 파라미터 개수를 갖는다.

 

BERT-Base : L=12, D=768, A=12 : 110M개의 파라미터
BERT-Large : L=24, D=1024, A=16 : 340M개의 파라미터

 

BERT의 문맥을 반영한 임베딩(Contextual Embedding)

BERT의 입력은 임베딩 층(Embedding Layer)를 지난 임베딩 벡터들이다. BERT base 기준 d_model을 768로 정의하였기 때문에 문장의 시퀀스들의 각각의 입력 차원은 768차원이다. 각 입력들은 총 12개의 레이어를 지나면서 연산된 후, 동일하게 각 단어에 대해서 768차원의 벡터를 출력하는데, 각 출력들은 모두 문맥을 고려한 벡터가 된다.

 

위 그림에서 [CLS] 토큰의 경우 초기 입력은 단순 임베딩 층을 지난 벡터에 지나지 않지만, 총 12개의 레이어를 지난 후 출력으로 나온 CLS의 벡터는 입력으로 들어간 모든 토큰을 참고한 문맥 정보를 가진 벡터가 된다. 이러한 연산은 CLS 토큰 이외의 모든 토큰도 마찬가지가 된다.

 

위 그림을 봤을 때 모든 토큰은 모든 토큰들을 참고하고 있다.

위 그림은 각 입력이 총 12개의 레이어를 지나는 모습과, 각 레이어의 세부 구성을 보여준다. 결론적으로는 각 토큰들은 12레이어를 지나면서 셀프 어텐션을 통해 문맥 정보를 담게 된다.

 

BERT의 서브워드 토크나이저(WordPiece)

BERT는 단어보다 더 작은 단위로 쪼개는 서브워드 토크나이저를 사용한다. 서브워드 토크나이저는 기본적으로 자주 등장하는 단어는 그대로 단어 집합에 추가하지만, 자주 등장하지 않는 단어의 경우에는 더 작은 단위인 서브워드로 분리되어 서브워드들이 단어 집합에 추가된다는 아이디어를 갖는다. 만약 일반적인 토크나이저라면 존재하지 않는 단어일 경우 OOV 문제가 발생하지만, 서브워드 토크나이저의 경우 해당 단어가 단어집합에 존재하지 않는다고 해서, 서브워드 또한 존재하지 않는다는 의미가 아니므로 해당 단어를 더 쪼개려고 시도한다.

 

print(tokenizer.vocab['embeddings'])
-> em, ##bed, ##ding, ##s

 

이렇게 서브워드 토크나이저를 이용하여 문장 시퀀스들에 대해 WordPiece Embedding(정수 인코딩)을 진행한다.

 

포지션 임베딩(Position Embedding)

트랜스포머 모델에서는 포지셔널 인코딩이라는 방법으로 단어의 위치를 표현했는데, 사인함수와 코사인 함수를 이용해 각 토큰 행렬에 위치정보를 더했다. BERT는 유사하지만 사인,코사인 함수를 이용하지는 않고, 학습을 통해 얻는 포지션 임베딩을 사용한다.

위 그림에서 보이듯 워드피스 임베딩을 통해 나온 벡터에 포지션 임베딩을 더해주는 행위를 하여 임베딩에 위치정보를 반영한다. 여기서 포지션 임베딩은 위치 정보를 위한 임베딩 레이어를 하나 더 사용하고, 만약 문장의 길이가 4라면 4개의 포지션 임베딩 벡터를 학습시킨다.

 

첫번째 단어의 임베딩 벡터 + 0번 포지션 임베딩 벡터
두번째 단어의 임베딩 벡터 + 1번 포지션 임베딩 벡터
세번째 단어의 임베딩 벡터 + 2번 포지션 임베딩 벡터
네번째 단어의 임베딩 벡터 + 3번 포지션 임베딩 벡터

 

실제 BERT에서는 문장의 최대 길이를 512로 하고 있으므로 총 512개의 포지션 임베딩 벡터가 학습된다. 지금까지 총 2개의 임베딩 레이어가 나왔는데 버트에서는 추가적으로 세그먼트 임베딩이라는 1개의 임베딩 층을 더 사용한다.

 

BERT의 pre-trained : 마스크드 언어 모델(Masked Language Model, MLM)

BERT는 사전 훈련을 위해서 입력으로 들어가는 입력 텍스트의 15%의 단어를 랜덤으로 마스킹한다. 그리고 인공 신경망에게 이 가려진 단어들을 예측하도록 한다. 더 정확하게는 15% 단어 전부를 마스킹 하지 않고 아래와 같은 규칙을 따른다.

 

80%의 단어들은 [MASK]로 변경한다.
Ex) The man went to the store → The man went to the [MASK]

10%의 단어들은 랜덤으로 단어가 변경된다.
Ex) The man went to the store → The man went to the dog

10%의 단어들은 동일하게 둔다.
Ex) The man went to the store → The man went to the store

 

전체 단어의 85%는 학습에 사용되지 않는다. 마스크드 언어 모델의 학습에 사용되는 단어는 전체 단어의 15%이다. 학습에 사용되는 12%는 마스킹된 후 원래 단어를 예측하는 방식, 1.5%는 랜덤으로 변경된 단어의 원래 단어를 예측하는 방식, 나머지 1.5%는 단어가 변경되지 않았지만 BERT는 이 단어가 원래의 단어인지 변경된 단어인지 모르기에 원래단어가 무엇이었는지 예측해본다.

'dog' 토큰은 [MASK]로 변경되었다.
'he'는 랜덤 단어 'king'으로 변경되었다.
'play'는 변경되진 않았지만 예측에 사용된다.

BERT의 pre-trained : 다음 문장 예측(Next Sentence Prediction, NSP)

BERT는 두 개의 문장을 준 후에 이 문장이 이어지는 문장인지 아닌지를 맞추는 방식으로 사전 학습한다. 

 

이어지는 문장의 경우
Sentence A : The man went to the store.
Sentence B : He bought a gallon of milk.
Label = IsNextSentence

이어지는 문장이 아닌 경우 경우
Sentence A : The man went to the store.
Sentence B : dogs are so cute.
Label = NotNextSentence

 

BERT의 입력으로 넣을 때에는 [SEP]라는 특별 토큰을 사용해 두 문장을 구분한다. 그리고 위 그림에서 보듯이 문장이 이어지는지 아닌지 등의 분류 문제에는 CLS 토큰의 출력을 이용한다. 또한 마스크드 언어 모델 학습과 다음 문장 예측은 서로 별도로 학습하는 것이 아니라, 각 문제의 loss를 합하여 학습이 동시에 이루어진다.

 

세그먼트 임베딩(Segment Embedding)

BERT는 QA등과 같은 두 개의 문장 입력이 필요한 태스크를 풀기도 하는데, 문장 구분을 위해서 세그먼트 임베딩이라는 또 다른 임베딩 층을 사용한다. 첫번째 문장에는 Sentence0 임베딩, 두번째 문장에는 Sentence1 임베딩을 더해주는 방식이며 임베딩 벡터는 두개만 사용된다.

 

결론적으로 BERT는 총 3개의 임베딩 층이 사용된다.

 

WordPiece Embedding : 실질적인 입력이 되는 워드 임베딩. 임베딩 벡터의 종류는 단어 집합의 크기로 30,522개.
Position Embedding : 위치 정보를 학습하기 위한 임베딩. 임베딩 벡터의 종류는 문장의 최대 길이인 512개.
Segment Embedding : 두 개의 문장을 구분하기 위한 임베딩. 임베딩 벡터의 종류는 문장의 최대 개수인 2개.

 

만약 BERT가 두 개의 문장을 입력받을 필요가 없는 태스크인 경우 세그먼트 임베딩을 전체 입력에 대해 Sentence 0 임베딩만 더해준다.

 

BERT를 파인 튜닝(fine-tunng) 하기

1)하나의 텍스트에 대한 텍스트 분류 유형(Single Text Claasification)

입력이 하나의 문장이고, 해당 텍스트에 대한 분류를 할때는 앞서 설명한 것과 같이 CLS 토큰의 출력을 이용한다. 즉, 파인 튜닝 단계에서 텍스트 분류 문제를 풀기 위해서 CLS 토큰 출력 위치에 Dense Layer(fully-connected layer) 층을 추가하여 분류에 대한 예측을 하게 된다.

 

2)하나의 텍스트에 대한 태깅 작업(Tagging)

하나의 텍스트에 대해 엔티티 혹은 품사를 태깅하는 작업에 대해 파인 튜닝 할때는 스페셜 토큰을 제외한 실제 입력 토큰의 출력층에 Dense Layer를 사용하여 분류에 대한 예측을 하게 된다.

 

3)하나의 텍스트에 대한 태깅 작업(Tagging)

텍스트의 쌍을 입력으로 받는 대표적인 태스크로 자연어 추론(Natural language inference)이 있는데,  두 문장이 입력으로 들어오고 두문장이 논리적으로 어떤 관계에 있는지를 분류하는 것이다. 유형으로는 모순 관계(contradiction), 함의 관계(entailment), 중립 관계(neutral)이 있다. 해당 문제의 입력은 두 개의 문장이므로 SEP라는 스페셜 토큰으로 문장을 구분한다. 그리고 해당 문제는 분류 문제에 속하므로, CLS 토큰의 출력층에 Dense Layer를 쌓아서 분류를 예측한다.

 

위에서 설명한 문제 이외로도 하나의 문장과 하나의 문단을 넣어서 첫번째 문장(질문)에 해당하는 답을 문단에서 뽑아내는 질의 응답에 대한 문제등도 있다.

 

어텐션 마스크(Attention Mask)

 

BERT는 입력으로 어텐션 마스크라는 시퀀스 입력이 추가로 필요하다. 쉽게 말해 어텐션 마스크는 연산이 필요없는 패딩 토큰에 대해 어텐션을 하지 않도록 마스킹해주는 역할이다. 이 값은 0과 1값으로 가지는데, 실제로 입력 시퀀스중 [PAD] 토큰의 위치에 해당하는 어텐션 마스크는 0으로, 실제 연산에 필요한 토큰 위치는 1로 채워지게 된다.

posted by 여성게
: