PHP
機械学習
統計学

PHPでベイジアンフィルタを書いてみた

More than 3 years have passed since last update.

勉強のため、PHPでベイジアンフィルタを書いてみました。下記のサイトを参考にしています。スムージングとして、単語の出現回数に1を足しています。アルゴリズムはリンク先の解説が正確だと思うので、割愛しますが、手計算での計算と結果は合っているので、多分正しく動作しているかと。

●参考:

第3回 ベイジアンフィルタを実装してみよう http://gihyo.jp/dev/serial/01/machine-learning/0003?page=2

P(word|cate)を求める時の分母になるカテゴリの全単語出現回数(getAllWordNumCate($cate))を都度計算しているので、無駄がありますが、分かりやすさを優先してそのままにしています。


Classifer.php

<?php

error_reporting(E_ALL & ~E_NOTICE);

/**
* Classifier
*
* @package
* @author kure
*/

class Classifier {

private $cc = array();
private $fc = array();

private function getwords($doc) {
return array_unique(preg_split("/\\W/", $doc));
}

/**
*
* @param type $doc
* @param type $cate
*/

public function train($doc, $cate) {
$this->cc[$cate] ++;
$words = $this->getwords($doc);
foreach ($words as $v) {
$this->fc[$v][$cate] ++;
}
}

/**
*
* @param type $cate
* @return type
*/

private function cateProb($cate) {
$total = 0;
foreach ($this->cc as $v) {
$total = $total + $v;
}
return $this->cc[$cate] / $total;
}

/**
*
* @param type $word
* @param type $cate
* @return type
*/

private function getWordNumCate($word, $cate) {
foreach ($this->fc as $key => $value) {
if ($key === $word) {
return $value[$cate] + 1;
}
}
}

/**
*
* @param type $cateSelected
* @return type
*/

private function getAllWordNumCate($cateSelected) {
$total = 0;
foreach ($this->fc as $key => $value) {
foreach ($value as $cate => $num) {
if ($cate === $cateSelected) {
$total = $total + $num;
}
}
}
return $total;
}

/**
* P(word|cat)
* @param type $word
* @param type $cate
* @return type
*/

private function wordCateProb($word, $cate) {
return $this->getWordNumCate($word, $cate) / $this->getAllWordNumCate($cate);
}

/**
* P(doc|cat) = P(word1|cat)P(word2|cat)...
* @param type $doc
* @param type $cate
* @return type
*/

private function docCateProb($doc, $cate) {
$wordArr = $this->getwords($doc);
$wordProbArr = array();
$wordProbTotal = 1;
foreach ($wordArr as $word) {
$wordProbTotal = $wordProbTotal * $this->wordCateProb($word, $cate);
}
return $wordProbTotal;
}

/**
* P(cat|doc) = P(doc|cat)P(cat)
* @param type $doc
*/

public function classify($doc) {
foreach ($this->cc as $cate => $num) {
echo $cate . ": " . $this->cateProb($cate) * $this->docCateProb($doc, $cate) . "\n";
}
}

}

$c = new Classifier();
$c->train("I have", "bad");
$c->train("I donnot", "good");
$c->train("I know", "bad");
$c->classify("I");



実行結果

bad: 0.5

good: 0.33333333333333