淺談用 Python 計算文本 BLEU 分數
BLEU, 全稱為 Bilingual Evaluation Understudy(雙語評估替換), 是一個比較候選文本翻譯與其他一個或多個參考翻譯的評價分數
盡管 BLEU 一開始是為翻譯工作而開發, 但它也可以被用于評估文本的質量, 這種文本是為一套自然語言處理任務而生成的
通過本教程, 你將探索 BLEU 評分, 并使用 Python 中的 NLTK 庫對候選文本進行評估和評分
完成本教程后, 你將收獲:
BLEU 評分的簡單入門介紹, 并直觀地感受到到底是什么正在被計算
如何使用 Python 中的 NLTK 庫來計算句子和文章的 BLEU 分數
如何用一系列的小例子來直觀地感受候選文本和參考文本之間的差異是如何影響最終的 BLEU 分數
讓我們開始吧
淺談用 Python 計算文本 BLEU 分數
照片由 Bernard Spragg. NZ 提供, 保留所有權
教程概述
本教程分為 4 個部分; 他們分別是:
雙語評估替換評分介紹
計算 BLEU 分數
累加和單獨的 BLEU 分數
運行示例
雙語評估替換評分
雙語評估替換分數 (簡稱 BLEU) 是一種對生成語句進行評估的指標
完美匹配的得分為 1.0, 而完全不匹配則得分為 0.0
這種評分標準是為了評估自動機器翻譯系統的預測結果而開發的盡管它還沒做到盡善盡美, 但還是具備了 5 個引人注目的優點:
計算速度快, 計算成本低
容易理解
與具體語言無關
和人類給的評估高度相關
已被廣泛采用
BLEU 評分是由 Kishore Papineni 等人在他們 2002 年的論文 BLEU: a Method for Automatic Evaluation of Machine Translation 中提出的
這種評測方法通過對候選翻譯與參考文本中的相匹配的 n 元組進行計數, 其中一元組 (稱為 1-gram 或 unigram) 比較的是每一個單詞, 而二元組 (bigram) 比較的將是每個單詞對這種比較是不管單詞順序的
BLEU 編程實現的主要任務是對候選翻譯和參考翻譯的 n 元組進行比較, 并計算相匹配的個數匹配個數與單詞的位置無關匹配個數越多, 表明候選翻譯的質量就越好
摘自論文 BLEU: a Method for Automatic Evaluation of Machine Translation,2002 年發表
n 元組匹配的計數結果會被修改, 以確保將參考文本中的單詞都考慮在內, 而不會對產生大量合理詞匯的候選翻譯進行加分在 BLEU 論文中這被稱之為修正的 n 元組精度
糟糕的是, 機器翻譯系統可能會生成過多的合理單詞, 從而導致翻譯結果不恰當, 盡管其精度高... 從直觀上這個問題是明顯的: 在識別出匹配的候選單詞之后, 相應的參考單詞應該被視為用過了我們將這種直覺定義為修正的單元組精度
摘自論文 BLEU: a Method for Automatic Evaluation of Machine Translation,2002 年發表
BLEU 評分是用來比較語句的, 但是又提出了一個能更好地對語句塊進行評分的修訂版本, 這個修訂版根據 n 元組出現的次數來使 n 元組評分正常化
我們首先逐句計算 n 元組匹配數目接下來, 我們為所有候選句子加上修剪過的 n 元組計數, 并除以測試語料庫中的候選 n 元組個數, 以計算整個測試語料庫修正后的精度分數 pn
摘自論文 BLEU: a Method for Automatic Evaluation of Machine Translation,2002 年發表
實際上, 一個完美的分數是不可能存在的, 因為這意味著翻譯必須完全符合參考甚至連人類翻譯家都不能做到這點對計算 BLEU 分數的參考文本的數量和質量的水平要求意味著在不同數據集之間的比較 BLEU 分數可能會很麻煩
BLEU 評分的范圍是從 0 到 1 很少有翻譯得分為 1, 除非它們與參考翻譯完全相同因此, 即使是一個人類翻譯, 也不一定會在一個大約 500 個句子 (也就是 40 個普通新聞報道的長度) 的測試語料上得 1 分, 一個人類翻譯在四個參考翻譯下的得分為 0.3468, 在兩個參考翻譯下的得分為 0.2571
摘自論文 BLEU: a Method for Automatic Evaluation of Machine Translation,2002 年發表
除了翻譯之外, 我們還可以將 BLEU 評分用于其他的語言生成問題, 通過使用深度學習方法, 例如:
語言生成
圖片標題生成
文本摘要
語音識別
以及更多
計算 BLEU 分數
Python 自然語言工具包庫 (NLTK) 提供了 BLEU 評分的實現, 你可以使用它來評估生成的文本, 通過與參考文本對比
語句 BLEU 分數
NLTK 提供了 sentence_bleu()函數, 用于根據一個或多個參考語句來評估候選語句
參考語句必須作為語句列表來提供, 其中每個語句是一個記號列表候選語句作為一個記號列表被提供例如:fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['this','is','a','test'],['this','is''test']]
candidate=['this','is','a','test']
score=sentence_bleu(reference,candidate)
print(score)
運行這個例子, 會輸出一個滿分, 因為候選語句完全匹配其中一個參考語句
1.0
語料庫 BLEU 分數
NLTK 還提供了一個稱為 corpus_bleu()的函數來計算多個句子 (如段落或文檔) 的 BLEU 分數
參考文本必須被指定為文檔列表, 其中每個文檔是一個參考語句列表, 并且每個可替換的參考語句也是記號列表, 也就是說文檔列表是記號列表的列表的列表候選文檔必須被指定為列表, 其中每個文件是一個記號列表, 也就是說候選文檔是記號列表的列表
這聽起來有點令人困惑; 以下是一個文檔的兩個參考文檔的例子# two references for one document
fromnltk.translate.bleu_scoreimportcorpus_bleu
references=[[['this','is','a','test'],['this','is''test']]]
candidates=[['this','is','a','test']]
score=corpus_bleu(references,candidates)
print(score)
運行這個例子就像之前一樣輸出滿分
1.0
累加和單獨的 BLEU 分數
NLTK 中提供的 BLEU 評分方法允許你在計算 BLEU 分數時為不同的 n 元組指定權重
這使你可以靈活地計算不同類型的 BLEU 分數, 如單獨和累加的 n-gram 分數
讓我們來看一下
單獨的 N-Gram 分數
單獨的 N-gram 分數是對特定順序的匹配 n 元組的評分, 例如單個單詞 (稱為 1-gram) 或單詞對(稱為 2-gram 或 bigram)
權重被指定為一個數組, 其中每個索引對應相應次序的 n 元組僅要計算 1-gram 匹配的 BLEU 分數, 你可以指定 1-gram 權重為 1, 對于 2 元, 3 元和 4 元指定權重為 0, 也就是權重為 (1,0,0,0) 例如:# 1-gram individual BLEU
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['this','is','small','test']]
candidate=['this','is','a','test']
score=sentence_bleu(reference,candidate,weights=(1,0,0,0))
print(score)
運行此例將輸出得分為 0.5
0.75
我們可以重復這個例子, 對于從 1 元到 4 元的各個 n-gram 運行語句如下所示:# n-gram individual BLEU
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['this','is','a','test']]
candidate=['this','is','a','test']
print('Individual 1-gram: %f'%sentence_bleu(reference,candidate,weights=(1,0,0,0)))
print('Individual 2-gram: %f'%sentence_bleu(reference,candidate,weights=(0,1,0,0)))
print('Individual 3-gram: %f'%sentence_bleu(reference,candidate,weights=(0,0,1,0)))
print('Individual 4-gram: %f'%sentence_bleu(reference,candidate,weights=(0,0,0,1))
運行該示例, 結果如下所示:Individual1-gram:1.000000
Individual2-gram:1.000000
Individual3-gram:1.000000
Individual4-gram:1.000000
雖然我們可以計算出單獨的 BLEU 分數, 但這并不是使用這個方法的初衷, 而且得出的分數也沒有過多的含義, 或者看起來具有說明性
累加的 N-Gram 分數
累加分數是指對從 1 到 n 的所有單獨 n-gram 分數的計算, 通過計算加權幾何平均值來對它們進行加權計算
默認情況下, sentence_bleu()和 corpus_bleu()分數計算累加的 4 元組 BLEU 分數, 也稱為 BLEU-4 分數
BLEU-4 對 1 元組, 2 元組, 3 元組和 4 元組分數的權重為 1/4(25%)或 0.25 例如:# 4-gram cumulative BLEU
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['this','is','small','test']]
candidate=['this','is','a','test']
score=sentence_bleu(reference,candidate,weights=(0.25,0.25,0.25,0.25))
print(score)
運行這個例子, 輸出下面的分數:
0.707106781187
累加的和單獨的 1 元組 BLEU 使用相同的權重, 也就是 (1,0,0,0) 計算累加的 2 元組 BLEU 分數為 1 元組和 2 元組分別賦 50%的權重, 計算累加的 3 元組 BLEU 為 1 元組, 2 元組和 3 元組分別為賦 33%的權重
讓我們通過計算 BLEU-1,BLEU-2,BLEU-3 和 BLEU-4 的累加得分來具體說明:# cumulative BLEU scores
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['this','is','small','test']]
candidate=['this','is','a','test']
print('Cumulative 1-gram: %f'%sentence_bleu(reference,candidate,weights=(1,0,0,0)))
print('Cumulative 2-gram: %f'%sentence_bleu(reference,candidate,weights=(0.5,0.5,0,0)))
print('Cumulative 3-gram: %f'%sentence_bleu(reference,candidate,weights=(0.33,0.33,0.33,0)))
print('Cumulative 4-gram: %f'%sentence_bleu(reference,candidate,weights=(0.25,0.25,0.25,0.25)))
運行該示例輸出下面的分數結果的差別很大, 比單獨的 n-gram 分數更具有表達性Cumulative1-gram:0.750000
Cumulative2-gram:0.500000
Cumulative3-gram:0.632878
Cumulative4-gram:0.707107
在描述文本生成系統的性能時, 通常會報告從 BLEU-1 到 BLEU-4 的累加分數
運行示例
在這一節中, 我們試圖通過一些例子來進一步獲取對 BLEU 評分的直覺
我們在語句層次上通過用下面的一條參考句子來說明:
the quick brown fox jumped over the lazy dog
首先, 我們來看一個完美的分數# prefect match
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['the','quick','brown','fox','jumped','over','the','lazy','dog']]
candidate=['the','quick','brown','fox','jumped','over','the','lazy','dog']
score=sentence_bleu(reference,candidate)
print(score)
運行例子輸出一個完美匹配的分數
1.0
接下來, 讓我們改變一個詞, 把 quick 改成 fast# one word different
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['the','quick','brown','fox','jumped','over','the','lazy','dog']]
candidate=['the','fast','brown','fox','jumped','over','the','lazy','dog']
score=sentence_bleu(reference,candidate)
print(score)
結果是分數略有下降
0.7506238537503395
嘗試改變兩個詞, 把 quick 改成 fast , 把 lazy 改成 sleepy# two words different
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['the','quick','brown','fox','jumped','over','the','lazy','dog']]
candidate=['the','fast','brown','fox','jumped','over','the','sleepy','dog']
score=sentence_bleu(reference,candidate)
print(score)
運行這個例子, 我們可以看到得分線性下降
0.4854917717073234
如果候選語句的所有單詞與參考語句的都不一樣呢?# all words different
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['the','quick','brown','fox','jumped','over','the','lazy','dog']]
candidate=['a','b','c','d','e','f','g','h','i']
score=sentence_bleu(reference,candidate)
print(score)
我們得到了一個更糟糕的分數
0.0
現在, 讓我們嘗試一個比參考語句的詞匯更少 (例如, 放棄最后兩個詞) 的候選語句, 但這些單詞都是正確的# shorter candidate
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['the','quick','brown','fox','jumped','over','the','lazy','dog']]
candidate=['the','quick','brown','fox','jumped','over','the']
score=sentence_bleu(reference,candidate)
print(score)
結果和之前的有兩個單詞錯誤的情況很相似
0.7514772930752859
如果我們把候選語句調整為比參考語句多兩個單詞, 那又會怎么樣?# longer candidate
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['the','quick','brown','fox','jumped','over','the','lazy','dog']]
candidate=['the','quick','brown','fox','jumped','over','the','lazy','dog','from','space']
score=sentence_bleu(reference,candidate)
print(score)
再一次, 我們可以看到, 我們的直覺是成立的, 得分還是有點像 有兩個錯字 的情況
0.7860753021519787
最后, 我們來比較一個很短的候選語句: 只有兩個單詞的長度# very short
fromnltk.translate.bleu_scoreimportsentence_bleu
reference=[['the','quick','brown','fox','jumped','over','the','lazy','dog']]
candidate=['the','quick']
score=sentence_bleu(reference,candidate)
print(score)
運行此示例首先會打印一條警告消息, 指出不能執行評估 3 元組及以上部分 (直到 4 元組) 這是合乎情理的, 因為在候選語句中我們最多只能用 2 元組來運行UserWarning:
Corpus/Sentencecontains0counts of3-gram overlaps.
BLEU scores might be undesirable;useSmoothingFunction().
warnings.warn(_msg)
接下來, 我們會得到一個非常低的分數
0.0301973834223185
你可以繼續用這些例子來進行其他試驗
BLEU 包含的數學知識非常簡單, 我也鼓勵你閱讀這篇論文, 并在自己電子表格程序中探索計算語句評估分數的方法
進一步閱讀
如果你要深入研究, 本節將提供更多有關該主題的資源
BLEU 在維基百科的主頁
BLEU: a Method for Automatic Evaluation of Machine Translation,2002 年發表
nltk.translate.bleu_score 的源碼
nltk.translate 包的 API 文檔
總結
在本教程中, 你探索了 BLEU 評分, 根據在機器翻譯和其他語言生成任務中的參考文本對候選文本進行評估和評分
具體來說, 你學到了:
BLEU 評分的簡單入門介紹, 并直觀地感受到到底是什么正在被計算
如何使用 Python 中的 NLTK 庫來計算語句和文章的 BLEU 分數
如何使用一系列的小例子來直觀地感受候選文本和參考文本的差異是如何影響最終的 BLEU 分數
來源: https://cloud.tencent.com/developer/article/1042161