推荐系统初探之一 —— 寻找相似的用户
不知当你登陆亚马逊、淘宝等购物网站时,是否留意过那神奇推荐栏:当你买过一部手机,那里会出现你需要的手机配件;但你买过一本书,它会给你推荐一大堆类似的书籍;而有时候它甚至会向你推荐你可能喜欢的影片,即使你可能只在这买过食品……
其实,大多数购物网站都会有一个推荐系统,通过分析你的兴趣偏好,找到与你有相同品味的人,以此来把你可能喜欢的商品推荐给你。
想知道这些推荐系统背后的秘密吗?现在开始,让我们使用python语言,揭开这些推荐系统背后的秘密。
一、数据的引入
首先,我们建一个名为recommendations.py的python文件,用一段代码建立一组简单的数据,内容为几位影评者对不同电影的评价
# -*- coding: cp936 -*- #一个涉及影评者机器对几部电影评分情况的字典 critics = {'Lisa Rose':{'Lady in the Water':2.5, 'Snacks on a Plane': 3.5, 'Lust My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5, 'The Night Listener': 3.0}, 'Gene Seymour':{'Lady in the Water':3.0, 'Snacks on a Plane': 3.5, 'Lust My Luck': 1.5, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5, 'The Night Listener': 3.0}, 'Michael Phillips':{'Lady in the Water':2.5, 'Snacks on a Plane': 3.0, 'Superman Returns': 3.5, 'The Night Listener': 4.0}, 'Claudia Puig':{'Snacks on a Plane': 3.5, 'Lust My Luck': 3.0, 'Superman Returns': 4.0, 'You, Me and Dupree': 2.5, 'The Night Listener': 4.5}, 'Mick LaSalle':{'Lady in the Water':3.0, 'Snacks on a Plane': 4.0, 'Lust My Luck': 2.0, 'Superman Returns': 3.0, 'You, Me and Dupree': 2.0, 'The Night Listener': 3.0}, 'Jack Matthews':{'Lady in the Water':3.0, 'Snacks on a Plane': 4.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5, 'The Night Listener': 3.0}, 'Toby':{'Snacks on a Plane': 4.5, 'Superman Returns': 4.0, 'You, Me and Dupree': 1.0}}
在这些数据中,通过1—5的评分来表示评价者对某影片的喜欢程度。而我们要做的,就是从这些评分中挖掘出不同用户的兴趣偏好,以此为依据进行推荐。
好了,有了数据,我们就可以开始工作了!
二、寻找相近的用户
接下来我们要做的,是找一种方法来确定人们的品味。品味是一个抽象的东西,没法衡量,但是可以比较。所以我们引入一个新的概念——相似度评价值,用以衡量不同人的品味相似度。为计算相似度评价值,我们在此继续引入两个概念:欧几里得距离和皮尔逊相关度。
〈1〉欧几里得距离评价
顾名思义,这是欧几里得最先提出的概念。这位古希腊几何大神的研究成果曾一度伴随着我们的成长,我们现在讨论的他老人家的成果,实质上是两点间距离公式向N维空间的类比拓展。
我们知道:
在一维空间(即直线)中两点的距离为 ;
二维空间中的距离为;
三维空间中的距离则为……
以此类推,可以认为N维空间中两点距离仍旧符合以上规律 ,由N组参数差的平方和开平方跟来表示,这种形式表示的距离就叫欧几里得距离。
好了,现在让我们回归正题。了解了欧几里得距离的概念,我们就可以用它来构建我们的相似度评价值体系了。
如图2—1所示,若将电影 'Snacks on a Plane' 与 'You, Me and Dupree' 的评分作为坐标轴的参数,则用户可以用二维空间中的点来表示,其坐标为各自的对应坐标轴电影的评分值,在此只给出了两个参数,如果用上所有六部电影的评分,可构成一个六维空间(靠自己想象了),那么该空间中两名用户(即两点)间的欧几里得距离越短,表示这两位用户的品味越相近。利用数据,我们可以很轻易得出所有用户之间的欧几里得距离,由此得到相似度——不过在这之前似乎还有个问题:我们希望评价的函数使得偏好越相近的用户得到的相似度函数值越高,而欧几里得距离结果却恰好与此相反。为此,我们采用对函数值+1(防止被零除的情况发生),然后取倒数的方法,使得函数返回0到1之间的值,数值越大表示相似度越高,其中1代表两个人品味完全相同。向recommendations.py中添加以下代码,构建欧几里得函数:
from math import sqrt #返回一个关于person1与person2基于欧几里得距离的相似度评价 def sim_distance(prefs, person1, person2): #得到两个人都看过的电影的列表 shared_moives = {} for moive in prefs[person1]: if moive in prefs[person2]: #两个人都看过的影片设为1 shared_moives[moive] = 1 #如果两人没有都看过的电影,函数返回0 if len(shared_moives) == 0: return 0 #求所有差值平方和,算出相似度 sum_of_squares = sum([pow(prefs[person1][moive] - prefs[person2][moive],2) for moive in prefs[person1] if moive in shared_moives]) sim = 1/(sqrt(sum_of_squares)+1) return sim
现在我们可以调用这个函数,通过输入两个人名,来得到两人基于欧几里得距离的相似度评价值。在解释器中执行如下测试命令:
>>> reload(recommendations) >>> sim_distance(recommendations.critics,'Lisa Rose', 'Gene Seymour') 0.29429805508554946
用这种方法可以得到任意两个人之间的相似度评价。
〈2〉皮尔逊相关度评价
前面我们了解了基于欧几里得距离的评价方法,现在我再介绍一种更复杂的方法——基于皮尔逊相关系数的评价方法。皮尔逊相关系数,听起来很NB,但仔细一看不过就是我们高中数学学过的相关系数,即用最小二乘法解决线性回归问题时用到的参数。当然,高中老师从未向我们解释过这个公式的含义,再此我们不妨自行研究一下。
这是高中课本上关于二维空间散点集的皮尔逊相关系数公式,表示两组数据之间的相关程度,取值为-1至1之间,其中+1/-1表示两组数据完全分布在一条上,1表示呈正相关,-1表示呈负相关。
事实上,皮尔逊相关系数又称为皮尔逊积矩相关系数,我们可以试着从几何角度理解它:
对于一组n个数据(xi,yi)(i = 1,2,3……n),我们可以用两个坐标轴的所有数据数据分别生成n维向量(如X =(x1,x2……xn),Y =(y1,y2……yn)),两个向量的夹角余弦值即为皮尔逊相关度。只是注意在该算法中要对数据进行中心化,即将向量的每一维根据均值进行平移,形成以样本中心为原点的向量。
设样本中心(x0, y0)则向量 X = [ (x1-x0), (x2-x0)……,(xn-x0)],Y = [ (y1-y0), (y2-y0)……(yn-y0)]。
再经过一些代数变换即可得到上面左边的式子,即我们接下来计算时要用到的式子。
类似的,我们选取两位用户的评分值为两坐标轴,可以将所有的电影映射为二维平面上的点,得到图2-2
通过我们中学学过的最小二乘法求线性回归直线的公式,我们也很容易找到一条“最佳拟合直线”。可以想象,如果两位用户品味完全相同,那么他们对所有电影的评分都会相同,我们将得到一条斜率为1的过原点的直线。图2-2中的皮尔逊相关系数约为0.4,而图2-3则展示了一个相关度更高的例子,约为0.75。
在采用皮尔逊方法进行评价时,我们还能发现一点,就是它可以修正评分者评分习惯对结果的影响。举个例子,2-3中,Jack对每部电影的评分都明显高于Lisa:我们可以认为Jack很慷慨,习惯打高分;而
Lisa比较吝啬,喜欢打低分。不过在皮尔逊相关度的计算中,这并不是问题,因为虽然两人的评分习惯不同,但大体的相关性还是显而易见的。然而,在欧几里得距离的计算中,结果就完全不同了——实际结果中两人的欧几里得距离会很大,因为他们在每一维中都有很大的分差,即使他们的品味是那么相似。因此,在这个场景中,皮尔逊方法显然更合适。
逊相关度评价的算法函数如下:
#返回person1与person2的皮尔逊相关度 def sim_pearson(prefs, person1, person2): #得到两个人都看过的电影的列表 shared_moives = {} for moive in prefs[person1]: if moive in prefs[person2]: #两个人都看过的影片设为1 shared_moives[moive] = 1 #如果两人没有都看过的电影,函数返回1 if len(shared_moives) == 0: return 1 #这里到底应该取几我持保留意见 #对所有偏好求和 sum1 = sum(prefs[person1][moive] for moive in shared_moives) sum2 = sum(prefs[person2][moive] for moive in shared_moives) #求平方和 sum1Sq = sum([pow(prefs[person1][moive],2) for moive in shared_moives]) sum2Sq = sum([pow(prefs[person2][moive],2) for moive in shared_moives]) #求乘积之和 pSum = sum([prefs[person1][moive] * prefs[person2][moive] for moive in shared_moives]) #计算皮尔逊评价值 n = len(shared_moives) 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
我们可以采用类似的方式在解释器中运行代码测试:
>>> reload(recommendations) >>> sim_pearson(recommendations.critics, 'Lisa Rose', 'Gene Seymour') 0.39605901719066977
至此,我们已经掌握了相似度评价的两大神器——欧几里得距离和皮尔逊相关度,怎么样?是不是没有想象中的那么难?嘿嘿,不要走开,后面的内容更精彩,下篇博客,我们将走进真正的机器推荐系统,向 Toby 推荐电影,请君拭目以待吧!
相关推荐
通过对在校大学生这一特殊用户群体的深入理解,团队成员能够准确把握用户需求,将物业管理的专业知识与现代信息技术相结合,创建一个便捷、高效的物业服务平台。APP的功能设计可能包括报修服务、投诉建议、生活缴费...
本次分享的核心内容是关于“SQL SERVER课程案例驱动教学初探”,作者为开封大学信息工程学院的张新成。文章探讨了如何在SQL Server课程教学中应用案例驱动的教学方法,从而提升教学效果和学生的学习兴趣。以下是文章...
### 开发一个最简单的“操作系统”——引导程序详解 #### 引言 在探索计算机启动原理及操作系统基础知识的过程中,引导程序作为一个重要的概念被频繁提及。本文旨在深入浅出地介绍如何开发一个最简单的“操作系统”...
城市广电媒体在数字化城市发展中的问题与出路初探 随着21世纪初数字化技术的飞速进步,人类社会逐渐步入了数字化生存的时代,"数字化城市"的概念也随之诞生。这个概念源于1998年美国副总统戈尔提出的"数字地球",指...
1. **Windows 8平台特性**:本书首先介绍了Windows 8作为新一代操作系统的显著特点,包括其对触控设备的优化设计,集成的云服务,以及全新的用户界面——“开始屏幕”和“磁贴”概念。这些特性不仅改变了用户的交互...
《构建寻找群组Web应用程序——基于JavaScript的LFG平台初探》 在互联网技术日新月异的今天,游戏社区的交流方式也在不断进化。"LFG:寻找群组Web应用程序"是一个旨在为通用视频游戏玩家提供便捷组队服务的在线平台...
《逆向工程初探:基于OD(Ollydbg)的学习实践——以ReverseMe.NAGs为例》 在计算机科学领域,逆向工程是一项至关重要的技能,尤其在软件安全、漏洞分析以及恶意代码研究中占据核心地位。OD(Ollydbg)是一款广受...
《人机五子棋对战:前端开发与AI算法初探》 在计算机科学与信息技术领域,游戏开发是一项深受开发者喜爱的实践项目,它既能够锻炼编程技能,又可以提升用户体验设计。今天我们将聚焦于一个特别有趣的话题——“人机...
《小坦克大战源代码解析与游戏编程初探》 在我们的技术分享中,我们将深入探讨一个名为“小坦克大战”的游戏源代码。这个项目是由一个初学者在学习游戏编程的过程中创作的,虽然可能存在一些不足,但它无疑是一个很...
《Cache Benchmark Framework——开源缓存性能测试框架初探》 在IT行业中,缓存技术是提高系统性能和响应速度的关键要素。一个高效、可靠的缓存系统能够显著提升用户体验,减少数据库压力,实现数据的快速访问。而...
《人脸检测技术初探——基于Haar级联分类器的实现》 人脸检测技术是计算机视觉领域中的一个重要分支,广泛应用于安全监控、社交媒体、人机交互等场景。本压缩包"**facedetection.zip**"提供了全面的学习资源,特别...
JavaLauncher源码分析——Doughnut项目初探 在Java编程的世界中,了解并学习一个项目的源码是提升技能和理解编程思想的重要途径。这里我们关注的是名为"Doughnut"的项目,它由作者作为其首次正式的编程尝试。...