2008年10月12日

集合知プログラミング その2

なんだかんだで全く読んでいなかった集合知プログラミング
EEEPCかったので、何となく続きを読み始めた。

せっかく買ったEEEPC使ってみたいので
取りあえず例のごとくコードをPHP西ながら読んでいるのですが。
EEEPCで本気で開発はあれだけど、遊び&ちょっと試すぐらいなら十分な感じ。

で本の方だが元々多少の誤差はあったんだが
18−19Pの例で明らかにおかしい結果になった。

例題で言えば-0.179とでるところが0となる。
誤差というには大きすぎるので、ソースを何度も見直すが
原因が分からない。
明示的に型キャストしても変わらないし・・・

Googleさんに問い合わせて
トライアウト ラボラトリ!さんのところでPHPのコードを載せておられるのを発見
私のコードと置き換えて動かして見るが直らない。
http://tryout-lab.com/category/%e9%9b%86%e5%90%88%e7%9f%a5%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%9f%e3%83%b3%e3%82%b0


で、ふと元データが悪いんじゃないか?と思い立ち最初のハッシュ部分を見てみると。
入力ミスがあるww
元データの値が1も違っていた。
それは誤差がでるな。

というわけで私が書いたコードは以下のような感じ。


<?php

$critics = array(
'Lisa Rose' => array(
'Lady in the Water' => 2.5,
'Snakes on a Plane' => 3.5,
'Just My Luck' => 3.0,
'Superman Returns' => 3.5,
'You, Me and Dupree' => 2.5,
'The Night Listener' => 3.0,
),
'Gene Seymour' => array(
'Lady in the Water' => 3.0,
'Snakes on a Plane' => 3.5,
'Just My Luck' => 1.5,
'Superman Returns' => 5.0,
'You, Me and Dupree' => 3.5,
'The Night Listener' => 3.0,
),
'Michael Phillips' => array(
'Lady in the Water' => 2.5,
'Snakes on a Plane' => 3.0,
'Superman Returns' => 3.5,
'The Night Listener' => 4.0,
),
'Claudia Puig' => array(
'Snakes on a Plane' => 3.5,
'Just My Luck' => 3.0,
'Superman Returns' => 4.0,
'You, Me and Dupree' => 2.5,
'The Night Listener' => 4.5,
),
'Mick LaSalle' => array(
'Lady in the Water' => 3.0,
'Snakes on a Plane' => 4.0,
'Just My Luck' => 2.0,
'Superman Returns' => 3.0,
'You, Me and Dupree' => 2.0,
'The Night Listener' => 3.0,
),
'Jack Matthews' => array(
'Lady in the Water' => 3.0,
'Snakes on a Plane' => 4.0,
'Superman Returns' => 5.0,
'You, Me and Dupree' => 3.5,
'The Night Listener' => 3.0,
),
'Toby' => array(
'Snakes on a Plane' => 4.5,
'Superman Returns' => 4.0,
'You, Me and Dupree' => 1.0,
),
);
// person1とperson2の距離を基にした類似性スコアを返す。
//返り値は0-1の範囲で1に近いほど類似性がある。
function sim_distance($prefs, $person1, $person2){
$si = array();

//二人とも評価しているアイテムのリストを得る。
foreach($prefs["$person1"] as $item => $val){
if(isset($prefs["$person2"]["$item"])){
$si["$item"] = 1;
}
}
if(count($si) == 0){ return 0;}

//すべての差の平方を足し合わせる。
//上のループでできるよな
$sum_of_squares = 0;
foreach($prefs["$person1"] as $item => $val){
if(isset($prefs["$person2"]["$item"])){
$sum_of_squares += pow( ( $prefs["$person1"]["$item"]
- $prefs["$person2"]["$item"]
),
2);
}
}

return 1/(1 + sqrt($sum_of_squares));

}

//P1とP2のピアソン相関係数を返す。
function sim_pearson($prefs,$p1,$p2){

//両者が互いに評価しているアイテムのリストを取得
$si = array();
foreach($prefs["$p1"] as $item => $val){
if(isset($prefs["$p2"]["$item"])){
$si["$item"] = 1;
}
}

//要素の数を調べる。
$n = count($si);

//すべての嗜好,平方,積を合計する

//嗜好の合計
$sum1 = 0;
$sum2 = 0;

//平方の合計
$sum1Sq = 0;
$sum2Sq = 0;

//積の合計
$pSum = 0;

foreach($si as $item => $val){
$sum1 += $prefs["$p1"]["$item"];
$sum2 += $prefs["$p2"]["$item"];
$sum1Sq += pow($prefs["$p1"]["$item"],2);
$sum2Sq += pow($prefs["$p2"]["$item"],2);
$pSum += $prefs["$p1"]["$item"] * $prefs["$p2"]["$item"];
}

//ピアソンスコアを計算する
$num = $pSum - ($sum1 * $sum2 / $n);
$den = sqrt(($sum1Sq - pow($sum1,2) / $n) * ($sum2Sq - pow($sum2,2) / $n));

if($den == 0){ return 0;}

$r = $num / $den;
return $r;
}

//ディクショナリprefsからpersonにもっともマッチするものたちを返す
//結果の数と類似性関数はオプションのパラメータ
function topMatches($prefs, $person, $n=5, $similarity="sim_pearson"){

$scores = array();
foreach($prefs as $other => $list){
if($other != $person){
switch($similarity){
case "sim_distance":
$scores[] = array(sim_distance($prefs,$person,$other),$other);
break;
case "sim_pearson":
$scores[] = array(sim_pearson($prefs,$person,$other),$other);
break;
}
}
}
sort($scores);
rsort($scores);
$res = array();
for($i = 0;$i < $n;$i++){
$res[] = array_shift($scores);
}
return $res;
}

