在文本挖掘中,咱们常常收集一些文档集合,例如博客文章或新闻文章,咱们但愿将其分红天然组,以便咱们能够分别理解它们。主题建模是对这些文档进行无监督分类的一种方法,相似于对数字数据进行聚类,即便咱们不肯定要查找什么,也能够找到天然的项目组。算法
潜在狄利克雷分配(LDA)是拟合主题模型特别流行的方法。它将每一个文档视为主题的混合体,并将每一个主题看做是单词的混合体。这容许文档在内容方面相互“重叠”,而不是分离成离散的组,以反映天然语言的典型用法。ide
结合主题建模的文本分析流程图。topicmodels包采用Document-Term Matrix做为输入,并生成一个能够经过tidytext进行处理的模型,以即可以使用dplyr和ggplot2对其进行处理和可视化。函数
如图所示,咱们可使用 文本原理来处理主题建模 。工具
潜在Dirichlet分配是主题建模中最经常使用的算法之一。 学习
每一个文档都是主题的混合体。咱们设想每一个文档可能包含来自几个主题的文字,特别是比例。例如,在双主题模型中,咱们能够说“文档1是90%的主题A和10%的主题B,而文档2是30%的主题A和70%的主题B.”测试
每一个主题都是词汇的混合。例如,咱们能够想象一个美国新闻的两个主题模型,一个话题是“政治”,一个是“娱乐”。政治话题中最多见的词语多是“总统”,“国会”和“政府“,而娱乐主题能够由诸如”电影“,”电视“和”演员“之类的词组成。 spa
LDA是一种同时估计这两种状况的数学方法:查找与每一个主题相关的单词混合,同时肯定描述每一个文档的主题混合。这个算法有不少现有的实现,咱们将深刻探讨其中的一个。code
library(topicmodels)data("AssociatedPress")AssociatedPress : term frequency (tf)
咱们可使用LDA()topicmodels包中的函数设置k = 2来建立两个主题的LDA模型。对象
实际上几乎全部的主题模型都会使用更大的模型k,但咱们很快就会看到,这种分析方法能够扩展到更多的主题。token
此函数返回一个包含模型拟合完整细节的对象,例如单词如何与主题关联以及主题如何与文档关联。
# set a seed so that the output of the model is predictableap_lda <- LDA(AssociatedPress,k =2,control =list(seed =1234))ap_lda
拟合模型是“简单部分”:分析的其他部分将涉及使用整理tidytext软件包中的函数来探索和解释模型。
tidytext包提供了这种方法来提取每一个主题的每一个词的几率,称为ββ (“测试版”)。
## # A tibble: 20,946 x 3## topic term beta## ## 1 1 aaron 1.69e-12## 2 2 aaron 3.90e- 5## 3 1 abandon 2.65e- 5## 4 2 abandon 3.99e- 5## 5 1 abandoned 1.39e- 4## 6 2 abandoned 5.88e- 5## 7 1 abandoning 2.45e-33## 8 2 abandoning 2.34e- 5## 9 1 abbott 2.13e- 6## 10 2 abbott 2.97e- 5## # ... with 20,936 more rows
R语言中对文本数据进行主题模型topicmodeling分析
每一个主题中最多见的术语
这种可视化让咱们了解从文章中提取的两个主题。话题1中最多见的词语包括“百分比”,“百万”,“十亿”和“公司”,这代表它可能表明商业或财务新闻。话题2中最多见的包括“总统”,“政府”和“苏维埃”,表示这个话题表明政治新闻。
做为替代方案,咱们能够认为有条款最大的区别在ββ在主题1和主题2之间。
## # A tibble: 198 x 4## term topic1 topic2 log_ratio## ## 1 administration 0.000431 0.00138 1.68## 2 ago 0.00107 0.000842 -0.339## 3 agreement 0.000671 0.00104 0.630## 4 aid 0.0000476 0.00105 4.46## 5 air 0.00214 0.000297 -2.85## 6 american 0.00203 0.00168 -0.270## 7 analysts 0.00109 0.000000578 -10.9## 8 area 0.00137 0.000231 -2.57## 9 army 0.000262 0.00105 2.00## 10 asked 0.000189 0.00156 3.05## # ... with 188 more rows
图显示了这两个主题之间差别最大的词。
R语言中对文本数据进行主题模型topicmodeling分析
图β中差别最大的词β 在主题2和主题1之间
咱们能够看到,话题2中更常见的词包括“民主”和“共和党”等政党,以及“dukakis”和“gorbachev”等政治家的名字。主题1的特色是“日元”和“美圆”等货币以及“指数”,“价格”和“利率”等金融术语。这有助于确认算法肯定的两个主题是政治和财务新闻。
除了将每一个主题评估为单词混合以外,LDA还将每一个文档建模为混合主题。咱们能够检查每一个文档的每一个主题几率,称为γγ(“伽玛”),其matrix = "gamma"论点是tidy()。
## # A tibble: 4,492 x 3## document topic gamma## ## 1 1 1 0.248## 2 2 1 0.362## 3 3 1 0.527## 4 4 1 0.357## 5 5 1 0.181## 6 6 1 0.000588## 7 7 1 0.773## 8 8 1 0.00445## 9 9 1 0.967## 10 10 1 0.147## # ... with 4,482 more rows
这些值中的每个都是该文档中从该主题生成的单词的估计比例。例如,该模型估计文档1中单词的大约24.8%是从主题1生成的。
咱们能够看到,这些文档中的许多文档都是从两个主题的混合中抽取出来的,但文档6几乎彻底是从主题2中得出的,其中有一个γγ从主题1接近零。为了检查这个答案,咱们能够tidy()使用文档术语矩阵,并检查该文档中最多见的词。
## # A tibble: 287 x 3## document term count## ## 1 6 noriega 16.## 2 6 panama 12.## 3 6 jackson 6.## 4 6 powell 6.## 5 6 administration 5.## 6 6 economic 5.## 7 6 general 5.## 8 6 i 5.## 9 6 panamanian 5.## 10 6 american 4.## # ... with 277 more rows
根据最多见的词汇,这彷佛是一篇关于美国政府与巴拿马独裁者曼努埃尔诺列加之间关系的文章,这意味着该算法将其置于专题2(做为政治/国家新闻)是正确的。
在考察一个统计方法时,在一个很是简单的状况下,你能够知道“正确的答案”。例如,咱们能够收集一组明确与四个不一样主题相关的文档,而后执行主题建模,以查看该算法是否能够正确区分这四个组。这让咱们仔细检查该方法是否有用,并了解它如何以及什么时候会出错。咱们将使用经典文献中的一些数据来尝试。
假设一个破坏者闯入你的书房并撕毁你的四本书:
Charles Dickens的伟大指望HG Wells 的世界大战
Jules Verne 在海底的两万里
傲慢与偏见简·奥斯汀
咱们将使用第3章介绍的gutenbergr包检索这四本书的内容。
titles <- c("Twenty Thousand Leagues under the Sea","The War of the Worlds","Pride and Prejudice","Great Expectations")
做为预处理,咱们将它们分红不一样的章节,使用tidytext unnest_tokens()将它们分离成单词,而后删除stop_words。咱们将每一章都视为一个单独的“文档”,每一个章节都有一个像“ Great Expectations_1或”这样的名字Pride and Prejudice_11。(在其余应用程序中,每一个文档多是一篇报纸文章或一篇博客文章)。
## # A tibble: 104,721 x 3## document word n## ## 1 Great Expectations_57 joe 88## 2 Great Expectations_7 joe 70## 3 Great Expectations_17 biddy 63## 4 Great Expectations_27 joe 58## 5 Great Expectations_38 estella 58## 6 Great Expectations_2 joe 56## 7 Great Expectations_23 pocket 53## 8 Great Expectations_15 joe 50## 9 Great Expectations_18 joe 50## 10 The War of the Worlds_16 brother 50## # ... with 104,711 more rows
如今咱们的数据框word_counts是整齐的,每行一个文档,但topicmodels包须要一个DocumentTermMatrix。 咱们能够将每行一个令牌转换为DocumentTermMatrix带有tidytext的表cast_dtm()。
chapters_dtm <- word_counts %>% cast_dtm(document, word, n)chapters_dtm
而后,咱们可使用该LDA()功能建立一个四主题模型。在这种状况下,咱们知道咱们正在寻找四个主题,由于有四本书; 在其余问题中,咱们可能须要尝试一些不一样的值k。
chapters_lda <- LDA(chapters_dtm,k =4,control =list(seed =1234))chapters_lda ## A LDA_VEM topic model with 4 topics.
就像咱们在美联社的数据中所作的那样,咱们能够检查每一个主题的每一个词的几率。
## # A tibble: 72,860 x 3## topic term beta## ## 1 1 joe 5.83e-17## 2 2 joe 3.19e-57## 3 3 joe 4.16e-24## 4 4 joe 1.45e- 2## 5 1 biddy 7.85e-27## 6 2 biddy 4.67e-69## 7 3 biddy 2.26e-46## 8 4 biddy 4.77e- 3## 9 1 estella 3.83e- 6## 10 2 estella 5.32e-65## # ... with 72,850 more rows
这已将模型转换为每行一个主题的单行格式。对于每一个组合,该模型计算该术语从该主题生成的几率。例如,术语“joe”从主题1,2或3产生几乎为零的几率,但它占主题4的1.45%。
咱们可使用dplyr top_n()来查找每一个主题中的前5个术语。
top_terms <- chapter_topics %>% group_by(topic) %>% top_n(5, beta) %>% ungroup() %>% arrange(topic, -beta)top_terms ## # A tibble: 20 x 3## topic term beta## ## 1 1 elizabeth 0.0141## 2 1 darcy 0.00881## 3 1 miss 0.00871## 4 1 bennet 0.00695## 5 1 jane 0.00650## 6 2 captain 0.0155## 7 2 nautilus 0.0131## 8 2 sea 0.00885## 9 2 nemo 0.00871## 10 2 ned 0.00803## 11 3 people 0.00680## 12 3 martians 0.00651## 13 3 time 0.00535## 14 3 black 0.00528## 15 3 night 0.00448## 16 4 joe 0.0145## 17 4 time 0.00685## 18 4 pip 0.00682## 19 4 looked 0.00637## 20 4 miss 0.00623
ggplot2可视化
R语言中对文本数据进行主题模型topicmodeling分析
本分析中的每一个文档都表明一个章节。所以,咱们可能想知道哪些主题与每一个文档相关联。
## # A tibble: 772 x 3## document topic gamma## ## 1 Great Expectations_57 1 0.0000135## 2 Great Expectations_7 1 0.0000147## 3 Great Expectations_17 1 0.0000212## 4 Great Expectations_27 1 0.0000192## 5 Great Expectations_38 1 0.354## 6 Great Expectations_2 1 0.0000172## 7 Great Expectations_23 1 0.551## 8 Great Expectations_15 1 0.0168## 9 Great Expectations_18 1 0.0000127## 10 The War of the Worlds_16 1 0.0000108## # ... with 762 more rows
这些值中的每个都是该文档中从该主题生成的单词的估计比例。例如,该模型估计,Great Expectations_57文档中的每一个单词只有来自主题1(“傲慢与偏见”)的几率为0.00135%。
如今咱们有了这些话题几率,咱们能够看到咱们的无监督学习在区分四本书方面作得如何。咱们但愿书中的章节大部分(或彻底)都是从相应的主题中产生的。
首先,咱们将文档名称从新分为标题和章节,以后咱们能够将每一个文档的每一个主题几率可视化。
## # A tibble: 772 x 4## title chapter topic gamma## ## 1 Great Expectations 57 1 0.0000135## 2 Great Expectations 7 1 0.0000147## 3 Great Expectations 17 1 0.0000212## 4 Great Expectations 27 1 0.0000192## 5 Great Expectations 38 1 0.354## 6 Great Expectations 2 1 0.0000172## 7 Great Expectations 23 1 0.551## 8 Great Expectations 15 1 0.0168## 9 Great Expectations 18 1 0.0000127## 10 The War of the Worlds 16 1 0.0000108## # ... with 762 more rows
R语言中对文本数据进行主题模型topicmodeling分析
咱们注意到,几乎全部来自“ 傲慢与偏见”,“世界大战 ”和“ 海底二万里 ”的章节都被认为是一个单独的主题。
chapter_classifications <- chapters_gamma %>% group_by(title, chapter) %>% top_n(1, gamma) %>% ungroup()chapter_classifications
而后,咱们能够将每本书与每本书的“共识”主题(其章节中最多见的主题)进行比较,并查看哪些主题常常被错误识别。
LDA算法的一个步骤是将每一个文档中的每一个单词分配给一个主题。文档中的单词越多,则一般gamma该文档 - 主题分类的权重越大()。
咱们可能想要采用原始文档字对,并查找每一个文档中的哪些字词分配给哪一个主题。
assignments <- augment(chapters_lda,data =chapters_dtm)assignments
.topic每一个文档中每一个术语都分配了一个主题。(augment老是以开头添加额外的列.,以防止覆盖现有的列)。咱们能够将此assignments表格与共识书籍标题结合起来,找出哪些词语被错误分类。
## # A tibble: 104,721 x 6## title chapter term count .topic consensus## ## 1 Great Expectations 57 joe 88. 4. Great Expectations## 2 Great Expectations 7 joe 70. 4. Great Expectations## 3 Great Expectations 17 joe 5. 4. Great Expectations## 4 Great Expectations 27 joe 58. 4. Great Expectations## 5 Great Expectations 2 joe 56. 4. Great Expectations## 6 Great Expectations 23 joe 1. 4. Great Expectations## 7 Great Expectations 15 joe 50. 4. Great Expectations## 8 Great Expectations 18 joe 50. 4. Great Expectations## 9 Great Expectations 9 joe 44. 4. Great Expectations## 10 Great Expectations 13 joe 40. 4. Great Expectations## # ... with 104,711 more rows
真正的book(title)和分配给它的book()的组合consensus对于进一步的探索是有用的。例如,咱们能够将混淆矩阵可视化,使用dplyr's count()和ggplot2 geom_tile显示一本书中的单词被分配给另外一本书的频率。
R语言中对文本数据进行主题模型topicmodeling分析
混淆矩阵显示了LDA分配每本书的单词的位置。这张表的每一行都表明每一个单词来自的真实书籍,每一列表明它分配的书籍。
什么是最多见的错误的话?
wrong_words <- assignments %>% filter(title != consensus)wrong_words ## # A tibble: 3,500 x 4## title consensus term n## ## 1 Great Expectations Pride and Prejudice love 44.## 2 Great Expectations Pride and Prejudice sergeant 37.## 3 Great Expectations Pride and Prejudice lady 32.## 4 Great Expectations Pride and Prejudice miss 26.## 5 Great Expectations The War of the Worlds boat 25.## 6 Great Expectations Pride and Prejudice father 19.## 7 Great Expectations The War of the Worlds water 19.## 8 Great Expectations Pride and Prejudice baby 18.## 9 Great Expectations Pride and Prejudice flopson 18.## 10 Great Expectations Pride and Prejudice family 16.## # ... with 3,490 more rows
咱们能够看到, 也经常将一些词语分配给“世界的傲慢与偏见”或“战争”。对于其中的一些词,如“爱”和“女士”,这是由于它们在“傲慢与偏见”中更常见(咱们能够经过检查计数来证明)。
另外一方面,有一些错误分类的词在他们错误分配的小说中从未出现过。例如,咱们能够确认只出如今“flopson” 远大前程,即便它分配给了“傲慢与偏见” 。
word_counts %>% filter(word == "flopson") ## # A tibble: 3 x 3## document word n## ## 1 Great Expectations_22 flopson 10## 2 Great Expectations_23 flopson 7## 3 Great Expectations_33 flopson 1
LDA()topicmodels包中的函数只是潜在Dirichlet分配算法的一个实现。例如,mallet包(Mimno 2013)实现了一个用于文本分类工具的MALLET Java包的包装,而tidytext包也为该模型输出提供了整理器。
library(mallet)# create a vector with one string per chaptercollapsed
然而,一旦模型建立完成,咱们就能够以几乎相同的方式使用本章其他部分描述的函数tidy()和augment()函数。这包括提取每一个主题中的单词几率或每一个文档中的主题。
可使用ggplot2以与LDA输出相同的方式探索和可视化模型。