R語(yǔ)言文本主題模型之潛在語(yǔ)義分析(LDA:Latent Dirichlet Allocation)
原文:http://tecdat.cn/?p=3897
?
文本分析:主題建模
library(tidyverse)
theme_set(?theme_bw())
?
目標(biāo)
定義主題建模
解釋Latent Dirichlet以及此過(guò)程的工作原理
演示如何使用LDA從一組已知主題中找到主題結(jié)構(gòu)
演示如何使用LDA從一組未知主題中找到主題結(jié)構(gòu)
確定k
選擇適當(dāng)參數(shù)的方法
主題建模
?
通常,當(dāng)我們?cè)诰€搜索信息時(shí),有兩種主要方法:
關(guān)鍵字 - 使用搜索引擎并輸入與我們想要查找的內(nèi)容相關(guān)的單詞
鏈接。鏈接的頁(yè)面可能共享相似或相關(guān)的內(nèi)容。
另一種方法是通過(guò)主題搜索和探索文檔。廣泛的主題可能與文章中的各個(gè)部分(國(guó)家事務(wù),體育)有關(guān),但這些部分內(nèi)或之間可能存在特定主題。
為此,我們需要有關(guān)每篇文章主題的詳細(xì)信息。對(duì)該語(yǔ)料庫(kù)進(jìn)行手工編碼將非常耗時(shí),更不用說(shuō)在開始編碼之前需要知道文檔的主題結(jié)構(gòu)。
因此,我們可以使用概率主題模型,分析原始文本文檔中的單詞的統(tǒng)計(jì)算法來(lái)揭示語(yǔ)料庫(kù)和單個(gè)文檔本身的主題結(jié)構(gòu)。在分析之前,它們不需要對(duì)文檔進(jìn)行任何手工編碼或標(biāo)記 - 相反,算法來(lái)自對(duì)文本的分析。
潛在Dirichlet分配
LDA假定語(yǔ)料庫(kù)中的每個(gè)文檔都包含在整個(gè)語(yǔ)料庫(kù)中的混合主題。主題結(jié)構(gòu)是隱藏的 - 我們只能觀察文檔和文字,而不是主題本身。因?yàn)榻Y(jié)構(gòu)是隱藏的(也稱為潛在的),所以該方法試圖在給定已知單詞和文檔的情況下推斷主題結(jié)構(gòu)。
食物和動(dòng)物
假設(shè)您有以下句子:
我早餐吃了香蕉和菠菜。
我喜歡吃西蘭花和香蕉。
龍貓和小貓很可愛。
我姐姐昨天收養(yǎng)了一只小貓。
看看這只可愛的倉(cāng)鼠嚼著一塊西蘭花。
Latent Dirichlet分配是一種自動(dòng)發(fā)現(xiàn)這些句子所包含的主題的方法。例如,給定這些句子并詢問(wèn)2個(gè)主題,LDA可能會(huì)產(chǎn)生類似的東西
句子1和2:100%主題A.
句子3和4:100%主題B.
句子5:60%主題A,40%主題B.
主題A:30%西蘭花,15%香蕉,10%早餐,10%咀嚼,......
主題B:20%龍貓,20%小貓,20%可愛,15%倉(cāng)鼠,......
您可以推斷出主題A是關(guān)于食物的主題,主題B是關(guān)于可愛動(dòng)物的主題。但是,LDA沒有以這種方式明確地確定主題。它所能做的就是告訴你特定單詞與主題相關(guān)的概率。
LDA文檔結(jié)構(gòu)
LDA將文檔表示為以某些概率單詞的主題組合。它假設(shè)文檔以下列方式生成:在編寫每個(gè)文檔時(shí),您
確定單詞數(shù)N.
為文檔選擇主題(根據(jù)K個(gè)主題)
例如,假設(shè)我們上面有兩個(gè)食物和可愛的動(dòng)物主題。
通過(guò)以下方式生成文檔中的每個(gè)單詞:
首先選擇一個(gè)主題(根據(jù)您在上面采樣的分配;例如,您可以選擇1/3概率的食物主題和2/3概率的可愛動(dòng)物主題)。
然后使用主題生成單詞本身(根據(jù)主題分配)。例如,食物主題可能輸出概率為30%的“西蘭花”,概率為15%的“香蕉”,依此類推。
?
我們?cè)趺茨茉谇懊娴睦又猩删渥??生成文檔D時(shí):
D 將是一半關(guān)于食物和一半關(guān)于可愛動(dòng)物。
選擇5為D的單詞數(shù)
從食物主題中選擇第一個(gè)詞,然后給出“西蘭花”這個(gè)詞。
選擇第二個(gè)詞來(lái)自可愛的動(dòng)物主題,如“熊貓”。
選擇第三個(gè)詞來(lái)自可愛的動(dòng)物主題,如“可愛”。
選擇第四個(gè)詞來(lái)源于食物主題,如“櫻桃”。
從食物主題中選出第五個(gè)詞,如“吃”。
因此,在LDA模型下生成的文件將是“可愛的熊貓吃櫻桃和西蘭花”(LDA使用的是詞袋模型)。
通過(guò)LDA學(xué)習(xí)主題模型
現(xiàn)在假設(shè)您有一組文檔。你選擇了一些固定數(shù)量的K.
?是要發(fā)現(xiàn)的主題,我們希望使用LDA來(lái)學(xué)習(xí)每個(gè)文檔的主題表示以及與每個(gè)主題相關(guān)聯(lián)的單詞。怎么做到這一點(diǎn)?一種方式(稱為吉布斯采樣)如下:
瀏覽每個(gè)文檔,并將文檔中的每個(gè)單詞隨機(jī)分配給K中的一個(gè)? 主題
但由于它是隨機(jī)的,這不是一個(gè)非常準(zhǔn)確的結(jié)構(gòu)。
換句話說(shuō),在這一步中,我們假設(shè)除了當(dāng)前單詞之外的所有主題分配都是正確的,然后使用我們的文檔生成模型更新當(dāng)前單詞的賦值。
重復(fù)上一步驟很多次,你最終會(huì)達(dá)到一個(gè)大致穩(wěn)定的狀態(tài)
您可以使用這些分配來(lái)估計(jì)兩件事:
每個(gè)文檔的主題(通過(guò)計(jì)算分配給該文檔中每個(gè)主題的單詞的比例)
與每個(gè)主題相關(guān)的單詞(通過(guò)計(jì)算分配給每個(gè)主題的單詞的比例)
具有已知主題結(jié)構(gòu)的LDA
如果先驗(yàn)地知道一組文檔的主題結(jié)構(gòu),LDA可能是有用的。
我們可以使用LDA和主題建模來(lái)發(fā)現(xiàn)章節(jié)與不同主題(即書籍)的關(guān)系。
作為預(yù)處理,我們將這些分為章節(jié),使用tidytext unnest_tokens將它們分成單詞,然后刪除stop_words。我們將每一章都視為一個(gè)單獨(dú)的“文檔” 。
by_chapter <- books %>%
group_by(title) %>%
mutate(chapter =?cumsum(?str_detect(text,?regex("^chapter ", ignore_case = TRUE)))) %>%
ungroup() %>%
count(title_chapter, word, sort = TRUE) %>%
ungroup()
# Joining, by = "word"
word_counts
# # A tibble: 104,721 × 3
# title_chapter word n
# <chr> <chr> <int>
# 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
?
?
潛在狄利克雷分配(latnet?Dirichlet?allocation, LDA)模型
topicmodels包需要一個(gè)DocumentTermMatrix(來(lái)自tm包)。我們可以用cast_dtm函數(shù)轉(zhuǎn)換為DocumentTermMatrix:
chapters_dtm
# <<DocumentTermMatrix (documents: 193, terms: 18215)>>
# Non-/sparse entries: 104721/3410774
# Sparsity : 97%
# Maximal term length: 19
# Weighting : term frequency (tf)
?
現(xiàn)在我們準(zhǔn)備創(chuàng)建一個(gè)四主題LDA模型。
chapters_lda <-?LDA(chapters_dtm, k = 4, control =?list(seed = 1234))
chapters_lda
## A LDA_VEM topic model with 4 topics.
?
在這種情況下,我們知道有四個(gè)主題,因?yàn)橛兴谋緯? 這是了解潛在主題結(jié)構(gòu)的價(jià)值
seed = 1234設(shè)置隨機(jī)迭代過(guò)程的起點(diǎn)。如果我們沒有設(shè)置種子,那么每次運(yùn)行腳本時(shí)我們都可以估算出略有不同的模型
我們從動(dòng)詞開始。
library(tidytext)
chapters_lda_td <-?tidy(chapters_lda)
chapters_lda_td
# # A tibble: 72,860 × 3
# topic term beta
# <int> <chr> <dbl>
# 1 1 joe 5.830326e-17
# 2 2 joe 3.194447e-57
# 3 3 joe 4.162676e-24
# 4 4 joe 1.445030e-02
# 5 1 biddy 7.846976e-27
# 6 2 biddy 4.672244e-69
# 7 3 biddy 2.259711e-46
# 8 4 biddy 4.767972e-03
# 9 1 estella 3.827272e-06
# 10 2 estella 5.316964e-65
# # ... with 72,850 more rows
?
?
我們可以使用dplyr's top_n來(lái)查找每個(gè)主題中的前5個(gè)詞:
top_n(5, beta) %>%
ungroup() %>%
arrange(topic, -beta)
top_terms
# # A tibble: 20 × 3
# topic term beta
# <int> <chr> <dbl>
# 1 1 elizabeth 0.014107538
# 2 1 darcy 0.008814258
# 3 1 miss 0.008706741
# 4 1 bennet 0.006947431
# 5 1 jane 0.006497512
?
可視化
ggplot(?aes(term, beta, fill =?factor(topic))) +
geom_bar(alpha = 0.8, stat
?

這些主題與四本書非常明顯相關(guān)
“nemo”,“sea”和“nautilus”屬于海底兩萬(wàn)里
“jane”,“darcy”和“elizabeth”屬于傲慢與偏見
另請(qǐng)注意,LDA()不會(huì)為每個(gè)主題分配任何標(biāo)簽。它們只是主題1,2,3和4. 我們可以推斷這些與每本書有關(guān),但它僅僅是我們的推論。
按文檔分類
每一章都是本分析中的“文件”。因此,我們可能想知道哪些主題與每個(gè)文檔相關(guān)聯(lián)。我們可以把這些章節(jié)放回正確的書中嗎?
chapters_lda_gamma
# # A tibble: 772 × 3
# document topic gamma
# <chr> <int> <dbl>
# 1 Great Expectations_57 1 1.351886e-05
# 2 Great Expectations_7 1 1.470726e-05
# 3 Great Expectations_17 1 2.117127e-05
# 4 Great Expectations_27 1 1.919746e-05
# 5 Great Expectations_38 1 3.544403e-01
# 6 Great Expectations_2 1 1.723723e-05
# 7 Great Expectations_23 1 5.507241e-01
# 8 Great Expectations_15 1 1.682503e-02
# 9 Great Expectations_18 1 1.272044e-05
# 10 The War of the Worlds_16 1 1.084337e-05
# # ... with 762 more rows
?
每行每個(gè)主題一個(gè)文檔。現(xiàn)在我們已經(jīng)有了這些文檔分類,我們可以看到我們的無(wú)監(jiān)督學(xué)習(xí)在區(qū)分四本書方面做得如何。
首先,我們將文檔名稱重新分為標(biāo)題和章節(jié):
chapters_lda_gamma <- chapters_lda_gamma %>%
separate(document,?c("title", "chapter"), sep = "_", convert = TRUE)
chapters_lda_gamma
# # A tibble: 772 × 4
# title chapter topic gamma
# * <chr> <int> <int> <dbl>
# 1 Great Expectations 57 1 1.351886e-05
# 2 Great Expectations 7 1 1.470726e-05
# 3 Great Expectations 17 1 2.117127e-05
# 4 Great Expectations 27 1 1.919746e-05
# 5 Great Expectations 38 1 3.544403e-01
# 6 Great Expectations 2 1 1.723723e-05
# 7 Great Expectations 23 1 5.507241e-01
# 8 Great Expectations 15 1 1.682503e-02
# 9 Great Expectations 18 1 1.272044e-05
# 10 The War of the Worlds 16 1 1.084337e-05
# # ... with 762 more rows
然后我們檢查每個(gè)章節(jié)的正確部分:
ggplot(chapters_lda_gamma,?aes(gamma, fill =?factor(topic))) +
geom_histogram() +
facet_wrap(~ title, nrow = 2)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
?

我們注意到,幾乎所有來(lái)自“ 傲慢與偏見”,“世界大戰(zhàn) ”和“ 海底兩萬(wàn)里 ”的章節(jié)都被確定為一個(gè)章節(jié)。
chapter_classifications <- chapters_lda_gamma %>%
group_by(title, chapter) %>%
top_n(1, gamma) %>%
ungroup() %>%
arrange(gamma)
chapter_classifications
# # A tibble: 193 × 4
# title chapter topic gamma
# <chr> <int> <int> <dbl>
# 1 Great Expectations 54 3 0.4803234
# 2 Great Expectations 22 4 0.5356506
# 3 Great Expectations 31 4 0.5464851
# 4 Great Expectations 23 1 0.5507241
# 5 Great Expectations 33 4 0.5700737
# 6 Great Expectations 47 4 0.5802089
# 7 Great Expectations 56 4 0.5984806
# 8 Great Expectations 38 4 0.6455341
# 9 Great Expectations 11 4 0.6689600
# 10 Great Expectations 44 4 0.6777974
# # ... with 183 more rows
?
主題建模期望最大化算法中的一個(gè)重要步驟是將每個(gè)文檔中的每個(gè)單詞分配給一個(gè)主題。文檔中的單詞越多分配給該主題,通常,權(quán)重(gamma)將在該文檔主題分類上。
?
具有未知主題結(jié)構(gòu)的LDA
通常在使用LDA時(shí),您實(shí)際上并不知道文檔的基礎(chǔ)主題結(jié)構(gòu)。通常,這就是您首先使用LDA分析文本的原因。
美聯(lián)社文章
數(shù)據(jù)是1992年發(fā)布的文章樣本的文檔術(shù)語(yǔ)矩陣。讓我們將它們加載到R中并轉(zhuǎn)換為整齊格式。
# 1 1 adding 1
## 2 1 adult 2
## 3 1 ago 1
## 4 1 alcohol 1
## 5 1 allegedly 1
## 6 1 allen 1
## 7 1 apparently 2
## 8 1 appeared 1
## 9 1 arrested 1
## 10 1 assault 1
## # ... with 302,021 more rows
為什么要先整理一下?因?yàn)樵嫉膁tm包含停用詞 - 我們想在建模數(shù)據(jù)之前刪除它們。然后將數(shù)據(jù)轉(zhuǎn)換回文檔矩陣。
# Sparsity : 99%
## Maximal term length: 18
## Weighting : term frequency (tf)
每個(gè)主題的頂級(jí)詞是什么樣的?
?
group_by(topic) %>%
top_n(5, beta) %>%
ungroup() %>%
arrange(topic, -beta)
top_terms
## # A tibble: 20 × 3
## topic term beta
## <int> <chr> <dbl>
## 1 1 soviet 0.009502197
## 2 1 government 0.009198486
## 3 1 president 0.007046753
## 4 1 united 0.006507324
## 5 1 people 0.005402784
## 6 2 people 0.007454587
## 7 2 police 0.006433472
## 8 2 city 0.003996852
## 9 2 time 0.003369658
## 10 2 school 0.003058213
## 11 3 court 0.006850723
## 12 3 bush 0.006510244
## 13 3 president 0.005777216
## 14 3 federal 0.005512805
## 15 3 house 0.004657550
## 16 4 percent 0.023766679
## 17 4 million 0.012489935
## 18 4 billion 0.009864418
## 19 4 market 0.008402463
## 20 4 prices 0.006693626
top_terms %>%
) +
coord_flip()

