Pregunta

Estoy tratando de poner en práctica el cálculo del coeficiente de correlación de personas entre dos conjuntos de datos en PHP. Sólo estoy tratando de hacer el guión de portabilidad pitón que se pueden encontrar en la siguiente dirección http://answers.oreilly.com / tema / 1066-how-to-find-usuarios-con-similares pitón /

mi aplicación es el siguiente:

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;

}
}

aclaración para comprender mejor el código, los fetchAllPreferences método regresan un conjunto de objetos que son en realidad los artículos, los convierte en una matriz para facilitar la gestión

No estoy seguro de que esta aplicación es correcta, en particular, tengo algunas dudas sobre la corrección del cálculo del denominador.

Cualquier consejo es bienvenido.

Gracias de antemano!

¿Fue útil?

Solución

Su algoritmo busca matemáticamente correcto, pero numéricamente inestable. Encontrar la suma de los cuadrados es explícitamente una receta para el desastre. ¿Qué pasa si usted tiene números como array(10000000001, 10000000002, 10000000003)? Un algoritmo de una sola pasada numéricamente estable para el cálculo de la varianza puede ser encontrado en la Wikipedia , y el mismo principio se puede aplicar a calcular la covarianza.

Más fácil todavía, si no le importa mucho acerca de la velocidad, es posible que utilices dos pases. Encuentra los medios en la primera pasada, y luego calcular las varianzas y covarianzas utilizando la fórmula libro de texto en el segundo pase.

Otros consejos

Esta es mi solución:

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-sencillo-pearson-correlación /

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top