4.1 潜在狄利克雷分配(LDA)
LDA 和LDA :很不幸,有两个机器学习方法都以首字母LDA来命名:潜在狄利克雷分配(Latent Dirichlet Allocation)和线性判别式分析(Linear Discriminant Analysis);前者是一种主题模型方法,后者是一种分类方法。这两者毫无关联,但LDA可以指代它们中的任何一个。这非常容易令人混淆。scikit-learn有一个子模块sklearn.lda ,它可以用来实现线性判别式分析。目前,scikit-learn还并没有实现潜在狄利克雷分配。
最简单的主题模型(是其他所有方法的基础)就是潜在狄利克雷分配 (LDA)。LDA背后的数学原理相当复杂,我们并不想在这里深入探讨具体细节。
对此感兴趣且勇于探索的读者,搜索一下维基百科就可以在如下链接中找到这些算法背后的所有公式:
http://en.wikipedia.org/wiki/Latent_Dirichlet_allocation
然而,我们理解,这些都是高阶内容,它们背后都有一些故事。在本故事中,主题是固定的。这么讲可能还是不太清晰。具体包括哪些文档呢?
举个例子,我们假设现在只有三个主题:
机器学习;
Python;
烘培。
每个主题都有一系列词语与之关联。本书就是前两个主题的混合,它们可能各占50%。可以这么说,在我们撰写本书的时候,一半词语是从机器学习主题中挑出来的,而另一半来自Python主题。在这个模型中,词语的顺序无关紧要。
前面这个解释是实际情况的一个简化版;每个主题对每个词语都会赋予一个概率,所以当主题是机器学习或烘培的时候,都可能会用到“面粉”这个词,但在烘培主题中这个词出现的可能性更大。
当然,我们并不知道都有哪些主题。否则,这就是一个不同的而且简单得多的问题。我们现在的任务是拿到一个文本集合并对它做反向工程,从中发现都有哪些主题,以及每个文档属于哪些主题。
构建主题模型
很不巧,scikit-learn并不支持潜在狄利克雷分配。所以,我们将要使用Python中的gensim 包。gensim 是由Radim Řehůřek开发出来的。他是机器学习方面的科研人员,也是捷克共和国的顾问。我们从安装该软件开始介绍。通过运行下面两个命令中的任意一个来实现安装:
pip install gensim easy_install gensim
我们将会使用美国联合通讯社(AP) 的新闻报道数据集。这是一个标准的数据集,它在主题模型的一些初始工作中被使用过。
>>> from gensim import corpora, models, similarities >>> corpus = corpora.BleiCorpus('./data/ap/ap.dat', '/data/ap/vocab.txt')
语料库就是预读进来的一个词语列表:
>>> model = models.ldamodel.LdaModel( corpus, num_topics=100, id2word=corpus.id2word)
这个一步过程会建立一个主题模型。我们能用多种方式探索这些主题。我们可以通过model [doc] 语法将一个文档中出现的主题都列出来:
>>> topics = [model[c] for c in corpus] >>> print topics[0] [(3, 0.023607255776894751), (13, 0.11679936618551275), (19, 0.075935855202707139), (92, 0.10781541687001292)]
这里我们省略了一些输出信息,但输出的格式就是一系列数据对(topic_index , topic_weight )。我们可以看到在每篇文档中只出现了一小部分主题。主题模型是一个稀疏的模型,即便每个文档中有很多潜在主题,也只有一小部分会被用到。我们画出了一个主题数的柱状图,如下图所示。
提示 稀疏性是说,当你有一个很大的矩阵或者向量的时候,基本上大多数的值都是0(或者小到可以近似为0)。因此,在任何时候,只有一小部分数据是相关的。
通常情况下,看起来规模大得难以解决的问题,其实是可以解决的,这是因为数据是稀疏的。例如,即使一个网页能够链接到其他任何网页上,但链接关系图其实是非常稀疏的,因为每个网页只会链接到极小一部分网页上。
在上图中我们可以看到,大约150 个文档中包含了5 个主题,大多数文档涵盖了10到12个主题。没有文档涉及20个以上的主题。
在很大程度上,这是一个参数的函数,叫做alpha参数。alpha的确切含义有一点抽象,但较大的alpha值会导致每个文档中包含更多的主题。alpha必须是正数,但通常很小,一般会小于1。gensim 会把alpha值默认设为1.0/len(corpus) ,不过你也可以自己设置它,如下所示:
>>> model = models.ldamodel.LdaModel( corpus, num_topics=100, id2word=corpus.id2word, alpha=1)
在这里,这是一个较大的alpha,它会使每个文档具有更多的主题。我们也可以用一个较小的值。如下面这个合并起来的柱状图所示,gensim 的表现符合预期。
现在我们看到很多文档触及了20至25个不同的主题。
这些主题是什么呢?从技术上讲,它们是词语上的多项式概率分布。它们赋予词表中每个词语一个概率。相对于概率低的词语,高概率词语与该主题相关性更大。
我们的大脑并不擅长根据概率分布进行推理,但是我们很容易理解一系列词语的意思。因此,我们通常使用一些高权重的词语来概括这些主题。这里列出了前10个主题:
dress military soviet president new state capt carlucci states leader stance government
koch zambia lusaka one-party orange kochs party i government mayor new political
human turkey rights abuses royal thompson threats new state wrote garden president
bill employees experiments levin taxation federal measure legislation senate president whistleblowers sponsor
ohijuly drought jesus disaster percent hartford mississippi crops northern valley Virginia
united percent billion year president world years states people i bush news
b hughes affidavit states united ounces squarefoot care delaying charged unrealistic bush
yeutter dukakis bush convention farm subsidies uruguay percent secretary general i told
Kashmir government people srinagar india dumps city twjammu-kashmir group moslem Pakistan
workers vietnamese irish wage immigrants percent bargaining last island police hutton I
尽管第一眼看上去令人畏惧,我们依然可以很清楚地看到,主题并不是一些随便拼凑的词语,它们是相关联的。我们还可以看到,这些主题包含了一些陈旧新闻的词语,例如苏联仍然存在,戈尔巴乔夫是总书记。我们还可以用词语云图来表示主题,让可能性更大的词语在图上显示得更大。例如,以下就是主题的可视化表示,它包含了中东和政治的主题。
还可以看到,一些词语或许应该删掉(例如词语I),因为它们并不那么有信息量(停用词)。在主题模型中,过滤掉停用词是很重要的,否则你得到的主题可能包含的全是停用词,没什么信息量。我们还希望将文本预处理成词根形式,使复数词和各种动词形式归一化。在前一章中我们已经介绍了这个过程,你可以回过头去查看详情。如果你有兴趣,可以从本书的网站上下载代码,并尝试这些变化方式,画出不同的图像。
注意 如果你想构建像前图那样的词语云图,那么有几个不同的软件可以选择。在这里,我选择使用的是线上工具wordle(http://www.wordle.net ),它可以生成非常富有吸引力的图像。由于只有几个例子,我还手动复制粘贴了一些词语,但实际上可以把它当做Web服务直接从Python中调用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论