Корреляция Пирсона в PHP

Я пытаюсь реализовать вычисление коэффициента корреляции людей между двумя наборами данных в php. Я просто пытаюсь выполнить портирующий скрипт python, который можно найти по этому URL- адресу http://answers.oreilly.com/topic/1066-how-to-find-similar-users-with-python/

моя реализация такова:

class LB_Similarity_PearsonCorrelation implements LB_Similarity_Interface{ public function similarity($user1, $user2){ $sharedItem = array(); $pref1 = array(); $pref2 = array(); $result1 = $user1->fetchAllPreferences(); $result2 = $user2->fetchAllPreferences(); foreach($result1 as $pref){ $pref1[$pref->item_id] = $pref->rate; } foreach($result2 as $pref){ $pref2[$pref->item_id] = $pref->rate; } foreach ($pref1 as $item => $preferenza){ if(key_exists($item,$pref2)){ $sharedItem[$item] = 1; } } $n = count($sharedItem); if ($n == 0) return 0; $sum1 = 0;$sum2 = 0;$sumSq1 = 0;$sumSq2 = 0;$pSum = 0; foreach ($sharedItem as $item_id => $pre) { $sum1 += $pref1[$item_id]; $sum2 += $pref2[$item_id]; $sumSq1 += pow($pref1[$item_id],2); $sumSq2 += pow($pref2[$item_id],2); $pSum += $pref1[$item_id] * $pref2[$item_id]; } $num = $pSum - (($sum1 * $sum2) / $n); $den = sqrt(($sumSq1 - pow($sum1,2)/$n) * ($sumSq2 - pow($sum2,2)/$n)); if ($den == 0) return 0; return $num/$den; } } 

разъяснение, чтобы лучше понять код, метод fetchAllPreferences возвращает обратно набор объектов, которые на самом деле являются элементами, превращает их в массив для удобства управления

Я не уверен, что эта реализация правильная, в частности у меня есть некоторые сомнения относительно правильности вычисления знаменателя.

любые советы приветствуются.

заранее спасибо!

Ваш алгоритм выглядит математически корректным, но численно неустойчивым. Явное определение суммы квадратов – это рецепт катастрофы. Что делать, если у вас есть числа, подобные array(10000000001, 10000000002, 10000000003) ? Численный стабильный однопроходный алгоритм вычисления дисперсии можно найти в Википедии , и тот же принцип может быть применен для вычисления ковариации.

Еще проще, если вам не все равно, о скорости, вы можете просто использовать два прохода. Найдите средства в первом проходе, затем вычислите отклонения и ковариации, используя формулу учебника во втором проходе.

попробуйте мой пакет здесь

http://www.phpclasses.org/browse/package/5854.html

Это мое решение:

 function php_correlation($x,$y){ if(count($x)!==count($y)){return -1;} $x=array_values($x); $y=array_values($y); $xs=array_sum($x)/count($x); $ys=array_sum($y)/count($y); $a=0;$bx=0;$by=0; for($i=0;$i<count($x);$i++){ $xr=$x[$i]-$xs; $yr=$y[$i]-$ys; $a+=$xr*$yr; $bx+=pow($xr,2); $by+=pow($yr,2); } $b = sqrt($bx*$by); if($b==0) return 0; return $a/$b; } - function php_correlation($x,$y){ if(count($x)!==count($y)){return -1;} $x=array_values($x); $y=array_values($y); $xs=array_sum($x)/count($x); $ys=array_sum($y)/count($y); $a=0;$bx=0;$by=0; for($i=0;$i<count($x);$i++){ $xr=$x[$i]-$xs; $yr=$y[$i]-$ys; $a+=$xr*$yr; $bx+=pow($xr,2); $by+=pow($yr,2); } $b = sqrt($bx*$by); if($b==0) return 0; return $a/$b; } - function php_correlation($x,$y){ if(count($x)!==count($y)){return -1;} $x=array_values($x); $y=array_values($y); $xs=array_sum($x)/count($x); $ys=array_sum($y)/count($y); $a=0;$bx=0;$by=0; for($i=0;$i<count($x);$i++){ $xr=$x[$i]-$xs; $yr=$y[$i]-$ys; $a+=$xr*$yr; $bx+=pow($xr,2); $by+=pow($yr,2); } $b = sqrt($bx*$by); if($b==0) return 0; return $a/$b; } в function php_correlation($x,$y){ if(count($x)!==count($y)){return -1;} $x=array_values($x); $y=array_values($y); $xs=array_sum($x)/count($x); $ys=array_sum($y)/count($y); $a=0;$bx=0;$by=0; for($i=0;$i<count($x);$i++){ $xr=$x[$i]-$xs; $yr=$y[$i]-$ys; $a+=$xr*$yr; $bx+=pow($xr,2); $by+=pow($yr,2); } $b = sqrt($bx*$by); if($b==0) return 0; return $a/$b; } в function php_correlation($x,$y){ if(count($x)!==count($y)){return -1;} $x=array_values($x); $y=array_values($y); $xs=array_sum($x)/count($x); $ys=array_sum($y)/count($y); $a=0;$bx=0;$by=0; for($i=0;$i<count($x);$i++){ $xr=$x[$i]-$xs; $yr=$y[$i]-$ys; $a+=$xr*$yr; $bx+=pow($xr,2); $by+=pow($yr,2); } $b = sqrt($bx*$by); if($b==0) return 0; return $a/$b; } в function php_correlation($x,$y){ if(count($x)!==count($y)){return -1;} $x=array_values($x); $y=array_values($y); $xs=array_sum($x)/count($x); $ys=array_sum($y)/count($y); $a=0;$bx=0;$by=0; for($i=0;$i<count($x);$i++){ $xr=$x[$i]-$xs; $yr=$y[$i]-$ys; $a+=$xr*$yr; $bx+=pow($xr,2); $by+=pow($yr,2); } $b = sqrt($bx*$by); if($b==0) return 0; return $a/$b; } 

http://profprog.ru/korrelyaciya-na-php-php-simple-pearson-correlation/