集体智慧编程 第二章 匹配商品
2017-01-05 14:54
357 查看
我们在前面学习了如何为指定人员寻找品味相近的人,以及如何向其推荐商品。但是如果我们想了解哪些商品是彼此相近的,应该如何做?
匹配商品
比如我们去淘宝,点击某个商品的时候,侧面总会给我们推荐一些类似商品。这是如何做到的呢?
首先我们要将之前的:{'Person':{'movie':score}} 的形式换成 {'Movie':{'person':score}}
用下列代码实现:
然后运行代码中添加:
现在我们就得到了一组与《Superman Returns》最为相近的电影。但是有一些相关评价值为负数,这说明喜欢《Superman Returns》的人,存在不喜欢《Just My Luck》的倾向。我们还可以为影片推荐评论者。
添加运行代码:
当然,书上也强调了对调人和物不一定总是有意义的。但是大多数情况下,这都有助于做出对比。
=============================================================================
构建一个基于 del.icio.us 的链接推荐系统
这一节我们将学习如何从在线书签网站上面获得数据,如何利用这些数据查找用户,并向他们推荐以前没看过的链接。
这个网站的网站是 http://del.icio.us
通过 API 访问 del.icio.us 网站获得的数据是以 XML 格式返回的,我们先要安装一些东西。
书上给出了两个链接,下载已经写好了的 API:
https://code.google.com/p/pydelicious/source
http://oreilly.com/catalog/9780596529321
当然我跟我一步一步来更简单:
1.进入网站 https://pypi.python.org/pypi/feedparser#downloads 下载 feedparser 5.2.1 这个库,注意是 feedparser-5.2.1.zip
2.用winRAR打开,解压到桌面,在 PowerShell 里面各种 cd 进入解压文件夹,输入
3.进入网站 https://pypi.python.org/pypi/pydelicious 下载 pydelicious 0.6.1。下载文件为:pydelicious-0.6.1.tar.gz
4.用winRAR打开,解压到桌面,进去再次解压 pydelicious-0.6.1.tar ,在 PowerShell 里面各种 cd 进入解压文件夹,输入
好了,安装完毕我们继续下一步走起。
跟着教材走,建立一个 run2.py:
运行发现:
吃屎啊...怎么破?
书上还给了两个选择,这里选择用 Dorisa 用户为例:
delicious.com/rss 破网站真的有毒,十有八九被墙了。
于是我决定死马当成活马医,继续跟书走吧。
============================================================
构造数据集
主要是下载一个子集信息。
新建一个 deliciousrec.py 文件:
利用这个函数构造一个数据集,类似之前的影评字典:
这里的第三行代码将用户 tsegaran 添加到了列表中。假如你也是使用 del.icio.us,则不妨以自己的名字来替换 tsegaran。
然后对于 fillItems 的调用要花费几分钟的时间来执行,因为要向网站发起数百个请求。
当然对于网站被墙来说并无卵用。
=============================================================================
推荐近邻与链接
为了随机选择一个用户,并且找出与其品味相近的其他用户,在 run2 里面添加代码:
也可以通过调用 getRecommendations 函数为该用户获取推荐链接。
=============================================================================
基于物品的过滤
刚刚的方法对于上千的用户和物品规模是没问题的,对于像淘宝亚马逊这样的网站,把单个用户和其他所有用户比较太慢了。之前我们采用的方法叫做基于用户的协作型过滤,此外,还有一种方法叫做基于物品的协作型过滤。在大数据情况下,这种方法能得出更好的结论。
总体思路就是为每件物品预先计算好最为相近的其他物品。区别在于物品间的比较不会像用户间的比较那么频繁变化。
=============================================================================
构造物品比较数据集
为了对物品比较,在 recommendations.py 里面加入:
先对反映评价值的字典倒置处理,从而得到一个有关物品及其用户评价的列表。然后程序循环遍历每个物品,并且把转换了的字典传入 topMatches 函数中,求得最为相近的物品及其相似度评价值。
在 run1.py 添加:
这里结果很有意思,书上第一个是0.4,而我计算的则是0.44。仔细检查发现书上的示例代码中 sim_distance 函数的返回值如果不加 sqrt 的话就是一致的。归根结底应该是书上的代码有点问题。
以上是结果。
=============================================================================
获得推荐
现在我们可以在不遍历整个数据集的情况下,利用反映物品相似度的字典给出推荐。具体数学方法参见书上。
在 recommendations.py 里面加入:
run1.py:
结果:
可以看出推荐物品排行。
=============================================================================
使用 MovieLens 数据集
从 http://www.grouplens.org/node/73 下载 MovieLens 数据集。注意下载的是小的数据集,十万数据的那个。
解压打开文件,我们主要关心的是 movies.csv 和 ratings.csv ,前者包含了一组有关影片ID和片面的列表,后者是实际评价情况。
每位用户都对较多影片做出过评价。在 recommendations.py 中新建一个方法,取名 loadMovieLens,用以加载数据。
很遗憾,就卡在了这一步。这里读不出来。也不知道是哪里出错了。
虽然止步于最后一步,但是基于用户和基于物品的推荐大概方法已经过了一遍。
文末还指出,对于稀疏数据集,基于物品的过滤方法通常要优于基于用户的过滤方法,对于密集数据集则两者差不多。
匹配商品
比如我们去淘宝,点击某个商品的时候,侧面总会给我们推荐一些类似商品。这是如何做到的呢?
首先我们要将之前的:{'Person':{'movie':score}} 的形式换成 {'Movie':{'person':score}}
用下列代码实现:
#这个函数就是将字典里面的人员和物品对调 def transformPrefs(prefs): result = {} for person in prefs: for item in prefs[person]: result.setdefault(item, {}) #将物品和人员对调 result[item][person] = prefs[person][item] return result
然后运行代码中添加:
print '\n==========================================' print 'topMatches-Superman Returns' movies = recommendations.transformPrefs(recommendations.critics) print recommendations.topMatches(movies, 'Superman Returns')可以看出结果:
现在我们就得到了一组与《Superman Returns》最为相近的电影。但是有一些相关评价值为负数,这说明喜欢《Superman Returns》的人,存在不喜欢《Just My Luck》的倾向。我们还可以为影片推荐评论者。
添加运行代码:
print '\n==========================================' print 'getRecommendations' movies = recommendations.transformPrefs(recommendations.critics) print recommendations.getRecommendations(movies, 'Just My Luck')
当然,书上也强调了对调人和物不一定总是有意义的。但是大多数情况下,这都有助于做出对比。
=============================================================================
构建一个基于 del.icio.us 的链接推荐系统
这一节我们将学习如何从在线书签网站上面获得数据,如何利用这些数据查找用户,并向他们推荐以前没看过的链接。
这个网站的网站是 http://del.icio.us
通过 API 访问 del.icio.us 网站获得的数据是以 XML 格式返回的,我们先要安装一些东西。
书上给出了两个链接,下载已经写好了的 API:
https://code.google.com/p/pydelicious/source
http://oreilly.com/catalog/9780596529321
当然我跟我一步一步来更简单:
1.进入网站 https://pypi.python.org/pypi/feedparser#downloads 下载 feedparser 5.2.1 这个库,注意是 feedparser-5.2.1.zip
2.用winRAR打开,解压到桌面,在 PowerShell 里面各种 cd 进入解压文件夹,输入
python setup.py installfeedparser安装完毕
3.进入网站 https://pypi.python.org/pypi/pydelicious 下载 pydelicious 0.6.1。下载文件为:pydelicious-0.6.1.tar.gz
4.用winRAR打开,解压到桌面,进去再次解压 pydelicious-0.6.1.tar ,在 PowerShell 里面各种 cd 进入解压文件夹,输入
python setup.py installpydelicious安装完毕
好了,安装完毕我们继续下一步走起。
跟着教材走,建立一个 run2.py:
import pydelicious print pydelicious.get_popular(tag = 'programming')
运行发现:
吃屎啊...怎么破?
书上还给了两个选择,这里选择用 Dorisa 用户为例:
print pydelicious.get_userposts('dorisa')然后还是不行。
delicious.com/rss 破网站真的有毒,十有八九被墙了。
于是我决定死马当成活马医,继续跟书走吧。
============================================================
构造数据集
主要是下载一个子集信息。
新建一个 deliciousrec.py 文件:
# -*- coding:utf-8 -*- # deliciousrec.pydelicous from pydelicious import get_popular, get_userposts, get_urlposts # 执行这个代码活的一个包含若干用户数据的字典,其中每一项都各自指向一个等待填入具体链接的空字典。 def initializeUserDict(tag, count = 5): user_dict = {} # 获取前 count 个最受欢迎的链接张贴记录 for p1 in get_popular(tag = tag)[0:count]: for p2 in get_urlposts(p1['href']): user = p2['user'] user_dict[user] = {} return user_dict # 只有两种评价值: # 0:用户没有张贴这一链接 # 1:用户张贴了这一链接 def fillItem(user_dict): all_items = {} # 查找所有用户都提交过的链接 for user in user_dict: for i in range(3): try: posts = get_userposts(user) break except: print "Failed user '+user+', retrying" time.sleep(4) for post in posts: url = post['herf'] user_dict[user][url] = 1.0 all_items[url] = 1 # 用 0 填充缺失的项目 for ratings in user_dict.values(): for item in all_items: if tiem not in ratings: ratings[item] = 0.0
利用这个函数构造一个数据集,类似之前的影评字典:
# -*- coding:utf-8 -*- # run deliciousrec.py from deliciousrec import * delusers = initializeUserDict('programming') delusers ['tsegaran'] = {} # 如果你也是用 delicious,则将自己也加入字典中 fillItems(delusers)
这里的第三行代码将用户 tsegaran 添加到了列表中。假如你也是使用 del.icio.us,则不妨以自己的名字来替换 tsegaran。
然后对于 fillItems 的调用要花费几分钟的时间来执行,因为要向网站发起数百个请求。
当然对于网站被墙来说并无卵用。
=============================================================================
推荐近邻与链接
为了随机选择一个用户,并且找出与其品味相近的其他用户,在 run2 里面添加代码:
import random user = delusers.keys()[random.randint(0, len(delusers) - 1)] print user print recommendations.topMatches(delusers, user)
也可以通过调用 getRecommendations 函数为该用户获取推荐链接。
print recommendations.getRecommendations(delusers, user)[0:10]也可以依据链接来搜索:
url = recommendations.getRecommendations(delusers,user)[0][1] print recommendations.topMatches(recommendations.transformPrefs(delusers), url)这样我们就给网站增加了一个推荐引擎。
=============================================================================
基于物品的过滤
刚刚的方法对于上千的用户和物品规模是没问题的,对于像淘宝亚马逊这样的网站,把单个用户和其他所有用户比较太慢了。之前我们采用的方法叫做基于用户的协作型过滤,此外,还有一种方法叫做基于物品的协作型过滤。在大数据情况下,这种方法能得出更好的结论。
总体思路就是为每件物品预先计算好最为相近的其他物品。区别在于物品间的比较不会像用户间的比较那么频繁变化。
=============================================================================
构造物品比较数据集
为了对物品比较,在 recommendations.py 里面加入:
def calculateSimilarItems(prefs, n = 10): # 建立字典,以给出与这些物品最为相近的所有其他物品 result = {} # 以物品为中心对偏好矩阵实施倒置处理 itemPrefs = transformPrefs(prefs) c = 0 for item in temPrefs: # 针对大数据集更新状态变量 c += 1 if c % 100 == 0:print "%d / %d" % (c, len(itemPrefs)) # 寻找最为相近的物品 scores = topMatches(itemPrefs, item, n = n, similarity = sim_distance) result[item] = scores return result # 返回一个包含物品及其最相近物品列表的字典
先对反映评价值的字典倒置处理,从而得到一个有关物品及其用户评价的列表。然后程序循环遍历每个物品,并且把转换了的字典传入 topMatches 函数中,求得最为相近的物品及其相似度评价值。
在 run1.py 添加:
print '\n==========================================' print 'itemsim' itemsim = recommendations.calculateSimilarItems(recommendations.critics) print itemsim
这里结果很有意思,书上第一个是0.4,而我计算的则是0.44。仔细检查发现书上的示例代码中 sim_distance 函数的返回值如果不加 sqrt 的话就是一致的。归根结底应该是书上的代码有点问题。
以上是结果。
=============================================================================
获得推荐
现在我们可以在不遍历整个数据集的情况下,利用反映物品相似度的字典给出推荐。具体数学方法参见书上。
在 recommendations.py 里面加入:
def getRecommendedItems(prefs, itemMatch, user): userRatings = prefs[user] scores = {} totalSim = {} # 循环遍历由当前用户评分的物品 for (item, rating) in userRatings.items(): # dict.items() 此方法返回元组对的列表。 # 寻遍遍历与当前物品相机的物品 for (similarity, item2) in itemMatch[item]: # 如果该用户已经对当前物品做过评价,则将其忽略 if item2 in userRatings: continue # 评价值与相似度的加权之和 scores.setdefault(item2, 0) # setdefault 见前面注释 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
run1.py:
print '\n==========================================' print 'getRecommendedItems' print recommendations.getRecommendedItems(recommendations.critics, itemsim, 'Toby')
结果:
可以看出推荐物品排行。
=============================================================================
使用 MovieLens 数据集
从 http://www.grouplens.org/node/73 下载 MovieLens 数据集。注意下载的是小的数据集,十万数据的那个。
解压打开文件,我们主要关心的是 movies.csv 和 ratings.csv ,前者包含了一组有关影片ID和片面的列表,后者是实际评价情况。
每位用户都对较多影片做出过评价。在 recommendations.py 中新建一个方法,取名 loadMovieLens,用以加载数据。
def loadMovieLens(path = 'MovieLens-latest-small/ml-latest-small'): # 获取影片标题 movies = {} for line in open(path + '/movies.csv'): (id, title, genres) = line.split('|')[0:2] # 这里文件中第三列是影片类型,略作修改 movies[id] = title # 把 title 和 id对应 # 加载数据 prefs = {} for line in open(path + '/ratings.csv'): (user, movieid, rating, ts) = line.split('\t') # 分割 prefs.setdefault(user, {}) prefs[user][movies[movieid]] = float(rating) return prefs
很遗憾,就卡在了这一步。这里读不出来。也不知道是哪里出错了。
虽然止步于最后一步,但是基于用户和基于物品的推荐大概方法已经过了一遍。
文末还指出,对于稀疏数据集,基于物品的过滤方法通常要优于基于用户的过滤方法,对于密集数据集则两者差不多。
相关文章推荐
- 【集体智慧编程】第二章、提供推荐
- 集体智慧编程学习笔记--第二章
- 集体智慧编程第二章学习笔记
- 集体智慧编程----第二章 提供推荐(Making Recommendations)
- 集体智慧编程 第二章 提供推荐
- 【转】读书笔记:“集体智慧编程”之第二章:推荐算法——协同滤波
- Spark实现 集体智慧编程 第二章电影推荐
- 集体智慧编程:第二章,推荐算法
- 集体编程智慧代码摘抄【第二章】
- “集体智慧编程”之第二章:推荐算法
- programming collective intelligence(集体智慧编程)第二章python3.x安装pydelicious
- 程序员编程艺术:第二章、字符串是否包含及匹配/查找/转换/拷贝问题
- 集体智慧编程_聚类
- 7.12-集体智慧编程-笔记-提供推荐--未完
- 集体智慧编程 读书笔记 二
- 【集体智慧编程 学习笔记】 Euclidean距离和Pearson相关系数
- 【集体智慧编程 学习笔记】统计订阅源中的单词数
- 集体智慧编程(一)推荐系统之欧里几德距离
- 集体智慧编程书中的一些关键概念
- 集体智慧编程——神经网络预测点击率-Python实现