NLTKのsentence_bleuで送出される警告について
機械翻訳などの論文を読むと評価尺度としてBLEUというものが用いられています。
NLTKやMosesといった有名な言語処理ライブラリにBLEUを計算する関数が実装されており、私のようによく知らずとも簡単に翻訳文の評価を行うことができます。
その場合、NLTKでは以下のように警告されることがあります。
UserWarning: Corpus/Sentence contains 0 counts of 4-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg)
これが発生する理由について、この記事では述べたいと思います。
sentence_bleuとcorpus_bleuの違い
pythonのライブラリであるNLTKにはbleuを計算する関数としてsentence_bleuとcorpus_bleuという2つの関数が実装されています。
ソースを読んでみるとsentence_bleuは1文をcorpus_bleuに渡しているだけなので基本的に処理自体は変わりません。
しかし、corpus_bleuで警告がでなくとも、一文ずつsentence_bleuで計算すると警告が発生してしまうことが多くあります。
この理由については、(気が向けば)別の記事で述べたいと思います。
BLEUの計算方法
BLEUの求め方は至って簡単です。
参照文(正しい翻訳)と仮定文(機械翻訳)があるとして、まずngram精度を求めます。
これはつまり、[a,b,c]と[a,d,a]があるとすれば
は
は
となるわけです。
このngram精度を使ってBLEU値は以下のように求めることができます。
ここでは考慮するngramの最大値です。NLTKでもMosesでもデフォルト値は4になっており、基本は4のようです。
また、短い文のngram精度は高くなるので、でペナルティを与えます。
計算できない
そうです、上の例におけるはになるのでとなり、計算することができないのです。
この時にNLTKから2gramの一致数が0であるためBLEUスコアが正しくない可能性があると、以下のように警告されます。
UserWarning: Corpus/Sentence contains 0 counts of 2-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg)
算出される値は何か
この警告がなされた場合でもNLTKは無理やりBLEU値を計算して出力します。
の場合、NLTKではとして計算します。
また、ngramに分割できないの場合も0として計算します(したがって、文の長さが4未満なら必ず警告が出ます)。
上の例を用いて、NLTKのsentence_bleuで計算すると
from nltk.translate import bleu_score ref = [["a", "b", "c"]] hypo = ["a", "d", "a"] print(bleu_score.sentence_bleu(ref, hypo)) """ 出力 UserWarning: Corpus/Sentence contains 0 counts of 2-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg) 0.7598356856515925 """
この値は
なので
この式は計算できないため
と同じになります。
from nltk.translate import bleu_score import math ref = [["a", "b", "c"]] hypo = ["a", "d", "a"] print("nltk:", bleu_score.sentence_bleu(ref, hypo)) print("math:", math.exp(math.log(1 / 3) / 4)) """ 出力 UserWarning: Corpus/Sentence contains 0 counts of 2-gram overlaps. BLEU scores might be undesirable; use SmoothingFunction(). warnings.warn(_msg) nltk: 0.7598356856515925 math: 0.7598356856515925 """
Mosesではどうなっているか
Mosesにはmulti-bleu.perlというプログラムが含まれており、これがbleuを計算するプログラムになっています。
上述のようなが含まれる場合、BLEU値は問答無用で0になります(警告文は出ます)。
警告を消す方法
警告を消す方法として最も簡単なものとして、sentence_bleu関数のemulate_multibleuのフラグをTrueにする方法が挙げられます。
これは、おそらくMosesのmulti-bleuと同じ動作にするフラグです(未調査)。
そのため、警告は出ませんがNLTKでもBLEU値が0になります。
from nltk.translate import bleu_score import math ref = [["a", "b", "c"]] hypo = ["a", "d", "a"] print("nltk:", bleu_score.sentence_bleu(ref, hypo, emulate_multibleu=True)) print("math:", math.exp( math.log(1/3) / 4)) """ 出力 nltk: 0.0 math: 0.7598356856515925 """
どちらが正しいのか
わかりません。
誰か詳しい方教えてくださいお願いします。