GPT-2는 다양한 텍스트 데이터를 학습하여 문장을 생성하는 강력한 능력을 가지고 있습니다.
이번 글에서는 GPT-2 모델을 활용한 학습 과정을 단계별로 설명하겠습니다.
1. 데이터셋 로드
GPT-2 모델을 학습시키기 위해서는 대량의 텍스트 데이터가 필요합니다.
이번 실습에서는 Hugging Face의 datasets 라이브러리를 활용하여 wikitext-2 데이터셋을 로드합니다.
!pip install datasets
from datasets import load_dataset
dataset = load_dataset("wikitext", name="wikitext-2-raw-v1")
✅ 설명
- datasets 라이브러리는 NLP 작업을 위한 다양한 데이터셋을 쉽게 가져올 수 있도록 도와줍니다.
- wikitext-2-raw-v1 데이터셋은 위키백과 텍스트 기반의 코퍼스로, 모델 학습에 적합한 데이터셋입니다.
허깅페이스에는 다양한 데이터셋이 준비되어있으니 잘 활용합시다. 😉
2. 모델 및 토크나이저 로드
GPT-2 모델을 활용하려면 사전 학습된 모델과 토크나이저를 불러와야 합니다.
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "gpt2"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
✅ 설명
- AutoModelForCausalLM.from_pretrained('gpt2'): 사전 학습된 GPT-2 모델을 불러옵니다.
- AutoTokenizer.from_pretrained('gpt2'): GPT-2 모델이 사용할 토크나이저를 불러옵니다.
🚨 주의! GPT-2에는 pad_token(패딩 토큰)이 기본적으로 없기 때문에 다음과 같이 설정해야 합니다:
tokenizer.pad_token = tokenizer.eos_token
이는 문장 끝을 의미하는 eos_token(End of Sequence Token)을 패딩 토큰으로 활용하는 방식입니다.
3. 데이터셋 토크나이징 (Tokenization)
GPT-2는 텍스트 데이터를 숫자로 변환하여 처리합니다. 이를 위해 토크나이징 함수를 정의합니다.
def tokenize_function(examples):
token = tokenizer(
examples['text'],
padding="max_length",
truncation=True,
max_length=512
)
return {
'input_ids': token['input_ids'],
'attention_mask': token['attention_mask'],
'labels': token['input_ids'] # 자기회귀 모델이므로 input_ids와 동일
}
✅ 설명
- padding="max_length": 문장의 길이를 512자로 맞춤.
- truncation=True: 길이가 512자를 초과하면 잘라냄(truncate).
- GPT-2는 자기회귀 모델이므로 labels를 input_ids와 동일하게 설정합니다.
그 후, 데이터셋에 토크나이징을 적용합니다.
dataset = dataset.map(tokenize_function)
4. 학습 데이터와 검증 데이터 분리
train_dataset = dataset['train']
test_dataset = dataset['test']
train_dataset = train_dataset.map(tokenize_function, batched=True, remove_columns=['text'])
test_dataset = test_dataset.map(tokenize_function, batched=True, remove_columns=['text'])
✅ 설명
- train_dataset: 모델 훈련을 위한 학습 데이터셋.
- test_dataset: 모델 평가를 위한 검증 데이터셋.
- remove_columns=['text']: 원본 텍스트 데이터는 필요 없으므로 제거. (텍스트 데이터는 토크나이징 처리 되었다!)
5. 학습 설정 (TrainingArguments)
from transformers import Trainer, TrainingArguments
training_args = TrainingArguments(
output_dir='./result',
evaluation_strategy='epoch',
num_train_epochs=2,
weight_decay=0.01,
per_device_train_batch_size=8,
per_device_eval_batch_size=8,
logging_dir='./logs',
save_strategy="epoch",
)
✅ 설명
- output_dir='./result': 학습된 모델을 저장할 경로.
- evaluation_strategy='epoch': 매 에포크마다 모델 평가 수행.
- num_train_epochs=2: 모델을 2번 반복 학습.
- weight_decay=0.01: 과적합 방지를 위한 가중치 감소.
- per_device_train_batch_size=8: 배치 크기를 8로 설정.
6. Trainer 객체 생성 및 학습 시작
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=test_dataset
)
trainer.train()
✅ 설명
- Trainer는 모델 학습을 쉽게 관리할 수 있도록 도와주는 Hugging Face의 도구입니다.
- trainer.train(): 모델 학습 시작.
7. 학습 후 결과 해석
# Training Loss - 학습 데이터의 에러
# Validation Loss - 테스트 데이터의 에러
# 에포크를 돌릴수록 Training Loss는 0에 가까워짐
# Validation Loss는 줄어들다가 어느 순간 증가 > 과적합 발생
✅ 과적합 해결 방법
- num_train_epochs 값을 너무 높이지 않기
- weight_decay 값을 조정하여 정규화 적용
- 데이터셋 크기를 증가시키기
Validation Loss이 줄어들다가, 어느순간 증가할 때가 최적의 모델이라고 봐도 됩니다. Early Stopping(조기 종료)
8. 모델 실행
prompt = "The future of AI is"
inputs = tokenizer(prompt, return_tensors='pt').to(model.device)
print(inputs)
print()
outputs = model.generate(**inputs)
print(outputs)
#만든 텐서(아웃풋)를 문자열로 전환 "디코드"
tokenizer.decode(outputs[0], skip_special_tokens=True)
#출력 결과
Setting pad_token_id to eos_token_id:50256 for open-end generation.
print(inputs)
{'input_ids': tensor([[ 464, 2003, 286, 9552, 318]], device='cuda:0'), 'attention_mask': tensor([[1, 1, 1, 1, 1]], device='cuda:0')}
print(outputs)
tensor([[ 464, 2003, 286, 9552, 318, 8627, 764, 383, 9552, 2055, 318, 9086, 656, 734, 11665, 1058, 883, 508, 1975, 326, 9552, 318, 257, 922, 2126]], device='cuda:0')
결과값:
'The future of AI is uncertain . The AI community is divided into two camps : those who believe that AI is a good idea'
텍스트 생성 (Text Generation) 모델이 새로운 텍스트를 만들어내는 과정
모델 추론 (Inference) 학습된 모델이 입력을 받고 결과를 생성하는 과정
디코딩 (Decoding) 모델이 만든 숫자(Tensor)를 사람이 읽을 수 있는 문장으로 변환
생성 추론 (Generative Inference) 생성 모델(GPT 등)이 출력값을 생성하는 과정
언어 모델 실행 (Running a Language Model) 언어 모델을 실행해서 결과를 받아오는 과정
📌 최종 요약
1️⃣ 데이터 로드 → Wikitext-2 데이터셋 사용.
2️⃣ 모델 및 토크나이저 로드 → GPT-2와 토크나이저 가져오기.
3️⃣ 데이터 전처리 → 텍스트를 숫자로 변환.
4️⃣ 학습 데이터 분리 → 학습 데이터 / 검증 데이터 나누기 (이데이터셋에서 미리 나눠져 있습니다)
5️⃣ 학습 설정 → Trainer와 TrainingArguments 활용.
6️⃣ 모델 학습 → trainer.train() 실행 후 결과 확인.
AutoModelForCausalLM이란?
AutoModelForCausalLM은 Hugging Face의 transformers 라이브러리에서 제공하는 "자연어 생성(Language Generation)" 모델을 자동으로 불러오는 클래스입니다.
Causal Language Modeling (CLM) 은 단어를 순차적으로 예측하는 방식
✔ 대표적인 CLM 모델:
- GPT-2 (gpt2)
- GPT-3 (gpt-neo, gpt-j, gpt-3)
- LLaMA (meta-llama)
- Falcon (falcon-7b)
- CodeGen (코드 생성 모델)
- Mistral, StarCoder 등
Hugging Face에는 다양한 AutoModel 클래스가 존재합니다.
각각 모델의 목적에 따라 적합한 클래스를 사용해야 합니다.
AutoModel 클래스역할대표적인 모델
AutoModelForCausalLM | 자연어 생성(Language Generation, CLM) | GPT-2, GPT-3, LLaMA |
AutoModelForMaskedLM | 빈칸 채우기(Masked LM, MLM) | BERT, RoBERTa |
AutoModelForSeq2SeqLM | 문장 변환 (Seq2Seq) / 번역 | T5, BART, mT5 |
AutoModelForSequenceClassification | 문장 분류(Classification) | BERT, DistilBERT |
AutoModelForTokenClassification | 개체명 인식(NER, Token-level Classification) | BERT, RoBERTa |
Causal LM과 Masked LM의 차이점
유형설명예시 모델
Causal Language Modeling (CLM) | 앞 단어를 보고 다음 단어 예측 | GPT-2, GPT-3, LLaMA |
Masked Language Modeling (MLM) | 문장에서 일부 단어를 [MASK]로 가리고 예측 | BERT, RoBERTa |
✔ Causal LM 모델(GPT 계열)은 이전 단어들을 기반으로 "새로운 단어"를 생성하는 방식입니다.
✔ 따라서 패딩(padding) 처리가 기본적으로 되어 있지 않으며, 학습 시 eos_token을 지정해 주어야 합니다.
✔ generate() 함수를 사용하여 텍스트 생성을 수행해야 합니다.