Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TokyoR#98_TextAnalysis

 TokyoR#98_TextAnalysis

第98回Tokyo.Rで発表したテキスト分析に関する内容です。

kilometer

April 16, 2022
Tweet

More Decks by kilometer

Other Decks in Technology

Transcript

  1. #98
    @kilometer00
    2022.04.16
    Text Analysis

    View Slide

  2. Who!?
    誰だ?

    View Slide

  3. Who!?
    名前: 三村 @kilometer
    職業: ポスドク (こうがくはくし)
    専⾨: ⾏動神経科学(霊⻑類)
    脳イメージング
    医療システム⼯学
    R歴: ~ 10年ぐらい
    流⾏: だんごむし

    View Slide

  4. View Slide

  5. 宣伝!!
    (書籍の翻訳に参加しました。)

    View Slide

  6. * Tokyo.R 運営チーム
    情報の科学と技術 70巻4号, pp.181-186, 2020
    1. はじめに
    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. おわりに

    View Slide

  7. RMeCab package installation on Mac
    brew install mecab
    brew install mecab-ipadic
    brew upgrade
    brew update
    brew doctor
    install.packages("RMeCab",
    repos = "http://rmecab.jp/R")
    1. Homebrew – maintenance
    2. Homebrew – install Mecab & its dictionary (IPA)
    3. R – install RMeCab package

    View Slide

  8. RMeCab package installation on Mac
    RMeCab::RMeCabC("すもももももももものうち")
    4. Demonstration – RMeCab package
    [[1]]
    名詞
    "すもも"
    [[2]]
    助詞
    "も"
    [[3]]
    名詞
    "もも"
    ...

    View Slide

  9. RMeCab package installation on Mac
    RMeCab::RMeCabC("すもももももももものうち") %>%
    unlist()
    名詞 助詞 名詞 助詞
    "すもも" "も" "もも" "も"
    名詞 助詞 名詞
    "もも" "の" "うち"
    4. Demonstration – RMeCab package

    View Slide

  10. ⾛れメロス
    太宰治
    メロスは激怒した。必ず、かの邪智暴虐の王を除かなければならぬと決意した。メロスには政治がわからぬ。メロスは、村の牧⼈である。
    笛を吹き、⽺と遊んで暮して来た。けれども邪悪に対しては、⼈⼀倍に敏感であった。きょう未明メロスは村を出発し、野を越え⼭越え、
    ⼗⾥はなれた此のシラクスの市にやって来た。メロスには⽗も、⺟も無い。⼥房も無い。⼗六の、内気な妹と⼆⼈暮しだ。この妹は、村の
    或る律気な⼀牧⼈を、近々、花婿として迎える事になっていた。結婚式も間近かなのである。メロスは、それゆえ、花嫁の⾐裳やら祝宴の
    御馳⾛やらを買いに、はるばる市にやって来たのだ。先ず、その品々を買い集め、それから都の⼤路をぶらぶら歩いた。メロスには⽵⾺の
    友があった。セリヌンティウスである。今は此のシラクスの市で、⽯⼯をしている。その友を、これから訪ねてみるつもりなのだ。久しく
    逢わなかったのだから、訪ねて⾏くのが楽しみである。歩いているうちにメロスは、まちの様⼦を怪しく思った。ひっそりしている。もう
    既に⽇も落ちて、まちの暗いのは当りまえだが、けれども、なんだか、夜のせいばかりでは無く、市全体が、やけに寂しい。のんきなメロ
    スも、だんだん不安になって来た。路で逢った若い衆をつかまえて、何かあったのか、⼆年まえに此の市に来たときは、夜でも皆が歌をう
    たって、まちは賑やかであった筈だが、と質問した。若い衆は、⾸を振って答えなかった。しばらく歩いて⽼爺に逢い、こんどはもっと、
    語勢を強くして質問した。⽼爺は答えなかった。メロスは両⼿で⽼爺のからだをゆすぶって質問を重ねた。⽼爺は、あたりをはばかる低声
    で、わずか答えた。
    「王様は、⼈を殺します。」
    「なぜ殺すのだ。」
    「悪⼼を抱いている、というのですが、誰もそんな、悪⼼を持っては居りませぬ。」
    「たくさんの⼈を殺したのか。」
    「はい、はじめは王様の妹婿さまを。それから、御⾃⾝のお世嗣を。それから、妹さまを。それから、妹さまの御⼦さまを。それから、皇
    后さまを。それから、賢⾂のアレキス様を。」
    「おどろいた。国王は乱⼼か。」
    「いいえ、乱⼼ではございませぬ。⼈を、信ずる事が出来ぬ、というのです。このごろは、⾂下の⼼をも、お疑いになり、少しく派⼿な暮
    しをしている者には、⼈質ひとりずつ差し出すことを命じて居ります。御命令を拒めば⼗字架にかけられて、殺されます。きょうは、六⼈
    殺されました。」
    聞いて、メロスは激怒した。「呆れた王だ。⽣かして置けぬ。」
    メロスは、単純な男であった。買い物を、背負ったままで、のそのそ王城にはいって⾏った。たちまち彼は、巡邏の警吏に捕縛された。
    調べられて、メロスの懐中からは短剣が出て来たので、騒ぎが⼤きくなってしまった。メロスは、王の前に引き出された。
    「この短⼑で何をするつもりであったか。⾔え!」暴君ディオニスは静かに、けれども威厳を以て問いつめた。その王の顔は蒼⽩で、眉間
    の皺は、刻み込まれたように深かった。
    「市を暴君の⼿から救うのだ。」とメロスは悪びれずに答えた。
    「おまえがか?」王は、憫笑した。「仕⽅の無いやつじゃ。おまえには、わしの孤独がわからぬ。」
    「⾔うな!」とメロスは、いきり⽴って反駁した。「⼈の⼼を疑うのは、最も恥ずべき悪徳だ。王は、⺠の忠誠をさえ疑って居られる。」
    「疑うのが、正当の⼼構えなのだと、わしに教えてくれたのは、おまえたちだ。⼈の⼼は、あてにならない。⼈間は、もともと私慾のかた
    まりさ。信じては、ならぬ。」暴君は落着いて呟き、ほっと溜息をついた。「わしだって、平和を望んでいるのだが。」
    「なんの為の平和だ。⾃分の地位を守る為か。」こんどはメロスが嘲笑した。「罪の無い⼈を殺して、何が平和だ。」
    電⼦付録 (1)
    太宰治作『⾛れメロス』テキストデータサンプル

    View Slide

  11. dat <-
    read.table(file = "data/melos.txt",
    fileEncoding = "shift-jis",
    header = FALSE,
    stringsAsFactors = FALSE))
    ⽇本語データの読み込み

    View Slide

  12. dat <-
    read.table(file = "data/melos.txt",
    fileEncoding = "shift-jis",
    header = FALSE,
    stringsAsFactors = FALSE))
    ⽇本語データの読み込み
    エンコーディング
    UTF-8
    Shift-JIS JIS X 0208
    Unicode
    Character
    Windows
    Mac, Linux
    ⽂字 ⽂字コード

    View Slide

  13. dat <-
    read.table(file = "data/melos.txt",
    fileEncoding = "shift-jis",
    header = FALSE,
    stringsAsFactors = FALSE))
    ⽇本語データの読み込み
    > dat %>% as_tibble()
    # A tibble: 77 x 1
    V1

    1 ⾛れメロス
    2 太宰治
    3 メロスは激怒した。必ず、かの邪智暴虐の王を除かな…
    4 「王様は、⼈を殺します。」
    5 「なぜ殺すのだ。」

    View Slide

  14. Text
    Data
    Intention
    Event
    decode
    encode
    feedback

    View Slide

  15. データ
    情報のうち意思伝達・解釈・処理に
    適した再利⽤可能なもの
    国際電気標準会議(International Electrotechnical Commission, IEC)による定義

    View Slide

  16. データ
    情報のうち意思伝達・解釈・処理に
    適した再利⽤可能なもの
    情報 実存を符号化した表象

    View Slide

  17. データ
    情報のうち意思伝達・解釈・処理に
    適した再利⽤可能なもの
    情報 実存を符号化した表象
    実存
    観察の有無によらず存在している
    ものそのもの
    写像(符号化)

    View Slide

  18. 写像 (mapping)
    !: # → %
    # %
    ある情報の集合の要素を、別の情報の集合の
    ただ1つの要素に対応づけるプロセス

    View Slide

  19. 写像
    リンゴ
    (実存)
    リンゴ
    (情報)
    mapping

    View Slide

  20. 情報量
    実存
    情報
    データ リンゴ = 1
    符号化

    View Slide

  21. 情報量
    実存
    情報
    データ リンゴ = 1
    符号化
    情報量の損失

    View Slide

  22. Text = Data
    Statistical
    modeling
    Intention
    Event
    decode
    encode
    feedback
    Computational
    estimation
    =

    View Slide

  23. 形態素解析
    すもももももももものうち
    すもも/も/もも/も/もも/の/うち
    名詞 助詞 名詞 助詞 名詞 助詞 名詞
    MeCab
    意味を担う最⼩の単位

    View Slide

  24. 雑談:どちらかというと「すもものうち」
    スモモ
    モモ
    スモモ属
    スモモ亜属
    スモモ亜属
    Shi et al., Journal of Integrative Plant Biology, 55(11), 2013

    View Slide

  25. mecab_result <-
    dat %>% # tibbleには変換せずdata.frameのまま使う
    RMeCab::RMeCabDF()
    > dat[9,1]
    [1] "「おどろいた。国王は乱⼼か。」"
    > mecab_result[[9]]
    記号 動詞 助動詞 記号
    "「" "おどろい" "た" "。"
    名詞 助詞 名詞 助詞
    "国王" "は" "乱⼼" "か"
    記号 記号
    "。" "」"
    形態素解析

    View Slide

  26. mecab_result[[9]] %>%
    data.frame(term = .,
    class = names(.))
    term class
    1 「 記号
    2 おどろい 動詞
    3 た 助動詞
    4 。 記号
    5 国王 名詞
    6 は 助詞
    7 乱⼼ 名詞
    8 か 助詞
    9 。 記号
    10 」 記号
    データの整形

    View Slide

  27. dat <- mecab_result %>%
    purrr::map_dfr(
    ~ data.frame(
    term = .,
    class = names(.))
    ) %>%
    tidyr::as_tibble()
    データの整形
    # A tibble: 6,432 x 2
    term class

    1 ⾛れ 動詞
    2 メロス 名詞
    3 太宰 名詞

    View Slide

  28. dat %>%
    write.csv(
    file = "data/melos_words.csv",
    row.names = FALSE
    )
    データの出⼒
    !
    !data
    melos_words.csv
    melos.txt
    tokyor98.Rproj
    !
    tokyor98

    View Slide

  29. 確率的⾔語モデル
    !
    語彙
    「/おどろい/た/。/国王/は/乱⼼/か/。/」
    ...
    確率
    単語i 単語j 単語k
    ... ...
    確率分布
    サンプリング

    View Slide

  30. Text = Data
    Intention
    Event
    decode
    encode
    feedback
    ! "#
    Estimation

    View Slide

  31. ! "
    芥川⿓之介 太宰治

    View Slide

  32. お伽草紙(作品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)

    View Slide

  33. お伽草紙(作品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)

    View Slide

  34. dat_AD %>%
    dplyr::filter(class == "形容詞") %>%
    dplyr::select(term) %>%
    table() %>%
    wordcloud::wordcloud(
    words = names(.),
    freq = .,
    min.freq = 5,
    family = "Hiragino Mincho Pro W6”
    )
    ワードクラウドの描画

    View Slide

  35. ! "
    芥川⿓之介 太宰治

    View Slide

  36. 確率的⾔語モデル
    !
    語彙
    「/おどろい/た/。/国王/は/乱⼼/か/。/」
    ...
    確率
    単語i 単語j 単語k
    ... ...
    確率分布
    互いに独⽴にサンプリング
    “Bag-of-words” モデル

    View Slide

  37. 形態素解析
    うらにわにはにわとりがいる
    うらにわ/には/にわとり/が/いる
    うらにわ/には/に/わ/とり/が/いる
    うら/に/わに/は/にわとり/が/いる
    ?

    View Slide

  38. 形態素解析
    うらにわにはにわとりがいる
    うらにわ/には/にわとり/が/いる
    うらにわ/には/に/わ/とり/が/いる
    うら/に/わに/は/にわとり/が/いる
    ?
    > RMeCabC("うらにわにはにわとりがいる") %>%
    + unlist()
    動詞 助詞 名詞 助詞 名詞 助詞 動詞
    "うら" "に" "わに" "は" "にわとり” "が" "いる"

    View Slide

  39. 形態素解析
    うらにわにはにわとりがいる
    うらにわ/には/にわとり/が/いる
    うらにわ/には/に/わ/とり/が/いる
    うら/に/わに/は/にわとり/が/いる
    ?
    Bi-gram モデル
    = 単語の出現確率は直前の単語に依存する

    View Slide

  40. .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 2
    pre post

    1 ⾛れ メロス
    2 メロス 太宰
    3 太宰 治
    4 治 メロス
    Bi-gram モデル

    View Slide

  41. .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 モデル

    View Slide

  42. Bi-gram モデル
    ! !
    !
    ! 共起ネットワークグラフ

    View Slide

  43. Text = Data
    Intention
    Event
    decode
    encode
    feedback
    ! "#
    Estimation

    View Slide

  44. ! " #
    確率


    i


    j


    k
    確率分布
    確率


    i


    j


    k
    確率分布
    確率


    i


    j


    k
    確率分布
    確率的⾔語モデル:トピック推定
    Estimation

    View Slide

  45. 潜在ディリクレ配分法
    Latent Dirichlet Allocation (LDA)
    !
    "
    #
    $ % &
    ⽂ごと
    単語ごと
    トピックごと
    Farhadloo & Rolland, Sentiment Analysis and Ontology Engineering, pp.1-24, Springer, 2013
    確率
    i j k
    Topicごとの単語頻度分布
    (Dirichlet分布)
    Word
    !
    1 2 3
    ⽂章dのTopicに対する
    帰属確率分布(Dirichlet分布)
    Topic
    "
    Dirichlet分布
    パラメータ
    Dirichlet分布
    パラメータ
    どのTopicに分類されそう?
    観察された単語
    Topicごとの特徴は?
    Topicの分布 潜在Topic
    (多項分布)
    単語の頻度分布

    View Slide

  46. お伽草紙(作品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)

    View Slide

  47. 蜘蛛の⽷(作品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
    データ

    View Slide

  48. > dat_AD %>%
    + filter(class %in% c("名詞", "形容詞", "動詞"))
    # A tibble: 163,729 x 5
    title author term class paragraph

    1 MENSURAZOILI 芥川⿓之介 僕 名詞 1
    2 MENSURAZOILI 芥川⿓之介 船 名詞 1
    3 MENSURAZOILI 芥川⿓之介 サルーン 名詞 1
    4 MENSURAZOILI 芥川⿓之介 まん中 名詞 1
    5 MENSURAZOILI 芥川⿓之介 テーブル 名詞 1
    6 MENSURAZOILI 芥川⿓之介 へだて 動詞 1
    7 MENSURAZOILI 芥川⿓之介 妙 名詞 1
    8 MENSURAZOILI 芥川⿓之介 男 名詞 1
    9 MENSURAZOILI 芥川⿓之介 向い 動詞 1
    10 MENSURAZOILI 芥川⿓之介 あっ 動詞 1
    # … with 163,719 more rows
    データ

    View Slide

  49. 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
    )
    前処理

    View Slide

  50. > dat_for_LDA
    # A tibble: 22 x 19,578
    # Groups: author, title [22]
    title author 僕_名詞 船_名詞 サルーン_名詞 まん

    1 MENS… 芥川⿓之介… 17 8 5
    2 煙草と悪… 芥川⿓之介… 0 1 0
    3 猿 芥川⿓之介… 1 0 0
    4 戯作三昧… 芥川⿓之介… 0 0 0
    5 ⻭⾞ 芥川⿓之介… 493 3 0
    6 邪宗⾨… 芥川⿓之介… 0 0 0
    7 酒⾍ 芥川⿓之介… 0 0 0
    8 神神の微… 芥川⿓之介… 0 2 0
    9 ⻄⽅の⼈… 芥川⿓之介… 0 0 0
    10 仙⼈ 芥川⿓之介… 0 0 0
    # … with 12 more rows, and 19,572 more variables:
    前処理

    View Slide

  51. 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つのトピックに分類
    作品ごとに割り当てられたトピックを整形

    View Slide

  52. LDAの実⾏結果
    ⾛れメロス
    斜陽
    ⼈間失格
    お伽草紙
    津軽
    Mensura Zoili, 煙草と悪魔
    戯作三昧, ⻭⾞, 神神の微笑
    ⻄⽅の⼈, 仙⼈, 蜘蛛の⽷
    ⽑利先⽣, 侏儒の⾔葉
    猿, 酒⾍, 地獄変, ⿐
    着物, 杜⼦春
    邪宗⾨
    芥川⿓之介 太宰治
    Topic
    1
    2
    3
    4
    5

    View Slide

  53. Text = Data
    Intention
    Event
    decode
    encode
    feedback
    ! "#
    Estimation

    View Slide

  54. Enjoy!!

    View Slide