ボールを蹴りたいシステムエンジニア

ボール蹴りが大好きなシステムエンジニア、ボールを蹴る時間確保の為に時間がある時には勉強する。

初心者がナイーブベイズ分類器を作成する為の備忘録

やりたい事

ナイーブベイズ分類器を用いてツイートの内容が修造BOTイチローBOTのどちらに分類されるかを識別する。

自分用の備忘録として纏めていますので、若干分かりづらい所があると思いますので悪しからず。
間違いがあれば指摘頂けると嬉しいです。

学習データ(訓練用データ)

修造BOTイチローBOTのツイートを150件ずつ合計300件

教師データ作成

Ci(クラス)のパターンを考える

今回は2パターンだけなので2つ

C1=修造BOT
C2=イチローBOT

Bag of Wordsを作成する

Bag of Wordsとは文書から抽出した単語の集合。

訓練用データを読み込んで、mecab分かち書きし、
[ツイート][単語]の2次元配列を作成する。

こんな感じなる

[
 [自分,絶対,駄目,人,全て],
 [自分,ない,人,目,バット]
]

訓練用データのBag of Wordsから教師データ(モデル)を作成する

教師データ作成では以下の情報を取得する。

P(Ci)=事前確率

教師データ作成の為に利用した全データのうちクラスCiの発生する確率。
各クラスの生起確率とも言う。

今回の識別器で扱うクラスは

C1=修造BOT
C2=イチローBOT

それぞれ150件、合計300件を利用しているので事前確率は等しい事となる。

P(C1) = 150 / 300 = 1/2
P(C2) = 150 / 300 = 1/2

全ての単語の、「単語の条件付き確率」の分子・分母

単語の条件付き確率は、識別時のベイズの定理での尤度で利用し、その際に計算しても良いが、
訓練時に予め算出しておく事で、識別処理を高速化する。

「単語の条件付き確率」の分子
ex)
イチローBOT」クラスで「野球」という単語は20回出現

という感じで全ての単語の値を求める。

「単語の条件付き確率」の分母
ex)
イチローBOT」クラスで出現した全ての単語の件数+ツイート全体(イチローBOT、修造BOT)での単語ユニーク件数
※何故後者を加算するかよく分かっていない・・

識別対象データのクラス識別する

識別対象データの特徴ベクトルを取得

今回の例だと識別対象のツイートから頻出単語上位5件を取得する。

取得した特徴ベクトルを特徴ベクトルxと呼ぶ事とする。

例)
[自分,明日,人,耳,バット]

観測データをベイズの定理に当てはめてそれぞれのクラスの事後確率を求める

P(Ci|x)=p(x|Ci)/p(x) * P(Ci)

以下の様に変形できる

P(x|Ci) * P(Ci)

p(x)とは特徴ベクトルxの生起確率、全てのクラスで共通なので無視できる。
例えば、特徴ベクトルxのC1クラスとC2クラスそれぞれの事後確率を比較する場合、

p(x|C1)/p(x) * P(C1)

p(x|C2)/p(x) * P(C2)

を比較する事となるが、p(x)はどちらでも共通の値(全文書で特徴ベクトルxの生起確率)なので無視できる。

なので
P(x|Ci) * P(Ci)
の式に当てはめて事後確率を求める。

P(Ci)=事前確率

訓練時に取得済み。

p(x|Ci)=尤度

特徴ベクトルが連続的なデータ(単語の出現回数)なので、多項分布モデルで分類する。
※単語が出たか出なかったか(0 or 1)のような離散的データならベルヌーイ分布モデル

観測データをx、分類クラスをCi(i=1,...,N)とし、書き直すと
=P(x|Ci)
=クラスCiに分類されたデータxの確率分布
=Ci の中でxが発生する確率(xがCiであることが尤もらしい度合い)。

イチローBOTの例で考えると、
イチローBOTのツイート全ての中で、特徴ベクトル[自分,ない,人,目,バット]が発生する確率。

P(x|Ci) = P( word1, word2, word3, ... | Ci)
と考えられる。

P(word_i | Ci)=単語の条件付き確率
各単語がイチローBOTのツイート全ての中で発生する確率「単語の条件付き確率」を求める。

P( word1, word2, word3, ... | Ci)
 =P(word1 | Ci) * P(word2 | Ci) * P(word3 | Ci) ...

 =特徴ベクトルxの単語の条件付き確率の積が尤度となる。


※注意
上記の式の変形では単語の出現確率の間に独立性を仮定して同時確率をそれぞれの確率の積で表しているが、
本来、単語の出現に独立性は成り立りたたない。
たとえば、「人工」と「知能」は共起しやすいし、「機械」と「学習」は共起しやすい。
これを無視して単語の出現は独立と無理矢理仮定して文書の確率を単語の確率の積で表して
単純化するのがナイーブベイズのナイーブたる所以。

P(word_i | Ci)=単語の条件付き確率

クラスCiでword_iが出現する確率。
例として、
イチローBOTでword_iが出現した単語数 / (イチローBOTで出現した全ての単語数 + 全文書のユニーク単語数)

ラプラススムージングとして、分母に全文書のユニーク単語数を加算してる。

尤度の対数を取る

ここまでの計算結果でベイズの定理の事後確率を求める事もできそうですが、
尤度=P(x|Ci)はというのは非常に小さい数な上に文書中にはたくさんの単語が含まれるので
かけ算部分がアンダーフローを起こす可能性がある。
ex)
P(word1 | Ci) * P(word2 | Ci) * P(word3 | Ci) ...
の積がアンダーフローを起こす可能性がある。

その対策として、対数をとってかけ算を足し算化する。
事後確率の大小関係は対数をとっても変化しないので問題無い。

スムージング

識別対象データの単語が教師データに含まれない場合、
単語の条件付き確率P(word_i|Ci)は0となり、尤度(単語の条件付き確率の積)も0となってしまい計算ができなくなる。
これをゼロ頻度問題と言う。
ゼロ頻度問題は、スムージングという方法で対処できる。
よく使われるのが単語の出現回数に1を加えるラプラススムージング(LaplaceSmoothing)。
新しい単語が出てくると確率は低くなりますが、0にはなりません。

今回の例だと、単語の条件付き確率の算出時に、
分子である、Ciでの単語(word_i)の出現回数に+1
分母である、Ciでの全ての単語数に+全文書のユニーク単語数

クラスの識別

各クラスの事後確率を比較して、最も事後確率が大きいクラスが該当する。
(Map推定)

おわりに

  • 修造BOTイチローBOTでは発言の傾向が似ているので若干識別がしずらい感じがするので、もっと発言が異なるBOTで識別器を作成した方が良いかも。
  • ナイーブベイズ分類器の理論を理解するにあたって、様々な数学の知識が必要。周辺情報の勉強にかなり時間かかった。
  • 本記事は誤りが多数ある可能性がある為、都度間違いは修正していく。