からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

こぶつば楽曲の歌詞をテキスト分類したい②~階層型クラスター分析~

○はじめに

 Rを使って機械学習の分野で言うところの教師なし学習である階層型クラスター分析を行います。
 テキスト中に使われている文字・単語の頻度を用いて各テキストの類似性を測り、グループに分類していきます。階層型というのは、1つずつのデータを小さなグループ(クラスター)にして、そしてさらにグループ同士をグループとし、最後は全てを含む大きなグループとなる。このように段階を踏んでクラスターを形成していく手法です。詳しい説明は参考書籍をご参照ください。

・分析データ

 ハロプロのグループ「こぶしファクトリー」と「つばきファクトリー」の歌詞。詳しくは前回の記事をご参照ください。

www.anarchive-beta.com

・主な参考書籍

『Rによるやさしいテキストマイニング』小林雄一郎,オーム社

○テキストのクラスタリングとデンドログラムの作成

・処理コード

パッケージ

library(RMeCab)
library(magrittr)
library(dplyr)
library(stringr)
library(dendextend)


準備

#ファイルを指定
folder_name1 <- "1人目フォルダ名"
folder_name2 <- "2人目フォルダ名"
file_name12   <- c(list.files(folder_name1), list.files(folder_name2))
file_path12   <- c(paste(folder_name1, list.files(folder_name1), sep = "/"), 
                   paste(folder_name2, list.files(folder_name2), sep = "/"))


特徴語の頻度表を作成

cluster1 <- term_100100[,1] #特徴語とする組を選び、語だけを抽出
for(i in 1:length(file_path12)) {
  #形態素解析
  tmp1 <- docDF(file_path12[i])
  #頻度表を整形
  colnames(tmp1) <- c("TERM", "FREQ") #後の処理のために列名を統一
  tmp2 <- tmp1 %>% filter(!grepl("\\s", TERM)) #doc()で空白が紛れ込むので取り除く
  tmp2$FREQ <- tmp2$FREQ / sum(tmp2$FREQ) * 1000 #相対頻度に変更
  cluster1 <- left_join(cluster1, tmp2, by = "TERM") #特徴語に含まれる語の頻度のみを残
}
cluster2 <- cluster1
cluster2[is.na(cluster2)] <- 0 #NAを0にする
cluster2 <- cluster2[, -1] #TERMの列を落とす

特徴語については前回の記事を読んでね。left_join()で特徴語(cluster1$TERM)と一致するものだけをデータフレーム(cluster1)に残すことができる。観測頻度で処理するならtmp2$FREQ <- tmp2$FREQ / sum(tmp2$FREQ) * 1000をコメントアウトする。
クラスタリングの段階では特徴量となる値だけでいいので、TERM列を削る(本当は転置した時に行名にするのが理想かも)。

これは文字レベルの処理になっているので単語レベルであれば次のようにする。

cluster1 <- term_200200[,1] #特徴語とする組を選び、語だけを抽出
for(i in 1:length(file_path12)) {
  #形態素解析
  tmp1 <- docDF(file_path12[i], type = 1) #, pos = c("名詞", "動詞", "形容詞", "形容動詞")
  #頻度表を整形
  colnames(tmp1) <- c("TERM", "POS1", "POS2", "FREQ") #後の処理のために列名を統一
  tmp2 <- tmp1 %>% 
          filter(!grepl("\\s", TERM)) %>%  #doc()で空白が紛れ込むので取り除く
          select(TERM, FREQ) %>%           #品詞は使わない
          group_by(TERM) %>%               #別の品詞として集計された同単語を統合
          summarise(FREQ = sum(FREQ))      #統合時に頻度を加算
  tmp2$FREQ <- tmp2$FREQ / sum(tmp2$FREQ) * 1000 #相対頻度に変更
  cluster1 <- left_join(cluster1, tmp2, by = "TERM") #特徴語に含まれる語の頻度のみを残
}
cluster2 <- cluster1
cluster2[is.na(cluster2)] <- 0 #NAを0にする
cluster2 <- cluster2[, -1]     #TERMの列を落とす

