2009-11-22 6 views
5

Esta función es del libro "Programación de la inteligencia colectiva”, y se supone que calcular el coeficiente de correlación de Pearson para P1 y P2, que se supone que es un número entre¿Qué hay de malo con el algoritmo pearson de "Programación de la inteligencia colectiva"?

si los elementos del tipo de dos críticos -1 y 1. Los de manera muy similar a la función debería devolver 1, o cercano a 1.

con los datos de usuario real a veces me da resultados extraños En el siguiente ejemplo, el conjunto de datos critics2 debería devolver 1 -. En su lugar, devuelve 0.

¿el punto cualquiera un error?

(Th no es un duplicado de What is wrong with this python function from “Programming Collective Intelligence”)

from __future__ import division 
from math import sqrt 

def sim_pearson(prefs,p1,p2): 
    si={} 
    for item in prefs[p1]: 
     if item in prefs[p2]: si[item]=1 
    if len(si)==0: return 0 
    n=len(si) 
    sum1=sum([prefs[p1][it] for it in si]) 
    sum2=sum([prefs[p2][it] for it in si]) 
    sum1Sq=sum([pow(prefs[p1][it],2) for it in si]) 
    sum2Sq=sum([pow(prefs[p2][it],2) for it in si]) 
    pSum=sum([prefs[p1][it]*prefs[p2][it] for it in si]) 
    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 

critics = { 
    'user1':{ 
     'item1': 3, 
     'item2': 5, 
     'item3': 5, 
     }, 
    'user2':{ 
     'item1': 4, 
     'item2': 5, 
     'item3': 5, 
     } 
} 
critics2 = { 
    'user1':{ 
     'item1': 5, 
     'item2': 5, 
     'item3': 5, 
     }, 
    'user2':{ 
     'item1': 5, 
     'item2': 5, 
     'item3': 5, 
     } 
} 
critics3 = { 
    'user1':{ 
     'item1': 1, 
     'item2': 3, 
     'item3': 5, 
     }, 
    'user2':{ 
     'item1': 5, 
     'item2': 3, 
     'item3': 1, 
     } 
} 

print sim_pearson(critics, 'user1', 'user2',) 
result: 1.0 (expected) 
print sim_pearson(critics2, 'user1', 'user2',) 
result: 0 (unexpected) 
print sim_pearson(critics3, 'user1', 'user2',) 
result: -1 (expected) 

Respuesta

11

No hay nada malo en su resultado. Estás tratando de trazar una línea a través de 3 puntos. En el segundo caso, tiene los tres puntos con las mismas coordenadas, es decir, efectivamente un punto. No se puede decir si estos puntos se correlacionan o no, porque se puede dibujar un número infinito de líneas en un punto (den en su código es igual a cero).

0

El algoritmo da el resultado correcto. 0 significa que no existe una correlación entre ellos (o al menos no se puede saber a partir de lo que usted sabe).

En general (según el dominio que aplique este algoritmo) puede considerar todo entre -0.9 < x < 0.09 como "Sin correlación observable".

0

La correlación no implica causalidad. Tenía que decirlo. Necesita desarrollar una comprensión de las estadísticas de correlación. La correlación puede estar entre -1 y 1 y un valor de 0 cae en este rango y es un resultado perfectamente razonable. Una correlación de 0 implica que no hay una relación estadísticamente significativa entre las 2 variables. Recuerde evitar hacer estadísticas con menos de 30 muestras.

3

Si mira hacia arriba Pearson correlation on wikipedia, verá que la fórmula utiliza la diferencia entre cada elemento de una serie y el promedio de la serie. Cuando todos los elementos de la serie son iguales, obtienes la división por cero, por lo que tu cálculo falla.

Si es más claro, se puede utilizar este código:

def simplified_sim_pearson(p1, p2): 
    n = len(p1) 
    assert (n != 0) 
    sum1 = sum(p1) 
    sum2 = sum(p2) 
    m1 = float(sum1)/n 
    m2 = float(sum2)/n 
    p1mean = [(x - m1) for x in p1] 
    p2mean = [(y - m2) for y in p2] 
    numerator = sum(x * y for x, y in zip(p1mean, p2mean)) 
    denominator = math.sqrt(sum(x * x for x in p1mean) * sum(y * y for y in p2mean)) 
    return numerator/denominator if denominator else 0 

def sim_pearson(prefs,p1,p2): 
    p1 = prefs[p1] 
    p2 = prefs[p2] 
    si = set(p1.keys()).intersection(set(p2.keys())) 
    p1_x = [p1[k] for k in sorted(si)] 
    p2_x = [p2[k] for k in sorted(si)] 
    return simplified_sim_pearson(p1_x, p2_x) 



critics = { 
    'user1':{ 
     'item1': 3, 
     'item2': 5, 
     'item3': 5, 
     }, 
    'user2':{ 
     'item1': 4, 
     'item2': 5, 
     'item3': 5, 
     } 
} 
critics2 = { 
    'user1':{ 
     'item1': 5, 
     'item2': 5, 
     'item3': 5, 
     }, 
    'user2':{ 
     'item1': 5, 
     'item2': 5, 
     'item3': 5, 
     } 
} 
critics3 = { 
    'user1':{ 
     'item1': 1, 
     'item2': 3, 
     'item3': 5, 
     }, 
    'user2':{ 
     'item1': 5, 
     'item2': 3, 
     'item3': 1, 
     } 
} 

print sim_pearson(critics, 'user1', 'user2',) 
print sim_pearson(critics2, 'user1', 'user2',) 
print sim_pearson(critics3, 'user1', 'user2',) 

Por cierto, el uso de Excel para determinar la respuesta correcta es una buena manera de validar la mayoría de los cálculos. En este caso, habría utilizado correl.

Cuestiones relacionadas