zoukankan      html  css  js  c++  java
  • 【火炉炼AI】机器学习032-用户之间相似度的计算

    【火炉炼AI】机器学习032-用户之间相似度的计算

    (本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

    在构建推荐引擎时,一般需要计算两个用户之间的相似度,以便找到与数据库中特定用户相似的用户。计算相似度的方法有很多种,其中比较常见的两种是计算欧几里得距离和皮尔逊相关系数,本文分别讲述使用这两种方法来计算用户之间的相似度。


    1. 计算两个用户的欧氏距离

    欧几里得距离是欧几里得空间中两点间的普通距离,即两点组成的直线的距离。其计算公式可以说是数学里的基本公式,如下,其基本含义就是计算两个点之间的空间距离。

    欧式距离很直观,是常见的一种相似度算法。其基本思路为:根据两用户之间共同评价的项目为维度,建立一个多维空间,用户对单一维度上的评价就可以组成一个数组或向量,一旦这个向量确定,那么就可以确定这个用户在这个多维空间的位置。但我们把多个用户都放置到这个多维空间后,距离非常近的两个用户,可以认为他们之间的相似度非常高,反之,距离较远的用户之间的相似度也较远,故而这种多维空间内的用户之间的欧式距离就标定了他们之间的相似度。

    但是在日常使用中,我们一般不太习惯数值小反而表示相似度高,故而对这种数值取一个倒数,使得数值都落在0-1之间,即使用 1/(1+Distance(X,Y))之后,得到的相似度范围为:0<=Similarity(X,y)<=1,越接近1,表示相似度越高,这种表示方式很符合我们的惯性思维。

    下面用代码来计算两个用户之间的欧式距离,其思想是,计算两个用户在数据集中的所有项目中的平方和,然后在开方,得到两个用户之间的距离,在用倒数法转变一下。

    # 定义一个函数来计算两个用户之间的欧式距离
    def euclidean_distance(dataset,user1,user2):
        # 首先要排除一种情况,如果数据集中不存在同时被两个用户评价过的电影,
        # 则表示两个用户之间的没有相似度,直接返回0
        both_rated_num=0 # 表示同时被两个用户都评价过的电影的数目
        for item in dataset[user1]: # 在user1评价过的电影中
            if item in dataset[user2]: # 如果user2也评价过,则+1
                both_rated_num+=1
        if both_rated_num==0:# 不存在同时被两个用户都评价过的电影
            return 0 # 直接返回0,表示两个用户之间相似度为0
        
        squared_difference=[] # 每一个元素表示同时被两个用户都评价过的电影得分的欧式距离
        for item in dataset[user1]:
            if item in dataset[user2]:
                squared_difference.append(np.square(dataset[user1][item]-dataset[user2][item]))
        return 1/(1+np.sqrt(np.sum(squared_difference)))
    
    

    由于原始的电影评价数据都存放在movie_ratings.json文件中,所以需要用json模块加载数据,并对其进行分析

    # 原始的电影评价数据都放置在 movie_ratings.json文件中,我们加载进来看看结果
    import json
    with open("E:PyProjectsDataSetFireAImovie_ratings.json",'r') as file:
        dataset=json.loads(file.read())
        
    # 现在计算两个随机用户之间的欧式距离
    user1='John Carson'
    user2='Michelle Peterson'
    print(" Euclidean score: ",euclidean_distance(dataset,user1,user2))
    

    -------------------------------------输---------出--------------------------------

    Euclidean score: 0.29429805508554946

    --------------------------------------------完-------------------------------------

    即此处计算出这两个用户之间的欧式距离为0.29,相似度不是很高。

    欧式距离虽然是比较常用的计算用户相似度的方法,但是它有其内在的缺点,比如:

    1,由于计算时基于各维度特征的绝对数值,所以欧式距离需要保证各维度指标在相同的刻度级别。

    2,欧式距离是数据上的直观体现,看似简单,但在处理一些受主观影响很大的评分数据时,效果则不太明显。即评价者的评价相对于平均水平偏离很大的时候欧式距离不能很好地揭示出真实的相似度。


    2. 计算两个用户的皮尔逊相关系数

    在统计学中,皮尔逊相关系数用于度量两个变量之间的线性相关性,其值位于-1到1之间。相关系数为1时,成为完全正相关;当相关系数为-1时,成为完全负相关;相关系数的绝对值越大,相关性越强;相关系数越接近于0,相关度越弱。

    # 定义一个函数来计算两个用户之间的皮尔逊相关系数
    def pearson_score(dataset,user1,user2):
        # 和上面的函数类似,先排除相似度为0的情况
    #     both_rated_num=0 # 表示同时被两个用户都评价过的电影的数目
    #     for item in dataset[user1]: # 在user1评价过的电影中
    #         if item in dataset[user2]: # 如果user2也评价过,则+1
    #             both_rated_num+=1
    #     if both_rated_num==0:# 不存在同时被两个用户都评价过的电影
    #         return 0 # 直接返回0,表示两个用户之间相似度为0
    
        both_rated={}
        for item in dataset[user1]:
            if item in dataset[user2]:
                both_rated[item]=1
        num_ratings=len(both_rated)
        if num_ratings==0: # 不存在同时被两个用户都评价过的电影
            return 0
        
        # 计算每个用户对每个相同电影的评价之和
        user1_sum=np.sum([dataset[user1][item] for item in both_rated])
        user2_sum=np.sum([dataset[user2][item] for item in both_rated])
        
        # 计算每个用户对每个相同电影的评价的平方和
        user1_squared_sum = np.sum([np.square(dataset[user1][item]) for item in both_rated])
        user2_squared_sum = np.sum([np.square(dataset[user2][item]) for item in both_rated])
    
        # 计算两个用户的相同电影的乘积
        product_sum=np.sum([dataset[user1][item]*dataset[user2][item] for item in both_rated])
        
        # 计算Pearson 相关系数
        Sxy = product_sum - (user1_sum * user2_sum / num_ratings)
        Sxx = user1_squared_sum - np.square(user1_sum) / num_ratings
        Syy = user2_squared_sum - np.square(user2_sum) / num_ratings
        
        if Sxx * Syy == 0:
            return 0
    
        return Sxy / np.sqrt(Sxx * Syy)
    

    同理计算得到两个用户的皮尔逊相关系数为: Peason score: 0.396. 相似度不能横向比较,即不能将Pearson得分和欧式距离进行比较,这样比较没有意义,只能用于纵向比较。

    ########################小**********结###############################

    1,用户之间的相似度计算可以采用欧式距离的方式计算,也可以采用皮尔逊相关系数来计算。

    2,貌似用皮尔逊相关系数来表示相似度更好一些,在很多时候能够克服欧式距离表示法的一些缺点。

    #################################################################


    注:本部分代码已经全部上传到(我的github)上,欢迎下载。

    参考资料:

    1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

  • 相关阅读:
    操作系统复习
    你不知道的JS(2)深入了解闭包
    剑指offer(66)机器人的运动范围
    剑指offer(65)矩阵中的路径
    剑指offer(64)滑动窗口中的最大值
    剑指offer(63)数据流中的中位数
    剑指offer(62)二叉搜索树的第K个节点
    剑指offer(61)序列化二叉树
    剑指offer(60)把二叉树打印成多行
    让 Laravel API 永远返回 JSON 格式响应!
  • 原文地址:https://www.cnblogs.com/RayDean/p/9765761.html
Copyright © 2011-2022 走看看