這四個(gè)主題通常用于描述:

如果我們?cè)O(shè)置k=12
我們的結(jié)果如何變化?
group_by(topic) %>%
top_n(5, beta) %>%
ungroup() %>%
arrange(topic, -beta)
top_terms
## # A tibble: 60 × 3
## topic term beta
## <int> <chr> <dbl>
## 1 1 military 0.011691176
## 2 1 united 0.011598436
## 3 1 iraq 0.010618221
## 4 1 president 0.009498227
## 5 1 american 0.008253379
## 6 2 dukakis 0.009819260
## 7 2 bush 0.007300830
## 8 2 campaign 0.006366915
## 9 2 people 0.006098596
## 10 2 school 0.005208529
## # ... with 50 more rows
?

?嗯,這些主題似乎更具體,但不易理解。

等。
LDA的某些方面是由直覺思維驅(qū)動(dòng)的。但是我們可以提供輔助方法。
困惑度是概率模型預(yù)測(cè)樣本的程度的統(tǒng)計(jì)量度。你估計(jì)LDA模型。然后給出由主題表示的理論單詞分配,將其與實(shí)際主題或文檔中單詞的分配進(jìn)行比較。
perplexity為給定模型計(jì)算該值的函數(shù)。
perplexity(ap_lda)
## [1] 2301.814
但是,統(tǒng)計(jì)數(shù)據(jù)本身有點(diǎn)無(wú)意義。這種統(tǒng)計(jì)數(shù)據(jù)的好處在于比較不同模型的不同k的困惑度。具有最低困惑度的模型通常被認(rèn)為是“最佳”。
讓我們估算美聯(lián)社數(shù)據(jù)集上的一系列LDA模型。
n_topics <-?c(2, 4, 10, 20, 50, 100)
ap_lda_compare <- n_topics %>%
map(LDA, x = ap_dtm, control =?list(seed = 1109))
geom_point() +
y = "Perplexity")

