MonaCat技術ブログ

主にDeep Learningの話をします

今更聞けない評価尺度BLEUの概要と実装(Python)

  • この記事の内容
    • BLEUを数式ベースで解説する
    • BLEUをPythonで実装する方法を解説する

BLEU概要

BLEUは最も有名な自動評価尺度です。自然言語処理ではシステムの質を人手で評価することも多々ありますが、人手評価は基準が必ずしも明確ではなく膨大なコストが必要であるため、多くの研究自動評価尺度が用いられています。

BLEUは『出力文と参照文(機械翻訳であればプロが翻訳した文章)が似ているほどシステムが優れている』と判断します。

$$BLUE=BP\cdot \exp(\sum_{n=1}^Nw_n\log p_n)$$

$$p_n=\frac{\sum _ {C\in{Candidates}}\sum _ {ngram\in C}Count _ {clip}(ngram)}{\sum _ {C'\in{Candidates}}\sum _ {ngram'\in C'}Count(ngram')}$$

ここで$p_n$はN-gramの適合率、BPは出力文が正解より短い場合に掛けるペナルティ項です。

また、$\sum _ {ngram \in C}Count _ {clip}(ngram)$は出力文と参照文で一致するN-gram数、$\sum_{ngram'\in C'}Count(ngram')$は出力文の全てのN-gram数です。

ペナルティを課す理由は単純です。$p_n$の分母は出力文の全てのN-gram数であるため、一致している可能性の高い単語のみで短文を生成すればスコアが上昇するはずですね。しかし例えば機械翻訳においてそのような出力文を生成することは理想的なのでしょうか。

このように、間違った最適化をしないようにペナルティを課しています。


\begin{equation} BP = \left \{ \begin{array}{l} 1 & if  c > r \\ e^{(1-r/c)} & if  c \leq r \\ \end{array} \right. \end{equation}

$w_n$は$p_n$に対する重みで、$\sum_{n=1}^Nw_n=1$となるように設定します。通常は単純な形式である$w_n=\frac{1}{N}$で使われるようです。

計算例

数式だけ見るとわかりにくいので、適当な例を考えてみます。

  • 参照文:Alice speak English
  • 出力文:Alice was speaking English yesterday

まず、今回は出力文の方が長いのでペナルティはありません。そのため$BP=1.0$です。

$p_1$を考えると単語1-gram(unigram)の一致数なので$p_n=\frac{2}{5}$となります(Alice, Englishの2単語が一致していますね)。

実装

BLEUの実装は、nltkを使えば簡単です。以下にサンプルコードを掲載します。コードは執筆時点でWindows10+Anacondaの環境で動作確認しました。

from nltk.translate.bleu_score import sentence_bleu

reference = [['Alice', 'speak', 'English']]
candidate = ['Alice', 'was', 'speaking', 'English', 'yesterday']

unigram = sentence_bleu(reference, candidate, weights=(1, 0, 0, 0))
bigram = sentence_bleu(reference, candidate, weights=(0, 1, 0, 0))

print('unigram:{}'.format(unigram))
print('bigram:{}'.format(bigram))

コードからわかるように、weightsを変更することで求めたいN-gramを選択できます。また、weightsは$[1,0]$ではなく累積スコアでも計算できます。今回は例を単純にするためにunigram, bigramのみを使用しています。詳細は下記の参考ページが役立つでしょう。

実行結果は以下の通りです。

unigram:0.4
bigram:2.2250738585072626e-308

unigramでは一致している単語がありますが、bigramでは一致していません。そのためbigramの実行結果がおかしい値になっています。

実際は$P_n\neq0$という前提のもと最大となるNを使用するため、このような問題は起きないでしょう。

なお、元論文では$N=4$としていますね。

動かないときは

当然ですがnltkがなければ動きません。Anacondaであれば

conda install nltk

でnltkをインストールしてください。

参考