2007/7/2 月曜日

PHPでベイズ推定の習作

Filed under: 技術メモ — dev0000 @ 17:48:31 このエントリをはてなブックマークに追加このエントリをdel.icio.usに追加このエントリをLivedoor Clipに追加このエントリをBuzzurl(バザール)に追加

今更ながら、ポールグレアムの有名な本を読んだ。
ハッカーと画家 コンピュータ時代の創造者たち

ベイジアンフィルタの作り方が書いてあった。
フィルタの作り方についてはよく理解できてなかったのだが(文系だし)、「あー思ったより簡単なのだな」ということはなんとなく分かったので、PHPで習作してみることに。

ただ本だけでは理解不足な部分もあったので、以下も参考。
Implement Bayesian inference using PHP, Part 1
ベイズ推定 - Wikipedia ベイジアンフィルタ
ベイジアンってどういう考え方なんだろう

整理の為に簡単なのを書いてみると、

例えば、とあるシステム会社があって、
・男が60%、女が40%
・男のウチ、99% がアニヲタ
・女のウチ、10% がアニヲタ
の場合、アニヲタだったとき、それが男の可能性は、
((0.6 x 0.99 ) / (( 0.6 x 0.99) + (0.4 x 0.1)) = 0.93
ってことで、なにもしなければ男の確率は60%だったのだが、アニヲタという条件を加えたことにより野郎率が変わるのを定理化したのがベイズの定理。

という理解でいいのかな。

まぁ、
Bayesian Setの種明かし

何のことはない確率の比を取っているだけである。

なので大体あっている気がするが。

ベイズ推定習作
ロジックとかはPaul Graham方式を参考にしてみたのだけど、本当は 偽陽性(false positive)・・・スパムじゃないのにスパムと判断されるのを防ぐ為に、Goodの確率を2倍にしたりとか、もう少し係数とか条件が増えてます。
このへんは判定すべき事象(「褒めている文章かDISっている文章か」とか)によって変わってくるチューニング事項なのかなぁ、って気がします。
で、ソースはこんな感じ。

PHP:
  1. <?php
  2.  
  3. $gpp = false;
  4.  
  5. if (isset($_POST['e'])) {
  6.     $g = $b = array();
  7.     foreach ($_POST['g'] as $row) {
  8.      $v = htmlspecialchars(trim(preg_replace('/ /', ' ', $row)));
  9.      if ($v != '') {
  10.         $g[] = $v;
  11.      }
  12.     }
  13.     foreach ($_POST['b'] as $row) {
  14.      $v = htmlspecialchars(trim(preg_replace('/ /', ' ', $row)));
  15.      if ($v != '') {
  16.         $b[] = $v;
  17.      }
  18.     }
  19.  
  20.     $total = array('g'=>sizeof($g), 'b'=>sizeof($b));
  21.     $gw = split(' ', join(' ', $g));
  22.     $bw = split(' ', join(' ', $b));
  23.     $tbl = array();
  24.     foreach($gw as $row) {
  25.         if (!isset($tbl[$row])) {
  26.              $tbl[$row] = array('g'=>0,'b'=>0);
  27.         }
  28.         $tbl[$row]['g']++;
  29.     }
  30.  
  31.     foreach($bw as $row) {
  32.         if (!isset($tbl[$row])) {
  33.             $tbl[$row] = array('g'=>0,'b'=>0);
  34.         }
  35.         $tbl[$row]['b']++;
  36.     }
  37.  
  38.     foreach($tbl as $k=>$v) {
  39.         $tbl[$k]['gp']max(.01,min(.99, $tbl[$k]['g'] / $total['g']));
  40.         $tbl[$k]['bp']max(.01,min(.99, $tbl[$k]['b'] / $total['b']));
  41.         $tbl[$k]['gpp'] = ($tbl[$k]['gp'] / ($tbl[$k]['gp']+$tbl[$k]['bp']));
  42.     }
  43.     $c = htmlspecialchars(preg_replace('/ /', ' ', $_POST['c']));
  44.     $cw = array_unique(split(' ', $c));
  45.  
  46.     $gp = $bp = 1;
  47.     $res = array();
  48.     foreach ($cw as $row) {
  49.         if (!isset($tbl[$row])) {
  50.              continue;
  51.         }
  52.         $gp *= $tbl[$row]['gpp'];
  53.         $bp *= (1 - $tbl[$row]['gpp']);
  54.         $res[$row] = $tbl[$row];
  55.     }
  56.     $gpp = $gp / ($gp+$bp);
  57. }
  58. ?><html>
  59. <head>
  60. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  61. </head>
  62. <body>
  63. <h1>bayes</h1>
  64. <form method="POST" action="index.php">
  65. <table border="2">
  66. <tr><td>Good Sentence</td><td>Bad Sentence</td></tr>
  67. <?php
  68. for ($i=0;$i<10;$i++) {
  69.     $gv = isset($g[$i]) ? $g[$i] : '';
  70.     $bv = isset($b[$i]) ? $b[$i] : '';
  71. ?>
  72. <tr>
  73. <td><input type="text" name="g[]" value="<?php echo $gv; ?>" size="50"/></td>
  74. <td><input type="text" name="b[]" value="<?php echo $bv; ?>" size="50"/></td>
  75. </tr>
  76. <?php
  77. }
  78. $cv = isset($c) ? $c : '';
  79. ?>
  80. </table>
  81. Check Sentence<br />
  82. <input type="text" name="c" value="<?php echo $cv; ?>" size="100" /><br />
  83. <input type="submit" name="e" />
  84. </form>
  85. <?php
  86. if ($gpp !== false) {
  87. ?>
  88. <hr />
  89. <?php echo $cv; ?>
  90. <br />
  91. Good Probablility:<?php echo $gpp; ?><br />
  92. <pre>
  93. total:
  94. <?php print_r($total); ?>
  95. words:
  96. <?php print_r($res); ?>
  97. <?php
  98. }
  99. ?>
  100. </body></html>

1件のコメント »

  1. [...] PHPでベイズ推定の習作 | 眠る開発屋blog [...]

    ピンバック by 怒涛のめもめもリンク集 | 一時リンク — 2009/8/24 月曜日 @ 13:08:17

この投稿へのコメントの RSS フィード。 TrackBack URL

コメントする

HTML convert time: 0.555 sec. Powered by WordPress ME