看起來(lái)100主題模型具有最低的困惑分?jǐn)?shù)。這會(huì)產(chǎn)生什么樣的主題?讓我們看一下模型產(chǎn)生的前12個(gè)主題:
ap_lda_td <-?tidy(ap_lda_compare[[6]])
top_terms <- ap_l
ungroup() %>%
arrange(topic, -beta)
top_terms
# # A tibble: 502 × 3
## topic term beta
## <int> <chr> <dbl>
## 1 1 party 0.020029039
## 2 1 communist 0.013810107
## 3 1 government 0.013221069
## 4 1 news 0.013036980
## 5 1 soviet 0.011512086
ggplot(aes(term, beta, fill =?factor(topic))) +
geom_bar(alpha = 0.8, stat = "identity", show.legend = FALSE) +
facet_wrap(~ topic, scales = "free", ncol = 3) +
coord_flip()

我們現(xiàn)在正在獲得更具體的主題。問(wèn)題是我們?nèi)绾纬尸F(xiàn)這些結(jié)果并以信息方式使用它們。
同樣,這也是您作為研究人員時(shí)直覺和領(lǐng)域知識(shí)非常重要的地方。您可以使用困惑作為決策過(guò)程中的一個(gè)數(shù)據(jù)點(diǎn),但很多時(shí)候它只是簡(jiǎn)單地查看主題本身以及與每個(gè)主題相關(guān)聯(lián)的最高概率詞來(lái)確定結(jié)構(gòu)是否有意義。如果您有一個(gè)已知的主題結(jié)構(gòu),您可以將其與之比較(例如上面的書籍示例),這也很有用。
?

最受歡迎的見解
1.探析大數(shù)據(jù)期刊文章研究熱點(diǎn)
2.618網(wǎng)購(gòu)數(shù)據(jù)盤點(diǎn)-剁手族在關(guān)注什么
3.r語(yǔ)言文本挖掘tf-idf主題建模,情感分析n-gram建模研究
4.python主題建模可視化lda和t-sne交互式可視化
5.r語(yǔ)言文本挖掘nasa數(shù)據(jù)網(wǎng)絡(luò)分析,tf-idf和主題建模
6.python主題lda建模和t-sne可視化
7.r語(yǔ)言中對(duì)文本數(shù)據(jù)進(jìn)行主題模型topic-modeling分析
8.r語(yǔ)言對(duì)nasa元數(shù)據(jù)進(jìn)行文本挖掘的主題建模分析
9.python爬蟲進(jìn)行web抓取lda主題語(yǔ)義數(shù)據(jù)分析