推荐系统浅浅的例子

  对于推荐系统,有很多的很强大的算法。这里作为练习,只介绍基本的协同过滤算法(userbased)和FM(通过梯度下降的角度,还可以通过交替优化的角度来看)。

  这里的例子是在七月算法的视频中看的,分析的内容基于自己的理解并对代码做了部分的勘误。

(一)简单的user-based协同过滤算法

  先来看一眼数据:

userss = {"小明": {"中国合伙人": 5.0, "太平轮": 3.0, "荒野猎人": 4.5,"老炮儿": 5.0, "我的少女时代": 3.0,"肖洛特烦恼": 4.5, "火星救援": 5.0},"小红": {"小时代4": 4.0, "荒野猎人": 3.0, "我的少女时代": 5.0, 
"肖洛特烦恼": 5.0, "火星救援": 3.0,"后会无期": 3.0},"小阳": {"小时代4": 2.0, "中国合伙人": 5.0, "我的少女时代": 3.0, 
"老炮儿": 5.0, "肖洛特烦恼": 4.5,"速度与激情7": 5.0},"小四": {"小时代4": 5.0, "中国合伙人": 3.0, "我的少女时代": 4.0,"匆匆那年": 4.0, "速度与激情7": 3.5, "火星救援": 3.5, "后会无期": 4.5},"六爷": {"小时代4": 2.0, "中国合伙人": 4.0, "荒野猎人": 4.5,"老炮儿": 5.0, "我的少女时代": 2.0},"小李":  {"荒野猎人": 5.0, "盗梦空间": 5.0, "我的少女时代": 3.0, 
"速度与激情7": 5.0, "蚁人": 4.5,"老炮儿": 4.0, "后会无期": 3.5},"隔壁老王": {"荒野猎人": 5.0, "中国合伙人": 4.0, 
"我的少女时代": 1.0, "Phoenix": 5.0,"甄嬛传": 4.0, "The Strokes": 5.0},"邻村小芳": {"小时代4": 4.0, "我的少女时代": 4.5,"匆匆那年": 4.5, "甄嬛传": 2.5, "The Strokes": 3.0}}

  这里是假想的一份数据,分别是每个用户对于自己看过的电影的评分。这里要进行userbased协同过滤,首先就要解释一下什么是userbased协同过滤;所谓userbased协同过滤,就是把一个用户看成是一条记录,然后看到的电影作为属性,对应的评分作为属性值。然后通过计算两条记录(两个user)之间的距离来衡量两条记录(两个user)的相近度。最后把距离最近的K(自己指定)的users看过而该user未看过的电影推荐给该user。所以最重要的就是计算距离了,下面介绍几种距离的计算方式:

(1)欧几里得距离

  DIS=\sqrt{(x_{1}-y_{1})^2+(x_{2}-y_{2})^2+...+(x_{n}-y_{n})^2}

def euclidean_dis(rating1, rating2):"""计算2个打分序列间的欧式距离. 输入的rating1和rating2都是打分dict格式为{'小时代4': 1.0, '疯狂动物城': 5.0}"""distance = 0common_ratings = Falsefor key in rating1:if key in rating2:distance += pow(rating1[key] - rating2[key], 2)common_ratings = True# 两个打分序列之间有公共打分电影if common_ratings:return distance# 无公共打分电影else:return float('inf')

 (2)曼哈顿距离

  DIS=\left | x_{1}-y_{1} \right |+\left|x_{2}-y_{2}\right|+...+\left|x_{n}-y_{n}\right|

def manhattan_dis(rating1, rating2):"""计算2个打分序列间的曼哈顿距离. 输入的rating1和rating2都是打分dict格式为{'小时代4': 1.0, '疯狂动物城': 5.0}"""distance = 0common_ratings = Falsefor key in rating1:if key in rating2:distance += abs(rating1[key] - rating2[key])common_ratings = True# 两个打分序列之间有公共打分电影if common_ratings:return distance# 无公共打分电影else:return float('inf')

 (3)COS距离

 DIS=1-\frac{x_{1}y_{1}+x_{2}y_{2}+...+x_{n}y_{n}}{\sqrt{(x_{1}^2+x_{2}^2+...+x_{n}^2)(y_{1}^2+y_{2}^2+...+y_{n}^2)}}

