推荐——基于python
资料来源:
《集体智慧编程》&网络
一.推荐系统 概述
定义
维基百科定义:
推荐系统属于资讯过滤的一种应用。
推荐系统能够将可能受喜好的资讯或实物(例如:电影、电视节目、音乐、书籍、新闻、图片、网页)推荐给使用者。
形成过程
随着互联网的发展,人们正处于一个信息爆炸的时代。相比于过去的信息匮乏,面对现阶段海量的信息数据,对信息的筛选和过滤成为了衡量一个系统好坏的重要指标。一个具有良好用户体验的系统,会将海量信息进行筛选、过滤,将用户最关注最感兴趣的信息展现在用户面前。这大大增加了系统工作的效率,也节省了用户筛选信息的时间。
搜索引擎的出现在一定程度上解决了信息筛选问题,但还远远不够。搜索引擎需要用户主动提供关键词来对海量信息进行筛选。当用户无法准确描述自己的需求时,搜索引擎的筛选效果将大打折扣,而用户将自己的需求和意图转化成关键词的过程本身就是一个并不轻松的过程。
在此背景下,推荐系统出现了,推荐系统的任务就是解决上述的问题,联系用户和信息,一方面帮助用户发现对自己有价值的信息,另一方面让信息能够展现在对他感兴趣的人群中,从而实现信息提供商与用户的双赢。
例子
接着以亚马逊(http://www.amazon.cn/)为例,让大家对推荐系统有一个初步的印象。
在亚马逊用自己的账号登录以后,主页会根据你浏览过的商品进行推荐。
随意进入一本书的链接,里边还会推荐看过该商品以后其它顾客买了什么。
协作型过滤
一个协作型过滤算法通常的做法是对一大群人进行搜索,并从中找出与我们品味相近的一小群人。
算法对这些人所偏爱的其它内容进行考察,并将它们组合起来构造出一个经过排名的推荐列表。
一.一个影评推荐例子
(一)搜集偏好
我们要做的第一件事情,就是寻找一种表达不同人及其偏好的方法。在python中,达到这一目的的一种非常简单的方法是使用一个嵌套的字典。
大概格式为:评价 = {评价者名称:{电影名称:评分},评价者名称:{电影名称:评分}}
新建一个名为recommendations.py的文件,并加入以下代码
########要做的第一件事就是寻找一种表达不同人及其偏好的方法,可以用嵌套的字典构造一个数据集:
critics={'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5,'Just 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, 'Snakes on a Plane': 3.5,'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0, 'You, Me and Dupree': 3.5}, 'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0,'Superman Returns': 3.5, 'The Night Listener': 4.0},'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0,'The Night Listener': 4.5, 'Superman Returns': 4.0, 'You, Me and Dupree': 2.5},'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0,'You, Me and Dupree': 2.0}, 'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5},'Toby': {'Snakes on a Plane':4.5,'You, Me and Dupree':1.0,'Superman Returns':4.0}}
启动python的交互式环境(我用的是python 2.7.11 Shell),可以开始输入代码查询用户的偏好了
在python用import或者from...import来导入相应的模块。模块其实就一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模块导入到我们的程序中,我们就可以使用了。
假如我们想查询某个用户对所有影片的评分,在本例中,相当于查询字典critics中相应用户的key的value值。
假如我们想知道某个用户对某个影片的评分,就需要找到这个用户名所对应的字典的key下的value,因为在这里用的是嵌套的字典,也就是说第一层字典的value也是一个字典,我们暂且称之为“字典中的字典”,我们需要的,是“字典中的字典”中相应影片名对应的key的value值,也即该用户对该影片的评分。
举个例子,要查询用户Lisa Rose对影片Lady in the Water的评分,我们可以输入以下代码并获得相应的评分。
(二)寻找相近的客户
搜集完人们的偏好数据之后,我们需要有一种方法来确定人们在品味方面的相似程度。
为此,我们可以将每个人与所有其他人进行对比,并进行他们的相似度评价值。
1.欧几里得距离评价
计算相似度评价值的一个非常简单的方法是使用欧几里得距离评价方法。
它以人们一直评价的物品为坐标轴,然后将参与评价的人绘制到图上,并考察他们彼此距离远近。
为了计算图上Toby和LaSalle之间的距离,我们可以按照上上图的公式进行计算,在交互式环境中用以下代码进行计算。
p.s.坐标Toby(1,4.5),LaSalle(2,4)
偏好越相似的人,其距离就越短,但是为了使得偏好越相近得到一个越大的值,同时为了让函数总是返回介于0~1之间的值,对公式进行一些加工,新的相似度公式为 1/(1+欧氏距离),分母加1是为了避免分母为0的情况出现,如果返回1,则表示两人具有一样的偏好。
我们将上述只是结合起来,就可以构造出一个计算相似度的公式了。
构造一个sim_distance函数以返回根据欧式距离计算出来的相似度公式,代码思路如下(以影评数据为例):
遍历person1评价过的电影,如果person2也评价过这个电影,把他俩都评价过的电影加入字典si,如果他俩没有同样评价的电影,返回0。
#######寻找相近的用户:欧几里得距离评价
from math import sqrt
#返回一个有关person1和person2的基于欧式距离的相似度评价
def sim_distance(prefs,person1,person2):
si={} #建立空字典si
for item in prefs[person1]: #遍历person1看过的电影(item)
if item in prefs[person2]: #如果person1看过的电影(item)也包含在person2的字典里
si[item]=1 #把person1和person2共同看过的电影名称填入空字典si if len(si)==0: return 0 #如果person1和person2没有共同看过的影片,则返回0 #计算相似度
sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2)
for item in prefs[person1] if item in prefs[person2]]) return 1/(1+sum_of_squares)
2.皮尔逊相关度评价
代码思路同上,只是最后的计算公式换了
######寻找相近的用户:皮尔逊相关度评价
##返回p1和p2的皮尔逊相关系数
def sim_pearson(prefs,p1,p2):
si={} #建立空字典si
#得到双方都评价过的物品
for item in prefs[p1]:
if item in prefs[p2]: si[item]=1 # 如果没有共同评价过得物品,则返回0
if len(si)==0: return 0 n=len(si) #Python 字典(Dictionary) len() 函数计算字典元素个数,即键的总数。 #计算过程
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
(三)为评价者打分
根据指定人员对每个人进行打分。
def topMatches(prefs,person,n=5,similarity=sim_pearson):
#参数n为返回的人数,默认为5;similarity为相似度评价方法,默认为皮尔逊相关度评价
scores=[(similarity(prefs,person,other),other) for other in prefs if other!=person]
#列表推导式:scores=[(相似度,要对比的人名)]
#for other in prefs if other!=person 意思为遍历prefs中和person不同的元素
scores.sort() #排序,sort为从低分到高分排序
scores.reverse() #转置一下让scores从高分到低分排序
return scores[0:n] #返回前n名
(四)推荐物品
代码思路书里写得很清楚啦P16最下边
# ##########推荐物品
# 利用所有他人评价值的加权平均,为某人提供建议
def getRecommendations(prefs,person,similarity=sim_pearson):
##相似度默认为皮尔逊相关度,可以改
totals={}
simSums={}
#####循环遍历位于字典prefs中的其他人,计算person和其它人的相似度
#以防出现自己和自己比较
for other in prefs:
if other==person:
continue #continue:跳出本次循环; break:跳出整个for循环
sim=similarity(prefs,person,other) ##相似度,遍历到一个人得到该人和person的相似度 if sim<=0: continue #忽略评价值为0或为负数的情况
for item in prefs[other]:
if item not in prefs[person] or prefs[person][item]==0:
# #此时item为other评价过而person没评价过的电影名称
totals.setdefault(item,0)
##此时totals={影片:0,影片:0,...}
totals[item]+=prefs[other][item]*sim
##相当于totals[item]=totals[item]+prefs[other][item]*sim
#此时totals={影片:评价值*相似度,影片:评价值*相似度,...}
#totals[item]=评价值*相似度求和
simSums.setdefault(item,0)
#此时simSums={影片:0,影片:0,...}
simSums[item]+=sim
#simSums[item]=相似度求和 #建立一个归一化列表
rankings=[(total/simSums[item],item) for item,total in totals.items()]
##此刻rankings=[(加权后的评价值,影片),...]
#返回经过排序的列表
rankings.sort()
rankings.reverse()
return rankings ##返回从高分到低分排序的rankings
#可以得到一个经过排名的影片列表,同时还可以推测出自己对每部影片评分的情况
(五)匹配商品
比较简单
############匹配商品(和之前用来决定人与人之间的相似度的方法是一样的,只需要将人员与物品对换即可)
#人员和物品的对换代码:
##将人和物品对调,把{人:{影片:评分}}转为{影片{人:评分}}
def transformPrefs(prefs):
result={}
for person in prefs:
for item in prefs[person]:
result.setdefault(item,{})
#将物品和人员对调
result[item][person]=prefs[person][item]
return result
(六)构造物品比较数据集
##为了对物品进行比较,我们要做到的第一件事就是编写一个函数,构造一个包含相近物品的完整数据集
def calculateSimilarItems(prefs,n=10):
#建立字典,以给出与这些物品最为相近的所有其他物品
result={} #建立空字典result itemPrefs=transformPrefs(prefs)# 以物品为中心对偏好矩阵实施倒置处理 c=0 #赋初值
for item in itemPrefs: #遍历每项物品
# 针对大数据集更新状态变量
c+=1
if c%100==0: print "%d / %d" % (c,len(itemPrefs)) #c%100==0 :取模,c除以100的余数
#寻找最为相近的物品
scores=topMatches(itemPrefs,item,n=n,similarity=sim_distance)
result[item]=scores #往空字典result填入数据,key为item,value为scores
return result
(七)获得推荐
#######获得推荐
#我们可以取到用户评价过的所有物品,找出其相近物品,并根据相似度对其进行加权。
def getRecommendedItems(prefs,itemMatch,user):
userRatings=prefs[user] #得到用户评价过的物品
scores={}
totalSim={}
#循环遍历由当前用户评分的物品
for (item,rating) in userRatings.items( ): # 循环遍历与当前物品相近的物品
for (similarity,item2) in itemMatch[item]: # 如果该用户已经对当前物品做过评价,则将其忽略
if item2 in userRatings: continue
# 评价值与相似度的加权之和
scores.setdefault(item2,0)
scores[item2]+=similarity*rating
#全部相似度之和
totalSim.setdefault(item2,0)
totalSim[item2]+=similarity # 将每个合计值除以加权和,求出平均值
rankings=[(score/totalSim[item],item) for item,score in scores.items( )] # 排序
rankings.sort( )
rankings.reverse( )
return rankings
二.构建一个基于delicious的链接推荐系统
这儿需要安装pydelicious,安装pydelicious前需要安装feedparser,安装feedparser还好,pip install即可,然而安装pydelicious略曲折。
懒人方法在我的电脑上全都不适用,pip install报错,easy_install也报错,最后只好上网安装了个包然后python setup.py install23333,还好最后解决了。ps.需要pydelicious安装包的同学可以找我要~
基本导入
from pydelicious import get_popular,get_userposts,get_urlposts
import time
(一)构造数据集
找到一组近期提交过某一热门链接,且连接附带指定标签(tag)的用户。
def initializeUserDict(tag,count=5):
user_dict={}
#建立空字典user_dict
for p1 in get_popular(tag=tag)[0:count]:
#此时p1为前count个最受欢迎的链接的张贴记录
#get_popular得到一个包含字典的列表,包含URL、描述、提交者;
#get_userposts返回给定用户的所有张贴记录
#get_urlposts返回给定URL的所有张贴记录
for p2 in get_urlposts(p1['href']): #貌似'href'现在应该改为'url' #get_urlposts返回给定url的所有张贴记录 user=p2['user'] user_dict[user]={} return user_dict #返回一个包含若干用户数据的字典,其中每一项都各自指定向一个等待填入具体链接的空字典 #count默认值为5,所以上述函数值搜集了前五个链接相对应的用户数据
##利用API来建立一个填充所有用户评价值的函数(0:用户没有张贴这一链接;1:用户张贴了这一链接。)
def fillItems(user_dict):
all_items={}
# 查找所有用户都提交过的链接
for user in user_dict:
for i in range(3):
try:
posts=get_userposts(user) #posts=user_dict中每个user的张贴记录
break #跳出所有循环
except:
print "Failed user "+user+", retrying" #异常处理,记录没有爬到的user
time.sleep(4)
for post in posts:
url=post['href'] #获得url
user_dict[user][url]=1.0 #如果有url张贴记录,赋值1
all_items[url]=1 #填充空字典all_items,key=url,value=1 #用0填充缺失的项
for ratings in user_dict.values():
for item in all_items:
if item not in ratings:
ratings[item]=0.0
三.使用MovieLens数据集
#########使用MovieLens数据集(涉及电影评价的真实数据集)
def loadMovieLens(path='/data/movielens'):
# Get movie titles
movies={}
for line in open(path+'/u.item'): #u.item包含一组有关影片ID和片名的列表
(id,title)=line.split('|')[0:2]
movies[id]=title # 加载数据
prefs={}
for line in open(path+'/u.data'): #u.data包含实际评价情况(P26)
(user,movieid,rating,ts)=line.split('\t')
prefs.setdefault(user,{})
prefs[user][movies[movieid]]=float(rating) #float(x ) 将x转换到一个浮点数
return prefs
推荐——基于python的更多相关文章
- psutil一个基于python的跨平台系统信息跟踪模块
受益于这个模块的帮助,在这里我推荐一手. https://pythonhosted.org/psutil/#processes psutil是一个基于python的跨平台系统信息监视模块.在pytho ...
- 基于python的互联网软件测试开发(自动化测试)-全集合
基于python的互联网软件测试开发(自动化测试)-全集合 1 关键字 为了便于搜索引擎收录本文,特别将本文的关键字给强调一下: python,互联网,自动化测试,测试开发,接口测试,服务测试,a ...
- 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)
目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构 前言 学习Python也有一个半月时间了,学到现在感觉 ...
- 基于Python的数据分析(1):配置安装环境
数据分析是一个历史久远的东西,但是直到近代微型计算机的普及,数据分析的价值才得到大家的重视.到了今天,数据分析已经成为企业生产运维的一个核心组成部分. 据我自己做数据分析的经验来看,目前数据分析按照使 ...
- 基于python语言的tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)
基于python语言的tensorflow的‘端到端’的字符型验证码识别 1 Abstract 验证码(CAPTCHA)的诞生本身是为了自动区分 自然人 和 机器人 的一套公开方法, 但是近几年的 ...
- 【笔记】基于Python的数字图像处理
[博客导航] [Python相关] 前言 基于Python的数字图像处理,离不开相关处理的第三方库函数.搜索网络资源,列出如下资源链接. Python图像处理库到底用哪家 python计算机视觉编程— ...
- 基于python的Selenium使用小结
之前介绍过基于Unittest和TestNG自动化测试框架,然而基于Web端的测试的基础框架是需要Selenium做主要支撑的,这里边给大家介绍下Web测试核心之基于Python的Selenium 一 ...
- 如何简单实现接口自动化测试(基于 python) 原博主地址https://blog.csdn.net/gitchat/article/details/77849725
如何简单实现接口自动化测试(基于 python) 2017年09月05日 11:52:25 阅读数:9904 GitChat 作者:饿了么技术社区 原文:如何简单实现接口自动化测试(基于 python ...
- 基于Python的selenuim自动化测试尝试
工作这么多年了,终于狠下心好好开始学学自动化测试相关知识,揭开这层神秘的面纱. 困难重重,障碍很多,但好在每天都多少有点小收获. 很感谢一个QQ好友推荐的虫师,也非常感谢在这个契机读到了虫师编著的&l ...
随机推荐
- react-router 踩坑记
react-router踩坑分享 背景 辛苦历程 JavaScript动态修改 第一次尝试 第二次尝试 第三次尝试 第四次尝试 总结步骤 其他方案 原理 History 常见的3种History Br ...
- CentOS6.4虚拟机设置固定IP、安装JDK、Tomcat、Redis并部署web项目
一.CentOS设置固定IP 1.直接修改配置文件的方式,原文地址:http://www.cnblogs.com/zhja/p/3964159.html (1)首先获取你的GATEWAY 方便后面在c ...
- jquery 变量和原生js变量的关系
其实js 变量和 jquery没什么不一样, 也可以直接 var hhhh=$("header"); 但是当用到用到hhh时依然要用jquery 的方式,而不能js原生的方式.
- SQL 中 decode()函数
文本转自 FreeSpider的微博 今天看别人的SQL时看这里面还有decode()函数,以前从来没接触到,上网查了一下,还挺好用的一个函数,写下来希望对朋友们有帮助哈! decode()函数简介: ...
- 2-用EasyNetQ连接RabbitMQ(黄亮翻译)
如果你连接过关系数据库,例如SQL Server.你会发现EasyNetQ处理connections有点奇怪.和关系数据库通讯一直都是通过client开始的.Client 打开一个连接, 发出一个SQ ...
- MongoDB数据库聚合
前面的话 聚合操作主要用于对数据的批量处理,将记录按条件分组以后,然后再进行一系列操作,例如,求最大值.最小值.平均值,求和等操作.聚合操作还能够对记录进行复杂的操作,主要用于数理统计和数据挖掘.在 ...
- Linux Redis自动启动,Redis开机启动,Linux Redis设置开机启动
Linux Redis自动启动,Redis开机启动,Linux Redis设置开机启动 >>>>>>>>>>>>>> ...
- AddBinary
二进制加法 输入2个字符串,字符串内由0和1组成:计算二者之和,返回字符串 Given two binary strings, return their sum (also a binary stri ...
- Java创建连接池连接不同数据库
在一个应用里面,可能涉及到连接多个不同数据库进行操作,而每次连接写不同的实现会很麻烦.前面已经会了用JDBC连接数据库,那么利用反射和工厂模式,可以实现连接不同的数据库,这样处理起来将会很方便.同时建 ...
- Ajax的简单实用实例
我将实现一个简单的Ajax页面无刷新进行用户验证案例: 效果如下图: