読者です 読者をやめる 読者になる 読者になる

日記とか、工作記録とか

自分に書けることを何でも書いてゆきます。作った物、買ったもの、コンピュータ系の話題が多くなるかもしれません。

単純ベイズ分類器

前々から、なんとか自分の知識として身に着けたい、と思っていたので以下のページを参考に勉強しました。どうにか実装できそうな気がしてきたところでノートを貼り付けておきます。ほかの人に見せてわかるようなメモになっていなくて申し訳ないです。


始めてみた方はしたのリンク先の記事をまずご覧になったほうが有益だと思われます。また、末尾の本は前に自分で勉強するために買ったものです。


ベイジアンフィルタを実装してみよう



■ 学習データを保存する

[TABLE1:カテゴリごとの、全単語の出現頻度をカウントする]

カテゴリ 単語 出現頻度(回)
A りんご 10
A みかん 4
B りんご 3
B みかん 15

※学習時、指定されたカテゴリの文書で単語がでてくるたびに出現頻度を+1する。

[TABLE2:カテゴリごとの学習回数をカウントする]

カテゴリ 学習回数(回)
A 5
B 3

※学習時、指定されたカテゴリの学習をするごとに学習回数+1する。

[TABLE3:既知の単語をリストアップしておく]

単語
りんご
みかん

※既知の単語かどうかの判定に使用する。また、総単語数も使用する。

■ 学習時の実装

words = 分類する文章を、単語に分解して、正規化(小さな単語やごみとなる記号を取り除く)したものを準備する

TABLE3にまだ単語が載っていなければ載せる。
TABLE2で、カテゴリの学習回数を1増やす。
foreach( words内の単語 ){
 TABLE1に単語がすでにあれば、出現頻度を+1する。TABLE1にまだ単語がない場合は、載せて出現頻度を1にする。
}

■ 分類時の数式

score( words, category ) = log( prioprob( category ) ) + foreach( words as word ){ log( wordprob( word, category ) ) }

prioprob( category ) = { categoryの学習文書数 } / { 全学習文書数 }

wordprob( word, category ) = { incategory( word, category ) + 1.0 } / { wordcount( category ) + vocabularies }

incategory( word, category ) = TABLE1でそのカテゴリでの単語の出現頻度

wordcount( category ) = TABLE1でそのカテゴリにある全単語について、出現頻度の合計

vocabularies = TABLE3の全単語数

■ 分類の実装時の順番

words = 分類する文章を、単語に分解して、正規化(小さな単語やごみとなる記号を取り除く)したものを準備する
vocabularies = TABLES3の行数を求める。

foreach( カテゴリセット ){
 foreach( カテゴリ ){
  wordcount = TABLE1から、カテゴリに属する全単語の出現頻度を合計する。
  log( prioprob ) = TABLE2の学習回数から計算してlogをとる。
 }
 foreach( words内の単語 ){
  foreach( カテゴリ ){
   wordprobのlogをとり、値を合計する
   ※単語スコアがカテゴリにより大きく違う単語は「特徴的な単語」としてリストに載せる
  }
 }
 スコアを求める
 }
 カテゴリとスコアの組のリストを作る
}

■ 「特徴的な単語」とは何か?

wordprob( word, category ) を各categoryについて求めたときに、差が大きいものが影響が大きい。
つまり、ある単語がカテゴリAでは多く出てくる割にカテゴリBでは大幅に少ない場合、影響が大きい。

ベイズな予測―ヒット率高める主観的確率論の話

ベイズな予測―ヒット率高める主観的確率論の話