def cos_dis(rating1, rating2):"""计算2个打分序列间的cos距离. 输入的rating1和rating2都是打分dict格式为{'小时代4': 1.0, '疯狂动物城': 5.0}"""distance = 0dot_product_1 = 0dot_product_2 = 0common_ratings = Falsefor score in rating1.values():dot_product_1 += pow(score, 2)for score in rating2.values():dot_product_2 += pow(score, 2)for key in rating1:if key in rating2:distance += rating1[key] * rating2[key]common_ratings = True# 两个打分序列之间有公共打分电影# 注意,上面的distance是相似度,相似度越大,距离就会越小,所以用1来减if common_ratings:return 1 - distance/sqrt(dot_product_1 * dot_product_2)# 无公共打分电影else:return 2

 (4)Person距离(相关系数)

  DIS=\frac{cov(\vec{x},\vec{y})}{\sqrt{var(\vec{x})var(\vec{y})}}

 这里使用了cov(x,y) = E[xy] - E[x]E[y]var(x)=E[x^2]-E[x]^2

def pearson_dis(rating1, rating2):"""计算2个打分序列间的pearson距离. 输入的rating1和rating2都是打分dict格式为{'小时代4': 1.0, '疯狂动物城': 5.0}"""sum_xy = 0sum_x = 0sum_y = 0sum_x2 = 0sum_y2 = 0n = 0for key in rating1:if key in rating2:n += 1x = rating1[key]y = rating2[key]sum_xy += x * ysum_x += xsum_y += ysum_x2 += pow(x, 2)sum_y2 += pow(y, 2)# now compute denominatordenominator = sqrt(sum_x2 - pow(sum_x, 2) / n) * sqrt(sum_y2 - pow(sum_y, 2) / n)# 相关系数的取值在-1到1之间,值越大相关性越大,距离就越小,所以要用1来减一下if denominator == 0:return 2else:return 1 - (sum_xy - (sum_x * sum_y) / n) / denominator

  有了各种距离的定义,我们就可以根据定义的距离来计算两个user之间的想近程度了,计算方法如下:

# 查找最近邻
def compute_nearest_neighbor(username, users):"""在给定username的情况下,计算其他用户和它的距离并排序"""distances = []# 查找最近邻的时候要除去自身,要不然肯定是自己离自己最近了for user in users:if not user == username:distance = pearson_dis(users[user], users[username])# distance = cos_dis(users[user], users[username])# distance = manhattan_dis(users[user], users[username])# distance = euclidean_dis(users[user], users[username])distances.append((distance, user))distances.sort()print(distances)return distances

 最终进行推荐:

# 推荐
def recommend(username, users):"""对指定的user推荐电影"""# 找到最邻近nearest = compute_nearest_neighbor(username, users)[0][1]print("爱好相同的人:", nearest)recommendations = []# 找到最邻近看过, 但是username本身没有看过的电影, 计算推荐neighbor_ratings = users[nearest]user_ratings = users[username]for artist in neighbor_ratings:if artist not in user_ratings:recommendations.append((artist, neighbor_ratings[artist]))results = sorted(recommendations, key=lambda artist_tuple: artist_tuple[1], reverse=True)print("推荐电影:")for result in results:print(result[0], result[1])

 测试:

recommend('六爷', userss)

 测试结果:

 

(二)简单的张量分解来实现推荐

  首先,把数据整理成一个矩阵,缺失的用0(根据实际情况来定)来表示

主要的目标就是填充缺失的评分,这里使用FunkSVD,其代价函数为:

\underset{p_{i}q_{j}}{\underbrace{argmin}}\sum_{i,j}^{ }(m_{ij}-q_{j}^Tp_{i})^2+\lambda(\left \| p_{i} \right \|_{2}^2+\left \| q_{j} \right \|_{2}^2),

详情请参见https://www.cnblogs.com/pinard/p/6351319.html

使用SGD来做优化,代码如下:

def matrix_factorization(R, P, Q, K, steps=10000, alpha=0.0002, beta=0.02):Q = Q.Tfor step in range(steps):for i in range(len(R)):for j in range(len(R[i])):if R[i][j] > 0:e_ij = R[i][j] - np.dot(P[i, :], Q[:, j])for k in range(K):P[i][k] = P[i][k] + alpha * (2 * e_ij * Q[k][j] - beta * P[i][k])Q[k][j] = Q[k][j] + alpha * (2 * e_ij * P[i][k] - beta * Q[k][j])e = 0for i in range(len(R)):for j in range(len(R[i])):if R[i][j] > 0:e = e + pow(R[i][j] - np.dot(P[i, :], Q[:, j]), 2)for k in range(K):e = e + (beta / 2) * (pow(P[i][k], 2) + pow(Q[k][j], 2))if e < 0.001:breakreturn P, Q.T

使用上述函数进行缺失值的填充:

