728x90

What is Pre-training

사전 훈련은 자연어 처리나 컴퓨터 비전 등 다양한 분야에서 사용되는 기계 학습 기술입니다. 이는 큰 데이터셋에서 모델을 훈련하여 데이터의 기반 구조를 포착하는 일반적인 패턴과 표현을 학습하는 과정입니다. 사전 훈련된 모델은 입력 데이터로부터 의미 있는 특징이나 임베딩을 추출하는 방법을 배우며, 이후 이를 작은 작업 특화 데이터셋에 맞게 미세 조정하거나 적용할 수 있습니다. 사전 훈련은 모델이 유용한 지식을 습득하고 작은 데이터셋에 대한 훈련을 줄여줌으로써, 하위 작업에서 더 나은 성능과 빠른 수렴을 이끌어냅니다.


 따라서 대규모 데이터를 통해 언어에 대한 사전 지식을 쌓는 과정으로 BERT에선 Unsupervised Task인 Masked Language model(MLM)과 Next Sentence Prediction(NSP)를 수행하게 된다. (흔히 풀고자하는 분류나 회귀문제가 아니라는 뜻이다.)

Why Pre-training?

  1. 데이터 희소성 보완
    작은 데이터셋에서는 모델을 충분히 훈련시키기 어려운 경우가 많습니다. 사전 훈련을 통해 모델이 데이터 희소성 문제를 극복하고 효과적인 표현을 습득할 수 있습니다.
  2. 자원 절약
    사전 훈련을 통해 모델의 초기 학습을 단축시키고 성능을 향상시킬 수 있으므로, 시간과 자원을 절약할 수 있습니다.
  3. 전이 학습
    사전 훈련된 모델을 다른 작업에 적용하는 것을 전이 학습이라고 합니다. 이는 초기 훈련 단계에서도 빠르게 수렴하게 하며, 새로운 작업에 적합한 표현을 만들어 줍니다. (ex. 리뷰 긍/부정 분류)
  4. 일반적인 특징 학습
    사전 훈련은 모델이 대규모 데이터에서 일반적인 언어 또는 패턴의 특징을 학습하도록 도와줍니다. 이는 다양한 작업에 유용한 범용 표현을 제공합니다.

How Pre-training?

  1. MLM (Masked Language model)
    기존의 RNN같은 방식들은 Unidirectional하게 훈련을 했으므로 Bidirectional하게 훈련하고자 하는 의미에서 수행되는 Task이다. Input이 주어지면 해당 문장의 일부분을 $[MASK]$ 토큰으로 바꾸고, 다른 단어들을 보며 해당 Mask토큰이 무엇일지 마지막 hidden vector를 거쳐 softmax로 들어가 어떤 단어를 출력하는 방식입니다(전체 단어들의 15%이며 이중 80%는 $[MASK]$토큰이며 10%는 랜덤한 단어 그리고 10%는 원본). 이때, Label은 원본 Token이지만 여느 Downstram Task처럼 Label data가 따로 필요없기 때문에 Unsupervised training이다.
  2. NSP (Next Sentence Prediction)
    NLP의 Question Answering (QA) and Natural Language Inference(NLI)와 같은 task에서 두 문장 간의 relationship을 파악하는 것이 매우 중요합니다. BERT는 두 문장이 연결되어 있던 문장인지 예측하는 next sentence prediction을 학습하여 문장 간의 relationship을 파악할 수 있도록 pre-training합니다. 학습을 위해 50%는 연결된 문장, 50%는 랜덤하게 뽑힌 문장으로 학습합니다.

Which point relate to Init_weight?

Hugging Face의 Transformer 라이브러리를 사용하게 되면 사람들의 다양한 사전훈련 모델을 불러올 수 있다. 하지만 우리는 NN(Neural Network)를 훈련하다 보면 모든 파라미터를 Initialize 해야한다. transformers.AutoModel.from_pretrained("bert-base-uncased")를 불러오게 되면 자동으로 init을 해주는데 (말도안되는 의문일지 모르겟지만?) "사전 학습이 된 Weight를 불러오는데 Init을 하게되면 무슨의미가 있나?"라는 생각이 들었다.

 