docDF()に引数type = 1とすると結果が単語レベルで返ってくる。単語レベルにすると品詞情報も付随して返ってくるので、colnames(tmp_freqency_table)のところをc("TERM", "POS1", "POS2", "FREQ")とする。品詞情報が加わることで同じ単語が品詞的には別の語としてカウントされることがあるので、それを統合する(ここでは品詞に注目していないため)。

クラスタリングとデンドログラムの作成

colnames(cluster2) <- str_remove(file_name12, ".txt") #列名をテキスト名に戻す
den <- cluster2 %>% t() %>% dist() %>% hclust("ward.D2") %>% as.dendrogram() #dist()で距離を測り、hclust()で類似度を測る
lab.col2 <- ifelse(substr(labels(den), 1,3) == "kbs", "#099800", "#FD9556") #色指定
labels_colors(den) <- lab.col2
plot(den, main = "グラフのタイトル")

特に必要ないので拡張子の部分を落とす。
次以降の処理のためにt()で転置する。各列の特徴量を基にdist()で文書間の距離を測る。その距離(非類似度)からhclust()で近しい(似ている)文書を探索する。類似度の測定には種類があるが、今回は"ward.D2"でウォード法を使う。最後にas.dendrogram()でデンドログラムのプロットをするためにデータの形式を変換する。
(正直よく分かってないのですが)kbsのところにテキスト名から一致させたい語を指定すると、カラーコード("#099800", "#FD9556")の前の方の色に、不一致なら後の方の色になる。
最後にplot()で分析結果を可視化する。

・使用文字によるクラスタ

相対頻度

テキストを文字レベルに区切り、文書ごとの出現頻度を基に各文書をグループ化していく。

f:id:anemptyarchive:20190107041053p:plainf:id:anemptyarchive:20190107041058p:plainf:id:anemptyarchive:20190107041103p:plain
相対頻度高使用文字による結果
この結果が一番良いっぽいので詳しく見てみる。

各文書の総語数の平均は542.8語で文字種類の平均は153.0語のところ、1文書内に含まれていた特徴語の平均はそれぞれ44.8語(特徴語56語)、72.3語(129語)、101語(258語)だった。(数値の詳細は下の項目を展開してください。)

2つずつグループ化できている数で言うと、相対頻度の文字レベルで特徴語を平均文字種の半数程度とした分析が一番良かったということになる。(本当に??)

詳細(クリックで展開)

##      FILE_NAME TOKENS TYPES N_5050 N_100100 N_200200
## 1  kbs_a1a.txt    430   124     38       55       73
## 2  kbs_a1e.txt    617   154     44       68       95
## 3  kbs_a1g.txt    607   134     50       83      104
## 4  kbs_a1i.txt    508   175     42       68      102
## 5  kbs_a1l.txt    313   114     34       51       77
## 6  kbs_a1o.txt    583   210     47       90      127
## 7  kbs_a1q.txt    621   156     45       73      103
## 8  kbs_s0a.txt    430   144     42       68       92
## 9  kbs_s0b.txt    339    88     38       56       69
## 10 kbs_s1a.txt    605   190     45       77      112
## 11 kbs_s2a.txt    615   156     44       77      105
## 12 kbs_s2b.txt    567   167     46       77      108
## 13 kbs_s2c.txt    602   131     41       68       89
## 14 kbs_s3a.txt    669   193     45       81      120
## 15 kbs_s3b.txt    647   174     49       72      116
## 16 kbs_s4a.txt    487   124     42       64       90
## 17 kbs_s5a.txt    714   211     53       85      131
## 18 kbs_s5b.txt    434   105     42       67       91
## 19 kbs_s6a.txt    717   150     44       74      107
## 20 kbs_s6b.txt    349   121     43       68       91
## 21 tbk_a1b.txt    625   160     49       84      107
## 22 tbk_a1f.txt    488   153     43       65       99
## 23 tbk_a1i.txt    573   140     49       72      101
## 24 tbk_a1m.txt    430   164     47       71      108
## 25 tbk_a1q.txt    612   190     45       80      116
## 26 tbk_a1r.txt    303   116     45       69       84
## 27 tbk_s0a.txt    359   109     45       67       86
## 28 tbk_s0b.txt    724   190     51       87      130
## 29 tbk_s0c.txt    265    95     42       58       72
## 30 tbk_s1a.txt    772   202     51       90      130
## 31 tbk_s1b.txt    771   145     47       70       99
## 32 tbk_s1c.txt    666   199     50       84      119
## 33 tbk_s2a.txt    896   180     48       77      107
## 34 tbk_s2b.txt    418   110     39       58       78
## 35 tbk_s2c.txt    333   128     38       67       86
## 36 tbk_s3a.txt    508   162     44       73      103
## 37 tbk_s3b.txt    467   173     46       78      112
## 38 tbk_s3c.txt    530   177     44       79      109
## 39 tbk_s4a.txt    488   138     44       68       89
## 40 tbk_s4b.txt    543   186     47       73      112
## 41 tbk_s4c.txt    628   133     47       71       92


