[개발이야기#06] 트랜스포머 모델을 활용한 '영 -> 한' 번역하기 (3) 학습을 통한 모델(번역기) 생성

in Korea • 한국 • KR • KO2 months ago (edited)

글 작성일: 2024년 9월 23일 (월)


안녕하세요. 요거트 @yoghurty 입니다!

파이썬/인공지능 공부를 위해
트랜스포머 모델을 이용한 영문을 한글로 번역할 수 있는 (간단한)번역기를 직접 만들어 보고 있습니다.
이를 위해 제가 참고하는 글은 다음의 두 가지입니다.

'영->한' 번역하기 프로젝트로 계획된 총 4회 중 오늘은 3번째 - 학습을 통한 모델(번역기) 생성 입니다.

(1회차) 학습용 데이터 셋 준비
👉 [개발이야기#03] 파이썬/인공지능- 트랜스포머 모델을 활용한 '영 -> 한' 번역하기 (1) 학습용 데이터셋 준비(feat. 가야태자님)

(2회차) 컴퓨터가 학습을 할 수 있도록 학습용 데이터 사전 작업(토크나이징, tokenizing)
👉 [개발이야기#05] 파이썬/인공지능- 트랜스포머 모델을 활용한 '영 -> 한' 번역하기 (2) 데이터 사전 작업-토크나이징

(3회차) 학습을 통한 모델(번역기) 생성

(4회차) 생성된 번역기를 이용한 영문->한글 번역 테스트


가상환경(engtokor) 구동 및 필요 패키지 설치


영문을 한글로 번역하기 위한 프로젝트 진행을 위해 지난시간-(1)회차-에 생성한 콘다 가상환경 engtokor 을 구동시켜 줍니다.

conda activate engtokor

학습을 통한 모델(번역기) 생성하기


이번에 모델을 학습시키는 과정을 대략 7개의 세부 과정으로 나누어 설명드립니다.

  1. 영->한 번역기를 만들기 위한 모델 얻어오기
  2. 모델에 학습용데이터(문제와 정답) 공급을 위한 준비하기
  3. 학습이 잘되는지 판단하기 위한 평가 도구 준비하기
  4. 학습 가이드 준비하기
  5. 트레이너(학습기) 준비하기
  6. 트레이너(학습기) 작동시키기 -> 학습하기!!!
  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()

1.png

아... 그런데, 이거, 학습하는데 시간 꽤 걸립니다.
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")

Sort:  

Upvoted! Thank you for supporting witness @jswit.

와우ㅎㅎ
지금 이거 다 독학으로 하시는거예요?? 'ㅡ';;??
이전에 관련 전공이나 관련 공부를 하신 적은 없으시구요??

그렇다면 진짜 대단하신 거 같아요 'ㅡ')b ㅎㅎ

에공~ 사실 제가 빈수레입니다. 😂

빈수레가 요란하다고...
참고한 링크에 설명들이 자세한데... 그 설명들 보고 제가 창의적(?)으로 약간의 살을 붙인 수준이거든요. ㅋ
이 글이 너무 잘되어있습니다. 다 이 글 덕분이에요!

  • 친절한 영어-한국어 번역기 만들기 A Gentle Introduction to Creating an English-to-Korean translator with Transformers

고맙습니다! ^^;

 2 months ago 

기계에 일 시키는 건 오래 걸리고 힘들지만
한 번 해놓으면 자동화로 슈류룩 되는거 아닙니까|

한 번 잘~ 길들여놓으면~
그 담 부터는 슈루룩~ 된다고 봐야겠죠? ㅋㅋㅋ

대단하십니다. AI를 이용한 번역기 기대가 됩니다.

로컬PC에서 제한된 학습을 시킨 것이라
번역 품질은 장담 못하겠지만...
일단 '영->한' 번역까지는 가보도록 해보겠습니다~!
고맙습니다! ^^

 2 months ago 

재능이 참 많으십니다~^^

과찬이십니다. 스팀의 가치를 높일 수 있는 양질의 글을 포스팅 할 수 있도록 더욱 노력하겠습니다~! ^^