결론부터 말하면, 원하는 모델 구조를 만들어 두고 weight init을 한 후에 사전학습 weight를 맞는 각 레이어에 overwrite(?)합니다. 예를 들어 분류모델을 하고 싶을 때 transformers.AutoModelForClassfication.from_pretrained("bert-base-uncased")로 모델을 불러온다 하면 BERT Model(output dim = 768) + Pooler Layer (output = 분류 갯수)이 될 것입니다. 따라서 BERT Model에는 사전학습 가중치가 덮어씌워지고 Pooler Layer에는 init_weight에 의한 모델 가중치 초기화가 이루어져 있습니다.


Reference

728x90

HuggingFace

 우리가 우리 입맛에 맞게 변동 시킬 수 있는 부분 3가지 중 가장 처음으로 고려해야할 Tokenizer를 알아보려고 한다.

  1. Tokenizer
  2. Embedding
  3. Classifier Layer

 Bert base모델의 tokenizer를 불러와서 그냥 깡으로 확인을 해보면 다음과 같다.

tokenizer

#PreTrainedTokenizerFast(name_or_path='bert-base-cased', vocab_size=28996, model_max_len=512, 
#is_fast=True, padding_side='right', truncation_side='right', 
#special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 
#				'cls_token': '[CLS]', 'mask_token': '[MASK]'})

 custom을 하기 전에 BERT만 보고서는 알 수 없는 단어들이 있다. padding과 truncation이다.

Padding

 우선 패딩을 실험해서 결과를 보자면 다음과 같다.

#CLS token은 : 101, PAD token은 : 0, MASK token은:103

 Tokenizer에 문장을 Feeding했을 경우 CLS, MASK 토큰이 자동적으로 치환이 되며, max_length가 문장보다 더 길 경우 PAD 토큰인 0으로 20만큼 채워주는 것으로 확인할 수 있다. 

기본 Tokenizer에서 출력된 값을 확인했을 땐, right이란 뜻은 padding이 되었을 때 문장끝의 오른쪽에 패딩토큰을 넣는 것으로도 확인이 된다.

Truncation

 Truncation같은 경우 해석을 하자면 문장이 짤리는 것이다. 즉, max_length보다 클 경우 자동적으로 잘라 준다는 것이다. 이번 실험엔 max_length를 5로 주면 다음과 같이 출력된다.

 계산대로라면 "France" 단어만 짤려야하는데 the부터 짤린 이유는 padding에서와 같이 cls과 sep토큰을 자동적으로 치환해주기 때문이다. 따라서 max_length-2개만큼 고려를 했다는 뜻이다. 

 그렇다면 "padding은 데이터 손실이 없지만 truncation은 데이터 손실이 일어나지 않는가?"라는 질문이 있을 수 있다. 그걸 고려하여 overflowing_token이라는 함수를 HuggingFace에서 만들어놨다(역시 갓깅페이스;).

 다음과 같이 짤린 갯수만큼 줄줄이 소세지로 반환받는 것을 확인할 수 있다.

'AI > Models' 카테고리의 다른 글

Pre-training과 init_weight  (0) 2023.08.18
HuggingFace 모델 A to Z (1) - 기본 구조와 흐름  (0) 2022.11.29
[NLP] Transformer - self-Attention  (1) 2022.10.06
728x90

HuggingFace

Condition : Model : "bert-base-cased", Sentence : "Paris is the [MASK] of France."

 

다양한 Task와 실험을 하기 위해 기본 BERT모델을 어떻게 사용하는지 내맘대로 무식하게 알아 보았다.

우선 BERT의 기본 구조는 다음과 같다.

 Sentence를 받아 Tokenize하여 Embedding하여 BERT의 Attention모듈에 넣어준다. 그것을 "bert-base-cased"모델 기준으로 12개를 걸쳐 Task에 맞게 Layer로 뽑아내는 것이 전체적인 흐름이다. 

 따라서 우리가 우리 입맛에 맞게 변동 시킬 수 있는 부분은 총 3가지라는 것이다. 

  1. Tokenizer
  2. Embedding
  3. Classifier Layer

위 3가지 모두 차례대로 무식하게 분해해서 분석할 것이지만 지금은 큰 흐름을 파악하고 넘어가기 위해 내일의 나에게 책임을 전가하겠다.

Tokenizer로 Embedding 벡터를 만들어 줄 때 필요한 요소는 다음과 같다.

Token Embeddings, Segment Embeddings, Position Embeddings 총 3가지이다. 하지만 transformer 라이브러리 중 Tokenzier를 통해 나오는 인자들은 다음과 같다.

input_ids, token_type_ids, attention_mask이다. 각각이 무엇을 의미하는 지는 또다시 내일의 내가 책임지겠다. 우선 이렇게 변형 후 모델 인풋값으로 넣어주면 된다.

 

