読者です 読者をやめる 読者になる 読者になる

Latent Dirichlet allocationを行う

r corpus

 今回は、Latent Dirichlet allocation (LDA) を使ったテクスト解析に挑戦してみたいと思います。以下では、ldaパッケージを使っています。*1
 今回の分析データは、X-MENX-MEN2X-Men: The Last StandについてのWikipedia記事です。各記事のPlotのセクションのみをコピーし、それぞれ"X1.txt", "X2.txt", "X3.txt"という名前でRのワーキング・ディレクトリに保存します。
 では、LDAを実行してみましょう。

# パッケージの読み込み
library(lda)
library(tm)
library(NLP)
# 分析データの読み込み
# 読み込む際に、全ての文字を小文字に変換
X1 <- tolower(scan("X1.txt", what = "char", sep = "\n", quiet = TRUE))
X2 <- tolower(scan("X2.txt", what = "char", sep = "\n", quiet = TRUE))
X3 <- tolower(scan("X3.txt", what = "char", sep = "\n", quiet = TRUE))
# 単語ベクトルに変換
X1.word.vector <- unlist(strsplit(X1, "([^-a-z0-9]+|--)"))
X2.word.vector <- unlist(strsplit(X2, "([^-a-z0-9]+|--)"))
X3.word.vector <- unlist(strsplit(X3, "([^-a-z0-9]+|--)"))
# ステミング処理
X1.stem <- stemDocument(X1.word.vector)
X2.stem <- stemDocument(X2.word.vector)
X3.stem <- stemDocument(X3.word.vector)
# ストップワードの除去
X1.sw <- removeWords(X1.stem, stopwords("english"))
X2.sw <- removeWords(X2.stem, stopwords("english"))
X3.sw <- removeWords(X3.stem, stopwords("english"))
# LDA用のデータ形式に変換
lex <- lexicalize(c(X1.sw, X2.sw, X3.sw))
# 推定するトピックの数
k <- 3
# LDA
# 以下の100, 0.1, 0.1は、それぞれ「繰り返し数」、「ディリクレ過程のハイパーパラメータα」、「ディリクレ過程のハイパーパラメータη」
result <- lda.collapsed.gibbs.sampler(lex$documents, k, lex$vocab, 100, 0.1, 0.1, compute.log.likelihood = TRUE)
# 結果の表示
summary(result)

 上記のスクリプトを実行すると、以下のような結果が表示されます。

                Length Class  Mode   
assignments     2000   -none- list   
topics          1629   -none- numeric
topic_sums         3   -none- numeric
document_sums   6000   -none- numeric
<NA>               0   -none- NULL   
<NA>               0   -none- NULL   
<NA>               0   -none- NULL   
<NA>               0   -none- NULL   
<NA>               0   -none- NULL   
log.likelihoods  200   -none- numeric

 そして、各トピックの上位10語を確認します。

# 各トピックの上位10語を確認
top.words <- top.topic.words(result$topics, 10, by.score = TRUE)
print(top.words)

 上記のスクリプトを実行すると、以下のような結果が表示されます。*2 トピック1はX-MENチーム関連、トピック2はマグニートー関連の語が多く含まれているように思われます。また、トピック3はやや分かりにくいですが、フェニックスやキュアという語が含まれているため、第3作 (The Last Stand) に関連するトピックかも知れません。

      [,1]        [,2]          [,3]         
 [1,] "xavier"    "magneto"     "mutant"     
 [2,] "jean"      "mystiqu"     "power"      
 [3,] "x-men"     "use"         "phoenix"    
 [4,] "cyclop"    "brotherhood" "human"   
 [5,] "rogu"      "machin"      "iceman"     
 [6,] "wolverin"  "attack"      "pyro"
 [7,] "arriv"     "escap"       "cure"       
 [8,] "cerebro"   "sabretooth"  "save"       
 [9,] "storm"     "base"     "group"      
[10,] "school"    "stryker"     "presid"

*1:topicmodelsパッケージを使うことも可能です。

*2:LDAは実行するたびに結果が微妙に異なるため、結果を固定したい場合は、set.seed関数などを使ってください。