Golangで言語処理100本ノック2015 第8章: 機械学習

言語処理100本ノック 2015の第8章: 機械学習の10問です。

本章では,Bo Pang氏とLillian Lee氏が公開しているMovie Review Dataのsentence polarity dataset v1.0を用い,文を肯定的(ポジティブ)もしくは否定的(ネガティブ)に分類するタスク(極性分析)に取り組む.

70. データの入手・整形

文に関する極性分析の正解データを用い,以下の要領で正解データ(sentiment.txt)を作成せよ.

  1. rt-polarity.posの各行の先頭に"+1 "という文字列を追加する(極性ラベル"+1"とスペースに続けて肯定的な文の内容が続く)
  2. rt-polarity.negの各行の先頭に"-1 "という文字列を追加する(極性ラベル"-1"とスペースに続けて否定的な文の内容が続く)
  3. 上述1と2の内容を結合(concatenate)し,行をランダムに並び替える sentiment.txtを作成したら,正例(肯定的な文)の数と負例(否定的な文)の数を確認せよ.

gist7abcc67e5e41ca5b7de31020c28aac7a

# go run q70.go
positive:  5331
negative:  5331

// 最初の5文のみ抜粋
# head -n 5 ../data/sentiment.txt
+1 you might want to take a reality check before you pay the full ticket price to see " simone , " and consider a dvd rental instead .
+1 birthday girl doesn't try to surprise us with plot twists , but rather seems to enjoy its own transparency .
+1 efteriades gives the neighborhood -- scenery , vibe and all -- the cinematic equivalent of a big , tender hug .
-1 the unceasing sadism is so graphically excessive , the director just ends up exposing his own obsession .
+1 works as pretty contagious fun .

教師データの作成ですが、実装内容自体は、今までやってきた内容で十分対応できます。

71. ストップワード

英語のストップワードのリスト(ストップリスト)を適当に作成せよ.さらに,引数に与えられた単語(文字列)がストップリストに含まれている場合は真,それ以外は偽を返す関数を実装せよ.さらに,その関数に対するテストを記述せよ.

giste459315cbddf0b696e9ec4241b349ac1

gist035fa3046d847cc7f82c2123e8282792

// PATHだけ書き換えています
# go test .
ok      _<PATH>/goNLP100knock2015/src/q71 0.007s

E Oracle Textのストップリストpythonのライブラリを参考にしました。

72-77は同じ問題として扱ったほうが見通しがいいのでまとめます。

72. 素性抽出

極性分析に有用そうな素性を各自で設計し,学習データから素性を抽出せよ.素性としては,レビューからストップワードを除去し,各単語をステミング処理したものが最低限のベースラインとなるであろう.

73. 学習

72で抽出した素性を用いて,ロジスティック回帰モデルを学習せよ.

74. 予測

73で学習したロジスティック回帰モデルを用い,与えられた文の極性ラベル(正例なら"+1",負例なら"-1")と,その予測確率を計算するプログラムを実装せよ.

75. 素性の重み

73で学習したロジスティック回帰モデルの中で,重みの高い素性トップ10と,重みの低い素性トップ10を確認せよ

76. ラベル付け

学習データに対してロジスティック回帰モデルを適用し,正解のラベル,予測されたラベル,予測確率をタブ区切り形式で出力せよ.

77. 正解率の計測

76の出力を受け取り,予測の正解率,正例に関する適合率,再現率,F1スコアを求めるプログラムを作成せよ.

gist3159bfb9a6735815106e74f20eba411d

# go run q72to77.go
**** labeling and the probablity ****
No. correct predicted   probability
--------------------------------------------
[ 0 ]    -1      -1      0.00022938614422040216
[ 1 ]    +1      +1      0.980844143721765
[ 2 ]    -1      -1      0.00708968717145575
[ 3 ]    +1      +1      0.6373159883859113
[ 4 ]    +1      +1      0.9916602446447373
[ 5 ]    +1      -1      0.03358930745405741
[ 6 ]    +1      +1      0.9719198377002579
[ 7 ]    -1      -1      0.01690622239135617
[ 8 ]    -1      -1      0.18087393421803644
[ 9 ]    +1      +1      0.9819855696689674

