import numpy as np from nltk.translate import bleu_score
def bp(references, candidate): # brevity penality,句子长度惩罚因子 ind = np.argmin([abs(len(i) - len(candidate)) for i in references]) if len(references[ind]) < len(candidate): return 1 scale = 1 - (len(candidate) / len(references[ind])) return np.e ** scale
def parse_ngram(sentence, gram): # 把一个句子分成n-gram return [sentence[i:i + gram] for i in range(len(sentence) - gram + 1)] # 此处一定要注意+1,否则会少一个gram
def sentence_bleu(references, candidate, weight): bp_value = bp(references, candidate) s = 1 for gram, wei in enumerate(weight): gram = gram + 1 # 拆分n-gram ref = [parse_ngram(i, gram) for i in references] can = parse_ngram(candidate, gram) # 统计n-gram出现次数 ref_counter = [Counter(i) for i in ref] can_counter = Counter(can) # 统计每个词在references中的出现次数 appear = sum(min(cnt, max(i.get(word, 0) for i in ref_counter)) for word, cnt in can_counter.items()) score = appear / len(can) # 每个score的权值不一样 s *= score ** wei s *= bp_value # 最后的分数需要乘以惩罚因子 return s
references = [ "the dog jumps high", "the cat runs fast", "dog and cats are good friends" ] candidate = "the d o g jump s hig" weights = [0.25, 0.25, 0.25, 0.25] print(sentence_bleu(references, candidate, weights)) print(bleu_score.sentence_bleu(references, candidate, weights))
def parse_ngram(sentence, gram): return [sentence[i:i + gram] for i in range(len(sentence) - gram + 1)]
def corpus_bleu(references_list, candidate_list, weights): candidate_len = sum(len(i) for i in candidate_list) reference_len = 0 for candidate, references in zip(candidate_list, references_list): ind = np.argmin([abs(len(i) - len(candidate)) for i in references]) reference_len += len(references[ind]) s = 1 for index, wei in enumerate(weights): up = 0 # 分子 down = 0 # 分母 gram = index + 1 for candidate, references in zip(candidate_list, references_list): # 拆分n-gram ref = [parse_ngram(i, gram) for i in references] can = parse_ngram(candidate, gram) # 统计n-gram出现次数 ref_counter = [Counter(i) for i in ref] can_counter = Counter(can) # 统计每个词在references中的出现次数 appear = sum(min(cnt, max(i.get(word, 0) for i in ref_counter)) for word, cnt in can_counter.items()) up += appear down += len(can) s *= (up / down) ** wei return bp(reference_len, candidate_len) * s
references = [ [ "the dog jumps high", "the cat runs fast", "dog and cats are good friends"], [ "ba ga ya", "lu ha a df", ] ] candidate = ["the d o g jump s hig", 'it is too bad'] weights = [0.25, 0.25, 0.25, 0.25] print(corpus_bleu(references, candidate, weights)) print(bleu_score.corpus_bleu(references, candidate, weights))
def nearest_len(references, candidate): return len(references[np.argmin([abs(len(i) - len(candidate)) for i in references])])
def parse_ngram(sentence, gram): return [sentence[i:i + gram] for i in range(len(sentence) - gram + 1)]
def appear_count(references, candidate, gram): ref = [parse_ngram(i, gram) for i in references] can = parse_ngram(candidate, gram) # 统计n-gram出现次数 ref_counter = [Counter(i) for i in ref] can_counter = Counter(can) # 统计每个词在references中的出现次数 appear = sum(min(cnt, max(i.get(word, 0) for i in ref_counter)) for word, cnt in can_counter.items()) return appear, len(can)
def corpus_bleu(references_list, candidate_list, weights): candidate_len = sum(len(i) for i in candidate_list) reference_len = sum(nearest_len(references, candidate) for candidate, references in zip(candidate_list, references_list)) bp_value = bp(reference_len, candidate_len) s = 1 for index, wei in enumerate(weights): up = 0 # 分子 down = 0 # 分母 gram = index + 1 for candidate, references in zip(candidate_list, references_list): appear, total = appear_count(references, candidate, gram) up += appear down += total s *= (up / down) ** wei return bp_value * s
def sentence_bleu(references, candidate, weight): bp_value = bp(nearest_len(references, candidate), len(candidate)) s = 1 for gram, wei in enumerate(weight): gram = gram + 1 appear, total = appear_count(references, candidate, gram) score = appear / total # 每个score的权值不一样 s *= score ** wei # 最后的分数需要乘以惩罚因子 return s * bp_value
if __name__ == '__main__': references = [ [ "the dog jumps high", "the cat runs fast", "dog and cats are good friends"], [ "ba ga ya", "lu ha a df", ] ] candidate = ["the d o g jump s hig", 'it is too bad'] weights = [0.25, 0.25, 0.25, 0.25] print(corpus_bleu(references, candidate, weights)) print(bleu_score.corpus_bleu(references, candidate, weights)) print(sentence_bleu(references[0], candidate[0], weights)) print(bleu_score.sentence_bleu(references[0], candidate[0], weights))