Domanda

Sto cercando di implementare il calcolo del coefficiente di correlazione di persone tra due insiemi di dati in PHP. Sto solo cercando di fare lo script python porting che si possono trovare a questo indirizzo http://answers.oreilly.com / topic / 1066-how-to-find-simili-utenti-con-python /

mia implementazione è la seguente:

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;

}
}

chiarimento per comprendere meglio il codice, il metodo fetchAllPreferences tornano indietro un insieme di oggetti che sono in realtà gli articoli, li trasforma in un array per facilità di gestione

Non sono sicuro che questa implementazione è corretto, in particolare ho qualche dubbio sulla correttezza del calcolo del denominatore.

qualsiasi consiglio è benvenuto.

grazie in anticipo!

È stato utile?

Soluzione

Il vostro algoritmo sembra matematicamente corretto ma numericamente instabile. Trovare la somma dei quadrati in modo esplicito è una ricetta per il disastro. Che cosa succede se si dispone di numeri come array(10000000001, 10000000002, 10000000003)? Un algoritmo di un passaggio numericamente stabile per calcolare la varianza può essere trovato su Wikipedia , e lo stesso principio può essere applicato al calcolo della covarianza.

Più facile ancora, se non si cura molto di velocità, si potrebbe utilizzare due passaggi. Trova il mezzo nel primo passaggio, poi calcolare le varianze e covarianze attraverso formulazioni libro di testo nel secondo passaggio.

Altri suggerimenti

Questa è la mia soluzione:

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-semplice-Pearson-correlazione /

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top