【问题标题】:What is wrong with the pearson algorithm from “Programming Collective Intelligence”?《编程集体智能》中的皮尔逊算法有什么问题?
【发布时间】:2010-12-19 04:51:44
【问题描述】:

此函数来自《Programming Collective Intelligence》一书,用于计算 p1 和 p2 的 Pearson 相关系数,应该是 -1 和 1 之间的数字。

如果两个评论家对项目的评分非常相似,则该函数应返回 1,或接近 1。

使用真实的用户数据,我有时会得到奇怪的结果。在以下示例中,数据集评论家 2 应返回 1 - 而不是返回 0。

有人发现错误吗?

(这不是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)

【问题讨论】:

    标签: python algorithm pearson


    【解决方案1】:

    如果您查看Pearson correlation on wikipedia,您会发现该公式使用了系列中每个项目之间的差异和系列的平均值。当系列中的所有项目都相同时,您会被零除,因此您的计算失败。

    如果更清楚,您可以使用此代码:

    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', )
    

    顺便说一句,使用 Excel 确定正确答案是验证大多数计算的好方法。在这种情况下,您应该使用correl

    【讨论】:

      【解决方案2】:

      相关性并不意味着因果关系。不得不说。您需要了解相关统计数据。相关性可以在 -1 和 1 之间,0 值落在此范围内,是一个完全合理的结果。相关性为 0 意味着 2 个变量之间不存在统计上显着的关系。请记住避免使用少于 30 个样本进行统计。

      【讨论】:

        【解决方案3】:

        算法给出了正确的结果。 0 表示它们之间没有相关性(或者至少你无法从你所知道的情况中分辨出来)。

        通常(取决于您应用此算法的领域)您可以将 -0.9

        【讨论】:

          【解决方案4】:

          您的结果没有任何问题。您正在尝试通过 3 个点绘制一条线。在第二种情况下,所有三个点都具有相同的坐标,即实际上是一个点。你不能说这些点是相关的还是反相关的,因为你可以通过一个点画出无数条线(代码中的den 等于零)。

          【讨论】:

            猜你喜欢
            • 2010-11-28
            • 2011-08-20
            • 2012-11-18
            • 2019-12-14
            • 2020-05-23
            • 2011-09-13
            • 1970-01-01
            • 1970-01-01
            • 2010-11-16
            相关资源
            最近更新 更多