喔的天
困惑度??perplexity,没有用也要用。
开头我就这么爆狼式发言,不是没有道理的,在现今的主题模型评判中,困惑度仍然是一种主流,虽然还有held-out-log likelihood (出自 Crowdsourced Time-sync Video tagging using temporal and personalized topic modeling )和 EL(empirical likelihood)等等,但是那些在我看来真的没有什么很实际很合理的解释。但是学术界就是这么玩的,那么我们也就入乡随俗吧。
wiki上有介绍了三种方式,下面我作个小小的翻译,不想看的直接跳过。
在信息论中,困惑度是一种评判概率模型或概率分布预测的衡量指标,可用于评价模型好坏。
可分为三种
- Perplexity of a probability distribution
- Perplexity of a probability model
- Perplexity per word(我们下面用的方法就是这个)
正文
本文介绍的perplexity是最基本的那一种。公式如下
计算方式也很简单,对每一个训练集里出现的单词通过tassign找到其对应的topic,然后从phi矩阵中获得p(w),也就是上公式中log后面的值。
最后讲一下,一般最后算出来的不是一个perplexity的值,而是不同topic个数得到的不同结果画出来的图,用于观察,我的下面的代码只是得到topic=10的结果,需要多个的直接加for循环就可以了
解释一下,tassign和phi都是传统lda里算出来保存成后缀名的文件,这个大家应该都知道的
import numpy as np
def f_testset_word_count(testset): #测试集的词数统计
'''reture the sum of words in testset which is the denominator of the formula of Perplexity'''
return (len(testset.split()))
def graph_draw(topic,perplexity): #做主题数与困惑度的折线图
x=topic
y=perplexity
plt.plot(x,y,marker="*",color="red",linewidth=2)
plt.xlabel("Number of Topic")
plt.ylabel("Perplexity")
plt.show()
phi = np.loadtxt('test_data/model-final.phi')
word_topic = {}
f = open('test_data/model-final.tassign')
patterns = f.read().split()
f = open('test_data/model-final.tassign')
testset_word_count = f_testset_word_count(f.read())
# 用作循环
_topic=[]
perplexity_list=[]
_topic.append(10)
for pattern in patterns:
word = int(pattern.split(':')[0])
topic = int(pattern.split(':')[1])
pattern = pattern.replace(':','_')
if not word_topic.has_key(pattern)==True:
word_topic[pattern] = phi[topic][word]
duishu = 0.0
for frequency in word_topic.values():
duishu += -math.log(frequency)
kuohaoli = duishu/testset_word_count
perplexity = math.exp(kuohaoli)
perplexity_list.append(perplexity)
graph_draw(_topic,perplexity_list)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。