集体智慧编程 读书笔记 一
2014-01-26 15:04
295 查看
这本书豆瓣上得分很高, 可以当作机器学习, 数据挖掘在当前web应用的入门书,我也是一个门外汉加初学者, 正在读这本书
*****第二章****
1. 相似度, 偏好
这是一个比较常用的数据挖掘的例子, 比如你在优酷上看电影, 看完后 会推荐你看一些类似的, 或者你去亚马逊购物, 他会根据的购物记录给你相关推荐。 推荐的方法很多, 书中提到的一种是找到跟你有类似喜好的人, 看看他们买了什么或者看了什么, 然后推荐给你,OK, 这就涉及到一个问题, 如何界定一个人是否跟你相近。
首先看例子, 现在有一个数据集(书中给出的),记录每个人对不同电影的打分, 如下所示
第一个数据的意思是: Lisa Rose这个人 对于 Lady in the Water的打分时2.5, 从这写数据里如何判定两个人的喜好是否一致? 书中给出了两种方法
欧几里德距离
将数据集中每个人对电影的打分 看作是不同维度上的坐标,那么欧几里得距离是两个点间的距离: A(X1, Y1), B(X2, Y2) 距离为:
两点距离越近,该值越小。 上面是二维的, 多维的也一样,比如坐标a (a1, a2, ...., an)和 b (b1,b2,...bn)距离 如下:
好 有了这些为基础, 第一个我们就可以写出给定数据集上, 给定的两个人之间的欧几里得距离是多少的函数
prefs,是给定的数据集, 求出的结果是参数里两个人的相似度,si 是这两个人评论过相同电影的集合, 也是将来求距离的维度, 只有都评论过的电影才能求出距离来。 sum_of_squares 是每一维度距离的平方和, 最后的相似度定义为 1/(1+欧几里得距离) 原因一是要让距离近,得出相似度高的结果,所以取倒数, 分母加1是防止出现0的情况
这杨算出来的准确吗? 我觉得是不太准确的, 假设两个人,都评论5部电影, 只共同评论过一部, 那这个结果就有待商榷了, 或者一个人评分普遍比另一个高, 但是趋势是一样的, 这个算出来可能不相近, 但实际两人的品味一样等等, 书中又给出了另一个求相似度的方法, pearson系数
Pearson系数
这个复杂得多, 算法不复杂, 但是介绍很复杂, 给出两个参考, 帮助理解 pearson 系数:
维基百科解释
网上解释
我觉得了解上面内容就可以了, 我也没有深入研究他为什么有效, 只知道确实有效,他的推倒公式:
根据这个公式那我们就方便写代码了,也是书中给出的代码:
还是先求共同的维度:
再来求
整个代码列出:
结合上面的公式能好理解
这里我有两个困惑的地方: 为什么si为空的时候, 返回的系数是1, 后经查看英文版发现应该是0, 果断换英文版来看, 不看翻译的了。 第二点是威尔逊系数和威尔逊距离还是有一定差异的, 哪个好些?
有了上面两个函数, 剩下的求出跟某人相近的几个人, 好办, 无非是排序, 那就牵扯另一个问题, 求出人不是目的, 目的是要真正的给出推荐的电影,书中给出的方法也很简单易懂, 就是加权取平均值, 权值就是相似度, 平均的分母是参与评分的权值的和, 要计算的部分是目标人物没看的但是跟他爱好相近的人看过的电影的排序:
我觉得稍微有点问题,就是数据量大的情况下, 我们可以先求出相近的几个人, 然后再在缩小的集合里求电影列表, 也就是说利用上书中的函数 topMatchs.
未完待续。。。。。。
*****第二章****
1. 相似度, 偏好
这是一个比较常用的数据挖掘的例子, 比如你在优酷上看电影, 看完后 会推荐你看一些类似的, 或者你去亚马逊购物, 他会根据的购物记录给你相关推荐。 推荐的方法很多, 书中提到的一种是找到跟你有类似喜好的人, 看看他们买了什么或者看了什么, 然后推荐给你,OK, 这就涉及到一个问题, 如何界定一个人是否跟你相近。
首先看例子, 现在有一个数据集(书中给出的),记录每个人对不同电影的打分, 如下所示
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}}
第一个数据的意思是: Lisa Rose这个人 对于 Lady in the Water的打分时2.5, 从这写数据里如何判定两个人的喜好是否一致? 书中给出了两种方法
欧几里德距离
将数据集中每个人对电影的打分 看作是不同维度上的坐标,那么欧几里得距离是两个点间的距离: A(X1, Y1), B(X2, Y2) 距离为:
两点距离越近,该值越小。 上面是二维的, 多维的也一样,比如坐标a (a1, a2, ...., an)和 b (b1,b2,...bn)距离 如下:
好 有了这些为基础, 第一个我们就可以写出给定数据集上, 给定的两个人之间的欧几里得距离是多少的函数
def sim_distance(prefs, person1, person2): # get shared_item list si = {} for item in prefs[person1]: if item in prefs[person2]: si[item] = 1 # if no shared return 0 if len(si) == 0: return 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+sqrt(sum_of_squares))
prefs,是给定的数据集, 求出的结果是参数里两个人的相似度,si 是这两个人评论过相同电影的集合, 也是将来求距离的维度, 只有都评论过的电影才能求出距离来。 sum_of_squares 是每一维度距离的平方和, 最后的相似度定义为 1/(1+欧几里得距离) 原因一是要让距离近,得出相似度高的结果,所以取倒数, 分母加1是防止出现0的情况
这杨算出来的准确吗? 我觉得是不太准确的, 假设两个人,都评论5部电影, 只共同评论过一部, 那这个结果就有待商榷了, 或者一个人评分普遍比另一个高, 但是趋势是一样的, 这个算出来可能不相近, 但实际两人的品味一样等等, 书中又给出了另一个求相似度的方法, pearson系数
Pearson系数
这个复杂得多, 算法不复杂, 但是介绍很复杂, 给出两个参考, 帮助理解 pearson 系数:
维基百科解释
网上解释
我觉得了解上面内容就可以了, 我也没有深入研究他为什么有效, 只知道确实有效,他的推倒公式:
根据这个公式那我们就方便写代码了,也是书中给出的代码:
还是先求共同的维度:
si = {} for item in prefs[p1]: if item in prefs[p2]: si[item] = 1
再来求
sumMul = sum(prefs[p1][item] * prefs[p2][item] for item in si)
整个代码列出:
def sim_pearson(prefs, p1, p2):
#get shared item list
si = {} for item in prefs[p1]: if item in prefs[p2]: si[item] = 1
n = len(si)
if n == 0:
return 1
# get sum of points
sum1 = sum([prefs[p1][item] for item in si])
sum2 = sum ([prefs[p2][item] for item in si])
# get pow sum of points
sum1Pow = sum([pow(prefs[p1][item], 2) for item in si])
sum2Pow = sum([pow(prefs[p2][item], 2) for item in si])
#get sum of multi
sumMul = sum(prefs[p1][item] * prefs[p2][item] for item in si)
#compute pearson value
num = sumMul - (sum1 * sum2/n)
den = sqrt((sum1Pow - pow(sum1, 2)/n) * (sum2Pow - pow(sum2, 2)/n))
if den == 0:
return 0
r = num/den
return r
结合上面的公式能好理解
这里我有两个困惑的地方: 为什么si为空的时候, 返回的系数是1, 后经查看英文版发现应该是0, 果断换英文版来看, 不看翻译的了。 第二点是威尔逊系数和威尔逊距离还是有一定差异的, 哪个好些?
有了上面两个函数, 剩下的求出跟某人相近的几个人, 好办, 无非是排序, 那就牵扯另一个问题, 求出人不是目的, 目的是要真正的给出推荐的电影,书中给出的方法也很简单易懂, 就是加权取平均值, 权值就是相似度, 平均的分母是参与评分的权值的和, 要计算的部分是目标人物没看的但是跟他爱好相近的人看过的电影的排序:
def getRecommendations(prefs, person, sim_func=sim_pearson): totals={} simSums={} for other in prefs: if other == person: continue sim = sim_func(prefs,person, other) if sim < 0: continue for item in prefs[other]: if item not in prefs[person]: totals.setdefault(item, 0) totals[item] += prefs[other][item] * sim simSums.setdefault(item, 0) simSums[item] += sim ranking = [(total/simSums[item], item) for item,total in totals.items()] ranking.sort() ranking.reverse() return ranking
我觉得稍微有点问题,就是数据量大的情况下, 我们可以先求出相近的几个人, 然后再在缩小的集合里求电影列表, 也就是说利用上书中的函数 topMatchs.
未完待续。。。。。。
相关文章推荐
- 《programming.collective.intelligence》(集体智慧编程)读书笔记
- 【转】读书笔记:“集体智慧编程”之第二章:推荐算法——协同滤波
- 集体智慧编程 读书笔记 三
- 读书笔记-集体智慧编程
- 集体智慧编程(一)推荐系统之欧里几德距离
- 集体智慧编程——推荐系统(2)
- 集体智慧编程(二)发现群组
- 集体智慧编程_推荐系统2
- 集体智慧编程_聚类
- 集体智慧编程 第二章 提供推荐
- 集体智慧编程 第二章 匹配商品
- 集体智慧编程--推荐系统
- 集体智慧编程——决策树建模(上)
- 【集体智慧编程】第三章 发现群组
- 集体智慧编程学习之决策树
- “集体智慧编程”之第三章:带偏好条件的聚类及聚类的展示方式
- 集体智慧学习编程—— 学习笔记一
- 集体智慧编程 推荐系统改进
- 7.12-集体智慧编程-笔记-导言--未完
- 集体智慧编程(一)提供推荐