Question

Je suis en train de mettre en œuvre le calcul du coefficient de corrélation des personnes entre deux ensembles de données en php. Je suis juste essayer de faire le script python portage qui peut être trouvé à cette adresse http://answers.oreilly.com / sujet / 1066 comment trouver-similaires-à-utilisateurs avec-python /

ma mise en œuvre est le suivant:

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;

}
}

clarification pour mieux comprendre le code, la méthode fetchAllPreferences retour en arrière un ensemble d'objets qui sont en fait les éléments, les transforme en un tableau pour faciliter la gestion

Je ne suis pas sûr que cette mise en œuvre est correcte, en particulier, j'ai quelques doutes sur l'exactitude du calcul du dénominateur.

tous les conseils sont les bienvenus.

Merci d'avance!

Était-ce utile?

La solution

Votre algorithme semble mathématiquement correct, mais numériquement instable. Trouver la somme des carrés est explicitement une recette pour un désastre. Que faire si vous avez des chiffres comme array(10000000001, 10000000002, 10000000003)? Un algorithme d'une passe numériquement stable pour le calcul de la variance peut être trouvés sur Wikipedia , et même principe peut être appliqué au calcul de la covariance.

Plus facile encore, si vous ne se soucient pas beaucoup de vitesse, vous pouvez simplement utiliser deux passes. Trouver les moyens dans le premier passage, puis le calcul des variances et des covariances à l'aide de la formule de manuel dans le second passage.

Autres conseils

Ceci est ma solution:

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 corrélation pearson /

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top