観測頻度

対象が歌詞なので総語数にそこまで差が出ないだろう、またある程度の長い短いもその文書の特徴と言えるのでは、との考えのもと実際の頻度である観測頻度でも分析を行う。

f:id:anemptyarchive:20190107043352p:plainf:id:anemptyarchive:20190107043345p:plainf:id:anemptyarchive:20190107043349p:plain
観測頻度高使用文字による結果
やはり、相対頻度の方が良いように感じる。クラスタの結果についての明確な評価基準はないようです(現在理論面も勉強途上です!)。

・使用単語によるクラスタ

相対頻度

テキストを単語レベルに区切り、文書ごとの出現頻度を基に各文書をグループ化していく。

f:id:anemptyarchive:20190107062446p:plainf:id:anemptyarchive:20190107062450p:plainf:id:anemptyarchive:20190110220352p:plain
相対頻度高使用単語による結果
各文書の総語数の平均は294.8語で文字種類の平均は126.5語のところ、1文書内に含まれていた特徴語の平均はそれぞれ32.5語(特徴語66語)、45.5語(139語)、62.0語(298語)だった。(数値の詳細は下の項目を展開してください。)

詳細(クリックで展開)

##      FILE_NAME TOKENS TYPES N_5050 N_100100 N_200200
## 1  kbs_a1a.txt    253   105     27       35       49
## 2  kbs_a1e.txt    344   126     35       48       63
## 3  kbs_a1g.txt    261    98     27       42       53
## 4  kbs_a1i.txt    312   162     41       54       69
## 5  kbs_a1l.txt    168    88     20       32       46
## 6  kbs_a1o.txt    301   146     28       39       54
## 7  kbs_a1q.txt    374   140     39       56       74
## 8  kbs_s0a.txt    232    98     26       30       41
## 9  kbs_s0b.txt    163    63     20       29       39
## 10 kbs_s1a.txt    365   152     37       50       70
## 11 kbs_s2a.txt    301   130     30       39       57
## 12 kbs_s2b.txt    272   126     30       42       57
## 13 kbs_s2c.txt    329   108     35       48       65
## 14 kbs_s3a.txt    325   143     30       45       59
## 15 kbs_s3b.txt    362   141     35       45       60
## 16 kbs_s4a.txt    247    87     27       36       47
## 17 kbs_s5a.txt    413   171     40       50       73
## 18 kbs_s5b.txt    254   104     36       54       75
## 19 kbs_s6a.txt    376   122     28       41       65
## 20 kbs_s6b.txt    193   103     24       41       60
## 21 tbk_a1b.txt    337   135     36       54       72
## 22 tbk_a1f.txt    274   118     26       41       55
## 23 tbk_a1i.txt    312   127     35       52       76
## 24 tbk_a1m.txt    245   136     32       45       64
## 25 tbk_a1q.txt    279   139     31       45       65
## 26 tbk_a1r.txt    171   103     38       52       63
## 27 tbk_s0a.txt    207   110     36       54       69
## 28 tbk_s0b.txt    379   158     37       53       70
## 29 tbk_s0c.txt    154    77     27       36       47
## 30 tbk_s1a.txt    410   167     35       52       78
## 31 tbk_s1b.txt    388   129     35       51       66
## 32 tbk_s1c.txt    433   200     39       47       60
## 33 tbk_s2a.txt    467   177     40       56       82
## 34 tbk_s2b.txt    218    89     29       38       53
## 35 tbk_s2c.txt    184    94     30       38       48
## 36 tbk_s3a.txt    279   133     36       48       65
## 37 tbk_s3b.txt    268   134     32       42       60
## 38 tbk_s3c.txt    311   140     35       46       67
## 39 tbk_s4a.txt    277   123     34       51       66
## 40 tbk_s4b.txt    305   156     37       54       69
## 41 tbk_s4c.txt    342   127     36       54       73


