文本分析:主题建模
library(tidyverse)
theme_set( theme_bw())
目标
- 定义主题建模
- 解释Latent Dirichlet分配以及此过程的工作原理
- 演示如何使用LDA从一组已知主题中恢复主题结构
- 演示如何使用LDA从一组未知主题中恢复主题结构
- 确定为k
- 选择适当参数的方法
- ķ
主题建模
通常,当我们在线搜索信息时,有两种主要方法:
- 关键字 - 使用搜索引擎并输入与我们想要查找的内容相关的单词
- 链接 - 使用网络的网络结构在页面之间移动。链接的页面可能共享相似或相关的内容。
另一种方法是通过主题搜索和探索文档。例如,David Blei建议搜索“纽约时报”的完整历史。广泛的主题可能与文章中的各个部分(外交政策,国家事务,体育)有关,但这些部分内或之间可能存在特定主题(中国外交政策,中东冲突,美国与俄罗斯的关系)。如果文档按这些主题分组,我们可以跟踪NYT随时间报告这些问题的演变,或者检查不同主题的讨论是如何相互交叉的。
为此,我们需要有关每篇文章主题的详细信息。对该语料库进行手工编码将非常耗时,更不用说在开始编码之前需要知道文档的主题结构。对于绝大多数的corpa来说,这不是一种可行的方法。
相反,我们可以使用概率主题模型,分析原始文本文档中的单词的统计算法来揭示语料库和单个文档本身的主题结构。在分析之前,它们不需要对文档进行任何手工编码或标记 - 相反,算法来自对文本的分析。
潜在的Dirichlet分配
LDA假定语料库中的每个文档都包含在整个语料库中找到的混合主题。主题结构是隐藏的 - 我们只能观察文档和文字,而不是主题本身。因为结构是隐藏的(也称为潜在的),所以该方法试图在给定已知单词和文档的情况下推断主题结构。
食物和动物
假设您有以下句子:
- 我早餐吃了香蕉和菠菜冰沙。
- 我喜欢吃西兰花和香蕉。
- 龙猫和小猫很可爱。
- 我姐姐昨天收养了一只小猫。
- 看看这只可爱的仓鼠嚼着一块西兰花。
Latent Dirichlet分配是一种自动发现这些句子所包含的主题的方法。例如,给定这些句子并询问2个主题,LDA可能会产生类似的东西
- 句子1和2:100%主题A.
- 句子3和4:100%主题B.
- 句子5:60%主题A,40%主题B.
- 主题A:30%西兰花,15%香蕉,10%早餐,10%咀嚼,......
- 主题B:20%的龙猫,20%的小猫,20%的可爱,15%的仓鼠,......
您可以推断出主题A是关于食物的主题,主题B是关于可爱动物的主题。但是,LDA没有以这种方式明确地确定主题。它所能做的就是告诉你特定单词与主题相关的概率。
LDA文档结构
LDA将文档表示为以某些概率吐出单词的主题混合。它假设文档以下列方式生成:在编写每个文档时,您
- 确定单词数N.
- ñ 该文件将有
- 为文档选择主题混合(根据固定K
- 集上的Dirichlet概率分布
- ķ主题)。例如,假设我们上面有两个食物和可爱的动物主题,你可以选择由1/3食物和2/3可爱动物组成的文件。
- 通过以下方式生成文档中的每个单词:
- 首先选择一个主题(根据您在上面采样的分布;例如,您可以选择1/3概率的食物主题和2/3概率的可爱动物主题)。
- 然后使用主题生成单词本身(根据主题的多项分布)。例如,食物主题可能输出概率为30%的“西兰花”,概率为15%的“香蕉”,依此类推。
假设这个文档集合的生成模型,LDA然后尝试从文档中回溯以找到可能已经生成集合的一组主题。
食物和动物
我们怎么能在前面的例子中生成句子?生成文档D时
d:
- 决定D
- d 将是关于食物的1/2和关于可爱动物的1/2。
- 选择5为D中
- 的单词数
- d。
- 从食物主题中选择第一个单词,然后给出“西兰花”这个词。
- 选择第二个词来自可爱的动物主题,它给你“熊猫”。
- 选择第三个词来自可爱的动物话题,给你“可爱”。
- 选择第四个词来源于食物主题,给你“樱桃”。
- 从食物主题中选出第五个词,给你“吃”。
因此,在LDA模型下生成的文件将是“西兰花熊猫可爱的樱桃吃”(请记住,LDA使用的是词袋模型)。
通过LDA学习主题结构
现在假设您有一组文档。你选择了一些固定数量的K.
ķ要发现的主题,并希望使用LDA来学习每个文档的主题表示以及与每个主题相关联的单词。你怎么做到这一点?一种方式(称为崩溃的吉布斯采样)如下:
- 浏览每个文档,并将文档中的每个单词随机分配给K中的一个
- ķ 主题
- 请注意,此随机分配已经为您提供了所有主题的所有文档和单词分布的主题表示。但由于它是随机的,这不是一个非常准确的结构。
- 换句话说,在这一步中,我们假设除了当前单词之外的所有主题分配都是正确的,然后使用我们的文档生成模型更新当前单词的赋值。
- 重复上一步骤很多次(真的很多次,比如最少10,000次),你最终会达到一个大致稳定的状态,你的任务非常好
- 您可以使用这些分配来估计两件事:
- 每个文档的主题混合(通过计算分配给该文档中每个主题的单词的比例)
- 与每个主题相关的单词(通过计算分配给每个主题的单词的比例)
具有已知主题结构的LDA
如果先验地知道一组文档的主题结构,则LDA可能是有用的。例如,假设您有四本书:
- 查尔斯狄更斯的远大前程
- HG威尔斯的世界大战
- 朱尔斯凡尔纳在海底的二万个联盟
- 简奥斯汀的傲慢与偏见
一个破坏者已经闯入你的家,并将书籍撕成了单独的章节,并将它们留在一个大堆中。我们可以使用LDA和主题建模来发现章节与不同主题(即书籍)的关系。
我们将使用gutenbergr包检索这四本书:
titles <- c("Twenty Thousand Leagues under the Sea", "The War of the Worlds",
%in% titles) %>%
gutenberg_download(meta_fields = "title")
作为预处理,我们将这些分为章节,使用tidytext unnest_tokens将它们分成单词,然后删除stop_words。我们将每一章都视为一个单独的“文档” 。
library(tidytext)
library(stringr)
by_chapter <- books %>%
group_by(title) %>%
mutate(chapter = cumsum( str_detect(text, regex("^chapter ", ignore_case = TRUE)))) %>%
ungroup() %>%
filter(chapter > 0)
anti_join(stop_words) %>%
count(title_chapter, word, sort