从头开始用Python实现Bleu评分

在观看了Andrew Ng关于Bleu评分的视频后,我想从头开始用Python实现一个。我用Python编写了完整的代码,并适量使用了numpy。这是完整的代码

import numpy as np
def n_gram_generator(sentence,n= 2,n_gram= False):
    '''
    N-Gram生成器,参数为sentence
    n用于指定n_grams的数量
    n_gram参数用于移除重复的n_grams
    '''
    sentence = sentence.lower() # 转换为小写
    sent_arr = np.array(sentence.split()) # 分割为字符串数组
    length = len(sent_arr)
    word_list = []
    for i in range(length+1):
        if i < n:
            continue
        word_range = list(range(i-n,i))
        s_list = sent_arr[word_range]
        string = ' '.join(s_list) # 将列表转换为字符串
        word_list.append(string) # 追加到word_list
        if n_gram:
            word_list = list(set(word_list))
    return word_list
def bleu_score(original,machine_translated):
    '''
    给定一个原始句子和一个机器翻译的句子,计算Bleu评分
    '''
    mt_length = len(machine_translated.split())
    o_length = len(original.split())
    # 简洁性惩罚
    if mt_length>o_length:
        BP=1
    else:
        penality=1-(mt_length/o_length)
        BP=np.exp(penality)
    # 计算精度
    precision_score = []
    for i in range(mt_length):
        original_n_gram = n_gram_generator(original,i)
        machine_n_gram = n_gram_generator(machine_translated,i)
        n_gram_list = list(set(machine_n_gram)) # 移除重复字符串
        # 计算出现的次数
        machine_score = 0
        original_score = 0
        for j in n_gram_list:
            machine_count = machine_n_gram.count(j)
            original_count = original_n_gram.count(j)
            machine_score = machine_score+machine_count
            original_score = original_score+original_count
        precision = original_score/machine_score
        precision_score.append(precision)
    precisions_sum = np.array(precision_score).sum()
    avg_precisions_sum=precisions_sum/mt_length
    bleu=BP*np.exp(avg_precisions_sum)
    return bleu
if __name__ == "__main__":
    original = "this is a test"
    bs=bleu_score(original,original)
    print("Bleu Score Original",bs)

我尝试用nltk测试我的得分

from nltk.translate.bleu_score import sentence_bleu
reference = [['this', 'is', 'a', 'test']]
candidate = ['this', 'is', 'a', 'test']
score = sentence_bleu(reference, candidate)
print(score)

问题是我计算的Bleu评分为2.718281,而nltk的为1。我哪里做错了?

以下是一些可能的原因:

1) 我根据机器翻译句子的长度计算ngrams。这里是从1到4

2) 我自己编写的n_gram_generator函数,不确定它的准确性

3) 我可能使用了错误的函数或错误地计算了Bleu评分

有人能查看我的代码并告诉我哪里出错了嗎?


回答:

你的Bleu评分计算有误。问题如下:

  • 你需要使用剪裁精度
  • sklearn对每个n-gram使用权重
  • sklearn使用ngrams,n = 1,2,3,4

修正后的代码

def bleu_score(original,machine_translated):
    '''
    给定一个原始句子和一个机器翻译的句子,计算Bleu评分
    '''
    mt_length = len(machine_translated.split())
    o_length = len(original.split())
    # 简洁性惩罚
    if mt_length>o_length:
        BP=1
    else:
        penality=1-(mt_length/o_length)
        BP=np.exp(penality)
    # 剪裁精度
    clipped_precision_score = []
    for i in range(1, 5):
        original_n_gram = Counter(n_gram_generator(original,i))
        machine_n_gram = Counter(n_gram_generator(machine_translated,i))
        c = sum(machine_n_gram.values())
        for j in machine_n_gram:
            if j in original_n_gram:
                if machine_n_gram[j] > original_n_gram[j]:
                    machine_n_gram[j] = original_n_gram[j]
            else:
                machine_n_gram[j] = 0
        #print (sum(machine_n_gram.values()), c)
        clipped_precision_score.append(sum(machine_n_gram.values())/c)
    #print (clipped_precision_score)
    weights =[0.25]*4
    s = (w_i * math.log(p_i) for w_i, p_i in zip(weights, clipped_precision_score))
    s = BP * math.exp(math.fsum(s))
    return s
original = "It is a guide to action which ensures that the military alwasy obeys the command of the party"
machine_translated = "It is the guiding principle which guarantees the military forces alwasy being under the command of the party"
print (bleu_score(original, machine_translated))
print (sentence_bleu([original.split()], machine_translated.split()))

输出:

0.27098211583470044
0.27098211583470044

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注