R = [[5.0, 0, 0, 3.5, 5.0, 0, 0, 0],[0, 0, 2.5, 0, 0, 4.0, 0, 0],[0, 0, 0, 0, 5.0, 0, 0, 0],[0, 0, 0, 0, 4.5, 0, 0, 0],[5.0, 5.0, 0, 0, 4.0, 0, 0, 5.0],[0, 0, 3.0, 0, 0, 5.0, 0, 0],[4.5, 0, 0, 0, 0, 0, 5.0, 4.5],[3.0, 2.0, 4.5, 4.0, 3.0, 1.0, 5.0, 3.0],[2.0, 2.0, 4.0, 5.0, 0, 0, 4.0, 0],[0, 0, 4.5, 4.0, 0, 0, 0, 0],[0, 0, 0, 3.5, 0, 0, 3.0, 5.0],[0, 0, 0, 0, 0, 5.0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 3.0],[0, 0, 0, 4.5, 3.5, 0, 3.0, 0],[0, 4.5, 0, 0, 5.0, 5.0, 3.0, 4.5],[5.0, 4.0, 0, 3.0, 0, 4.0, 0, 5.0]]
R = np.array(R)
M, N = np.shape(R)
# 设置隐藏属性的个数为2
K = 2
P = np.random.rand(M, K)
Q = np.random.rand(N, K)
nP, nQ = matrix_factorization(R, P, Q, K)
nR = np.dot(nP, nQ.T)
nR = np.around(nR, decimals=1)
print("更新后的得分矩阵为")
print(nR)

运行结果:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/569151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TPL Dataflow .Net 数据流组件,了解一下?

回顾上文 作为单体程序&#xff0c;依赖的第三方服务虽不多&#xff0c;但是2C的程序还是有不少内容可讲&#xff1b; 作为一个常规互联网系统&#xff0c;无外乎就是接受请求、处理请求&#xff0c;输出响应。 由于业务渐渐增长&#xff0c;数据处理的过程会越来越复杂和冗长&…

推荐系统实例

协同过滤与隐语义模型 在机器学习问题中&#xff0c;我们见到的数据集通常是如下的格式&#xff1a; input target ... ... &#xff0c;一个输入向量的集合以及对应的数据集合,就是我们想要去预测的值。 对于…

【转】深入理解JavaScript闭包(closure)

文章来源&#xff1a;http://www.felixwoo.com/archives/247 最近在网上查阅了不少Javascript闭包(closure)相关的资料&#xff0c;写的大多是非常的学术和专业。对于初学者来说别说理解闭包了&#xff0c;就连文字叙述都很难看懂。撰写此文的目的就是用最通俗的文字揭开Java…

从头开始建立神经网络翻译及扩展

目录翻译从头开始建立神经网络-简介导包和配置生成一个数据集实现用来展示决策边界的辅助函数Logistic Regression训练一个神经网络我们的神经网络如何进行预测学习神经网络的参数实现神经网络训练一个隐层有3个神经元的神经网络验证隐层神经元个数对神经网络的影响练习练习题解…

对比 C++ 和 Python,谈谈指针与引用

花下猫语&#xff1a;本文是学习群内 樱雨楼 小姐姐的投稿。之前已发布过她的一篇作品《当谈论迭代器时&#xff0c;我谈些什么&#xff1f;》&#xff0c;大受好评。本文依然是对比 C 与 Python&#xff0c;来探讨编程语言中极其重要的概念。祝大家读有所获&#xff0c;学有所…

《吴恩达深度学习》第一课第四周任意层的神经网络实现及BUG处理

目录一、实现1、吴恩达提供的工具函数sigmoidsigmoid求导relurelu求导2、实现代码导包和配置初始化参数前向运算计算损失后向运算更新参数组装模型3、问题及思考一、实现 1、吴恩达提供的工具函数 这几个函数这里只是展示一下&#xff0c;这是吴恩达写好的工具类&#xff0c;…

球形坐标和Cartesian 坐标的转换 spherical coordinate

spherical coordinate 和cartesian坐标的转换&#xff0c; 个人认为在控制camera的时候最为有用&#xff0c;比如CS中的操作方式&#xff0c; 鼠标负责方向的改变&#xff0c;其恰恰就是球形坐标的改变。而camera的位置改变就是cartesian的改变&#xff0c;所以这两者的转换就必…

【HANA系列】SAP HANA Studio出现Fetching Children...问题

公众号&#xff1a;SAP Technical本文作者&#xff1a;matinal原文出处&#xff1a;http://www.cnblogs.com/SAPmatinal/ 原文链接&#xff1a;【ABAP系列】SAP HANA Studio出现"Fetching Children..."问题前言部分 大家可以关注我的公众号&#xff0c;公众号里的排版…

朴素Bayse新闻分类实践

目录1、信息增益&#xff08;互信息&#xff09;介绍&#xff08;1&#xff09;西瓜书中的信息增益[^1]&#xff08;2&#xff09;PRML中的互信息[^2]&#xff08;3&#xff09; 其实他们是一个东西2、朴素Bayse新闻分类[^3]&#xff08;1&#xff09;常量及辅助函数&#xff0…

