前奏:
【NLG】(二)文本生成评价指标—— METEOR原理及代码示例
【NLG】(三)文本生成评价指标—— ENTROPY原理及代码示例
【NLG】(四)文本生成评价指标—— diversity原理及代码示例
1.kl_divergence原理
相对熵又称KL散度,如果我们对于同一个随机变量 x 有两个单独的概率分布 P(x) 和 Q(x),我们可以使用 KL 散度(Kullback-Leibler (KL) divergence)来衡量这两个分布的差异。
在机器学习中,P往往用来表示样本的真实分布,Q用来表示模型所预测的分布,那么KL散度就可以计算两个分布的差异,也就是Loss损失值:
从KL散度公式中可以看到Q的分布越接近P(Q分布越拟合P),那么散度值越小,即损失值越小。
因为对数函数是凸函数,所以KL散度的值为非负数。
有时会将KL散度称为KL距离,但它并不满足距离的性质:
- KL散度不是对称的;
- KL散度不满足三角不等式。
在文本生成中,用来判断生成的文本跟参考文本数据之间的分布之间的差异。
2.优缺点
这个没有明确的优缺点,该指标在陈述一个事实。
3.如何算kl_divergence
这个demo仅供参考,根据公式以及自己的理解写的代码,得出的KL散度值非常小,10-8,感觉不太对,但是还没有发现哪里有问题。如果那位博友看出问题,求指正~
def kl_divergence(labels, predicts):
'''
从predict的角度看,与labels有多大不同,Dkl=sigma P_p * log(P_p / P_l)
'''
counter_label = [defaultdict(int), defaultdict(int),
defaultdict(int), defaultdict(int)]
for gg in labels:
g = gg.rstrip().split()
for n in range(4):
for idx in range(len(g)-n):
ngram = ' '.join(g[idx:idx+n+1])
counter_label[n][ngram] += 1
counter_predict = [defaultdict(int), defaultdict(int),
defaultdict(int), defaultdict(int)]
for gg in predicts:
g = gg.rstrip().split()
for n in range(4):
for idx in range(len(g)-n):
ngram = ' '.join(g[idx:idx+n+1])
counter_predict[n][ngram] += 1
# Dkl=sigma P_p * log(P_p / P_l) 从p的角度看与l有多大不同
kv_score = [0.0, 0.0, 0.0, 0.0]
for n in range(4):
total_label = sum(counter_label[n].values()) + 1e-10
total_predict = sum(counter_predict[n].values()) + 1e-10
for k in counter_label[n].keys():
p_l = (counter_label[n][k] + 0.0) / total_label
p_p = 0.0
if k in counter_predict[n].keys():
p_p = (counter_predict[n][k] + 0.0) / total_predict
kv_score[n] += p_p * np.log((p_p + 1e-10) / p_l)
return kv_score
if __name__ == '__main__':
labels_split = ['你 说 什 么 啊, 听 不 懂?', '你 说 的 是 啥 ?']
predicts_split = ['你 说 什 么 ?', '你 说 的 是 啥 ?']
kl_d = kl_divergence(labels_split, predicts_split)
参考:
1.原理:https://blog.csdn.net/weixinhum/article/details/85064685