Rによるトピックモデル―AKB総選挙2017上位7人のコメントを3つのトピックに分類してみた結果―

Rによるトピックモデルの練習としてとりあえずやってみました。

使用するパッケージ

> library(RMeCab)
> library(dplyr)
> library(magrittr)
> library(topicmodels)
> library(lda)
> library(ggplot2)
> library(tm)
> library(tidyr)

データセット

AKB総選挙2017の上位7名のスピーチのコメントを利用します。スピーチの全文については以下のブログにまとめられていたので利用させていただきました。
www.bakakoara.com

7名のスピーチをそれぞれ7個のテキストファイルにコピペしましたが、そのまま利用するのではなく以下のようにしています。

  • 徳光さんが話しかける前のスピーチ部分を使用(徳光さんに誘導されて答えている部分は使用せず最初に自分で考えて喋った部分を採用)
  • 上記ブログでは「えー」「あー」なども含まれているため、分析に必要ないと判断できる部分を除く。
  • 「みなさん」「皆様」などファンに対する敬称を統一した。

前処理

データの読込み

分析に用いる品詞は「名詞」と「形容詞」に限定し、単語の頻度は2以上のものを使用します。ここではRMeDCabパッケージのdocDF関数を使用します。作成したデータをgod7というフォルダに入れて、そのフォルダがあるフルパスをdocDF関数に読み込ませて処理を行います。

> election <- RMeCab::docDF("C:\\Users\\admin\\data\\god7", type=1,
>                pos=c("名詞","形容詞"), minFreq=2)
> dim(election)
159 10

> head(election,3)
TERM	POS1	POS2	1位_指原莉乃.txt	2位_渡辺麻友.txt	3位_松井珠理奈.txt	4位_宮脇咲良.txt	5位_荻野由佳.txt	6位_須田亜香里.txt	7位_横山由依.txt
1	名詞	数	0	5	0	1	1	2	1
2	名詞	数	0	5	0	0	1	0	0
3	名詞	数	0	2	0	0	0	0	1

単語の絞り込み

抽出された単語は159となりました。この159にはトピックとして役に立たないが頻度が高いもの(数や代名詞)が多く含まれているので、品詞細分類(POS2)を利用してさらに単語を絞り込みます。今回は"一般","自立","サ変接続","形容動詞語幹"の品詞細分類に絞り込み単語を抽出してみます。

> election2 <- election %>% filter(POS2 %in% c("一般","自立","サ変接続","形容動詞語幹"))
> election3 <- election2 %>% select(-c(TERM:POS2))
> rownames(election3) <- election2$TERM
> dim(election3)[1]
86

> head(election3)
1位_指原莉乃.txt	2位_渡辺麻友.txt	3位_松井珠理奈.txt	4位_宮脇咲良.txt	5位_荻野由佳.txt	6位_須田亜香里.txt	7位_横山由依.txt
AKB	2	6	0	0	6	0	8
NGT	0	0	0	0	3	0	1
いい	0	0	0	2	0	4	1

データ構造(class)の変換

次に、topicmodelsパッケージのLDA()関数を使用するためにはelection3のクラスを今のデータフレームからDocumentTermMatrixに変更しなければいけないようです。なのでデータフレームをt()関数で転置させてDocumentTermMatrixクラスに変換させたいと思います(ちなみに、weightは単語の頻度weightTfとします)。

> election3a <- election3 %>% t() %>% tm::as.DocumentTermMatrix(weighting=weightTf)

分析

topicmodelsパッケージによるトピックモデルの推定

前処理が終わったので、初めにtopicmodelsパッケージのLDA()関数でlatent Dirichlet allocationによるトピックの推定を行ってみます。トピック数の選択はクラスタの選択と同じようにアドホックに決めるものだと思われるので、ここではトピック数を3つで試してみます。

> k <- 3
> res1 <- election3a %>% topicmodels::LDA(k)
> terms(res1)
Topic 1
'自分'
Topic 2
'AKB'
Topic 3
'皆さん'

推定の結果、トピック1が「自分」、トピック2が「AKB」、トピック3が「皆さん」となりました。

ldaパッケージによるトピックモデルの推定

次に、ldaパッケージのlda.collapsed.gibbs.sampler()関数で推定してみます。ldaパッケージを使用するためにはelection3aのデータ構造を変換する必要がありtopicmodelsパッケージのdtm2ldaformat()関数を使用してリスト型へと変換します(リストの要素は文書と単語)。その後、ldaパッケージのlda.collapsed.gibbs.sampler()関数で推定を行います。ここでも推定するトピック数は3とします。

