R语言中对文本数据进行主题模型topicmodeling分析

原文链接:https://segmentfault.com/a/1190000015322229

主题建模

在文本挖掘中,我们经常收集一些文档集合,例如博客文章或新闻文章,我们希望将其分成自然组,以便我们可以分别理解它们。主题建模是对这些文档进行无监督分类的一种方法,类似于对数字数据进行聚类,即使我们不确定要查找什么,也可以找到自然的项目组。

潜在狄利克雷分配(LDA)是拟合主题模型特别流行的方法。它将每个文档视为主题的混合体,并将每个主题看作是单词的混合体。这允许文档在内容方面相互“重叠”,而不是分离成离散的组,以反映自然语言的典型用法。

R语言中对文本数据进行主题模型topicmodeling分析

结合主题建模的文本分析流程图。topicmodels包采用Document-Term Matrix作为输入,并生成一个可以通过tidytext进行处理的模型,以便可以使用dplyr和ggplot2对其进行处理和可视化。
clipboard.png

如图所示,我们可以使用 文本原理来处理主题建模 。

潜在狄利克雷分配

潜在Dirichlet分配是主题建模中最常用的算法之一。

每个文档都是主题的混合体。我们设想每个文档可能包含来自几个主题的文字,特别是比例。例如,在双主题模型中,我们可以说“文档1是90%的主题A和10%的主题B,而文档2是30%的主题A和70%的主题B.”

每个主题都是词汇的混合。例如,我们可以想象一个美国新闻的两个主题模型,一个话题是“政治”,一个是“娱乐”。政治话题中最常见的词语可能是“总统”,“国会”和“政府“,而娱乐主题可以由诸如”电影“,”电视“和”演员“之类的词组成。

LDA是一种同时估计这两种情况的数学方法:查找与每个主题相关的单词混合,同时确定描述每个文档的主题混合。这个算法有很多现有的实现,我们将深入探讨其中的一个。

library(topicmodels)data("AssociatedPress")AssociatedPress

  : term frequency (tf)

我们可以使用LDA()topicmodels包中的函数设置k = 2来创建两个主题的LDA模型。

实际上几乎所有的主题模型都会使用更大的模型k,但我们很快就会看到,这种分析方法可以扩展到更多的主题。

此函数返回一个包含模型拟合完整细节的对象,例如单词如何与主题关联以及主题如何与文档关联。

# 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

clipboard.png

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

图显示了这两个主题之间差异最大的词。

clipboard.png

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

章节中的LDA

现在我们的数据框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可视化

clipboard.png

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

clipboard.png

R语言中对文本数据进行主题模型topicmodeling分析

我们注意到,几乎所有来自“ 傲慢与偏见”,“世界大战 ”和“ 海底二万里 ”的章节都被认为是一个单独的主题。

chapter_classifications <- chapters_gamma %>%  group_by(title, chapter) %>%  top_n(1, gamma) %>%  ungroup()chapter_classifications

然后,我们可以将每本书与每本书的“共识”主题(其章节中最常见的主题)进行比较,并查看哪些主题经常被错误识别。

通过词汇分配:augment

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显示一本书中的单词被分配给另一本书的频率。

clipboard.png

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实现

LDA()topicmodels包中的函数只是潜在Dirichlet分配算法的一个实现。例如,mallet包(Mimno 2013)实现了一个用于文本分类工具的MALLET Java包的包装,而tidytext包也为该模型输出提供了整理器。

library(mallet)# create a vector with one string per chaptercollapsed 

然而,一旦模型创建完成,我们就可以以几乎相同的方式使用本章其余部分描述的函数tidy()和augment()函数。这包括提取每个主题中的单词概率或每个文档中的主题。

可以使用ggplot2以与LDA输出相同的方式探索和可视化模型。

展开阅读全文

没有更多推荐了,返回首页