**** 10 highest weighted words ****
rank    word    weight
--------------------------------------------
[ 0 ]    engross     4.153318843524091
[ 1 ]    rare    3.9660695001044313
[ 2 ]    enjoy   3.646668750763667
[ 3 ]    beauti      3.5124131099641485
[ 4 ]    refreshingli    3.4833226288262464
[ 5 ]    memori      3.2698092911328422
[ 6 ]    move    3.181494225222411
[ 7 ]    consider    3.171432544641585
[ 8 ]    smart   3.1655141347852407
[ 9 ]    refresh     3.1581078779050067

**** 10 lowest weighted words ****
rank    word    weight
--------------------------------------------
[ 0 ]    dull    -4.366239700419224
[ 1 ]    neither     -4.070251251158453
[ 2 ]    name    -4.016387870547353
[ 3 ]    littl   -3.534095627137484
[ 4 ]    bore    -3.4944640249118266
[ 5 ]    badli   -3.397328927368818
[ 6 ]    worst   -3.3778081685478982
[ 7 ]    sort    -3.3675428257686875
[ 8 ]    bare    -3.3492559829926902
[ 9 ]    colleg      -3.3407574407648783

**** rates ****
accuracy rate:   0.812886888013506
precision rate:  0.8719892952720785
recall rate:     0.733445882573626
F1 score:    0.7967396841569028

予測率が上がらないと思ったら学習フェーズでデータXが参照渡しになっていて、ScaleVecによって更新されてしまっていました。値渡しかどうかは気をつけないとダメですね。

78. 5分割交差検定

76-77の実験では,学習に用いた事例を評価にも用いたため,正当な評価とは言えない.すなわち,分類器が訓練事例を丸暗記する際の性能を評価しており,モデルの汎化性能を測定していない.そこで,5分割交差検定により,極性分類の正解率,適合率,再現率,F1スコアを求めよ.

gist44a00f5d2f3cfeaf00c39b54c41e5d80

# go run q78.go
**** rates ( 0 / 5 ) ****
accuracy rate:   0.70042194092827
precision rate:  0.7175974710221286
recall rate:     0.6473384030418251
F1 score:    0.6806596701649176

**** rates ( 1 / 5 ) ****
accuracy rate:   0.6980778246601032
precision rate:  0.7402597402597403
recall rate:     0.6286764705882353
F1 score:    0.679920477137177

**** rates ( 2 / 5 ) ****
accuracy rate:   0.7018284106891702
precision rate:  0.7192982456140351
recall rate:     0.6569274269557022
F1 score:    0.6866995073891625

**** rates ( 3 / 5 ) ****
accuracy rate:   0.6957337083919363
precision rate:  0.7040816326530612
recall rate:     0.657769304099142
F1 score:    0.6801379990142927

**** rates ( 4 / 5 ) ****
accuracy rate:   0.6873239436619718
precision rate:  0.6619828259172521
recall rate:     0.7844588344125809
F1 score:    0.7180355630821337

学習データをそのまま判別データとすると8割だったので、もっと落ちるかと思いましたが、7割程度の判別率が出てますね。

79. 適合率-再現率グラフの描画

ロジスティック回帰モデルの分類の閾値を変化させることで,適合率-再現率グラフを描画せよ.

gistdc829ce8a45d892126337e30c6bdf184

f:id:cipepser:20171015142932p:plain

f:id:cipepser:20171015142939p:plain

感想

機械学習の流れ自体は、学生時代に触っていたので頭に入っているものの素性など、NLP特有の用語で少し戸惑いました。あと2値分類といえば、SVMばかりだったのでロジスティック回帰も改めて勉強して整理できたのでよかったです。

いつも通りコードはGithubにも置いてあります。

Reference