相対頻度,品詞限定(名詞,動詞,形容詞,形容動詞)

歌詞の内容によって特徴が出ているのでは、との考えのもと意味的役割を持つ名詞・動詞・形容詞・形容動詞に限定した分析を行う。

f:id:anemptyarchive:20190111022040p:plainf:id:anemptyarchive:20190111022045p:plainf:id:anemptyarchive:20190111022051p:plain
相対頻度高使用単語(品詞限定)による結果
意味の面から特徴が見えるのではと考えた訳だが、仮にそれがあったとしても歌詞という特性上様々な表現を用いるだろう。この分析では類語をいくら使っていても文書として似ているという結果にならないため、うまくいかないのではないかと考える。むしろ高頻度な助詞といった品詞の差の方が、頻度面で特徴をよく表すのだろう。また文字レベルだと、熟語が漢字単位に分解されることで、ある程度の類語の類似性が反映されたのではと考える。

TF-IDF

その単語がどれだけ文書を特徴づけているのかに注目した値であるので、TF-IDFも基準として使い分析を行う。

f:id:anemptyarchive:20190111023422p:plainf:id:anemptyarchive:20190111023430p:plainf:id:anemptyarchive:20190111023426p:plain
TF-IDF高使用単語による結果

今回は、両グループそれぞれの文書から別々にTF-IDFを求め、それぞれの上位の語を特徴語とした。その上で、クラスタリングの際には両グループを合わせてTF-IDFを出し、その数値を基に分析を行った。TF-IDFの適当な扱い方が思いつかず、正直中途半端な処理の仕方だったのではと感じている。

全体を通してkbk_s4aがグループを作っていないのが気になった。

○おわりに

 そもそもは、こぶしの曲は「今は大変でも前を向いて頑張っていこう」つばきは「センチメンタルな乙女の恋心」な歌詞だから(感覚的主観)、意味ベースで客観的にそれぞれの特徴を示したいというのが動機でした。今回の結果では、意味的機能を持つ名詞・動詞等よりも助詞も含めた全ての単語を特徴語として使う方が良さそうだし、なんなら文字単位で分類するのが一番高精度っぽいのはちょっとね…。まぁ元々歌詞の表現には幅を持たせてグループ感を形作っていく訳だし、類語単位でなければコンセプトや方向性のようなものを示せないだろうなとは思っていましたがね。あー早く分散表現完全に理解したい!

 あとは、分類したい(別の特徴を持って欲しい)両グループから特徴語をそれぞれ選んで全体の特徴語とするのは、ひょっとしてズルなのでは?と思ったり。機械学習の様々な手法を通しで試してみるという今回の目的からは、分類しやすくなるのは理解のためにはいいのかなーとか思いつつ、このまま進めます。でもどうしたらいいでしょうか、全体の上位語を特徴語とするのが素直だとは始めから思っていたのですが、特徴語を含まない文書が出てきたら困るので今回の方法にした。他には文書ごとに上位一定語数を選ぶ方法は考えましたけども。
 うーむ独学つらい誰か良い教材教えてください―。いえさっさと教科書3巻(活用事例編)の著者推定などなどをやればいいんです。文字の2-gramを特徴語に!

 とまぁ、多少ネガティブになりましたが、心の方では楽しんでるのでガンガン進めます―!前にこの分析をした時よりもかなり良くなったしね。では、次回は線形判別分析によるカテゴライゼーションです。最後まで読んでいただきありがとうございました。次回もよろしくお願いします。

www.anarchive-beta.com