第98回Tokyo.Rで発表したテキスト分析に関する内容です。
#98@kilometer002022.04.16Text Analysis
View Slide
Who!?誰だ?
Who!?名前: 三村 @kilometer職業: ポスドク (こうがくはくし)専⾨: ⾏動神経科学(霊⻑類)脳イメージング医療システム⼯学R歴: ~ 10年ぐらい流⾏: だんごむし
宣伝!!(書籍の翻訳に参加しました。)
* Tokyo.R 運営チーム情報の科学と技術 70巻4号, pp.181-186, 20201. はじめに2. Rの基礎知識2.1. Rとは2.2. RとRStudioのインストール2.3. 基本的操作2.4. パッケージについて2.5. tidyverseについて2.6. ⽇本語エンコード3. テキスト・マイニング3.1. 形態素解析3.2. RMeCabのセットアップ3.3. サンプルデータの準備4. 単語の出現頻度4.1. バッグ・オブ・ワーズ4.2. ワードクラウド5. 2-グラム・モデル5.1. 共起ネットワークグラフ6. 確率的⾔語モデル6.1. トピックモデル6.2. LDA実⾏例7. おわりに
RMeCab package installation on Macbrew install mecabbrew install mecab-ipadicbrew upgradebrew updatebrew doctorinstall.packages("RMeCab",repos = "http://rmecab.jp/R")1. Homebrew – maintenance2. Homebrew – install Mecab & its dictionary (IPA)3. R – install RMeCab package
RMeCab package installation on MacRMeCab::RMeCabC("すもももももももものうち")4. Demonstration – RMeCab package[[1]]名詞"すもも"[[2]]助詞"も"[[3]]名詞"もも"...
RMeCab package installation on MacRMeCab::RMeCabC("すもももももももものうち") %>%unlist()名詞 助詞 名詞 助詞"すもも" "も" "もも" "も"名詞 助詞 名詞"もも" "の" "うち"4. Demonstration – RMeCab package
⾛れメロス太宰治メロスは激怒した。必ず、かの邪智暴虐の王を除かなければならぬと決意した。メロスには政治がわからぬ。メロスは、村の牧⼈である。笛を吹き、⽺と遊んで暮して来た。けれども邪悪に対しては、⼈⼀倍に敏感であった。きょう未明メロスは村を出発し、野を越え⼭越え、⼗⾥はなれた此のシラクスの市にやって来た。メロスには⽗も、⺟も無い。⼥房も無い。⼗六の、内気な妹と⼆⼈暮しだ。この妹は、村の或る律気な⼀牧⼈を、近々、花婿として迎える事になっていた。結婚式も間近かなのである。メロスは、それゆえ、花嫁の⾐裳やら祝宴の御馳⾛やらを買いに、はるばる市にやって来たのだ。先ず、その品々を買い集め、それから都の⼤路をぶらぶら歩いた。メロスには⽵⾺の友があった。セリヌンティウスである。今は此のシラクスの市で、⽯⼯をしている。その友を、これから訪ねてみるつもりなのだ。久しく逢わなかったのだから、訪ねて⾏くのが楽しみである。歩いているうちにメロスは、まちの様⼦を怪しく思った。ひっそりしている。もう既に⽇も落ちて、まちの暗いのは当りまえだが、けれども、なんだか、夜のせいばかりでは無く、市全体が、やけに寂しい。のんきなメロスも、だんだん不安になって来た。路で逢った若い衆をつかまえて、何かあったのか、⼆年まえに此の市に来たときは、夜でも皆が歌をうたって、まちは賑やかであった筈だが、と質問した。若い衆は、⾸を振って答えなかった。しばらく歩いて⽼爺に逢い、こんどはもっと、語勢を強くして質問した。⽼爺は答えなかった。メロスは両⼿で⽼爺のからだをゆすぶって質問を重ねた。⽼爺は、あたりをはばかる低声で、わずか答えた。「王様は、⼈を殺します。」「なぜ殺すのだ。」「悪⼼を抱いている、というのですが、誰もそんな、悪⼼を持っては居りませぬ。」「たくさんの⼈を殺したのか。」「はい、はじめは王様の妹婿さまを。それから、御⾃⾝のお世嗣を。それから、妹さまを。それから、妹さまの御⼦さまを。それから、皇后さまを。それから、賢⾂のアレキス様を。」「おどろいた。国王は乱⼼か。」「いいえ、乱⼼ではございませぬ。⼈を、信ずる事が出来ぬ、というのです。このごろは、⾂下の⼼をも、お疑いになり、少しく派⼿な暮しをしている者には、⼈質ひとりずつ差し出すことを命じて居ります。御命令を拒めば⼗字架にかけられて、殺されます。きょうは、六⼈殺されました。」聞いて、メロスは激怒した。「呆れた王だ。⽣かして置けぬ。」メロスは、単純な男であった。買い物を、背負ったままで、のそのそ王城にはいって⾏った。たちまち彼は、巡邏の警吏に捕縛された。調べられて、メロスの懐中からは短剣が出て来たので、騒ぎが⼤きくなってしまった。メロスは、王の前に引き出された。「この短⼑で何をするつもりであったか。⾔え!」暴君ディオニスは静かに、けれども威厳を以て問いつめた。その王の顔は蒼⽩で、眉間の皺は、刻み込まれたように深かった。「市を暴君の⼿から救うのだ。」とメロスは悪びれずに答えた。「おまえがか?」王は、憫笑した。「仕⽅の無いやつじゃ。おまえには、わしの孤独がわからぬ。」「⾔うな!」とメロスは、いきり⽴って反駁した。「⼈の⼼を疑うのは、最も恥ずべき悪徳だ。王は、⺠の忠誠をさえ疑って居られる。」「疑うのが、正当の⼼構えなのだと、わしに教えてくれたのは、おまえたちだ。⼈の⼼は、あてにならない。⼈間は、もともと私慾のかたまりさ。信じては、ならぬ。」暴君は落着いて呟き、ほっと溜息をついた。「わしだって、平和を望んでいるのだが。」「なんの為の平和だ。⾃分の地位を守る為か。」こんどはメロスが嘲笑した。「罪の無い⼈を殺して、何が平和だ。」電⼦付録 (1)太宰治作『⾛れメロス』テキストデータサンプル
dat <-read.table(file = "data/melos.txt",fileEncoding = "shift-jis",header = FALSE,stringsAsFactors = FALSE))⽇本語データの読み込み
dat <-read.table(file = "data/melos.txt",fileEncoding = "shift-jis",header = FALSE,stringsAsFactors = FALSE))⽇本語データの読み込みエンコーディングUTF-8Shift-JIS JIS X 0208UnicodeCharacterWindowsMac, Linux⽂字 ⽂字コード
dat <-read.table(file = "data/melos.txt",fileEncoding = "shift-jis",header = FALSE,stringsAsFactors = FALSE))⽇本語データの読み込み> dat %>% as_tibble()# A tibble: 77 x 1V11 ⾛れメロス2 太宰治3 メロスは激怒した。必ず、かの邪智暴虐の王を除かな…4 「王様は、⼈を殺します。」5 「なぜ殺すのだ。」
TextDataIntentionEventdecodeencodefeedback
データ情報のうち意思伝達・解釈・処理に適した再利⽤可能なもの国際電気標準会議(International Electrotechnical Commission, IEC)による定義
データ情報のうち意思伝達・解釈・処理に適した再利⽤可能なもの情報 実存を符号化した表象
データ情報のうち意思伝達・解釈・処理に適した再利⽤可能なもの情報 実存を符号化した表象実存観察の有無によらず存在しているものそのもの写像(符号化)
写像 (mapping)!: # → %# %ある情報の集合の要素を、別の情報の集合のただ1つの要素に対応づけるプロセス
写像リンゴ(実存)リンゴ(情報)mapping
情報量実存情報データ リンゴ = 1符号化
情報量実存情報データ リンゴ = 1符号化情報量の損失
Text = DataStatisticalmodelingIntentionEventdecodeencodefeedbackComputationalestimation=
形態素解析すもももももももものうちすもも/も/もも/も/もも/の/うち名詞 助詞 名詞 助詞 名詞 助詞 名詞MeCab意味を担う最⼩の単位
雑談:どちらかというと「すもものうち」スモモモモスモモ属スモモ亜属スモモ亜属Shi et al., Journal of Integrative Plant Biology, 55(11), 2013
mecab_result <-dat %>% # tibbleには変換せずdata.frameのまま使うRMeCab::RMeCabDF()> dat[9,1][1] "「おどろいた。国王は乱⼼か。」"> mecab_result[[9]]記号 動詞 助動詞 記号"「" "おどろい" "た" "。"名詞 助詞 名詞 助詞"国王" "は" "乱⼼" "か"記号 記号"。" "」"形態素解析
mecab_result[[9]] %>%data.frame(term = .,class = names(.))term class1 「 記号2 おどろい 動詞3 た 助動詞4 。 記号5 国王 名詞6 は 助詞7 乱⼼ 名詞8 か 助詞9 。 記号10 」 記号データの整形
dat <- mecab_result %>%purrr::map_dfr(~ data.frame(term = .,class = names(.))) %>%tidyr::as_tibble()データの整形# A tibble: 6,432 x 2term class 1 ⾛れ 動詞2 メロス 名詞3 太宰 名詞
dat %>%write.csv(file = "data/melos_words.csv",row.names = FALSE)データの出⼒!!datamelos_words.csvmelos.txttokyor98.Rproj!tokyor98
確率的⾔語モデル!語彙「/おどろい/た/。/国王/は/乱⼼/か/。/」...確率単語i 単語j 単語k... ...確率分布サンプリング
Text = DataIntentionEventdecodeencodefeedback! "#Estimation
! "芥川⿓之介 太宰治
お伽草紙(作品ID:307)⼈間失格(作品ID:301)斜陽(作品ID:1565)津軽(作品ID:2282)⾛れメロス(作品ID:1567)芥川⿓之介 太宰治! "単語155,333単語233,063単語⻘空⽂庫:https://www.aozora.gr.jp/index.html蜘蛛の⽷(作品ID:92)猿(作品ID:139)⻭⾞(作品ID:42377)地獄変(作品ID:60)⿐(作品ID:42)侏儒の⾔葉(作品ID:43751)着物(作品ID:1137)煙草と悪魔(作品ID:163)神神の微笑(作品ID:68)⻄⽅の⼈(作品ID:141)邪宗⾨(作品ID:59)酒⾍(作品ID:161)⽑利先⽣(作品ID:101)戯作三昧(作品ID:37)仙⼈(作品ID:143)杜⼦春(作品ID:170)Mensura Zoili(作品ID:97)
お伽草紙(作品ID:307)⼈間失格(作品ID:301)斜陽(作品ID:1565)津軽(作品ID:2282)⾛れメロス(作品ID:1567)芥川⿓之介 太宰治! "形容詞2,219単語4,704単語⻘空⽂庫:https://www.aozora.gr.jp/index.html蜘蛛の⽷(作品ID:92)猿(作品ID:139)⻭⾞(作品ID:42377)地獄変(作品ID:60)⿐(作品ID:42)侏儒の⾔葉(作品ID:43751)着物(作品ID:1137)煙草と悪魔(作品ID:163)神神の微笑(作品ID:68)⻄⽅の⼈(作品ID:141)邪宗⾨(作品ID:59)酒⾍(作品ID:161)⽑利先⽣(作品ID:101)戯作三昧(作品ID:37)仙⼈(作品ID:143)杜⼦春(作品ID:170)Mensura Zoili(作品ID:97)
dat_AD %>%dplyr::filter(class == "形容詞") %>%dplyr::select(term) %>%table() %>%wordcloud::wordcloud(words = names(.),freq = .,min.freq = 5,family = "Hiragino Mincho Pro W6”)ワードクラウドの描画
確率的⾔語モデル!語彙「/おどろい/た/。/国王/は/乱⼼/か/。/」...確率単語i 単語j 単語k... ...確率分布互いに独⽴にサンプリング“Bag-of-words” モデル
形態素解析うらにわにはにわとりがいるうらにわ/には/にわとり/が/いるうらにわ/には/に/わ/とり/が/いるうら/に/わに/は/にわとり/が/いる?
形態素解析うらにわにはにわとりがいるうらにわ/には/にわとり/が/いるうらにわ/には/に/わ/とり/が/いるうら/に/わに/は/にわとり/が/いる?> RMeCabC("うらにわにはにわとりがいる") %>%+ unlist()動詞 助詞 名詞 助詞 名詞 助詞 動詞"うら" "に" "わに" "は" "にわとり” "が" "いる"
形態素解析うらにわにはにわとりがいるうらにわ/には/にわとり/が/いるうらにわ/には/に/わ/とり/が/いるうら/に/わに/は/にわとり/が/いる?Bi-gram モデル= 単語の出現確率は直前の単語に依存する
.class <- c("名詞", "形容詞", "動詞")dat_bigram <-dat %>%dplyr::filter(class %in% .class) %>%dplyr::rename(pre = term) %>%dplyr::mutate(post = lead(pre)) %>%dplyr::select(pre, post) %>%dplyr::filter(!is.na(post))> dat_bigram# A tibble: 2,676 x 2pre post 1 ⾛れ メロス2 メロス 太宰3 太宰 治4 治 メロスBi-gram モデル
.word <- c("メロス", "王", "妹","セリヌンティウス").font <- "Hiragino Mincho Pro W6"dat_bigram %>%dplyr::filter(pre %in% .word) %>%igraph::graph.data.frame() %>%plot(vertex.color = "white",vertex.label.family = .font)Bi-gram モデル
Bi-gram モデル! !!! 共起ネットワークグラフ
! " #確率単語i単語j単語k確率分布確率単語i単語j単語k確率分布確率単語i単語j単語k確率分布確率的⾔語モデル:トピック推定Estimation
潜在ディリクレ配分法Latent Dirichlet Allocation (LDA)!"#$ % &⽂ごと単語ごとトピックごとFarhadloo & Rolland, Sentiment Analysis and Ontology Engineering, pp.1-24, Springer, 2013確率i j kTopicごとの単語頻度分布(Dirichlet分布)Word!1 2 3⽂章dのTopicに対する帰属確率分布(Dirichlet分布)Topic"Dirichlet分布パラメータDirichlet分布パラメータどのTopicに分類されそう?観察された単語Topicごとの特徴は?Topicの分布 潜在Topic(多項分布)単語の頻度分布
お伽草紙(作品ID:307)⼈間失格(作品ID:301)斜陽(作品ID:1565)津軽(作品ID:2282)⾛れメロス(作品ID:1567)芥川⿓之介 太宰治! "単語155,333単語233,063単語⻘空⽂庫:https://www.aozora.gr.jp/index.htmlデータ蜘蛛の⽷(作品ID:92)猿(作品ID:139)⻭⾞(作品ID:42377)地獄変(作品ID:60)⿐(作品ID:42)侏儒の⾔葉(作品ID:43751)着物(作品ID:1137)煙草と悪魔(作品ID:163)神神の微笑(作品ID:68)⻄⽅の⼈(作品ID:141)邪宗⾨(作品ID:59)酒⾍(作品ID:161)⽑利先⽣(作品ID:101)戯作三昧(作品ID:37)仙⼈(作品ID:143)杜⼦春(作品ID:170)Mensura Zoili(作品ID:97)
蜘蛛の⽷(作品ID:92)猿(作品ID:139)⻭⾞(作品ID:42377)地獄変(作品ID:60)⿐(作品ID:42)侏儒の⾔葉(作品ID:43751)着物(作品ID:1137)煙草と悪魔(作品ID:163)神神の微笑(作品ID:68)⻄⽅の⼈(作品ID:141)邪宗⾨(作品ID:59)酒⾍(作品ID:161)⽑利先⽣(作品ID:101)戯作三昧(作品ID:37)仙⼈(作品ID:143)杜⼦春(作品ID:170)Mensura Zoili(作品ID:97)お伽草紙(作品ID:307)⼈間失格(作品ID:301)斜陽(作品ID:1565)津軽(作品ID:2282)⾛れメロス(作品ID:1567)芥川⿓之介 太宰治! "動詞, 形容詞, 名詞66,065単語97,664単語⻘空⽂庫:https://www.aozora.gr.jp/index.htmlデータ
> dat_AD %>%+ filter(class %in% c("名詞", "形容詞", "動詞"))# A tibble: 163,729 x 5title author term class paragraph 1 MENSURAZOILI 芥川⿓之介 僕 名詞 12 MENSURAZOILI 芥川⿓之介 船 名詞 13 MENSURAZOILI 芥川⿓之介 サルーン 名詞 14 MENSURAZOILI 芥川⿓之介 まん中 名詞 15 MENSURAZOILI 芥川⿓之介 テーブル 名詞 16 MENSURAZOILI 芥川⿓之介 へだて 動詞 17 MENSURAZOILI 芥川⿓之介 妙 名詞 18 MENSURAZOILI 芥川⿓之介 男 名詞 19 MENSURAZOILI 芥川⿓之介 向い 動詞 110 MENSURAZOILI 芥川⿓之介 あっ 動詞 1# … with 163,719 more rowsデータ
dat_for_LDA <-dat_AD %>%dplyr::select(-paragraph) %>%dplyr::filter(class %in% .class) %>%dplyr::unite(col = term,c(term, class)) %>%dplyr::group_by(author, title, term) %>%dplyr::mutate(wordCount = n()) %>%dplyr::distinct() %>%tidyr::pivot_wider(values_from = wordCount,values_fill = 0,names_from = term)前処理
> dat_for_LDA# A tibble: 22 x 19,578# Groups: author, title [22]title author 僕_名詞 船_名詞 サルーン_名詞 まん 1 MENS… 芥川⿓之介… 17 8 52 煙草と悪… 芥川⿓之介… 0 1 03 猿 芥川⿓之介… 1 0 04 戯作三昧… 芥川⿓之介… 0 0 05 ⻭⾞ 芥川⿓之介… 493 3 06 邪宗⾨… 芥川⿓之介… 0 0 07 酒⾍ 芥川⿓之介… 0 0 08 神神の微… 芥川⿓之介… 0 2 09 ⻄⽅の⼈… 芥川⿓之介… 0 0 010 仙⼈ 芥川⿓之介… 0 0 0# … with 12 more rows, and 19,572 more variables:前処理
result <-dat_for_LDA %>%dplyr::ungroup() %>%dplyr::select(!c(title, author)) %>%topicmodels::LDA(k = 5,control = list(seed = 0))LDAの実⾏dat_topics <-result %>%topicmodels::topics() %>%dplyr::bind_cols(dat_for_LDA %>%dplyr::select(title, author),topic = .) %>%dplyr::arrange(topic, author)22作品(芥川17, 太宰5)を5つのトピックに分類作品ごとに割り当てられたトピックを整形
LDAの実⾏結果⾛れメロス斜陽⼈間失格お伽草紙津軽Mensura Zoili, 煙草と悪魔戯作三昧, ⻭⾞, 神神の微笑⻄⽅の⼈, 仙⼈, 蜘蛛の⽷⽑利先⽣, 侏儒の⾔葉猿, 酒⾍, 地獄変, ⿐着物, 杜⼦春邪宗⾨芥川⿓之介 太宰治Topic12345
Enjoy!!