안녕하세요! 글또 8기 AI 연구 채널의 최민주 입니다 🙋🏻♀️
지난 NMT 시리즈에서 NMT 학습용 데이터셋을 구축하기 위해 고려할 점에 대해 간단히 이야기하였습니다.
이번 글에서는 구축된 데이터셋의 완성도를 높이기 위한 방법 중 PCF (Parallel Corpus Filtering) 에 주목하여
가장 기본적이고 간단한 PCF 기법 몇 가지를 소개하겠습니다.
기계번역 모델을 학습할 때에는 1:1 로 매칭된 문장 쌍을 이용하는데요,
바로 이 1:1 문장 쌍을 모아서 만든 데이터셋이 Parallel Corpus 이고,
PCF는 Parallel Corpus Filtering, 한국어로 '병렬 코퍼스 필터링' 이라 부르며
정제와 다르게 학습 데이터에 부합하지 않다고 판단되면 문장 쌍을 모두 삭제하는 필터링 방식입니다.
이 글에서는 '언어의 종류에 상관없이 일괄적으로 적용 가능한 방법' 만을 소개합니다.
(LASER 의 경우 지원하는 언어가 200개 이상이므로 대부분의 언어에 적용 가능하여 이번 시리즈에서 소개합니다.)
*예시 코드는 제 GitHub 에서 참고하실 수 있습니다.
Simple is the Best
가장 간단하면서도 강력한 방법이며, 데이터셋 정제(필터링), 전처리 과정에서 꼭 필요한 작업입니다.
가장 기본적이면서도 필수적인 방법으로 문장 길이가 일정 범위 이내인 문장 쌍만 남기는 방법이 있습니다.
문장 길이 기준 필터링을 응용하여 문장 길이 비율을 기준으로 필터링할 수도 있습니다.
Meta AI (구 Facebook AI) 에서는 'm2m-100' 다국어 번역 모델 학습 데이터셋을 구축하는 과정에서
다음과 같은 필터링 기준을 적용하였으니 참고하시면 좋겠습니다.
더욱 세밀한 Rule-base 필터링이 필요한 경우 다음 필터링 기준도 참고할 수 있습니다.
(출처 : 병렬 코퍼스 필터링과 한국어에 최적화된 서브 워드 분절 기법을 이용한 기계번역)
필터링 이외에 추가로 제각각인 데이터를 통일하여 데이터셋을 정제할 수도 있는데요,
같은 모양의 글자를 서로 다른 코드로 표현이 가능할 때 이를 하나의 코드로 정규화합니다.
https://arxiv.org/abs/2010.11125
https://koreascience.kr/article/CFKO201930060758842.pdf
학습된 번역기와 평가 지표를 이용하는 손쉬운 필터링 방법
Source - Target - MT 3개의 언어 쌍 (Triplet) 데이터셋이 존재할 때 적용 가능한 방법입니다.
BLEU는 기계 번역 결과(MT)와 사람이 직접 번역한 결과(Target)가 얼마나 유사한지 비교하여 번역에 대한 성능을 측정하는 대표적인 방법입니다.
(번역 이외에도 Style Transfer 등 다른 Task 에서도 이용하는 평가 지표입니다.)
BLEU 의 장단점은 다음과 같습니다.
MT와 Target 문장의 유사도를 측정하기 위해 N-gram 을 이용하는데요,
문장을 구성하는 단어들을 N-gram으로 만들고, 그 N-gram들이 서로 얼마나 매칭되는지를 보는 식으로 구성되며, 보통 3~4-gram까지 진행됩니다.
먼저 N-gram은 문장을 어떤 단위로 분할했을 때 인접한 N 개를 모은 것을 의미합니다.
간단하게 띄어쓰기를 단위로 한 3-gram을 구하면 다음과 같습니다.
예) 집에 가고 싶다'
3-gram: 'I want to', 'want to go', 'to go home'
(이렇게 문장을 쪼개는 이유는 문장 간의 유사도를 측정할 때 문장의 일부로서 매칭을 해보기 위함입니다.)
BLEU score 를 이용하여 문장 쌍을 필터링하는 가장 간단한 방법으로
1. MT - Target 문장 간 BLEU score 를 계산하고,
2. BLEU score 범위가 0~100, 숫자가 클수록 번역 모델의 성능이 좋은 점,
다시 말해 두 문장의 유사도가 높음을 이용하여 특정 score 이상인 문장 쌍만 남기는 방법이 있습니다.
다만 이 경우는 데이터셋이 클수록 각각의 문장 쌍 당 BLEU score 를 계산하는 데에 시간이 오래 걸리므로
대규모 데이터셋 (문장 쌍 천만개 이상) 을 반복적으로 필터링할 때에는 그다지 추천하고 싶지 않고
문법 구조, 유의어 등을 고려할 수 없는 BLEU 의 단점 때문에 BLEU score 를 온전히 신뢰할 수 없으므로
다른 필터링 방법을 함께 이용하는 것을 추천하고 싶습니다.
또한 이 방법은 이미 학습된 번역 모델이 없으면 MT 데이터를 얻을 수 없어 적용이 불가능합니다.
개인적인 견해로 데이터셋 구축 과정에서 Back-Translation 을 이용하면 source - MT - target 모두 얻을 수 있는데,
이렇게 얻은 Triplet 에 바로 BLEU score 를 계산하여 필터링하면 효율적일 것이라 생각합니다.
Target 과 MT 문장의 BLEU score 를 측정해 보겠습니다.
NLTK 및 MOSES 라이브러리에서 BLEU score 를 측정하는 모듈을 제공하지만
예제에서는 WMT 에서 평가 지표로 쓰이는 SacreBLEU 를 이용하겠습니다.
import sacrebleu
# Target
refs = ["I want to go home"]
# MT (Generated by a MT model)
candis = ["I want to go"]
bleu = sacrebleu.corpus_bleu(candis, [refs]).score
측정 결과는 다음과 같으며, 각각의 문장 쌍에 BLEU score 를 계산한 후
score 가 70점 이상인 문장 쌍만 남기는 형태로 필터링이 가능합니다.
(BLEU)
https://wikidocs.net/31695
(BLEU & N-gram)
https://tech.kakaoenterprise.com/50
(SacreBleu)
https://github.com/mjpost/sacrebleu
(SacreBleu in Python)
https://github.com/isi-nlp/sacrebleu
앞서 BLEU score 를 이용하는 방법으로는 문법 구조, 유의어를 고려할 수 없다고 설명하였고,
이미 학습된 번역 모델이 없으면 적용 불가능하다는 점도 함께 언급하였습니다.
그렇다면, 각 언어의 문법 구조나 유의어에 크게 구애받지 않으면서
학습된 번역 모델 없이도 두 문장의 유사도를 얻을 수 있는 방법은 없을까요?
해답은 '다국어 문장 임베딩' 입니다.
딥러닝을 이용해 사전 학습된 다국어 임베딩 모델을 이용하면 코드 몇 줄만으로
다양한 언어 문장 쌍 간의 유사도를 구할 수 있습니다.
딥러닝을 이용한 다국어 문장 임베딩 계산
2020년 Fasebook AI 에서 다국어 문장 임베딩을 계산하는 라이브러리 'LASER' 를 발표했습니다.
LASER는 각 언어에 대해 별도의 모델을 사용하지 않고, 하나의 모델을 이용해 모든 언어를 하나의 shared space 에 join 시킵니다.
(= 다국어 문장을 고차원 공간의 한 지점에 매핑합니다.)
현재 LASER2 를 거쳐 LASER3 까지 발표되었으며, 사용 가능한 언어가 지속적으로 추가되었습니다.
LASER 를 이용해 원문, 번역문 각각 임베딩 벡터를 구한 후, 두 벡터의 유사도를 구하는 예제입니다.
유사도를 계산하는 방법으로 가장 기본적인 코사인 유사도를 사용하였습니다.
from laserembeddings import Laser
laser = Laser()
src = "집에 가고 싶다"
tgt = "I want to go home"
# Get embedding vector of sentences
src_embed = laser.embed_sentences(src, lang='ko')
tgt_embed = laser.embed_sentences(tgt, lang='en')
import numpy as np
# Get cosine similarity between 2 vectors
def cosine_similarity(v1, v2):
n1 = np.linalg.norm(v1)
n2 = np.linalg.norm(v2)
return np.dot(v1, v2.T).squeeze() / n1 / n2
# Get cosine similarity score between src, tgt embeddings
cs_score = cosine_similarity(src_embed, tgt_embed)
동일한 방법으로 여러 번역 쌍의 유사도를 구한 뒤
유사도가 (예를 들어) 0.7 이상인 번역 쌍만 남기는 방법으로 필터링할 수 있습니다.
(LASER 임베딩 벡터 구하기)
https://github.com/yannvgn/laserembeddings
이번 글에서 1:1 문장 쌍으로 구성된 Parallel Corpus 를 필터링하는 방법에 대해 몇 가지 방법을 소개하였는데요,
그렇다면 관점을 바꿔서 이미 구축된 1:1 데이터셋을 필터링하여 클린한 데이터셋을 만드는 것에 그치지 않고
처음 데이터셋을 구축할 때부터 최대한 클린한 초기 데이터셋을 만드는 방법은 없을까요?
보통 데이터셋을 구축할 때 2개 이상의 언어로 쓰여진 웹사이트(특히 뉴스 사이트)를 크롤링하거나 문서 파일을 파싱하여 구축하곤 하는데요,
보통은 문장 단위로 1:1 매칭이 되어있지 않고 단락(Paragraph) 내지 글 (Article) 단위로 매칭이 되어 있습니다.
따라서 단락/글 단위로 언어 쌍이 매칭되어 있는 raw dataset 으로부터 문장을 추출한 뒤
뜻이 맞는 문장끼리 짝을 지어 주어야 하는데, 다시 말해 문장 단위로 정렬(Align)을 해 줘야 합니다.
(Align 작업에는 이 글에서 언급한 BLEU 와 LASER 도 사용됩니다.
BLEU Align, LASER + FAISS 또는 VecAlign...)
추후에 Align 라이브러리들의 종류와 사용법도 정리해 보겠습니다. 👩🏻💻