资料来源:

《集体智慧编程》&网络


一.推荐系统 概述

定义

维基百科定义:

推荐系统属于资讯过滤的一种应用。

推荐系统能够将可能受喜好的资讯或实物(例如:电影、电视节目、音乐、书籍、新闻、图片、网页)推荐给使用者。

形成过程

  随着互联网的发展,人们正处于一个信息爆炸的时代。相比于过去的信息匮乏,面对现阶段海量的信息数据,对信息的筛选和过滤成为了衡量一个系统好坏的重要指标。一个具有良好用户体验的系统,会将海量信息进行筛选、过滤,将用户最关注最感兴趣的信息展现在用户面前。这大大增加了系统工作的效率,也节省了用户筛选信息的时间。
  搜索引擎的出现在一定程度上解决了信息筛选问题,但还远远不够。搜索引擎需要用户主动提供关键词来对海量信息进行筛选。当用户无法准确描述自己的需求时,搜索引擎的筛选效果将大打折扣,而用户将自己的需求和意图转化成关键词的过程本身就是一个并不轻松的过程。
  在此背景下,推荐系统出现了,推荐系统的任务就是解决上述的问题,联系用户和信息,一方面帮助用户发现对自己有价值的信息,另一方面让信息能够展现在对他感兴趣的人群中,从而实现信息提供商与用户的双赢。

例子

  接着以亚马逊(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的更多相关文章

  1. psutil一个基于python的跨平台系统信息跟踪模块

    受益于这个模块的帮助,在这里我推荐一手. https://pythonhosted.org/psutil/#processes psutil是一个基于python的跨平台系统信息监视模块.在pytho ...

  2. 基于python的互联网软件测试开发(自动化测试)-全集合

    基于python的互联网软件测试开发(自动化测试)-全集合 1   关键字 为了便于搜索引擎收录本文,特别将本文的关键字给强调一下: python,互联网,自动化测试,测试开发,接口测试,服务测试,a ...

  3. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)

    目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构   前言 学习Python也有一个半月时间了,学到现在感觉 ...

  4. 基于Python的数据分析(1):配置安装环境

    数据分析是一个历史久远的东西,但是直到近代微型计算机的普及,数据分析的价值才得到大家的重视.到了今天,数据分析已经成为企业生产运维的一个核心组成部分. 据我自己做数据分析的经验来看,目前数据分析按照使 ...

  5. 基于python语言的tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)

    基于python语言的tensorflow的‘端到端’的字符型验证码识别 1   Abstract 验证码(CAPTCHA)的诞生本身是为了自动区分 自然人 和 机器人 的一套公开方法, 但是近几年的 ...

  6. 【笔记】基于Python的数字图像处理

    [博客导航] [Python相关] 前言 基于Python的数字图像处理,离不开相关处理的第三方库函数.搜索网络资源,列出如下资源链接. Python图像处理库到底用哪家 python计算机视觉编程— ...

  7. 基于python的Selenium使用小结

    之前介绍过基于Unittest和TestNG自动化测试框架,然而基于Web端的测试的基础框架是需要Selenium做主要支撑的,这里边给大家介绍下Web测试核心之基于Python的Selenium 一 ...

  8. 如何简单实现接口自动化测试(基于 python) 原博主地址https://blog.csdn.net/gitchat/article/details/77849725

    如何简单实现接口自动化测试(基于 python) 2017年09月05日 11:52:25 阅读数:9904 GitChat 作者:饿了么技术社区 原文:如何简单实现接口自动化测试(基于 python ...

  9. 基于Python的selenuim自动化测试尝试

    工作这么多年了,终于狠下心好好开始学学自动化测试相关知识,揭开这层神秘的面纱. 困难重重,障碍很多,但好在每天都多少有点小收获. 很感谢一个QQ好友推荐的虫师,也非常感谢在这个契机读到了虫师编著的&l ...

随机推荐

  1. 第一章(认识jQuery)

    1.3.2编写简单的jQuery代码 ①$是jQuery的简写 ②$("#foo") = $("#foo") ③$.ajax  =  jQuery.ajax ④ ...

  2. H5学习第三周

    今天主要总结弹性布局 flex使用 1.给父容器添加display flex/inline-flex;属性 2.父容器可以使用的属性值有 >>>flex-direction 属性决定 ...

  3. H3CNE实验:H3C设备文件管理

    第1步:配置文件的管理操作 (1) save [ safely ]--在H3C设备上将当前配置保存到存储介质的根目录下. 快速保存方式:不带 safely 参数. 安全方式:带 safely 参数. ...

  4. C#工作笔记

    没想到一个Java后端开发还要负责C#桌面程序,我感觉有点方.不过方归方,活还是要干的.简单记录下学到的一些知识点. 1.引用API函数 namespace Demo { class MyUtil { ...

  5. Linux学习笔记(二)——文件/目录/VIM

    文件和目录管理 及 VI编辑器的使用 文件和目录管理,刚开始学这块的时候感觉内容很多很杂,但是学完进行总结后,发现其实很有条理的而且没什么难度,只是熟练掌握这些常用的命令就行了.至于Vim编辑器,不得 ...

  6. Samba远程代码执行漏洞(CVE-2017-7494)本地复现

    一.复现环境搭建 搭建Debian和kali两个虚拟机: 攻击机:kali (192.168.217.162): 靶机:debian (192.168.217.150). 二.Debian安装并配置s ...

  7. JS实现为控件添加倒计时功能

    一.概述 在有些报表需求中,需要为控件添加倒计时功能,限制到某一个时间点后能进行一项操作或不能进行某项操作,比如查询,导出功能等等,又需要人性化地显示还有多少时间,即倒计时功能,比如下图中我们限制这个 ...

  8. Luogu 1090 合并果子(贪心,优先队列,STL运用)

    Luogu 1090 合并果子(贪心,优先队列,STL运用) Description 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每 ...

  9. Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)

    Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...

  10. H5读取本地文件操作

    H5读取本地文件操作 本文转自:转:http://hushicai.com/2014/03/29/html5-du-qu-ben-di-wen-jian.html感谢大神分享. 常见的语言比如php. ...