PLSA是个从文档中发现topic的算法,它认为文本可以分三个层次来理解。1,文档(d);2,主题(z);3,单词(w),既一个文档包含若干主题,每个主题包含若干单词。从概率层面来讲,这里的包含其实是某种分布。也就是说,一个文档可以看做在一些主题上面的分布(P(z|d),而每个主题看做在单词上面的某种分布(P(w|z))。 pLSA就是对这些分布进行建模。
相信大部分人都可能理解之前的这些内容,关键难点在于求解。其实呢,一切古典概率都是纸老虎,概率,在文本处理里面,本质就是词频。
pLSA模型的目标函数就是使得所有文档单词组合的似然函数最大:
这里
问题的解可以用EM算法实现。
首先,对变量初始化。
在E step里面,计算
这里就是求一个文档中的某个单词在某主题下面的分布,一个简单的概率计算,下标省略,注意一致。
在M step,计算
这里求得是在所有文档中一个单词在某个主题下面的概率。
另外一个更新是
这里求的是某文档在主题上面的分布。
关于示例代码,网上很多,比如
#!/usr/bin/env python
from random import random
from math import log, exp
def normalize(P):
return [p / sum(P) for p in P]
# test data
D = [[2,10,0],[1,5,0],[0,0,8],[0,1,9]]
N = len(D)
W = len(D[0])
print 'D = ', D
#initialize
K = 5
Q = [normalize([random() for n in range(N)]) for k in range(K)]
R = [normalize([random() for w in range(W)]) for k in range(K)]
P = normalize([random() for k in range(K)])
print 'Q = ', Q
print 'R = ', R
#iteration
for loop in range(10):
# e-step
C = [[normalize([Q[k][w] * R[k][w] * P[k] for k in range(K)]) for w in range(W)] for n in range(N)]
# m-step
for k in range(K):
Q[k] = normalize([sum([C[n][w][k] * D[n][w] for w in range(W)]) for n in range(N)])
R[k] = normalize([sum([C[n][w][k] * D[n][w] for n in range(N)]) for w in range(W)])
P = normalize([sum(D[n][w] * C[n][w][k] for w in range(W) for n in range(N)) for k in range(K)])
# log likelihood
L = sum(D[n][w] * log(sum(Q[k][n] * R[k][w] for k in range(K))) for n in range(N) for w in range(W))
print 'L = ', L