// person以外の全ユーザの評点の重み付き平均を使い。personへの推薦を算出する
function getRecommendations($prefs, $person, $similarity = "sim_pearson"){
$totals = array();
$simSums = array();

foreach ($prefs as $other => $list) {
// 自分自身とは比較しない
if ($other === $person){ continue; }

switch($similarity){
case "sim_distance":
$sim = sim_distance($prefs,$person,$other);
break;
case "sim_pearson":
$sim = sim_pearson($prefs,$person,$other);
break;
}
// 0以下のスコアは無視
if ($sim <= 0) { continue; }

foreach ($prefs["$other"] as $item => $scor) {
if (! isset($prefs["$person"]["$item"]) || $prefs["$person"]["$item"] == 0) {
// 類似度 * スコア
$other_item_scor = isset($prefs["$other"]["$item"]) ? $prefs["$other"]["$item"] : 0;
$totals["$item"] += $other_item_scor * $sim;

// 類似度を合計
$simSums["$item"] += $sim;
}
}
}
// 正規化したリストを作る
$rankings = array();
foreach ($totals as $item => $total){
$rankings[] = array( ($total / $simSums["$item"]), $item);
}
// ソート済みのリストを返す
sort($rankings);
rsort($rankings);

return $rankings;
}

function transformPrefs($prefs){
$result = array();
foreach($prefs as $person => $items){
foreach($prefs["$person"] as $item => $scor){
$result["$item"]["$person"] = $prefs["$person"]["$item"];
}
}
return $result;
}


//20-24Pのプログラムは無視

function calculateSimilarItems($prefs, $n=10){
//アイテムをキーとしてもち、それぞれのアイテムに似ている
//アイテムのリストを値として持つハッシュの作成

$result = array();

//嗜好の行列をアイテム中心な形に反転させる
$itemPrefs = transformPrefs($prefs);
$c = 0;
foreach ($itemPrefs as $item => $arr){
//巨大なデータセット用にステータスを表示

$c +=1;
if (($c % 100) == 0){
printf("%d / %d",$c,count($itemPrefs));
}
$scores = topMatches($itemPrefs, $item, $n,'sim_distance');
$result["$item"] = $scores;
}
return $result;
}
?>


コード表示用にCSSとか用意しないとあれかなぁ
そういえば本に載ってるPythonのコードをPHPに変換して載せるのも著作権的に不味いのだろうか。




posted by Belial at 23:51 | Comment(7) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする
この記事へのコメント

あういぇ━━━━(゚∀゚)━━━━い!!!!
こんなイカくせぇ包茎チムッポでも10人斬り余裕だったよ!!!!www

みんな「かーわーいーいー♪」とか言ってチムッポに興味津々www
チンカスついててもお構いなしにペロペロしてくれるしなっ♪♪♪
こんなウマウマ(゜∀゜)バイトあんならもっと早く教えてほしかったYO!!
http://met.pinknotel.net/ybrx298/
Posted by ちょろ毛 at 2010年01月24日 09:01

ザ〜メン大好きっ子に5万でチムッポのフルコースご馳走してきた!!!
つーかホテルにINして1分足らずでしゃぶりついてたっスwwwww

「はわわ〜!!めちゃ搾り取られてる!!」ってな具合に飲まれまくって
もうカウパ−1滴すら残ってないっス!!!!wwwww(*´д`*)ハァハァ
http://crackedpudding.com/nike/vtnz06z/
Posted by 正太郎 at 2010年01月27日 03:39

もー無理だってーーー!!!!(*≧д≦)
ティンティンしごくの止めてくれねぇし!!www
水鉄砲みたいにどっぴゅぅぅっ!って1mぐらい精子飛んじゃったよ!!!
確かに5万もらえたけど、まさかこんなプレイされるとはwwwww
http://ino.buta-infr.net/vu5of6d/
Posted by はるぞう at 2010年02月02日 07:19

おぉい!!オ-ナ-ニ−でテンションあがりすぎだっての!!
まさか押し倒されて逆レ-イ-プされるとは思わなかったわwwwww
マ-ヌ-コが吸盤みたいにチ-ム-コに食いついて離さねぇし!!(爆)

ま、お侘びに報酬が5マン→10マンにUPしたから全然おkだけどなwwww
http://ziku.aiyorikane.net/kzwbao4/
Posted by ベルカンポ at 2010年02月04日 08:18

アイマスクつけて手コキされたけどやっばいな!!
牛の乳しぼるみたいにシコシコされて、チン先からミルクいっぱい出ちゃった(笑)
恥ずかしかったけど6万もらえたし、Mな俺にはマジご褒美すぎる♪(*゚∀゚)=3
http://xabrina.net/don/6s-0slt/
Posted by MOGMOG at 2010年02月11日 05:25

ふわぁぁぁぁ!!おОんこってすごいな!!!!
根元までズッポリ飲み込まれた上にキューッて締めつけてくんの!!
ずっと童帝だったけど、ここで買ってもらってマジでよかったぁぁぁ!!
俺、もうオナホは捨てることにしまーす(笑)
http://nuda.pocket-m.net/r6ojt9k/
Posted by おっぱい大好き at 2010年02月17日 08:30

ちょっとした、ドキドキがほしいな
http://mjdu4w2.love.chu-g.net/
Posted by 夏だからね at 2011年07月31日 03:47
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/107991482

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。