Alternating Least Squares(ASL) for Implicit Feedback Datasets的数学推导以及用Python实现
近期在看CF的相关论文,《Collaborative Filtering for Implicit Feedback Datasets》思想非常好,非常easy理解。可是从目标函数
是怎样推导出Xu和Yi的更新公式的推导过程却没有非常好的描写叙述。所以以下写一下
推导:
首先对Xu求导:
当中Y是item矩阵,n*f维,每一行是一个item_vec,C^u是n*n维的对角矩阵。
对角线上的每个元素是c_ui,P(u)是n*1的列向量,它的第i个元素为p_ui。
然后令导数=0,可得:
因为x_u和y_i在目标函数中是对称的。所以非常easy得到:
当中X是user矩阵,m*f维度,每一行是一个user_vec,C^i是m*m的对角矩阵。对角线上的每个元素是c_ui。P(i)是m*1的列向量。它的第u和元素是p_ui
然后令导数=0,可得:
以下是论文算法思想的Python实现:
import numpy as np
import scipy.sparse as sparse
from scipy.sparse.linalg import spsolve
import time
def load_matrix(filename, num_users, num_items):
t0 = time.time()
counts = np.zeros((num_users, num_items))
total = 0.0
num_zeros = num_users * num_items
'''假设要对一个列表或者数组既要遍历索引又要遍历元素时。能够用enumerate,当传入參数为文件时,索引为
行号,元素相应的一行内容'''
for i, line in enumerate(open(filename, 'r')):
#strip()去除最前面和最后面的空格
user, item, count = line.strip().split('\t')
user = int(user)
item = int(item)
count = float(count)
if user >= num_users:
continue
if item >= num_items:
continue
if count != 0:
counts[user, item] = count
total += count
num_zeros -= 1
if i % 100000 == 0:
print 'loaded %i counts...' % i
#数据导入完成后计算稀疏矩阵中零元素个数和非零元素个数的比例,记为alpha
alpha = num_zeros / total
print 'alpha %.2f' % alpha
counts *= alpha
#用CompressedSparse Row Format将稀疏矩阵压缩
counts = sparse.csr_matrix(counts)
t1 = time.time()
print 'Finished loading matrix in %f seconds' % (t1 - t0)
return counts
class ImplicitMF():
def __init__(self, counts, num_factors=40, num_iterations=30,
reg_param=0.8):
self.counts = counts
self.num_users = counts.shape[0]
self.num_items = counts.shape[1]
self.num_factors = num_factors
self.num_iterations = num_iterations
self.reg_param = reg_param
def train_model(self):
#创建user_vectors和item_vectors,他们的元素~N(0,1)的正态分布
self.user_vectors = np.random.normal(size=(self.num_users,
self.num_factors))
self.item_vectors = np.random.normal(size=(self.num_items,
self.num_factors))
'''要生成非常大的数字序列的时候,用xrange会比range性能优非常多,
因为不须要一上来就开辟一块非常大的内存空间,这两个基本上都是在循环的时候用'''
for i in xrange(self.num_iterations):
t0 = time.time()
print 'Solving for user vectors...'
self.user_vectors = self.iteration(True, sparse.csr_matrix(self.item_vectors))
print 'Solving for item vectors...'
self.item_vectors = self.iteration(False, sparse.csr_matrix(self.user_vectors))
t1 = time.time()
print 'iteration %i finished in %f seconds' % (i + 1, t1 - t0)
def iteration(self, user, fixed_vecs):
#相当于C的三木运算符。if user=True num_solve = num_users,反之为num_items
num_solve = self.num_users if user else self.num_items
num_fixed = fixed_vecs.shape[0]
YTY = fixed_vecs.T.dot(fixed_vecs)
eye = sparse.eye(num_fixed)
lambda_eye = self.reg_param * sparse.eye(self.num_factors)
solve_vecs = np.zeros((num_solve, self.num_factors))
t = time.time()
for i in xrange(num_solve):
if user:
counts_i = self.counts[i].toarray()
else:
#假设要求item_vec,counts_i为counts中的第i列的转置
counts_i = self.counts[:, i].T.toarray()
''' 原论文中c_ui=1+alpha*r_ui,可是在计算Y’CuY时为了减少时间复杂度,利用了
Y'CuY=Y'Y+Y'(Cu-I)Y,因为Cu是对角矩阵,其元素为c_ui,即1+alpha*r_ui。
所以Cu-I也就是对角元素为alpha*r_ui的对角矩阵'''
CuI = sparse.diags(counts_i, [0])
pu = counts_i.copy()
#np.where(pu != 0)返回pu中元素不为0的索引,然后将这些元素赋值为1,不知道这里为什么要赋值为1?
pu[np.where(pu != 0)] = 1.0
YTCuIY = fixed_vecs.T.dot(CuI).dot(fixed_vecs)
YTCupu = fixed_vecs.T.dot(CuI + eye).dot(sparse.csr_matrix(pu).T)
xu = spsolve(YTY + YTCuIY + lambda_eye, YTCupu)
solve_vecs[i] = xu
if i % 1000 == 0:
print 'Solved %i vecs in %d seconds' % (i, time.time() - t)
t = time.time()
return solve_vecs
Alternating Least Squares(ASL) for Implicit Feedback Datasets的数学推导以及用Python实现的更多相关文章
- 【论文笔记】 Denoising Implicit Feedback for Recommendation
Denoising Implicit Feedback for Recommendation Authors: 王文杰,冯福利,何向南,聂礼强,蔡达成 WSDM'21 新加坡国立大学,中国科学技术大学 ...
- 【RS】Using graded implicit feedback for bayesian personalized ranking - 使用分级隐式反馈来进行贝叶斯个性化排序
[论文标题]Using graded implicit feedback for bayesian personalized ranking (RecSys '14 recsys.ACM ) [论文 ...
- 【RS】BPR:Bayesian Personalized Ranking from Implicit Feedback - BPR:利用隐反馈的贝叶斯个性化排序
[论文标题]BPR:Bayesian Personalized Ranking from Implicit Feedback (2012,Published by ACM Press) [论文作者]S ...
- spark MLlib 概念 6:ALS(Alternating Least Squares) or (ALS-WR)
Large-scale Parallel Collaborative Filtering for the Netflix Prize http://www.hpl.hp.com/personal/Ro ...
- 【论文笔记】Leveraging Post-click Feedback for Content Recommendations
Leveraging Post-click Feedback for Content Recommendations Authors: Hongyi Wen, Longqi Yang, Deborah ...
- 阿基米德项目ALS矩阵分解算法应用案例
转自:https://github.com/ceys/jdml/wiki/ALS 阿基米德项目ALS矩阵分解算法应用案例 编写人:ceys/youyis 最后更新时间:2014.5.12 一.算法描述 ...
- MLlib-协同过滤
协同过滤 显示vs隐式反馈 参数调整 实例 教程 协同过滤 协同过滤是推荐系统的常用方法.可以填充user-item相关矩阵中的缺失值.MLlib支持基于模型的协同过滤,即使用能够预测缺失值的一个隐藏 ...
- 共轭梯度法求解协同过滤中的 ALS
协同过滤是一类基于用户行为数据的推荐方法,主要是利用已有用户群体过去的行为或意见来预测当前用户的偏好,进而为其产生推荐.能用于协同过滤的算法很多,大致可分为:基于最近邻推荐和基于模型的推荐.其中基于最 ...
- 推荐系统-协同过滤在Spark中的实现
作者:vivo 互联网服务器团队-Tang Shutao 现如今推荐无处不在,例如抖音.淘宝.京东App均能见到推荐系统的身影,其背后涉及许多的技术.本文以经典的协同过滤为切入点,重点介绍了被工业界广 ...
随机推荐
- php多台服务器实现session共享
使用Redis存储Session(前提是服务期间已实现redis共享,可参照:laravel项目使用twemproxy部署redis集群) 修改php.ini: session.save_handle ...
- oracle 11g在大表中添加字段及默认值--加速
今天遇到这个问题了.简单的增加语句,默认SQLPLUS执行,却会超时. 要增加客户端的TIMEOUT时间才可以解决.(感觉超过两三分钟,默认超时30秒) 另外, 也可以用两步操作(1,增加字段,2,修 ...
- C#在 64位系统下出现 “未能加载文件或程序集”错误
64位系统下,Build的时候,如果选择Any CPU,默认会按照64位进行编译,便无法加载某些旧的dll,这些dll可能是特定到X86 CPU的. 所以,把编译选项中改为 X86CPU,就可以运行了 ...
- ThreadLocal深度解析
本文基于jdk1.8.0_66写成 0. ThreadLocal简介 ThreadLocal可以提供线程内的局部对象,合理的使用可以避免线程冲突的问题比方说SimpleDateFormat是线程不安全 ...
- HDU 2824.The Euler function-筛选法求欧拉函数
欧拉函数: φ(n)=n*(1-1/p1)(1-1/p2)....(1-1/pk),其中p1.p2…pk为n的所有素因子.比如:φ(12)=12*(1-1/2)(1-1/3)=4.可以用类似求素数的筛 ...
- 使用Xshell上传下载文件
很多时候我们需要在Windows跟Linux之间,或者Linux跟Linux之间传文件,这里我们讲的是使用Xshell实现文件上传下载. 一.使用rz,sz实现Windows,linux上传下载 1. ...
- hdu6191(树上启发式合并)
hdu6191 题意 给你一棵带点权的树,每次查询 \(u\) 和 \(x\) ,求以 \(u\) 为根结点的子树上的结点与 \(x\) 异或后最大的结果. 分析 看到子树,直接上树上启发式合并,看到 ...
- ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)
要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...
- 【枚举】Codeforces Round #394 (Div. 2) C. Dasha and Password
纪念死去的智商(虽然本来就没有吧……) 三重循环枚举将哪三个fix string作为数字.字母和符号位.记下最小的值就行了. 预处理之后这个做法应该是O(n^3)的,当然完全足够.不预处理是O(n^3 ...
- STL之vector4
描述 将一个n行m列矩阵元素输入存储后并输出. 部分代码已经给出,请补充完整,提交时请勿包含已经给出的代码. int main() { vector< vector<int> > ...