からっぽのしょこ

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

こぶつば楽曲の歌詞をテキスト分類したい⑥~サポートベクターマシン~

〇はじめに

 この記事ではRを使って教師あり学習のサポートベクターマシンによる文書分類を行います。基本的な内容は本に沿ってやっているので、詳しい説明は参考書籍をご参照ください。
 こぶしとつばきの歌詞を文字・単語に切り分け、曲ごとの出現頻度を特徴量として各グループに分類することに挑戦します。どのように特徴語を選べば分類精度が上がるのかを調べるのも目的としています。

・分析データ

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

特徴語の選択について www.anarchive-beta.com 特徴語の頻度表作成について(前半部分) www.anarchive-beta.com

・主な参考書籍

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

〇サポートベクターマシンによる文書分類

・処理コード

使用パッケージ

library(e1071)


ランダムフォレストによる分類

result1 <- svm(TYPE ~ ., type = "C-classification", data = train_data, cost = 7)
result2 <- predict(result1, test_data, type = "class")
result3 <- table(test_data$TYPE, result2)

#分類精度
result3
sum(diag(result3)) / sum(result3)

svm()を使って訓練データから分類モデルを作る。引数に教師データの列(TYPE) ~ .data =に訓練データを指定する。type = "C-classification"を指定すると分類となる。cost =で、誤分類をどの程度許容するかを指定できる(ある程度緩めないと過学習気味に??)。predict()で分類モデルを使って評価データの分類を行う。

検証

all_data <- freq_table
result <- NULL
for(i in 1:100) {
  # データの振り分け
  n <- c(sample(1:length(file_name1), length(file_name1) / 2), 
         sample((length(file_name1) + 1):(length(file_name1) + length(file_name2)), length(file_name2) / 2))
  train_data <- all_data[n, ]
  test_data  <- all_data[-n, ]
  
  # 分析
  result1 <- svm(TYPE ~ ., type = "C-classification", data = train_data, cost = 5)
  result2 <- predict(result1, test_data, type = "class")
  result3 <- table(test_data$TYPE, result2)
  
  result <- c(result, sum(diag(result3))/sum(result3))
}
mean(result)
sd(result)

分類精度の検証として、100回分の分析結果の平均と標準偏差をみる。両グループから半数ずつランダムに訓練・評価データに振り分けて分類を行うのを100回繰り返す。

・分析結果

各種分類手法や各特徴語の抽出パターンでの分類精度を比較するために、シングル楽曲を訓練データとして構築した分類モデルを使って、アルバム楽曲を評価データとして分類した結果を見る。それに加えて、両グループから半数ずつランダムに訓練データ・評価データに振り分けて分類するのを100回繰り返した際の正解率の平均値と標準偏差も載せている。

文字の出現頻度を特徴量とした場合

相対頻度
両グループから50語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   3   4
##   tbk   1   5

> sum(diag(result3)) / sum(result3)
## [1] 0.6153846

分析を100回行った正解率の平均値は0.6280952で標準偏差は0.08816833だった。

今回の分析だとこれでかなり良い精度、他は酷い…

ちなみに訓練データでテストしたところ下の結果でした。

> result3
##      rf_predict
##       kbs tbk
##   kbs  13   0
##   tbk   0  15

> sum(diag(result3)) / sum(result3)
## [1] 1

他の分類手法でも当然高精度だったが100%はあまり見なかった(全てで確認した訳ではないが)。
しかし他の手法だと、訓練データで評価して精度が高いと評価データを分類した精度も良く、悪いと分類精度も悪いという印象だったのだが、サポートベクターマシンでは概ね訓練データは100%分類できるのだが、その分過学習的な作用なのか評価データでの分類精度が悪いくなる印象を持った。

両グループから100語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   3   4
##   tbk   2   4

> sum(diag(result3)) / sum(result3)
## [1] 0.5384615

分析を100回行った正解率の平均値は0.6090476で標準偏差は0.09768267だった。

両グループから200語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   1   6
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.5384615

分析を100回行った正解率の平均値は0.5428571で標準偏差は0.07475806だった。

特徴語の数が少ない方が精度が高い傾向。ちなみに、答えは2択なのでテキトーに分類すれば大体精度は50%になる。

観測頻度
両グループから50語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   3   4
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.6923077

分析を100回行った正解率の平均値は0.5928571で標準偏差は0.09239999だった。

両グループから100語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   5   2
##   tbk   2   4

> sum(diag(result3)) / sum(result3)
## [1] 0.6923077

分析を100回行った正解率の平均値は0.6004762で標準偏差は0.09203239だった。

両グループから200語ずつを特徴語とした結果

##      result2
##       kbs tbk
##   kbs   6   1
##   tbk   1   5

> sum(diag(result3)) / sum(result3)
## [1] 0.8461538

分析を100回行った正解率の平均値は0.5790476で標準偏差は0.09589002だった。

シングル・アルバム分類だと高い精度だが、ランダムだと60%程度に落ち着いた。相対頻度と観測頻度で大きな差は見られない(他の分類手法だと相対頻度の方が良い印象)。

単語の出現頻度を特徴量とした場合

相対頻度
両グループから50語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   4   3
##   tbk   1   5

> sum(diag(result3)) / sum(result3)
## [1] 0.6923077

分析を100回行った正解率の平均値は0.512381で標準偏差は0.05419695だった。

69%はたまたまの模様

両グループから100語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.5128571で標準偏差は0.04272868だった。

両グループから200語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.54で標準偏差は0.06211346だった。

特徴語の数に依らず50%程度の結果。

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

相対頻度

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

両グループから50語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.5038095で標準偏差は0.04498741だった。

両グループから100語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.5085714で標準偏差は0.05817569だった。

両グループから200語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.5052381で標準偏差は0.04634911だった。

どの語数でもつばきに全振りしており、正解率の平均は50%。つまりダメダメ。

TF-IDF

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

両グループから50語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.5571429で標準偏差は0.06294861だった。

両グループか100語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.5847619で標準偏差は0.08616737だった。

両グループか200語ずつを特徴語とした結果

> result3
##      result2
##       kbs tbk
##   kbs   0   7
##   tbk   0   6

> sum(diag(result3)) / sum(result3)
## [1] 0.4615385

分析を100回行った正解率の平均値は0.6290476で標準偏差は0.09554904だった。

これもどの語数でもつばきに全振りしているが、正解率の平均は60%前後。判断に困る…。

語数が少ない方が良い傾向が見られたので、もっと少ない語数でも分析してみる必要がある。

以上です。

〇おわりに

 前回のランダムフォレストが良い結果だったので、なんとも言えない気持ちです。さて、次はどの手法にしようか。

 それにしてもこのシリーズ始めてからひと月が経ってしまいました。全然進まん。というのも日が経つごとに前に書いたコードの意図が分からなくなり、増えるスクリプトの管理ができなくなり、どうしたものか。というのが最近の悩み。
 という様に第2弾(これ)シリーズがぐだぐだにもかかわらず、同時に第3弾用の準備も進めていて余計ごちゃごちゃなんです笑。今までの結果を踏まえてどのように特徴語を抽出すれば良い結果が出そうか考えつつ、その為のデータを増やして前々処理をしております。楽しみです。

 最後までお読みくださりありがとうございました。間が空きそうですが、次もよろしくお願いします!