【数据仓库】OLTP系统和OLAP系统区别

OLTP&#xff1a;联机事务处理系统(OnLine Transaction Processing) OLAP&#xff1a;联机分析处理系统(OnLine Analytical Processing) 参考文档&#xff1a; 操作数据库系统(OLTP)和联机分析处理系统(OLAP)的区别转载于:https://www.cnblogs.com/badboy200800/p/11189478.htm…

Good Numbers(HDU5447+唯一分解)

题目链接 传送门 题面 题意 首先定义对于\(k\)的好数\(u\)&#xff1a;如果\(u\leq k\)且\(u\)的所有质因子与\(k\)的质因子一样则称\(u\)对于\(k\)是一个好数。 现给你两个数\(k1,k2(1\leq k1,k2\leq 10^{24})\)&#xff0c;要你求\(k1,k2\)的好数个数&#xff0c;对于\(k1,k2…

从机器码到面向对象

1.从机器码到面向对象 本章节主要探讨是什么驱动着编程从机器码发展到了汇编语言&#xff0c;又从汇编语言发展到了面向过程编程&#xff0c;最后从面向过程编程发展到面向对象编程。通过这些探讨最终明确多年来的软件工程发展我们都解决了哪些棘手的问题。 1.1机器码 在真正…

spfa_队列

spfa:1.当给定的图存在负权边时&#xff0c;Dijkstra等算法便没有了用武之地&#xff0c;而Bellman-Ford算法的复杂度又过高&#xff0c;SPFA算法便派上用场了.2.我们约定有向加权图G不存在负权回路&#xff0c;即最短路径一定存在3.思路&#xff1a;用数组d记录每个结点的最短…

Tomcat配置解析

Tomcat文件配置 tomcat解压后目录 bin&#xff1a;可执行文件&#xff08;startup.bat shutdown.bat) conf&#xff1a;配置文件&#xff08;server.xml&#xff09; lib&#xff1a;tomcat依赖的jar文件 log&#xff1a;日志文件&#xff08;记录出错等信息&#xff09; temp&…

教你配置安全的ProFTPD服务器(中)

二、 基本加固ProFTPD服务器步骤 1.升级版本 注&#xff1a;如果当前版本已经是最新版本&#xff0c;可以跳过第一步。 升级陈旧的ProFTPD版本&#xff0c;因为早期的ProFTPD版本存在的安全漏洞。对于一个新配置的ProFTPD服务器来说使用最新稳定版本是最明智的选择&#xff0c;…

Java 将Word转为PDF、PNG、SVG、RTF、XPS、TXT、XML

同一文档在不同的编译或阅读环境中&#xff0c;需要使用特定的文档格式来打开&#xff0c;通常需要通过转换文档格式的方式来实现。下面将介绍在Java程序中如何来转换Word文档为其他几种常见文档格式&#xff0c;如PDF、图片png、svg、xps、rtf、txt、xml等。 使用工具&#xf…

CentOS7上GitLab的使用

生成SSH Keys 生成root账号的ssh key # ssh-keygen -t rsa -C "adminexample.com" 显示pub key的值 # cat ~/.ssh/id_rsa.pub 复制显示出来的 pub key 以root账号登陆gitlab&#xff0c;点击 "profile settings" 然后点击 "SSH Keys" 将复制的pu…

数据库:除运算

除运算 设关系R除以关系S的结果为关系T&#xff0c;则T包含所有在R但不在S中的属性及其值&#xff0c;则T的原则与S的元组的所有组合都在R中。用象集来定义除法&#xff1a;给定关系R&#xff08;X&#xff0c;Y&#xff09;和S&#xff08;Y&#xff0c;Z&#xff09;。其中X&…

[图解tensorflow源码] 入门准备工作附常用的矩阵计算工具[转]

[图解tensorflow源码] 入门准备工作附常用的矩阵计算工具[转] Link: https://www.cnblogs.com/yao62995/p/5773142.html tensorflow使用了自动化构建工具bazel、脚本语言调用c或cpp的包裹工具swig、使用EIGEN作为矩阵处理工具、Nvidia-cuBLAS GPU加速计算库、结构化数据存储格式…

现共收到 5 个分组,其目的地址分别为: (1) 128.96.40.10 (2) 128.96.41.12 (3) 128.96.41.151 (4) 192.4.123.17 (5) 192.4.

计算目的地址的下一跳&#xff1a; 设某路由器建立了如表 1 所示路由表。现共收到 5 个分组&#xff0c;其目的地址分别为&#xff1a;(1) 128.96.40.10(2) 128.96.41.12(3) 128.96.41.151(4) 192.4.123.17(5) 192.4.123.90试分别计算下一跳解答&#xff1a; 用目的IP地址和路由…