Biterm Topic Model(BTM)的python 实现

前言
最近在看话题模型相关的论文。有关话题模型现在比较主流的解决方法有LDA,PLSA以及mixture of unigrams,本人研究了LDA(Latent Dirichlet Allocation),BTM等话题模型。首先说明在研究和实验LDA话题模型时发现,在解决short text话题分析时,这是由于其基于文档词共现的实现原理分析时无法解决short text的离散问题。之后通过查阅相关文献,找到了一篇有关BTM 话题模型的文章,于是就想象着找个第三方python包看一下算法的效果,但是没有找到,于是乎就自己动手造了个轮子,以下具体介绍造轮子的步骤。

什么是BTM?

简单讲就是一个话题分析的聚类模型,其原理和LDA很相似,如果对LDA不实很了解的可以查阅相关文献或技术博客,下面附上个人学习是的博客和论文仅供大家参考。
简书:LDA话题模型与推荐系统:·http://www.jianshu.com/p/50295398d802
有关BTM的论文参考文献有
A Biterm Topic Model for Short Texts

Xiaohui Yan, Jiafeng Guo, Yanyan Lan, Xueqi Cheng
Institute of Computing Technology, CAS
Beijing, China 100190 yanxiaohui@software.ict.ac.cn, {guojiafeng, lanyanyan, cxq}@ict.ac.cn
BTM 于LDA的不同在于,LDA是document-level,
BTM是corpus-level,LDA 计算的是topic-document-word
的概率分布,BTM计算的是topic-Biterm的概率分布。
相同点在于,都是基于词共现,只是BTM基于word pair pattern。
BTM 模型能够离散词共现(原文:sparse word co-occurrence patterns at document-level,本人英语水平有限,如有理解不当,还请指正)的问题。

BTM 的算法流程:

  1. For each topic z(a) draw a topic-specific word distribution φz ∼ Dir(β)
  2. Draw a topic distribution θ ∼ Dir(α) for the whole collection
  3. For each biterm b in the biterm set B
    (a) draw a topic assignment z ∼ Multi(θ)
    (b) draw two words: wi,wj ∼ Mulit(φz)

BTM实现
针对实现主要介绍核心部分的实现,主要涉及的问题主要有:
计算P(z) 、P(b|z)迭代计算的更新
代码块

def assign_biterm_topic(self, bit, topic_id):
	"""
	为 biterm 赋予 topic ,并更新 相关nwz 及 nb_z 数据
	:param bit:
	:param topic_id:
	:return:
	"""
	w1 = int(bit.get_word()) - 1
	w2 = int(bit.get_word(2)) - 1
	bit.setTopic(topic_id)
	self.nb_z[topic_id] += 1
	self.nwz[int(topic_id)][w1] = self.nwz[int(topic_id)][w1] + 1
	self.nwz[int(topic_id)][w2] = self.nwz[int(topic_id)][w2] + 1

def compute_pz_b(self, bit, pz):
"""
更新 话题的概率分布
:param bit:
:param pz:
:return:
"""
w1 = bit.get_word() - 1
w2 = bit.get_word(2) - 1
for k in xrange(self.topic_num):
	if self.has_background and k == 0:
		pw1k = self.pw_b[w1]
		pw2k = self.pw_b[w2]
	else:
		pw1k = (self.nwz[k][w1] + self.beta) / (2 * self.nb_z[k] + self.voca_size * self.beta)
		pw2k = (self.nwz[k][w2] + self.beta) / (2 * self.nb_z[k] + 1 + self.voca_size * self.beta)
	pk = (self.nb_z[k] + self.alpha) / (len(self.biterms) + self.topic_num * self.alpha)
	pz[k] = pk * pw1k * pw2k
def mult_sample(self, pz):
	"""
	sample from mult pz
	:param pz:
	:return:
	"""
	for i in xrange(1, self.topic_num):
		pz[i] += pz[i - 1]

	u = random.random()
	k = None
	for k in xrange(0, self.topic_num):
		if pz[k] >= u * pz[self.topic_num - 1]:
			break
	if k == self.topic_num:
		k -= 1
	return k

分析结果的应用,主要计算

P(z|d)=p(z|B)p(B|d)
B 表示句子中的所有Biterm项b,上式表示计算:
P(z|b)P(b|d)的乘积的最大值
代码块
def infer_sentence_topic(self, sentence, topic_num=1, min_pro=0.001):
“”"
BTM topic model to infer a document or sentence 's topic
基于 biterm s 计算问题
:param sentence: sentence
:param topic_num: 返回 可能话题数目 最多返回
:param min_pro: 话题概率最小阈值,只有概率大于该值,才是有效话题,否则不返回
:return: 返回可能的话题列表,及话题概率
“”"
sentence_biterms = self.SentenceProcess(sentence)

	topic_pro = [0] * self.topic_num
	# 短文本分析中,p (b|d) = nd_b/doc(nd_b)  doc(nd_b) 表示 计算的query 的所有biterm的计数
	# 因此,在short text 的p(b|d) 计算为1/biterm的数量
	bit_size = len(sentence_biterms)
	if not sentence_biterms:
		return [(1.0, -1)]
	for bit in sentence_biterms:
		# cal p(z|d) = p(z|b)*p(b|d)
		# cal p(z|b)
		pz = [0] * self.topic_num
		self.compute_pz_b(bit, pz)
		pz_sum = sum(pz)
		pz = map(lambda pzk: pzk / pz_sum, pz)

		for x, y in zip(range(self.topic_num), pz):
			topic_pro[x] += y / bit_size

	min_result = zip(topic_pro, range(self.topic_num))
	min_result.sort(key=lambda x: x[0], reverse=True)
	result = []
	for re in min_result:
		if re[0] > min_pro:
			result.append(re)
	return result[:topic_num]

至此BTM的python实现介绍完毕,其中文文本分析源码见个人github:
https://github.com/liguoyu1/python/tree/master/TopicModel
其中MyCode函数未找到,会在codeNLP/tools下找到,或者修改注释掉即可
本人是个NLP新人,许多地方可能还存在一些问题,如果发现,请不吝赐教!

  • 8
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 47
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 47
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值