python机器学习案例系列教程——匹配和推荐
来源:互联网 发布:linux dns 添加mx 编辑:程序博客网 时间:2024/06/07 05:13
全栈工程师开发手册 (作者:栾鹏)
python数据挖掘系列教程
python机器学习系列教程——匹配和推荐
本文我们通过为用户推荐物品的方式学习协作性过滤算法
只要数据集符合“主语-宾语-取值”,也就是说,每行代表一个主语对不通过宾语的取值,每一列代表不同主语对同一宾语的取值。取值甚至可以只有0、1固定值都可以使用这种算法。进行行列的匹配、推荐。
例如:
影评人(主语)给电影(宾语)打分(取值)。 向影评人推荐相似影评人,向影评人推荐电影。
买家(主语)给宝贝(宾语)评分(取值)。向淘宝买家推荐宝贝等。
读者(主语)停留在某类文章(宾语)上的时间长度(取值)。向读者推荐类似文件的强度。
上网用户(主语)对某博主(宾语)进行了点击(取值0、1)。向用户推荐感性的博主。
有多的应用需要在工作中学会洞察。
构造数据集
首先需要构造数据集,下载地址
https://grouplens.org/datasets/movielens/
这里我们先不使用网页中复杂的数据集,我们先使用如下简单的数据集。至于如何读取下载的数据集成下面的字典格式,相信大家肯定会了。不会的可以参考csv文件读写http://blog.csdn.net/luanpeng825485697/article/details/78358997
# 偏好数据集(人-电影-评分)prefs={ 'name1': {'movie1': 2.5, 'movie2': 3.5,'movie3': 3.0, 'movie4': 3.5, 'movie5': 2.5, 'movie6': 3.0}, 'name2': {'movie1': 3.0, 'movie2': 3.5,'movie3': 1.5, 'movie4': 5.0, 'movie6': 3.0,'movie5': 3.5}, 'name3': {'movie1': 2.5, 'movie2': 3.0,'movie4': 3.5, 'movie6': 4.0}, 'name4': {'movie2': 3.5, 'movie3': 3.0, 'movie6': 4.5, 'movie4': 4.0, 'movie5': 2.5}, 'name5': {'movie1': 3.0, 'movie2': 4.0, 'movie3': 2.0, 'movie4': 3.0, 'movie6': 3.0,'movie5': 2.0}, 'name6': {'movie1': 3.0, 'movie2': 4.0, 'movie6': 3.0, 'movie4': 5.0, 'movie5': 3.5}, 'name7': {'movie2':4.5,'movie5':1.0,'movie4':4.0}}
相似度计算方法
我们可以对行或对列进行相似度匹配。这里先了解如何对计算两个行的相似程度。我们采用欧几里得距离和皮尔逊相似度。将值映射的0-1上来代表相似程度,1代表完全相同,0代表完全不同。
欧几里得距离计算
from math import sqrt# 计算两行之间的欧几里得距离,以此来代表相似度。prefs表示偏好数据集def sim_distance(prefs,row1_name,row2_name): # 首先计算是否有共同列(都看过的电影) si={} for item in prefs[row1_name]: if item in prefs[row2_name]: si[item]=1 # 如果没有共同列,则两行之间相似度为0 if len(si)==0: return 0 # 根据共同列计算两行的欧几里得距离,并将距离映射到0-1上。0表示完全不相似,1表示完全相似 sum_of_squares=sum([pow(prefs[row1_name][item]-prefs[row2_name][item],2) for item in prefs[row1_name] if item in prefs[row2_name]]) return 1/(1+sum_of_squares)
皮尔逊相似度计算
# 计算两行的皮尔逊相似度,以此来代表相似度。prefs表示数据集def sim_pearson(prefs,row1_name,row2_name): # 首先计算是否有共同列(都看过的电影) si={} for item in prefs[row1_name]: if item in prefs[row2_name]: si[item]=1 # 如果没有共同列,两行之间相似度为0 if len(si)==0: return 0 # 得到列表元素个数 n=len(si) # 对两行的共同列求和 sum1=sum([prefs[row1_name][it] for it in si]) sum2=sum([prefs[row2_name][it] for it in si]) # 对两行的共同列求平方和 sum1Sq=sum([pow(prefs[row1_name][it],2) for it in si]) sum2Sq=sum([pow(prefs[row2_name][it],2) for it in si]) # 对两行的共同列求乘积之和 pSum=sum([prefs[row1_name][it]*prefs[row2_name][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
匹配相似行
根据相似度距离算法计算每行的相似行。对于两个数据量不同的行计算相似度,只用计算公共数据集即可。
# 匹配相似行# 根据偏好数据集,返回与某个行最匹配的n行。person表示要匹配的行(人),similarity表示相似度计算函数def topMatches(prefs,row_name,n=5,similarity=sim_pearson): scores=[(similarity(prefs,row_name,other),other) for other in prefs if other!=row_name] scores.sort() scores.reverse() num = n if n>len(scores):num= len(scores) return scores[0:num]
利用相似行估计列的值,并排名
有了相似行,某一行就可以根据相似行对各列的评值,来估计当前行各列存在的空白值。为了避免算法的不精准,所以相似行不止一个,每个相似行根据相似度确定权重。最后估值采用加权平均的方式。
对当前行各列存在的空白值进行估计以后,将估计的值进行排名推荐。
# 利用相似行,估计某行所有列存在的空白值,并排名(估计影片评分,并排名推荐)# 利用所有其他行的各列取值的加权平均(相似度为权值),为某行各列提供估值def getRecommendations(prefs,row_name,similarity=sim_pearson): totals={} simSums={} for other in prefs: # 不和自己做比较 if other==row_name: continue sim=similarity(prefs,row_name,other) # 忽略评价值为0或为负的情况 if sim<=0: continue for item in prefs[other]: # 只对自己还未有的列进行临时估值 if item not in prefs[row_name] or prefs[row_name][item]==0: # 相似度*临时估值 totals.setdefault(item,0) totals[item]+=prefs[other][item]*sim # 相似度之和 simSums.setdefault(item,0) simSums[item]+=sim # 建立归一化列表 rankings=[(total/simSums[item],item) for item,total in totals.items()] # 返回最终估值经过排序的列表 rankings.sort() rankings.reverse() return rankings
匹配相似列
对于数据来说他无法识别每行的含义,只是在做行间运算。如果我们把数据矩阵进行转置,再做行间运算。那就是进行的列匹配。
数据集转置
def transformPrefs(prefs): result={} for row_name in prefs: for item in prefs[row_name]: result.setdefault(item,{}) # 将行与列对调 result[item][row_name]=prefs[row_name][item] return result
匹配相似列
# 匹配相似列,返回各列的匹配集合(因为各列的匹配可提前在用户登陆前完成),# 根据转置后的偏好数据集,获取每列相似的n个其他列def calculateSimilarItems(prefs,n=10): # 建立字典,以给出与这些列最为相近的所有其他列 itemMatch={} # 以列为中心对偏好矩阵实施转置处理 itemPrefs=transformPrefs(prefs) c=0 for item in itemPrefs: # 针对大数据集更新状态变量 c+=1 if c%100==0: print("%d / %d" % (c,len(itemPrefs))) # 寻找最为相近的列 scores=topMatches(itemPrefs,item,n=n,similarity=sim_distance) itemMatch[item]=scores return itemMatch #返回每列匹配的其他列
利用相似列,对某一行的各列空白处进行估值
与根据相似行对各列的空白值进行估计类似。
# 利用相似列,对某一行的各列进行估值,(估计影片评分,并排名推荐):根据偏好数据集和提前构造好的物品匹配库,向用户推荐物品def getRecommendedItems(prefs,itemMatch,row_name): onerow=prefs[row_name] #获取当前行所拥有的列 scores={} totalSim={} # 循环遍历由当前行所拥有的列 for (item,rating) in onerow.items( ): # 循环遍历与当前列相似的列 for (similarity,item2) in itemMatch[item]: # 忽略行已经拥有的列 if item2 in onerow: 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
运行试验
有了上面的算法,我们就可以来尝试效果了。
if __name__=="__main__": #只有在执行当前模块时才会运行此函数 #利用相似人推荐相似物品 rankings = getRecommendations(prefs,'name7') print(rankings) #打印推荐排名 #利用相似物品推荐相似物品 itemMatch = calculateSimilarItems(prefs) # 提前计算所有物品的相似物品 rankings = getRecommendedItems(prefs,itemMatch,'name7') print(rankings) #打印推荐排名
完整的代码
#根据偏好数据集,匹配行和列,进而实现推荐行和推荐列# 偏好数据集(人-电影-评分)prefs={ 'name1': {'movie1': 2.5, 'movie2': 3.5,'movie3': 3.0, 'movie4': 3.5, 'movie5': 2.5, 'movie6': 3.0}, 'name2': {'movie1': 3.0, 'movie2': 3.5,'movie3': 1.5, 'movie4': 5.0, 'movie6': 3.0,'movie5': 3.5}, 'name3': {'movie1': 2.5, 'movie2': 3.0,'movie4': 3.5, 'movie6': 4.0}, 'name4': {'movie2': 3.5, 'movie3': 3.0, 'movie6': 4.5, 'movie4': 4.0, 'movie5': 2.5}, 'name5': {'movie1': 3.0, 'movie2': 4.0, 'movie3': 2.0, 'movie4': 3.0, 'movie6': 3.0,'movie5': 2.0}, 'name6': {'movie1': 3.0, 'movie2': 4.0, 'movie6': 3.0, 'movie4': 5.0, 'movie5': 3.5}, 'name7': {'movie2':4.5,'movie5':1.0,'movie4':4.0}}from math import sqrt# 计算两行之间的欧几里得距离,以此来代表相似度。prefs表示偏好数据集def sim_distance(prefs,row1_name,row2_name): # 首先计算是否有共同列(都看过的电影) si={} for item in prefs[row1_name]: if item in prefs[row2_name]: si[item]=1 # 如果没有共同列,则两行之间相似度为0 if len(si)==0: return 0 # 根据共同列计算两行的欧几里得距离,并将距离映射到0-1上。0表示完全不相似,1表示完全相似 sum_of_squares=sum([pow(prefs[row1_name][item]-prefs[row2_name][item],2) for item in prefs[row1_name] if item in prefs[row2_name]]) return 1/(1+sum_of_squares)# 计算两行的皮尔逊相似度,以此来代表相似度。prefs表示数据集def sim_pearson(prefs,row1_name,row2_name): # 首先计算是否有共同列(都看过的电影) si={} for item in prefs[row1_name]: if item in prefs[row2_name]: si[item]=1 # 如果没有共同列,两行之间相似度为0 if len(si)==0: return 0 # 得到列表元素个数 n=len(si) # 对两行的共同列求和 sum1=sum([prefs[row1_name][it] for it in si]) sum2=sum([prefs[row2_name][it] for it in si]) # 对两行的共同列求平方和 sum1Sq=sum([pow(prefs[row1_name][it],2) for it in si]) sum2Sq=sum([pow(prefs[row2_name][it],2) for it in si]) # 对两行的共同列求乘积之和 pSum=sum([prefs[row1_name][it]*prefs[row2_name][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# 匹配相似行# 根据偏好数据集,返回与某个行最匹配的n行。person表示要匹配的行(人),similarity表示相似度计算函数def topMatches(prefs,row_name,n=5,similarity=sim_pearson): scores=[(similarity(prefs,row_name,other),other) for other in prefs if other!=row_name] scores.sort() scores.reverse() num = n if n>len(scores):num= len(scores) return scores[0:num]# 利用相似行,估计某行所有列存在的空白值,并排名(估计影片评分,并排名推荐)# 利用所有其他行的各列取值的加权平均(相似度为权值),为某行各列提供估值def getRecommendations(prefs,row_name,similarity=sim_pearson): totals={} simSums={} for other in prefs: # 不和自己做比较 if other==row_name: continue sim=similarity(prefs,row_name,other) # 忽略评价值为0或为负的情况 if sim<=0: continue for item in prefs[other]: # 只对自己还未有的列进行临时估值 if item not in prefs[row_name] or prefs[row_name][item]==0: # 相似度*临时估值 totals.setdefault(item,0) totals[item]+=prefs[other][item]*sim # 相似度之和 simSums.setdefault(item,0) simSums[item]+=sim # 建立归一化列表 rankings=[(total/simSums[item],item) for item,total in totals.items()] # 返回最终估值经过排序的列表 rankings.sort() rankings.reverse() return rankings# 转置偏好数据集,以便实现匹配列def transformPrefs(prefs): result={} for row_name in prefs: for item in prefs[row_name]: result.setdefault(item,{}) # 将行与列对调 result[item][row_name]=prefs[row_name][item] return result# 匹配相似列,返回各列的匹配集合(因为各列的匹配可提前在用户登陆前完成),# 根据转置后的偏好数据集,获取每列相似的n个其他列def calculateSimilarItems(prefs,n=10): # 建立字典,以给出与这些列最为相近的所有其他列 itemMatch={} # 以列为中心对偏好矩阵实施转置处理 itemPrefs=transformPrefs(prefs) c=0 for item in itemPrefs: # 针对大数据集更新状态变量 c+=1 if c%100==0: print("%d / %d" % (c,len(itemPrefs))) # 寻找最为相近的列 scores=topMatches(itemPrefs,item,n=n,similarity=sim_distance) itemMatch[item]=scores return itemMatch #返回每列匹配的其他列# 利用相似列,对某一行的各列进行估值,(估计影片评分,并排名推荐):根据偏好数据集和提前构造好的物品匹配库,向用户推荐物品def getRecommendedItems(prefs,itemMatch,row_name): onerow=prefs[row_name] #获取当前行所拥有的列 scores={} totalSim={} # 循环遍历由当前行所拥有的列 for (item,rating) in onerow.items( ): # 循环遍历与当前列相似的列 for (similarity,item2) in itemMatch[item]: # 忽略行已经拥有的列 if item2 in onerow: 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 rankingsif __name__=="__main__": #只有在执行当前模块时才会运行此函数 #利用相似人推荐相似物品 rankings = getRecommendations(prefs,'name7') print(rankings) #打印推荐排名 #利用相似物品推荐相似物品 itemMatch = calculateSimilarItems(prefs) # 提前计算所有物品的相似物品 rankings = getRecommendedItems(prefs,itemMatch,'name7') print(rankings) #打印推荐排名
- python机器学习案例系列教程——匹配和推荐
- python机器学习案例系列教程——决策树
- python机器学习案例系列教程——核方法
- python机器学习案例系列教程——线性分类器
- python机器学习案例系列教程——优化,寻找使成本函数最小的最优解
- python机器学习案例系列教程——分类器,朴素贝叶斯分类器,费舍尔分类器
- python机器学习案例教程——K最近邻算法
- 推荐算法和机器学习系列 - 推荐算法综述
- 基于Python数据分析与机器学习案例实战教程
- 推荐一个机器学习框架——python实现
- 【Python学习系列九】Python机器学习库scikit-learn实现SVM案例
- 【Python学习系列十】Python机器学习库scikit-learn实现Decision Trees案例
- 机器学习 — 提供推荐
- 机器学习 — 提供推荐
- Python机器学习算法 推荐
- python爬虫案例系列教程——python爬取百度新闻RSS数据
- Python机器学习教程——逻辑回归
- python机器学习库教程——结巴中文分词
- CUDA并行排序(4)——双调排序(二维double型数据)
- EOJ Monthly 2017.12 (暨 ECNU 12 月内部选拔)解题报告
- Linux CentOS 7 下 Apache Tomcat 7 安装与配置
- 管理好项目——带好技术团队的秘籍
- SpringBoot入门
- python机器学习案例系列教程——匹配和推荐
- 【广告】前端架构师独家揭秘:月薪30k难吗?
- mybatis官网参考文档-入门(版本: 3.4.6-SNAPSHOT)
- dp优化 12
- table导航条+侧滑菜单+布局
- 万亿级调用系统:微信序列号生成器架构设计及演变
- POJ 3660 Cow Contest
- 二维码扫码
- 什么是红黑树