- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在计算中文句子的 BLEU 分数时发现了零值。
候选句子是c
,两个引用是r1
和r2
c=[u'\u9274\u4e8e', u'\u7f8e\u56fd', u'\u96c6', u'\u7ecf\u6d4e', u'\u4e0e', u'\u8d38\u6613', u'\u6700\u5927', u'\u56fd\u4e8e', u'\u4e00\u8eab', u'\uff0c', u'\u4e0a\u8ff0', u'\u56e0\u7d20', u'\u76f4\u63a5', u'\u5f71\u54cd', u'\u7740', u'\u4e16\u754c', u'\u8d38\u6613', u'\u3002']
r1 = [u'\u8fd9\u4e9b', u'\u76f4\u63a5', u'\u5f71\u54cd', u'\u5168\u7403', u'\u8d38\u6613', u'\u548c', u'\u7f8e\u56fd', u'\u662f', u'\u4e16\u754c', u'\u4e0a', u'\u6700\u5927', u'\u7684', u'\u5355\u4e00', u'\u7684', u'\u7ecf\u6d4e', u'\u548c', u'\u8d38\u6613\u5546', u'\u3002']
r2=[u'\u8fd9\u4e9b', u'\u76f4\u63a5', u'\u5f71\u54cd', u'\u5168\u7403', u'\u8d38\u6613', u'\uff0c', u'\u56e0\u4e3a', u'\u7f8e\u56fd', u'\u662f', u'\u4e16\u754c', u'\u4e0a', u'\u6700\u5927', u'\u7684', u'\u5355\u4e00', u'\u7684', u'\u7ecf\u6d4e\u4f53', u'\u548c', u'\u8d38\u6613\u5546', u'\u3002']
代码为:
weights = [0.1, 0.8, 0.05, 0.05]
print nltk.align.bleu_score.bleu(c, [r1, r2], weights)
但是我得到了一个结果 0
。当我进入bleu
进程时,我发现
try:
s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns))
except ValueError:
# some p_ns is 0
return 0
以上程序转到except ValueError
。但是,我不知道为什么会返回错误。如果我尝试其他句子,我可以获得非零值。
最佳答案
您似乎发现了 NLTK 实现中的错误!这try-except
https://github.com/alvations/nltk/blob/develop/nltk/translate/bleu_score.py#L76 错误
在长:
首先,让我们来看看 p_n
是什么在 BLEU 分数中表示:
注意:
Count_match(ngram)
基于具有更高计数的引用(参见 https://github.com/alvations/nltk/blob/develop/nltk/translate/bleu_score.py#L270 )。所以默认的 BLEU 分数使用 n=4
其中包括 unigrams 到 4grams。对于每个 ngram,让我们计算 p_n
:
>>> from collections import Counter
>>> from nltk import ngrams
>>> hyp = u"鉴于 美国 集 经济 与 贸易 最大 国于 一身 , 上述 因素 直接 影响 着 世界 贸易 。".split()
>>> ref1 = u"这些 直接 影响 全球 贸易 和 美国 是 世界 上 最大 的 单一 的 经济 和 贸易商 。".split()
>>> ref2 = u"这些 直接 影响 全球 贸易 和 美国 是 世界 上 最大 的 单一 的 经济 和 贸易商 。".split()
# Calculate p_1, p_2, p_3 and p_4
>>> from nltk.translate.bleu_score import _modified_precision
>>> p_1 = _modified_precision([ref1, ref2], hyp, 1)
>>> p_2 = _modified_precision([ref1, ref2], hyp, 2)
>>> p_3 = _modified_precision([ref1, ref2], hyp, 3)
>>> p_4 = _modified_precision([ref1, ref2], hyp, 4)
>>> p_1, p_2, p_3, p_4
(Fraction(4, 9), Fraction(1, 17), Fraction(0, 1), Fraction(0, 1))
注意最新版本_modified_precision
自此以来的 BLEU 分数https://github.com/nltk/nltk/pull/1229一直在用Fraction
而不是 float
输出。所以现在,我们可以清楚地看到分子和分母。
现在让我们验证 _modified_precision
的输出对于一元组。在假设中,粗体字出现在引用文献中:
有 9 个标记重叠,这 9 个标记中有 1 个是重复出现的两次。
>>> from collections import Counter
>>> ref1_unigram_counts = Counter(ngrams(ref1, 1))
>>> ref2_unigram_counts = Counter(ngrams(ref2, 1))
>>> hyp_unigram_counts = Counter(ngrams(hyp,1))
>>> for overlaps in set(hyp_unigram_counts.keys()).intersection(ref1_unigram_counts.keys()):
... print " ".join(overlaps)
...
美国
直接
经济
影响
。
最大
世界
贸易
>>> overlap_counts = Counter({ng:hyp_unigram_counts[ng] for ng in set(hyp_unigram_counts.keys()).intersection(ref1_unigram_counts.keys())})
>>> overlap_counts
Counter({(u'\u8d38\u6613',): 2, (u'\u7f8e\u56fd',): 1, (u'\u76f4\u63a5',): 1, (u'\u7ecf\u6d4e',): 1, (u'\u5f71\u54cd',): 1, (u'\u3002',): 1, (u'\u6700\u5927',): 1, (u'\u4e16\u754c',): 1})
现在让我们检查一下这些重叠词在引用文献中出现了多少次。将来自不同引用文献的“组合”计数器的值作为 p_1
的分子。公式。如果两个引用文献中出现相同的词,则取最大计数。
>>> overlap_counts_in_ref1 = Counter({ng:ref1_unigram_counts[ng] for ng in set(hyp_unigram_counts.keys()).intersection(ref1_unigram_counts.keys())})
>>> overlap_counts_in_ref2 = Counter({ng:ref2_unigram_counts[ng] for ng in set(hyp_unigram_counts.keys()).intersection(ref1_unigram_counts.keys())})
>>> overlap_counts_in_ref1
Counter({(u'\u7f8e\u56fd',): 1, (u'\u76f4\u63a5',): 1, (u'\u7ecf\u6d4e',): 1, (u'\u5f71\u54cd',): 1, (u'\u3002',): 1, (u'\u6700\u5927',): 1, (u'\u4e16\u754c',): 1, (u'\u8d38\u6613',): 1})
>>> overlap_counts_in_ref2
Counter({(u'\u7f8e\u56fd',): 1, (u'\u76f4\u63a5',): 1, (u'\u7ecf\u6d4e',): 1, (u'\u5f71\u54cd',): 1, (u'\u3002',): 1, (u'\u6700\u5927',): 1, (u'\u4e16\u754c',): 1, (u'\u8d38\u6613',): 1})
>>> overlap_counts_in_ref1_ref2 = Counter()
>>> numerator = overlap_counts_in_ref1_ref2
>>>
>>> for c in [overlap_counts_in_ref1, overlap_counts_in_ref2]:
... for k in c:
... numerator[k] = max(numerator.get(k,0), c[k])
...
>>> numerator
Counter({(u'\u7f8e\u56fd',): 1, (u'\u76f4\u63a5',): 1, (u'\u7ecf\u6d4e',): 1, (u'\u5f71\u54cd',): 1, (u'\u3002',): 1, (u'\u6700\u5927',): 1, (u'\u4e16\u754c',): 1, (u'\u8d38\u6613',): 1})
>>> sum(numerator.values())
8
现在对于分母来说,它就是数字。出现在假设中的 unigrams:
>>> hyp_unigram_counts
Counter({(u'\u8d38\u6613',): 2, (u'\u4e0e',): 1, (u'\u7f8e\u56fd',): 1, (u'\u56fd\u4e8e',): 1, (u'\u7740',): 1, (u'\u7ecf\u6d4e',): 1, (u'\u5f71\u54cd',): 1, (u'\u56e0\u7d20',): 1, (u'\u4e16\u754c',): 1, (u'\u3002',): 1, (u'\u4e00\u8eab',): 1, (u'\u6700\u5927',): 1, (u'\u9274\u4e8e',): 1, (u'\u4e0a\u8ff0',): 1, (u'\u96c6',): 1, (u'\u76f4\u63a5',): 1, (u'\uff0c',): 1})
>>> sum(hyp_unigram_counts.values())
18
所以得到的分数是 8/18 -> 4/9
和我们的 _modified_precision
功能 checkout 。
现在让我们来看看完整的 BLEU 公式:
根据公式,我们现在只考虑求和的指数,即 exp(...)
.也可以简化为各种p_n
的对数之和正如我们之前计算的那样,即 sum(log(p_n))
.这就是它在 NLTK 中的实现方式,请参阅 https://github.com/alvations/nltk/blob/develop/nltk/translate/bleu_score.py#L79
暂时忽略 BP,让我们考虑对 p_n
求和并考虑到它们各自的权重:
>>> from fractions import Fraction
>>> from math import log
>>> log(Fraction(4, 9))
-0.8109302162163288
>>> log(Fraction(1, 17))
-2.833213344056216
>>> log(Fraction(0, 1))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
啊哈!这就是出现错误的地方,日志的总和将返回 ValueError
。当他们通过math.fsum()
.
>>> try:
... sum(log(pi) for pi in (Fraction(4, 9), Fraction(1, 17), Fraction(0, 1), Fraction(0, 1)))
... except ValueError:
... 0
...
0
要更正实现,the try-except
应该是:
s = []
# Calculates the overall modified precision for all ngrams.
# by summing the the product of the weights and the respective log *p_n*
for w, p_n in zip(weights, p_ns)):
try:
s.append(w * math.log(p_n))
except ValueError:
# some p_ns is 0
s.append(0)
return sum(s)
引用资料:
公式来自http://lotus.kuee.kyoto-u.ac.jp/WAT/papers/submissions/W15/W15-5009.pdf描述了 BLEU 的一些敏感性问题。
关于python - 为什么 nltk.align.bleu_score.bleu 会报错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34557078/
我在计算中文句子的 BLEU 分数时发现了零值。 候选句子是c,两个引用是r1和r2 c=[u'\u9274\u4e8e', u'\u7f8e\u56fd', u'\u96c6', u'\u7ecf\
如果我有中文单词表:like reference = ['我' '是', '好' ,'人'],假设 = ['我', '是', '善良的','人]。我可以使用:nltk.translate.bleu_s
我是一名优秀的程序员,十分优秀!