PHPでベイズ推定の習作
今更ながら、ポールグレアムの有名な本を読んだ。
ハッカーと画家 コンピュータ時代の創造者たち
ベイジアンフィルタの作り方が書いてあった。
フィルタの作り方についてはよく理解できてなかったのだが(文系だし)、「あー思ったより簡単なのだな」ということはなんとなく分かったので、PHPで習作してみることに。
ただ本だけでは理解不足な部分もあったので、以下も参考。
Implement Bayesian inference using PHP, Part 1
ベイズ推定 - Wikipedia</a
ベイジアンフィルタ
ベイジアンってどういう考え方なんだろう
整理の為に簡単なのを書いてみると、
例えば、とあるシステム会社があって、
・男が60%、女が40%
・男のウチ、99% がアニヲタ
・女のウチ、10% がアニヲタ
の場合、アニヲタだったとき、それが男の可能性は、
*1 = 0.93
ってことで、なにもしなければ男の確率は60%だったのだが、アニヲタという条件を加えたことにより野郎率が変わるのを定理化したのがベイズの定理。
という理解でいいのかな。
まぁ、
Bayesian Setの種明かし
何のことはない確率の比を取っているだけである。
なので大体あっている気がするが。
ベイズ推定習作
ロジックとかはPaul Graham方式を参考にしてみたのだけど、本当は 偽陽性(false positive)・・・スパムじゃないのにスパムと判断されるのを防ぐ為に、Goodの確率を2倍にしたりとか、もう少し係数とか条件が増えてます。
このへんは判定すべき事象(「褒めている文章かDISっている文章か」とか)によって変わってくるチューニング事項なのかなぁ、って気がします。
で、ソースはこんな感じ。
[php]<?php
mb_internal_encoding('UTF-8');
$gpp = false;
if (isset($POST['e'])) { $g = $b = array(); foreach ($POST['g'] as $row) { $v = htmlspecialchars(trim(preg_replace('/ /', ' ', $row))); if ($v != '') { $g = $v; } } foreach ($_POST['b'] as $row) { $v = htmlspecialchars(trim(preg_replace('/ /', ' ', $row))); if ($v != '') { $b = $v; } }
$total = array('g'=>sizeof($g), 'b'=>sizeof($b));
$gw = split(' ', join(' ', $g));
$bw = split(' ', join(' ', $b));
$tbl = array();
foreach($gw as $row) {
if (!isset($tbl[$row])) {
$tbl[$row] = array('g'=>0,'b'=>0);
}
$tbl[$row]['g']++;
}
foreach($bw as $row) {
if (!isset($tbl[$row])) {
$tbl[$row] = array('g'=>0,'b'=>0);
}
$tbl[$row]['b']++;
}
foreach($tbl as $k=>$v) {
$tbl[$k]['gp'] = max(.01,min(.99, $tbl[$k]['g'] / $total['g']));
$tbl[$k]['bp'] = max(.01,min(.99, $tbl[$k]['b'] / $total['b']));
$tbl[$k]['gpp'] = ($tbl[$k]['gp'] / ($tbl[$k]['gp']+$tbl[$k]['bp']));
}
$c = htmlspecialchars(preg_replace('/ /', ' ', $_POST['c']));
$cw = array_unique(split(' ', $c));
$gp = $bp = 1;
$res = array();
foreach ($cw as $row) {
if (!isset($tbl[$row])) {
continue;
}
$gp *= $tbl[$row]['gpp'];
$bp *= (1 - $tbl[$row]['gpp']);
$res[$row] = $tbl[$row];
}
$gpp = $gp / ($gp+$bp);
} ?>
bayes
<?php if ($gpp !== false) { ?><?php echo $cv; ?>
Good Probablility:<?php echo $gpp; ?>
total: <?php print_r($total); ?> words: <?php print_r($res); ?> <?php } ?> [/php]*1:0.6 x 0.99 ) / (( 0.6 x 0.99) + (0.4 x 0.1