모델 선언은 다음과 같이 하면 모델의 구조를 파악할 수 있다.

뭐가 엄청 많아보이지만 사실 크게 3가지 레이어로 구성되어 있다.

  1. embeddings
  2. encoder(12개)
  3. pooler

임베딩을 거쳐 12개의 BERT Attention Encoder를 지나 Pooler layer를 거치게 되면 어떤 Task인지 간 사용가능한 Last Hidden State 벡터값이 나오게 된다!

'AI > Models' 카테고리의 다른 글

Pre-training과 init_weight  (0) 2023.08.18
HuggingFace 모델 A to Z (2) - Tokenizer  (2) 2023.01.19
[NLP] Transformer - self-Attention  (1) 2022.10.06
728x90

Sequence2 Sequence라는 task를 다룰 때, 입출력의 도메인과 사이즈를 다르게 하고 싶을 땐 재귀적인 구조를 가진 RNN으로 표현하기는 매우 힘들다. 그렇다고 RNN구조를 사용하지 않기엔 Sequence가 가지고 있는 순차적인 연관성을 무시할 순 없다. 두 성질을 전부 반영하기 위해 Attention 구조를 활용한 모델이 Transformer이다. 

 

논문 "Attention is all you need"에서 발표한 모델 구조에 따르면 기존 Sequence2 Sequence모델처럼 인코더 to 디코더 모델을 따르지만 인코더 내부가 Attention구조를 따르기 때문에 핵심적으로 봐야 하는 부분은 Self-attention 작동원리이다.

 

1. Encoder

우선 인코더는 RNN처럼 단어 하나하나를 받는 것이 아닌 문장이 가지고 있는 N개의 단어가 한 번에 입력된다.

그렇다면, N개의 단어가 어떻게 처리되는지를 봐야 한다. 기본적으로 Encoder 내부는 N개의 데이터가 한 번에 Self-Attention을 통해 Feed Forward Network로 N개의 Z(출력 값)을 반환한다. 

그림 1. Encoder 내부

그렇다면 self-attention은 어떤식으로 연산이 될까?

self-attetnion

우선 연산과정을 살펴보기 전 왜 해야하는지에 대한 설명이 살짝 첨가되야할 것 같다.

RNN의 연산과정 같은 경우 Cell의 재귀를 통해 하나씩 차례대로 이전 정보를 반영하는 구조인데, 지금은 N개의 단어가 한 번에 input이 되는 상황이므로 이전 정보를 반영할 방법을 찾다 발견한 것이 attention기법이다. 따라서 단어 간의 관련성이나 단어의 위치 정보 등을 반영하기 위한 과정이라고 생각하면 편하다.

 

그럼 연산과정을 차례대로 파헤쳐보면 단어 벡터들에 대한 Query, Key, Value를 얻기 위해 Weight벡터에 행렬곱을 하여 Query, Key, Value (이하 Q, K, V) 값을 산출한다. 이때, 주의할 점은 Q와 K의 벡터는 차원이 동일해야 하고 (이는 계산하면서 차근차근 설명) V의 벡터는 크기 상관없지만 코딩이나 계산 구조 편의상 엔간하면 동일시한다.

*여기서 가중치행렬 W는 처음에 임의의 값을 가지며, 학습 과정에서 촤적값을 얻는다.

* 학습을 통해 최적의 가중치 행렬값이 생성되면 더욱 정확한 Q, K, V를 얻게 되는 구조다.

 

Q, K, V 값을 구했다면 Q, K를 통해 단어 간 관련 정도를 파악하기 위해 다음과 같이 스케일드 닷 프로덕트(Scaled dot-product) 연산을 시행한다. 이때, 차원의 제곱근으로 나눠주는 이유는 내적의 크기를 대폭 줄여주기 위함이다. 

 

여기까지 연산이 끝났으면 사실 self-attention 과정은 거의 끝났다. 다음은 단어별 V를 통해 Z를 연산하기 위해 Softmax를 통해 Attention을 구한다.


Reference 

http://jalammar.github.io/illustrated-transformer/

https://wikidocs.net/31379

'AI > Models' 카테고리의 다른 글

Pre-training과 init_weight  (0) 2023.08.18
HuggingFace 모델 A to Z (2) - Tokenizer  (2) 2023.01.19
HuggingFace 모델 A to Z (1) - 기본 구조와 흐름  (0) 2022.11.29

+ Recent posts