앞서 시리즈에서 번역 모델 학습용 데이터셋을 구축하였는데요,
구축한 데이터셋을 이용해 번역 모델을 만들기 위해 대표적인 오픈소스 NMT 모델 프레임워크 2가지를 소개합니다.
(2가지 프레임워크 모두 연구와 현업에서 활발하게 쓰입니다.)
각 프레임워크 사용방법은 튜토리얼로 제작하여 GitHub 에 올려두었습니다.
OpenNMT 는 2016년 12월 Harvard NLP 그룹과 SYSTRAN에서 공개한 대표적인 오픈소스 NMT 프레임워크로
번역, 언어 모델링, 요약 및 기타 많은 NLP 작업을 지원합니다.
(text generation, tagging, summarization, image to text, and speech to text...)
특히 Pytorch, Tensorflow 2.0 모두 지원하므로 개발할 때 선택의 폭이 넓습니다.
각 태스크의 전처리, 학습, 평가까지 모든 기능에 걸쳐 매우 많은 옵션을 제공하므로 공식문서를 한번 훑어보는 것을 추천드리고요,
학습에 필요한 주요 옵션은 바로 이어지는 실습에서 다루겠습니다.
실습 예제는 Pytorch 버전인 OpenNMT-py 를 이용하겠습니다.
Tensorflow 버전의 경우 OpenNMT-tf 공식 문서를 참고하시면 되는데요,
명령어 및 설정파일(config.yml) 포맷은 약간 다릅니다.
OpenNMT 설치 방법은 튜토리얼을 참고하시면 됩니다.
모델을 학습할 1:1 번역 문장 쌍 데이터셋을 준비합니다.
저는 AI Hub 에서 제공하는 '한-영 병렬 번역 말뭉치' 를 이용하겠습니다.
https://aihub.or.kr/aihubdata/data/view.do?currMenu=115&topMenu=100&aihubDataSe=realm&dataSetSn=126
데이터는 조례 항목 등 일부를 제외하고 약 160만 쌍이며, 학습을 위해 다음과 같이 나누었습니다.
각각의 source, target 문장에 Subword tokenization 을 적용합니다.
Source 와 target 각각에 맞는 tokenizer 를 적용한 뒤에 BPE 를 추가로 적용하는데
저는 언어 종류와 상관없이 tokenize + BPE 를 적용하는 수고를 덜고 한 큐에 끝내기 위해 SentencePiece 를 적용하겠습니다.
(SentencePiece 설치는 공식 깃헙 리포지토리를 참고하시면 됩니다)
SentencePiece 는 unsupervised 방식, 다시 말해 사전 학습된 tokenizer 가 아닙니다.
다시 말해 우리가 구축한 데이터셋으로 SentencePiece 모델을 학습시켜서 tokenizer 로 이용해야 한다는 뜻입니다.
따라서 다음과 같이 SentencePiece 모델을 학습시킵니다.
!spm_train --input=train.ko --model_prefix=korean --vocab_size=32000 --character_coverage=1.0
!spm_train --input=train.en --model_prefix=english --vocab_size=32000 --character_coverage=1.0
단, 데이터셋 양이 너무 많으면 SentencePiece 가 학습 중에 에러가 날 텐데요,
다음과 같이 추가 옵션을 넣어서 에러를 방지할 수 있습니다.
!spm_train --input=train.ko --model_prefix=korean --vocab_size=32000 --character_coverage=1.0 --train_extremely_large_corpus --input_sentence_size=1000000 and --shuffle_input_sentence=true
!spm_train --input=train.en --model_prefix=english --vocab_size=32000 --character_coverage=1.0 --train_extremely_large_corpus --input_sentence_size=1000000 and --shuffle_input_sentence=true
학습이 끝나면 korean.spm, korean.vocab, english.spm, english.vocab 파일이 생성됩니다.
우리는 다음 단계에서 학습된 tokenizer 모델인 '.spm' 을 이용하면 됩니다.
앞에서 만든 .spm 모델을 이용해 각 데이터셋을 tokenizing 합니다.
SentencePiece 를 적용한다고도 표현할 수 있겠네요.
SentencePiece 를 적용하면 문장의 Subword 를 분절(Segmentation) 하는 효과를 볼 수 있고
공백(" ") 은 특수한 유니코드 문자 ("▁" (U+2581)) 로 변환됩니다.
바로 이렇게요.
(Before) The comfortable machine with single-wheel suspension.
(After) ▁The ▁comfortable ▁machine ▁with ▁single - wheel ▁suspension .
Encoding 할 때에는 옵션을 -model 'spm 모델' -output '인코딩된 문장이 저장되는 파일' '원본 파일' 순으로 적어 줍니다.
!spm_encode --model korean.model --output train.ko.encoded train.ko
!spm_encode --model korean.model --output val.ko.encoded val.ko
!spm_encode --model korean.model --output test.ko.encoded test.ko
!spm_encode --model english.model --output train.en.encoded train.en
!spm_encode --model english.model --output val.en.encoded val.en
!spm_encode --model english.model --output test.en.encoded test.en
Model 학습 조건을 한 파일에 적습니다. (config.yml)
이 파일에는 데이터셋의 경로를 포함하여 학습 모델 종류, 모델의 layer 갯수 및 optimizer 등과 같이
학습에 필요한 hyper-parameter 를 적어 넣습니다.
OpenNMT 는 이 config.yml 파일을 참고하여 조건에 맞게 학습하게 되고
적어넣지 않은 학습 조건들은 default 값으로 설정됩니다.
(default 값이 궁금하다면 공식 문서를 참고해 보세요.)
# 아래 경로 및 파일명은 명시하지 않으면 경로 및 파일을 찾지 못해서 에러가 납니다.
## Where the samples will be written
save_data: data
## Where the vocab(s) will be written
src_vocab: vocab/vocab.ko
tgt_vocab: vocab/vocab.en
# Corpus opts:
data:
corpus_1:
path_src: train.ko.encoded
path_tgt: train.en.encoded
valid:
path_src: val.ko.encoded
path_tgt: val.en.encoded
# checkpoint 덮어쓰기 금지
overwrite: False
# checkpoint 최대 4개까지 저장
keep_checkpoint: 4
# 최대 3회까지 학습 후 성능 개선이 없으면 학습 종료
early_stopping: 3
# General opts
save_model: ko-en
# 학습 몇 번마다 checkpoint 저장할지
save_checkpoint_steps: 10000
# 학습 몇 step 마다 validation 수행할지
valid_steps: 10000
# 총 몇 step 까지 학습할지
train_steps: 200000
# batch size 및 accum count 를 절반 단위로 줄이면 학습 속도가 기본 단위당 2~30초 -> 8초로 대폭 단축될 수 있습니다.
# 경험상 AI Hub 와 같이 잘 필터링된 데이터는 각 사이즈를 줄여도 성능에 크게 영향을 받지 않지만
# 노이즈가 좀 있는 데이터는 성능이 크게 떨어지므로 실서비스 모델에는 사용하지 않는 것을 권장합니다.
batch_size: 2048
accum_count: [4]
# Model
encoder_type: transformer
decoder_type: transformer
enc_layers: 6
dec_layers: 6
heads: 8
rnn_size: 512
word_vec_size: 512
transformer_ff: 2048
dropout_steps: [0]
dropout: [0.1]
attention_dropout: [0.1]
# Optimization
optim: "adam"
# Single GPU (Multi-GPU 학습을 원하면 다음 gpu 옵션을 바꿔줍니다. 공식문서 참고.)
gpu_ranks: -0
...
모델 학습에 필요한 vocab 을 생성하는 단계입니다.
vocab 파일이 저장될 경로는 3-1 에서 config.yml 파일에 적어 두었고
기타 필요한 옵션을 붙일 수 있습니다.
!onmt_build_vocab -config config.yml -n_sample -1
config.yml 에 적어 둔 조건에 따라 모델을 학습합니다.
!onmt_train -config config.yml
학습된 모델에 tokenized 된 테스트 데이터를 넣어서 번역문을 만들어 봅니다.
모델이 얼마나 학습을 잘 했는지 검증하기 위함이죠.
!onmt_translate -model ko-en_step_80000.pt -src test.ko.encoded -output pred.ko-en --replace_unk --verbose --max_length=512
(원본 문장) ▁저는 ▁일요일 ▁오전 에는 ▁거의 ▁잠 만 ▁잡 니다 .
(번역 결과) ▁I ▁almost ▁sleep ▁on ▁Sunday ▁morning .
이렇게 번역한(생성한) 문장은 tokenized 된 형태이므로 다시 SentencePiece 를 이용해 decoding,
즉 detokenize 하여 정상적인 문장으로 만들어 줘야 하는데요,
detokenize 및 BLEU 를 이용한 evaluation 설명은 생략하겠습니다. (튜토리얼에는 있어요)
(100개의 test 문장 쌍에 대한 BLEU score = 35.97 나왔습니다. 준수한 성능이죠.)
(OpenNMT) https://opennmt.net/
(OpenNMT 공식문서) https://opennmt.net/OpenNMT-py/, https://opennmt.net/OpenNMT-tf/
Fairseq 은 Meta (구 Facebook) 에서 공개한 오픈소스 sequence modeling toolkit 으로,
번역, 요약,생성 등을 포함한 language modeling 기능을 제공합니다.
또한 Multi-GPU를 사용하여 빠르고 효율적인 학습을 지원하며
Meta 에서 개발한 프레임워크이므로 Pytorch 를 지원합니다.
실습 예제에 사용할 Dataset 및 서브워드 전처리는 OpenNMT 예제와 동일하므로 설명은 생략하겠습니다.
Fairseq 설치 방법은 튜토리얼을 참고하시면 됩니다.
Data pre-processing: build vocabularies and binarize training data
학습 데이터 dictionary(=vocab) 를 구축하고 바이너리로 변환합니다.
(dictionary 및 바이너리 파일은 destdir 에 저장됩니다.)
!fairseq-preprocess \
--source-lang ko \
--target-lang en \
--validpref $dir/dataset/valid \
--trainpref $dir/dataset/train \
--testpref $dir/dataset/test \
--destdir $dir/preprocess
모델을 학습하는 단계로, 필수적인 parameter 는 아래와 같이 학습 데이터 경로, 모델 종류, 학습한 모델이 저장될 위치 등등입니다.
!fairseq-train $dir/preprocess \
--source-lang ko \
--target-lang en \
--task translation \
--arch transformer \
--optimizer adam \
--save-dir "$dir/checkpoints"
validation 을 수행할 때 사용할 metric 을 지정할 수 있고,
학습 과정에서 validation 을 수행하여 가장 성능이 좋은 모델 즉 best checkpoint 모델만을 저장할 수 있는데요,
이 때 validation metric 을 지정할 수 있습니다.
만약 BLEU 를 이용한다면 다음 parameter 를 적어 주면 됩니다.
--eval-bleu \
--eval-bleu-args '{"beam": 5, "max_len_a": 1.2, "max_len_b": 10}' \
--eval-bleu-detok moses \
--eval-bleu-remove-bpe \
--eval-bleu-print-samples
학습이 끝난 번역 모델을 이용해 테스트 데이터를 번역해 봅니다.
!fairseq-generate $dir/preprocess/ \
--path $dir/checkpoints/checkpoint_best.pt \
--source-lang ko --target-lang en \
--max-sentences 100 \
--beam 5 \
--task translation \
--gen-subset test \
--skip-invalid-size-inputs-valid-test \
--batch-size 64 \
--remove-bpe sentencepiece \
--results-path prediction
테스트 파일 번역이 끝나면 지정한 경로에 'generate-test.txt' 파일이 생성되고 번역 결과가 여기에 저장됩니다.
fairseq-score
를 이용해 원본 문장과 번역 결과 간 BLEU score 를 측정할 수도 있지만
fairseq-generate
만 실행해도 생성된 generate-test.txt 파일에서 전체 BLEU score 평균을 확인할 수 있습니다.
5 epochs 만 학습했는데 BLEU score = 28.36 입니다. 나쁘지 않네요.
(원본 문장) 저는 일요일 오전에는 거의 잠만 잡니다.
(번역 결과) I sleep almost every Sunday morning.
(GitHub) https://github.com/facebookresearch/fairseq
(공식문서) https://fairseq.readthedocs.io/en/latest/
https://fairseq.readthedocs.io/en/latest/command_line_tools.html
https://rlqof7ogm.toastcdn.net/references/2021_session_20.pdf
https://github.com/matsunagadaiki151/FairseqTutorial/blob/main/FairseqTranslation.ipynb
https://github.com/Lainshower/jeju-blues/blob/main/Ko-Je%20translation/transformer_translation.ipynb
번역 태스크는 기본적으로 transformer 및 응용 모델을 이용하게 되는데,
그 이유는 번역 태스크가 encoder 를 이용해 번역할 문장으로부터 인코딩 정보를 얻고
decoder 에서 인코딩 정보를 참고하여 새로운 문장을 생성하는 작업이기 때문입니다.
(이 때문에 번역 태스크는 생성 태스크와 가까워요.
Style transfer 와 가깝기도 하고요.)
다시 말해 Transformer 뿐만이 아니라 그 응용 모델을 이용하여 NMT 를 구현할 수 있지요.
또한 번역 도메인이 좀 특수한 도메인이거나 언어 종류가 소수 언어라서 Low resource problem, 즉 학습 데이터가 적은 문제가 있는 경우
혹은 기타 필요한 경우에 사전 학습된 NMT 모델을 이용하여 목적에 맞는 번역 모델을 개발할 수 있습니다.
이 단락에서는 NMT 구현에 종종 쓰이는 몇 가지 모델 소개와 더불어
모델 학습 방법 튜토리얼, 사전 학습된 multilingual 모델의 fine-tuning 튜토리얼 참고 링크를 덧붙입니다.
Text-to-Text Transfer Transformer
T5는 구글에서 개발한 Transformer 기반 언어 모델로, 다양한 자연어 처리 태스크에서 사용할 수 있도록 설계되었습니다.
T5 모델은 입력 문장과 출력 문장을 일반적인 형태로 변환하여 모든 자연어 처리 문제를 "text-to-text" 형태로 풀도록 학습합니다. 예를 들어, 기계 번역 태스크에서는 "영어 문장을 프랑스어 문장으로 번역하기"와 같은 형태로 변환하며, 질문 응답 태스크에서는 "질문에 대한 답변 생성하기"와 같은 형태로 변환합니다.
T5 모델은 다양한 크기의 모델로 제공되며, "small", "base", "large", "3B", "11B" 등이 있습니다. 더 큰 모델은 더 많은 매개 변수를 가지며, 보다 복잡하고 정확한 자연어 처리 태스크를 수행할 수 있습니다.
T5 모델은 기계 번역, 질문 응답, 요약, 문서 생성 등 다양한 NLP 태스크에서 사용될 수 있으며, 다양한 언어에 적용할 수 있습니다.
(친절한 영어-한국어 번역기 만들기)
https://github.com/metamath1/ml-simple-works/blob/master/t5/gentle_t5_trans.ipynb
(구어체 말뭉치 & 넷플릭스 자막을 학습시켜 mT5 모델로 만든 자연스러운 번역기)
https://github.com/da-head0/mT5translator
multilingual Bidirectional Encoder Representations from Transformers
mBART는 Facebook AI Research 에서 개발한 다국어 문제에 대한 자연어 처리(NLP) 모델로, 100개 이상의 언어로 이루어진 다국어 데이터셋을 사용하여 사전 학습된 Transformer 기반 언어 모델입니다.
mBART 모델은 25개의 언어에서 높은 성능을 보여주며, zero-shot 번역 문제에서도 효과적으로 작동합니다. 즉, 이전에 본 적 없는 언어 쌍에 대해서도 번역을 수행할 수 있습니다. 이러한 성능은 mBART 모델이 모든 언어에 대해 공유된 범용 언어 모델을 사용하기 때문입니다.
mBART 모델은 기계 번역, 감성 분석, 질문 응답, 문서 분류 등 다양한 자연어 처리 태스크에서 사용될 수 있으며, 다양한 언어를 다루는 다국어 환경에서 특히 유용합니다.
특히 문장 단위로 번역하는 모델들과 달리 mBART 는 주로 특허 등의 문서 단위 번역에 사용되는 경향이 있습니다.
또한 Facebook AI Research 팀에서 개발하였으므로 Fairseq 을 이용하면 어렵지 않게 실험할 수 있습니다.
(카카오 i 번역 성능 향상 실험 : 대규모 말뭉치를 활용한 사전학습)
https://tech.kakaoenterprise.com/48
(mBART English-Japanese finetuning (Fairseq mBART fine-tuning))
https://github.com/tmramalho/finetune-mbart
잘 정리된 포스팅 감사합니다.