prollerweg 发表于 2015-11-29 14:42:19

lda模型的python实现


[*]LDA(Latent Dirichlet Allocation)是一种文档主题生成模型,最近看了点资料,准备使用python实现一下。至于数学模型相关知识,某度一大堆,这里也给出之前参考过的一个挺详细的文档lda算法漫游指南
[*]这篇博文只讲算法的sampling方法python实现。
[*]完整实现项目开源python-LDA
  



[*]
lda模型变量申请及初始化



#
#伪代码
#
输入:文章集合(分词处理后),K(类的个数)
输出:已经随机分派了一次的lda模型
begin
申请几个统计量:
p 概率向量 维度:K
nw 词在类上的分布 维度:M*K 其中M为文章集合的词的总个数
nwsum 每个类上的词的总数 维度:K
nd 每篇文章中,各个类的词个数分布 维度:V*K 其中V为文章的总个数
ndsum 每篇文章中的词的总个数 维度:V
Z 每个词分派一个类 维度:V*每篇文章词的个数
theta 文章->类的概率分布 维度:V*K
phi 类->词的概率分布 维度:K*M
#初始化随机分配类
for x in 文章数:
统计ndsum[文章id][词的个数]
for y in 每篇文章的词个数:
给所有词随机分派一个类
词在此类上的分布数目+1
此文章中此类的词的个数+1
此类的总词数 +1
end


#
#实现代码片段,更详细看github项目
#
class LDAModel(object):
def __init__(self,dpre):
self.dpre = dpre #获取预处理参数
#
      #模型参数
#聚类个数K,迭代次数iter_times,每个类特征词个数top_words_num,超参数α(alpha) β(beta)
#
      self.K = K
self.beta = beta
self.alpha = alpha
self.iter_times = iter_times
self.top_words_num = top_words_num
#
      #文件变量
#分好词的文件trainfile
#词对应id文件wordidmapfile
#文章-主题分布文件thetafile
#词-主题分布文件phifile
#每个主题topN词文件topNfile
#最后分派结果文件tassginfile
#模型训练选择的参数文件paramfile
#
      self.wordidmapfile = wordidmapfile
self.trainfile = trainfile
self.thetafile = thetafile
self.phifile = phifile
self.topNfile = topNfile
self.tassginfile = tassginfile
self.paramfile = paramfile
# p,概率向量 double类型,存储采样的临时变量
# nw,词word在主题topic上的分布
# nwsum,每各topic的词的总数
# nd,每个doc中各个topic的词的总数
# ndsum,每各doc中词的总数
self.p = np.zeros(self.K)      
self.nw = np.zeros((self.dpre.words_count,self.K),dtype="int")      
self.nwsum = np.zeros(self.K,dtype="int")   
self.nd = np.zeros((self.dpre.docs_count,self.K),dtype="int")      
self.ndsum = np.zeros(dpre.docs_count,dtype="int")   
self.Z = np.array([ .length)] for x in xrange(dpre.docs_count)])      # M*doc.size(),文档中词的主题分布
#随机先分配类型
for x in xrange(len(self.Z)):
self.ndsum = self.dpre.docs.length
for y in xrange(self.dpre.docs.length):
topic = random.randint(0,self.K-1)
self.Z = topic
self.nw.words] += 1
self.nd += 1
self.nwsum += 1
self.theta = np.array([ for x in xrange(self.dpre.docs_count) ])
self.phi = np.array([ [ 0.0 for y in xrange(self.dpre.words_count) ] for x in xrange(self.K)])

[*]
sampling抽样过程



#
#伪代码
#
输入:初始化后的lda_model,迭代次数iter_times,超参数α、β,聚类个数K
输出:theta(文章对应类的分布概率),phi(类对应词的分布概率),tassgin(文章中每个词的分派类结果),twords(每个类topN个高频词)
begin
for i in 迭代次数:
for m in 文章个数:
for v in 文章中词:
取topic = Z
令nw、nwsum、nd的统计量均-1
计算概率p[] #p[]为此词属于每个topic的概率
for k in (1,类的个数-1):
p += p
再随机分派一次,记录被分派的新的topic
令nw、nwsum、nd的统计量均+1
#迭代完成后
    输出模型
end


#代码片段
def sampling(self,i,j):
topic = self.Z
word = self.dpre.docs.words
self.nw -= 1
self.nd -= 1
self.nwsum -= 1
self.ndsum -= 1
Vbeta = self.dpre.words_count * self.beta
Kalpha = self.K * self.alpha
self.p = (self.nw + self.beta)/(self.nwsum + Vbeta) * \
(self.nd + self.alpha) / (self.ndsum + Kalpha)
for k in xrange(1,self.K):
self.p += self.p
u = random.uniform(0,self.p)
for topic in xrange(self.K):
if self.p>u:
break
self.nw +=1
self.nwsum +=1
self.nd +=1
self.ndsum +=1
return topic
  

  此实现为最基础的LDA模型实现,聚类个数K,和超参数的设置要靠人工输入,自动计算的版本会在以后研究。
页: [1]
查看完整版本: lda模型的python实现