FEATURED · 精选文章

协同过滤实现Python?别骗自己了,这算法谁用谁爽到飞起

发布时间 / 2026/9/7 21:44:55
来源 / 创域科博编辑部
栏目 / 资讯中心
协同过滤实现Python?别骗自己了,这算法谁用谁爽到飞起 常见推荐算法 协同过滤协同过滤, 身为推荐算法里最为经典的类别, 涵盖在线协同、离线过滤两步。在线协同, 即借由在线数据查到用户兴许中意的物品。离线过滤, 乃是滤除某些不值得举荐的数据, 像推荐值评分低的数据, 又或者虽推荐值高但用户已经选购的数据。协同过滤的模型, 一般是针对m个物品, 以及m个用户的数据, 其中, 只有部分用户和部分数据之间存在评分数据, 而其它部分的评分是空白的, 在这种情况下, 我们需要利用已有的部分稀疏数据, 来预测那些空白的物品与数据之间的评分关系, 进而找到最高评分的物品, 将其推荐给用户。说来通常情况下, 协同过滤推荐被划分成三种类别类型。其一为基于用户也就是(user - based)这般的协同过滤, 其二是基于项目即(item - based)此品类的协同过滤, 其三作为基于模型即(model based)这类的的协同过滤。所有用户针对物品或者信息具有相应偏好根据这一点, 基于用户这种偏好, 据此针对所有可能, 发现与当前用户口味和偏好相似的用户群, 接着依据这些有着的用户的历史偏好, 为当前用户开展推荐工作, 这便是基于用户的协同过滤含有的基本原理。给出这样一种假设情况, 存在用户A, 其对物品A、物品C有着喜好之情, 还有用户B, 其喜欢物品B, 另外有用户C, 其喜欢物品A、物品C以及物品D。从这些用户过往的偏好情形展现里, 能够看出用户A与用户C的偏好存在类似之处。与此同时, 能够观察到用户C对物品D有喜欢之情, 所以据此可以猜测用户A有可能也会喜欢物品D, 进而能够将物品D推荐给用户A。分解矩阵这是个极为优雅的推荐算法, 鉴于涉及矩阵分解时, 正常情形下我们不会过多去思索哪些项目会留在所获矩阵的行列当中。然而运用这款推荐引擎, 我们清晰瞧见, u是第i个用户的兴趣向量, v是第j个电影的参数向量。由于如此, 我们能够运用u跟v的点积去估算, 此x即第i个用户针对第j个电影所给出的评分。我们凭借已知的分数构建起这些向量, 进而运用它们去预测不清楚的得分。例如, 矩阵分解完成之后, Ted的向量呈现为(1.4; .8), 商品A的向量呈现为(1.4; .9), 就当前所处局面来说, 我们能够借助将(1.4; .8)与(1.4; .9)进行点积计算的方式手法 , 以此来还原商品A与Ted之间的得分情况。最终的结果呢 , 我们所获取到的分数是2.68分。聚类于上面的那两种有着极其简单特性的算法而言, 它们是适用于小型系统的。在这两者方法里头, 我们将推荐问题当作一个需要通过有监督学习这一方式才可解决的机器学习相关任务。现在该开始用无监督学习来解决问题了。打个比方, 我们正着手构建一个规模巨大的推荐系统, 于这个时候, 协同过滤以及矩阵分解所耗费的时间变得更长起来, 首先在脑海当中浮现出来的能够用来化解问题的办法, 便是聚类。业务开展之初缺乏之前的用户数据聚类将是最好的方法。即便如此, 聚类属于一种相对较弱的个性化推荐方式, 究其原因在于, 该方法的本质是去识别用户组, 并且针对这个组里的用户推荐相同的内容。于我们具备充足数据之际, 最优选择是运用聚类当作初始步骤, 以此去削减协同过滤算法里相关邻居的挑选范畴, 此方法还能够提升复杂推荐系统的性能喽。每一个聚类, 均会依据其中用户予以的偏好, 去分配一组典型的偏好, 每个聚类里的用户, 都将会收到为这个聚类而计算得出的推荐内容。深度学习过去十年里面, 神经网络取得了极大的进步。现如今, 神经网络获得了广泛运用, 并且渐渐替代了传统的机器学习方式。接下来我要介绍一下如何使用深度学习方法来做个性化推荐。毫无疑义, 鉴于体量极大, 还有动态库以及种种难以观察到的外部因素, 给用户予以推荐内容, 这是一项极具挑战性的任务。依照《Deep for 》, 其推, 荐系统算法, 是由甲, 乙两个神经网络构成的: 其中一个是用来进行候选生成的, 另一个则是用于排序的。万一你抽不出时间认真研习论文的话, 那么不妨瞧瞧我们于下面所给出的简短总结。将用户的浏览历史当作输入, 候选生成网络能够极大地缩减可推荐的视频数量, 于庞大的库之中挑选出一组最为相关的视频。如此生成的候选视频跟用户的相关性是最高的, 接着我们要来对用户评分展开预测。这个网络的目标只是通过协同过滤提供更广泛的个性化。开展至这般程度, 我们收获了一组规模更为微小然而相关性更为显著的内容。我们的目的是审慎剖析这些候选内容, 从而作出最佳的抉择。这个任务由排序网络完成。视频描述数据以及基于用户行为信息, 以此来进行排序排序时会取用设计好目标函数, 为每个视频去打分, 通过这个选出得分最高视频呈献给用户最终被拿去献给至需视频给用户的是得分最高视频。经由这两步, 我们能够于极为庞大的视频库之中挑选视频, 然后朝着用户予以有针对性的推荐。此方法能够使我们将其他来源的内容也收纳进来。存在一个推荐任务, 它属于极端的多类分类问题范畴, 该预测问题的实质在于, 要依据用户U以及语境C, 于给定的时刻 t, 从库V里数量达上百万之多的视频类i当中, 去精准地针对特定的视频观看Wt情形展开分类。协同过滤原理采用基于物品的协同过滤方式, 就得去维护一个物品相似度矩阵, 采用基于用户的协同过滤方式, 就得去维护一个用户相似度矩阵。对俩用户之间相似度予以计算这件行为, 实际上是颇为简易的, 用户i跟用户j的相似度等于, i、j均已打开过的网页数量除以根号下i打开过的网页数量乘以j打开过的网页数量。此计算跟“基于物品的协同过滤”里物品之相似度的计算是相类似的。上面存在一个关于用户相似度计算的案例, 我们尝试着去计算A与D之间的相似度 , 从“用户打开过的网页”能够看出来, A和D两者都打开过的网页唯有d这一个, 也就是说仅有1个 , 用户A打开过的网页数量等于3 , 用户D打开过的网页数量等于3 , 所以A和D的相似度等于1除以根号下3乘以3 , 其他的计算与之相类似。具备用户彼此间的相似度后, 随即能够开展推荐度的计算。假定e属于刚发布出的文案, 此之际用户B、C、D均浏览至e新闻的标题处, 当中C、D付诸了点击行为, 就能开展针对A对e的兴趣的热度予以计算的操作了。A对于e的兴趣程度, 等于A跟B的相似程度与B对e的兴趣程度的乘积, 加上A跟C的相似程度与C对e的兴趣程度的乘积, , 再加上A跟D的相似程度乘以D对e的兴趣程度。由于我们在此处运用的并非评分制度, , 而是考量是否进行点击所以D点击了e, , D对e的兴趣程度等于1。A对于e的兴趣程度, 等于, 1除以根号6再乘以1, 加上, 1除以根号6再乘以1, 与, 1除以根号9再乘以1的和。所以, 比如说, 有100篇新的文章出现了, 之后对部分用户进行了曝光, 接着, 能够依据用户相似度, 来预估其他用户对这篇文章的兴趣程度, 进而, 在这100篇里挑选出预计兴趣度最高的30篇, 将其曝光给这群用户。系统设计 示例代码(py)from abc import ABCMeta, abstractmethod import numpy as np from collections import defaultdict class CF_base(metaclassABCMeta): def __init__(self, k3): self.k k self.n_user None self.n_item None abstractmethod def init_param(self, data): pass abstractmethod def cal_prediction(self, *args): pass abstractmethod def cal_recommendation(self, user_id, data): pass def fit(self, data): # 计算所有用户的推荐物品 self.init_param(data) all_users [] for i in range(self.n_user): all_users.append(self.cal_recommendation(i, data)) return all_users class CF_knearest(CF_base): 基于物品的K近邻协同过滤推荐算法 def __init__(self, k, criterioncosine): super(CF_knearest, self).__init__(k) self.criterion criterion self.simi_mat None return def init_param(self, data): # 初始化参数 self.n_user data.shape[0] self.n_item data.shape[1] self.simi_mat self.cal_simi_mat(data) return def cal_similarity(self, i, j, data): # 计算物品i和物品j的相似度 items data[:, [i, j]] del_inds np.where(items 0)[0] items np.delete(items, del_inds, axis0) if items.size 0: similarity 0 else: v1 items[:, 0] v2 items[:, 1] if self.criterion cosine: if np.std(v1) 1e-3: # 方差过大表明用户间评价尺度差别大需要进行调整 v1 v1 - v1.mean() if np.std(v2) 1e-3: v2 v2 - v2.mean() similarity (v1 v2) / np.linalg.norm(v1, 2) / np.linalg.norm(v2, 2) elif self.criterion pearson: similarity np.corrcoef(v1, v2)[0, 1] else: raise ValueError(the method is not supported now) return similarity def cal_simi_mat(self, data): # 计算物品间的相似度矩阵 simi_mat np.ones((self.n_item, self.n_item)) for i in range(self.n_item): for j in range(i 1, self.n_item): simi_mat[i, j] self.cal_similarity(i, j, data) simi_mat[j, i] simi_mat[i, j] return simi_mat def cal_prediction(self, user_row, item_ind): # 计算预推荐物品i对目标活跃用户u的吸引力 purchase_item_inds np.where(user_row 0)[0] rates user_row[purchase_item_inds] simi self.simi_mat[item_ind][purchase_item_inds] return np.sum(rates * simi) / np.linalg.norm(simi, 1) def cal_recommendation(self, user_ind, data): # 计算目标用户的最具吸引力的k个物品list item_prediction defaultdict(float) user_row data[user_ind] un_purchase_item_inds np.where(user_row 0)[0] for item_ind in un_purchase_item_inds: item_prediction[item_ind] self.cal_prediction(user_row, item_ind) res sorted(item_prediction, keyitem_prediction.get, reverseTrue) return res[:self.k] class CF_svd(CF_base): 基于矩阵分解的协同过滤算法 def __init__(self, k3, r3): super(CF_svd, self).__init__(k) self.r r # 选取前k个奇异值 self.uk None # 用户的隐因子向量 self.vk None # 物品的隐因子向量 return def init_param(self, data): # 初始化预处理 self.n_user data.shape[0] self.n_item data.shape[1] self.svd_simplify(data) return data def svd_simplify(self, data): # 奇异值分解以及简化 u, s, v np.linalg.svd(data) u, s, v u[:, :self.r], s[:self.r], v[:self.r, :] # 简化 sk np.diag(np.sqrt(s)) # r*r self.uk u sk # m*r self.vk sk v # r*n return def cal_prediction(self, user_ind, item_ind, user_row): rate_ave np.mean(user_row) # 用户已购物品的评价的平均值(未评价的评分为0) return rate_ave self.uk[user_ind] self.vk[:, item_ind] # 两个隐因子向量的内积加上平均值就是最终的预测分值 def cal_recommendation(self, user_ind, data): # 计算目标用户的最具吸引力的k个物品list item_prediction defaultdict(float) user_row data[user_ind] un_purchase_item_inds np.where(user_row 0)[0] for item_ind in un_purchase_item_inds: item_prediction[item_ind] self.cal_prediction(user_ind, item_ind, user_row) res sorted(item_prediction, keyitem_prediction.get, reverseTrue) return res[:self.k] if __name__ __main__: # data np.array([[4, 3, 0, 5, 0], # [4, 0, 4, 4, 0], # [4, 0, 5, 0, 3], # [2, 3, 0, 1, 0], # [0, 4, 2, 0, 5]]) data np.array([[3.5, 1.0, 0.0, 0.0, 0.0, 0.0], [2.5, 3.5, 3.0, 3.5, 2.5, 3.0], [3.0, 3.5, 1.5, 5.0, 3.0, 3.5], [2.5, 3.5, 0.0, 3.5, 4.0, 0.0], [3.5, 2.0, 4.5, 0.0, 3.5, 2.0], [3.0, 4.0, 2.0, 3.0, 3.0, 2.0], [4.5, 1.5, 3.0, 5.0, 3.5, 0.0]]) # cf CF_svd(k1, r3) cf CF_knearest(k1) print(cf.fit(data))系统展示 系统界面推荐效果
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