[개발이야기#06] 트랜스포머 모델을 활용한 '영 -> 한' 번역하기 (3) 학습을 통한 모델(번역기) 생성
글 작성일: 2024년 9월 23일 (월)
안녕하세요. 요거트 @yoghurty 입니다!
파이썬/인공지능 공부를 위해
트랜스포머 모델을 이용한 영문을 한글로 번역할 수 있는 (간단한)번역기를 직접 만들어 보고 있습니다.
이를 위해 제가 참고하는 글은 다음의 두 가지입니다.
- [개발이야기#017] 파이썬/인공지능 영어를 한글로 번역해보자. - 트랜스포머모델 두번째
- 친절한 영어-한국어 번역기 만들기 A Gentle Introduction to Creating an English-to-Korean translator with Transformers
'영->한' 번역하기 프로젝트로 계획된 총 4회 중 오늘은 3번째 - 학습을 통한 모델(번역기) 생성 입니다.
(1회차) 학습용 데이터 셋 준비
👉 [개발이야기#03] 파이썬/인공지능- 트랜스포머 모델을 활용한 '영 -> 한' 번역하기 (1) 학습용 데이터셋 준비(feat. 가야태자님)
(2회차) 컴퓨터가 학습을 할 수 있도록 학습용 데이터 사전 작업(토크나이징, tokenizing)
👉 [개발이야기#05] 파이썬/인공지능- 트랜스포머 모델을 활용한 '영 -> 한' 번역하기 (2) 데이터 사전 작업-토크나이징
(3회차) 학습을 통한 모델(번역기) 생성
(4회차) 생성된 번역기를 이용한 영문->한글 번역 테스트
가상환경(engtokor) 구동 및 필요 패키지 설치
영문을 한글로 번역하기 위한 프로젝트 진행을 위해 지난시간-(1)회차-에 생성한 콘다 가상환경 engtokor 을 구동시켜 줍니다.
conda activate engtokor
학습을 통한 모델(번역기) 생성하기
이번에 모델을 학습시키는 과정을 대략 7개의 세부 과정으로 나누어 설명드립니다.
- 영->한 번역기를 만들기 위한 모델 얻어오기
- 모델에 학습용데이터(문제와 정답) 공급을 위한 준비하기
- 학습이 잘되는지 판단하기 위한 평가 도구 준비하기
- 학습 가이드 준비하기
- 트레이너(학습기) 준비하기
- 트레이너(학습기) 작동시키기 -> 학습하기!!!
- 학습결과(훈련된 모델) 저장하기
1. 영->한 번역기를 만들기 위한 모델 얻어오기
맨땅에 헤딩하는 것은 아니고, 기존에 선학습 모델을 이용하여 우리가 원하는 내용을 추가 학습시킵니다. 기존 모델을 사용자화(커스터마이징) 한다고 보셔도 좋을 것 같네요! ^^
AutoModelForSeq2SeqLM를 사용해서 선학습 모델을 불러오면
선학습된 T5모델 마지막에 파인튜닝할 수 있는 분류 헤드를 붙인 모델을 반환합니다.
model = AutoModelForSeq2SeqLM.from_pretrained(model_ckpt).to(device)
2. 모델에 학습용데이터(문제와 정답) 공급을 위한 준비하기
머신러닝을 위해서는 기계가 학습을 해야 하는데,
학습시키기 위해서는 문제와 정답을 함께 알려줍니다.
학교 다닐때 수학 문제집 풀던 생각해보시면 될 것 같아요.
앞쪽에서 문제 풀고, 뒤쪽에 답안지 보면서, 맞게 풀었나 확인하고, 잘 이해 안되면 풀이과정 보면서(이거 봐도 이해 안되긴 마찬가지!지만 ㅋㅋ) 공부한다고 했었죠? 수능시험지가 아닌 다음에야 일반 문제집에는 늘 답지가 함께 있습니다. 정답이 있어야 그것 보면서 공부... ㅋ
우리도 기계에게 공부시키기 위해서 문제와 답지를 함께 제공합니다. ^^
1번에서 준비한 모델이 우리가 준비한 자료를 이용해서 잘 학습할 수 있도록 학습용 데이터(문제, 정답)을 전달하는 데이터 공급기를 준비해 줍니다.
data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
3. 학습이 잘되는지 판단하기 위한 평가 도구 준비 하기
학교 다닐때 수업시간에 배운 내용을 얼마나 잘 이해했는지 평가하는 방법으로 기말시험을 보곤하죠?
좀 더 크게 보면, 수능시험 같은 것... 얼마나 학습을 잘했는지 평가하는 방법 중의 하나죠.
이 모델이 얼마나 잘 학습하고 있는지 알아야
우리가 이 모델에 계속 공부시켜야 할지 말지 결정할 수 있기 때문에(우리애를 이 학원에 계속 보내야 하나 말아야 하나? ),
수능 문제지 같은 평가 도구도 준비해 줍니다.
즉, 모델이 얼마나 학습을 잘하고 있는지 평가하는 도구 (학습모델을 측정할 매트릭)를 준비합니다.
metric = evaluate.load("sacrebleu")
4. 학습 가이드 준비하기
기계에게 공부시키려니 손이 좀 많이 가네요. ㅎ
학습을 할때 어떻게 학습을 하면 좋을지, 그 가이드라인을 알려줍니다.
이건 공부시키는 사람 마음이겠죠?
training_args 라는 변수를 이용해서 우리가 모델을 학습시킬때 기계가 알아야할 각종 수치와 방법을 사전에 정해 줍니다.
training_args = Seq2SeqTrainingArguments(
output_dir="chkpt",
learning_rate=0.0005,
weight_decay=0.01,
per_device_train_batch_size=64,
per_device_eval_batch_size=128,
num_train_epochs=1,
save_steps=500,
save_total_limit=2,
eval_strategy="epoch",
logging_strategy="no", predict_with_generate=True,
fp16=False, gradient_accumulation_steps=2,
report_to="none"
)
5. 트레이너(학습기) 준비하기
자~ 이제 트레이너(과외선생님?)를 수소문해서 우리가 이제까지 준비했던 내용들을 알려줍니다.
조금 억지스러운(?) 느낌은 있지만 이해를 돕기위해... 😅
과외 선생님을 불러서, 공부해야할 학생, 학생을 어떻게 과외시킬지에 대한 부모님 방침, 문제집 등을 전달해 주는 것으로 비유를 해볼 수 있을 것 같습니다. ㅋ
즉, 모델, 학습가이드, 데이터셋(학습용, 평가용), 데이터공급기, 토크나이저, 평가도구 등을 모아서 트레이너(학습기)를 생성합니다.
trainer = Seq2SeqTrainer(
model,
training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["valid"],
data_collator=data_collator,
tokenizer=tokenizer,
compute_metrics=compute_metrics,
)
6. 트레이너(학습기) 작동시키기 -> 학습하기!!!
다 됬습니다!
이제 학습 들어가면 됩니다.
트레이너를 가동 시킵니다.
(과외 선생님 불러옵니다! 엥? 방문과외?? 우리애를 학원/혹은 과외선생님에게 보내는 것도 가능!합니다 ^^;)
trainer.train()
아... 그런데, 이거, 학습하는데 시간 꽤 걸립니다.
Virtual Box 위에 올린 우분투에서 학습시켰는데, 잘 안됩니다. ㅠㅠ
아무래도 로컬PC의 가상OS 환경에서는 학습이 곤란한 것 같습니다.
그래서 저는 결국 다른 PC에서 학습시켰습니다.
7. 학습결과(훈련된 모델) 저장하기
트레이너를 통해 학습한 결과를 저장합니다.
힘들게 공부했는데, 전원 껏다고 공부한거 다 날라가면 억울하겠죠?
충분히 공부한 모델의 상태를 'results'라는 폴더 아래에 저장해두겠습니다.
학습된 모델만 있으면, 다시 또 학습을 안해도 되거든요. ^^
trainer.save_model("./results")
- 저의 경우 학습결과물이 저장된 resuls 폴더의 사이즈가 대략 996M 정도 되는 것 같습니다.
이것을 공유해보려고 했는데, 스팀잇에는 올릴 수 있는 방법을 잘 모르겠네요. 이거 있어야 다음 4회차 영->한 번역 실습을 할 수 있거든요~ ^^
마무리
이번 작업은
영어를 한글로 번역할 수 있는 모델(번역기)을 만들기 위해,
지난시간(2회차)에 토크나이징(tokenizing)작업으로 준비해 놓았던,
토큰화된 데이터셋(tokenized dataset)을 이용하여
트레이너를 통해 모델을 학습시켰습니다.
다음 4번째 마지막시간에는
이렇게 학습된 모델(번역기)을 이용하여
영어 문장을 한글 문장으로 번역시켜보겠습니다!
이상 요거트 였습니다!
고맙습니다~ ^^
<3회차 전체코드>
3회차 전체 코드입니다.
데이터 파일들(train.tsv, valid.tsv, test.tsv)이 있는 작업 폴더에서
이 코드를 사용하시면, 학습 가능 합니다.
(만약, 에러나면 댓글 달아주세요~ ^^)
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
from datasets import load_dataset, load_metric
import torch
import multiprocessing
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model_ckpt = "KETI-AIR/ke-t5-base"
max_token_length = 64
# dataset 읽어오기
data_files = {"train": "train.tsv", "valid": "valid.tsv", "test": "test.tsv"}
dataset = load_dataset("csv", data_files=data_files, delimiter="\t")
# Tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_ckpt)
def convert_examples_to_features(examples):
model_inputs = tokenizer(examples['en'],
text_target=examples['ko'],
max_length=max_token_length, truncation=True)
return model_inputs
NUM_CPU = multiprocessing.cpu_count()
tokenized_datasets = dataset.map(convert_examples_to_features,
batched=True,
remove_columns=dataset["train"].column_names,
num_proc=NUM_CPU)
print('\n')
print( '## 학습을 위해 기존 학습용 데이터를 토큰화된 데이터셋으로 변경하여 준비.##\n' )
####################################################################
######################## 3. modeling ###############################
####################################################################
from transformers import DataCollatorForSeq2Seq
from transformers import Seq2SeqTrainingArguments, Seq2SeqTrainer
import numpy as np
import evaluate
# AutoModelForSeq2SeqLM를 사용해서 선학습 모델을 불러오면 선학습된 T5모델 마지막에 파인튜닝할 수 있는 분류 헤드를 붙인 모델을 반환한다.
print( '### model \n' )
model = AutoModelForSeq2SeqLM.from_pretrained(model_ckpt).to(device)
# 학습기가 모델을이용하여 학습용 데이터를 잘 학습할 수 있도록 학습용데이터(문제, 정답)을 전달하는 데이터 공급기를 만들자
print( '### data_collator \n' )
data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
## 모델이 얼마나 학습을 잘하고 있는지 평가하는 도구 (학습모델을 측정할 매트릭)를 만들자
print( '### metric\n' )
metric = evaluate.load("sacrebleu")
def compute_metrics(eval_preds):
preds, labels = eval_preds
if isinstance(preds, tuple):
preds = preds[0]
decoded_preds = tokenizer.batch_decode(preds, skip_special_tokens=True)
# Replace -100 in the labels as we can't decode them.
labels = np.where(labels != -100, labels, tokenizer.pad_token_id)
decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)
# Some simple post-processing
decoded_preds = [pred.strip() for pred in decoded_preds]
decoded_labels = [[label.strip()] for label in decoded_labels]
result = metric.compute(predictions=decoded_preds, references=decoded_labels)
result = {"bleu": result["score"]}
return result
## 학습을 시키기 위해서는, 학습용데이터, 모델, 평가도구, 학습가이드(학습전략) 등이 필요!
# 어떻게 학습을 할 것인지 학습가이드를 설정한다.
print( '### training_args\n' )
training_args = Seq2SeqTrainingArguments(
output_dir="chkpt",
learning_rate=0.0005,
weight_decay=0.01,
per_device_train_batch_size=64,
per_device_eval_batch_size=128,
num_train_epochs=1,
save_steps=500,
save_total_limit=2,
eval_strategy="epoch",
#evaluation_strategy="epoch", 'evaluation_strategy' is deprecated
logging_strategy="no",
predict_with_generate=True,
fp16=False,
gradient_accumulation_steps=2,
report_to="none"
)
# 학습기에 이제까지 준비한 것들을 모은다.
# 즉, 모델, 학습가이드, 학습용데이터셋, 평가용데이터셋, 데이터공급기, 토크나이저, 평가도구
trainer = Seq2SeqTrainer(
model,
training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["valid"],
data_collator=data_collator,
tokenizer=tokenizer,
compute_metrics=compute_metrics,
)
# 학습기를 이용하여 학습을 실행시키자.
print( '## 학습 시작!##\n' )
trainer.train()
print( '## 학습 완료!##\n' )
# 학습결과를 저장한다. => 충분히 공부한 모델의 상태를 저장해둔다. 학습된 모델만 있으면, 다시 또 학습을 안해도 된다.
print( '## 학습 결과 저장!##\n' )
trainer.save_model("./results")
Upvoted! Thank you for supporting witness @jswit.
와우ㅎㅎ
지금 이거 다 독학으로 하시는거예요?? 'ㅡ';;??
이전에 관련 전공이나 관련 공부를 하신 적은 없으시구요??
그렇다면 진짜 대단하신 거 같아요 'ㅡ')b ㅎㅎ
에공~ 사실 제가 빈수레입니다. 😂
빈수레가 요란하다고...
참고한 링크에 설명들이 자세한데... 그 설명들 보고 제가 창의적(?)으로 약간의 살을 붙인 수준이거든요. ㅋ
이 글이 너무 잘되어있습니다. 다 이 글 덕분이에요!
고맙습니다! ^^;
기계에 일 시키는 건 오래 걸리고 힘들지만
한 번 해놓으면 자동화로 슈류룩 되는거 아닙니까|
한 번 잘~ 길들여놓으면~
그 담 부터는 슈루룩~ 된다고 봐야겠죠? ㅋㅋㅋ
대단하십니다. AI를 이용한 번역기 기대가 됩니다.
로컬PC에서 제한된 학습을 시킨 것이라
번역 품질은 장담 못하겠지만...
일단 '영->한' 번역까지는 가보도록 해보겠습니다~!
고맙습니다! ^^
재능이 참 많으십니다~^^
과찬이십니다. 스팀의 가치를 높일 수 있는 양질의 글을 포스팅 할 수 있도록 더욱 노력하겠습니다~! ^^