Biterm Topic Model(BTM)的python 实现

来源:互联网 发布:小满软件 垃圾 编辑:程序博客网 时间:2024/06/11 19:47

前言
最近在看话题模型相关的论文。有关话题模型现在比较主流的解决方法有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] + 1def compute_pz_b(self, bit, pz):"""更新 话题的概率分布:param bit::param pz::return:"""w1 = bit.get_word() - 1w2 = bit.get_word(2) - 1for 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 * pw2kdef 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/codeNLP/Algorithm/TopicModel/BTM
本人是个NLP新人,许多地方可能还存在一些问题,如果发现,请不吝赐教!

原创粉丝点击