> election4 <- topicmodels::dtm2ldaformat(election3a)
> set.seed(123)
> result <- lda::lda.collapsed.gibbs.sampler(election4$documents, K = 3,
>                                      election4$vocab, 25, 0.1, 0.1, compute.log.likelihood=TRUE)

推定結果からトピックごとに出現スコアの高いキーワードを5つ抽出した結果は以下のとおりです。

> top.words <- lda::top.topic.words(result$topics, 5,by.score=T)
> print(top.words)
    [,1]   [,2]       [,3]      
[1,] "自分" "AKB"      "皆さん"  
[2,] "いい" "選挙"     "グループ"
[3,] "思い" "メンバー" "ファン"  
[4,] "疑問" "気持ち"   "人"      
[5,] "香"   "努力"     "テレビ" 

print()関数で出力した1列目から3列目をそれぞれトピック1、トピック2、トピック3とします。トピック1の出現スコアが高いキーワードを見ると「自分」「いい」「思い」など主観的なワードが上位に出てきています。これはスピーチで自分自身について言及したことでトピックが形成されたのではと思います。次にトピック2をみると「AKB」「選挙」「メンバー」というワードが上位に表れており、AKBという組織やそのメンバー、そして総選挙について言及したワードでトピックが形成されています。最後にトピック3をみると「皆さん」「グループ」「ファン」というワードが上位に来ており、これはファンに対して言及したワードから形成されていることがわかります。つまり、ざっくりと各トピックを表現するならば、トピック1は「自分について」、トピック2は「AKBグループやメンバーについて」、トピック3は「ファンについて」のトピックといえるのではないでしょうか。

推定結果の可視化

次にトピック1から3について上位7名の方のスピーチの内容(トピック)に違いがあるのかを調べてみます。

# 文書全体のトピック割合
> topic.proportions <- t(result$document_sums) / colSums(result$document_sums)
# ggplot2へ渡すためにデータフレームへ変形
> rank_name <- colnames(election[-1:-3]) %<>% str_replace(".txt","")
> elect_DF <- as.data.frame(topic.proportions) %>% set_names(paste0("topic",1:3)) %>% 
>             mutate(num = rank_name)
# tidyr::gather()を使用してlongに変形
> elect_DF <- elect_DF %>% tidyr::gather(key=topic, value=props, -num)
# ggplot2で可視化
> elect_DF %>% ggplot(aes(x=topic, y=props, fill=num))+geom_bar(stat="identity")+facet_wrap(~num)

f:id:joure:20170709112948p:plain

結果の解釈

特徴的な結果をピックアップしてみると、3位の松井さんはトピック3の値が高いことが分かります。これはスピーチの中に「ファン」「皆さん」を多用しており、今回の分析では単語の頻度のみに着目していることでこのような結果になったと思われます。また、5位の荻野さんはトピック2の値が高いことが分かります。彼女のスピーチの内容を確認してみると、小さな頃からAKBに入ることが夢であり、その夢が叶ったという内容となっており、そのスピーチのなかで「AKB」というワードを何度も繰り返していたことがトピック2が高くなった理由だと思います。同様に、7位の横山さんもトピック2の値が高くなっており、スピーチの内容もグループの総監督ということもありKABグループのことについてお話されており納得の結果でした。最後に上位4名をみると、それぞれトピック3がすべてのトピックの中で最も高い値を有しており、ファンに対するワードをスピーチの中で多く取り入れていることが特徴として表れているなと思いました。

おわりに

モデルの理論的なことをすっ飛ばし、とりあえず手を動かしてみようの精神で分析をしてみました。なので、結果の解釈が本当にこんな解釈でいいのかなと思っています(誤りを見つけた場合は後日訂正します)。また、分析結果がロバストでなかったことも言及しておきます。また、単に単語の頻度に着目するのではなく係り受け関係など他のことにも着目する必要があるのではなど色々思うことろはあるのですが、それはこれから自然言語処理の学習を進めてあとで、再度この記事を振り返ってみたいと思います。

参考資料

石田基広.2017.『Rによるテキストマイニング入門(第2版)』森北出版.
http://www.bakakoara.com/entry/akb-sousenkyo-2017-speech