矩阵分解(MF)-推荐系统+python代码

本文深入探讨了协同过滤中的矩阵分解方法,通过将大矩阵拆分为两个小矩阵,解决用户-项目评分矩阵的稀疏性和相关性问题。介绍了矩阵分解的推导过程,包括损失函数与正则项的构建,并使用梯度下降法更新参数。最后,给出了Python代码实例,展示了如何运用矩阵分解进行预测评分并优化误差。
摘要由CSDN通过智能技术生成

前言

推荐系统中最为主流与经典的技术之一是协同过滤技术(Collaborative Filtering),
它是基于这样的假设:用户如果在过去对某些项目产生过兴趣,那么将来他很可能依然对其保持热忱。
目前推荐系统中用的最多的就是矩阵分解(Matrix Factorization)方法。
矩阵分解就是预测出评分矩阵中的缺失值,然后根据预测值以某种方式向用户推荐。
矩阵分解可以解决一些近邻模型无法解决的问题,近邻模型存在的问题:
1、物品之间存在相关性,信息量并不是随着向量维度增加而线性增加
2、矩阵元素稀疏,计算结果不稳定,增减一个向量维度,导致紧邻结果差异很大的情况出现。
这里以用户-项目评分为例来详解矩阵分解。

一、矩阵分解

1.案例

用户-项目评分矩阵R(M×N)
打分矩阵R(n,m)是n行m列,n表示user个数,m表示item个数,‘-’表示用户没有打分
在这里插入图片描述

2.思路

矩阵分解就是把大矩阵分解成两个小矩阵,
即矩阵R可近似表示为矩阵P与矩阵Q的乘积:
R n × m ≈ P n × k × Q k × m = R ^ n × m R_{n×m}\approx P_{n×k} × Q_{k×m} = \hat R_{n×m} Rn×mPn×k×Qk×m=R^n×m
矩阵P(n,k)表示n个user和K个特征之间的关系矩阵,将矩阵Q(m,k)表示m个item和K个特征之间的关系矩阵,
接下来就是要求的矩阵P和Q,即可的预测矩阵R

3.推导步骤

  1. 首先:
    r ^ i j = ∑ k = 1 K p i k q k j \hat r_{ij}=\sum^K_{k=1}p_{ik}q_{kj} r^ij=k=1Kpikqkj
  2. 损失函数:
    e i j 2 = ( r i j − r ^ i j ) 2 = ( r i j − ∑ k = 1 k p i k q k j ) 2 e^2_{ij}=(r_{ij}-\hat r_{ij})^2=(r_{ij}-\sum^k_{k=1}p_{ik}q_{kj})^2 eij2=(rijr^ij)2=(rijk=1kpik
以下是使用Python实现矩阵分解推荐系统代码: ```python import numpy as np from sklearn.metrics import mean_squared_error from scipy.sparse.linalg import svds class MatrixFactorization: def __init__(self, R, K, learning_rate, reg_param, epochs, verbose=False): self.R = R self.num_users, self.num_items = R.shape self.K = K self.learning_rate = learning_rate self.reg_param = reg_param self.epochs = epochs self.verbose = verbose def fit(self): self.P = np.random.normal(scale=1./self.K, size=(self.num_users, self.K)) self.Q = np.random.normal(scale=1./self.K, size=(self.num_items, self.K)) self.b_u = np.zeros(self.num_users) self.b_i = np.zeros(self.num_items) self.b = np.mean(self.R[np.where(self.R != 0)]) self.samples = [ (i, j, self.R[i, j]) for i in range(self.num_users) for j in range(self.num_items) if self.R[i, j] > 0 ] training_process = [] for i in range(self.epochs): np.random.shuffle(self.samples) self.sgd() mse = self.mse() training_process.append((i, mse)) if self.verbose: if (i+1) % 10 == 0: print("Iteration: %d ; error = %.4f" % (i+1, mse)) return training_process def mse(self): xs, ys = self.R.nonzero() predicted = self.full_matrix() error = 0 for x, y in zip(xs, ys): error += pow(self.R[x, y] - predicted[x, y], 2) return np.sqrt(error) def sgd(self): for i, j, r in self.samples: prediction = self.get_rating(i, j) e = (r - prediction) self.b_u[i] += self.learning_rate * (e - self.reg_param * self.b_u[i]) self.b_i[j] += self.learning_rate * (e - self.reg_param * self.b_i[j]) self.P[i, :] += self.learning_rate * (e * self.Q[j, :] - self.reg_param * self.P[i,:]) self.Q[j, :] += self.learning_rate * (e * self.P[i, :] - self.reg_param * self.Q[j,:]) def get_rating(self, i, j): prediction = self.b + self.b_u[i] + self.b_i[j] + self.P[i, :].dot(self.Q[j, :].T) return prediction def full_matrix(self): return self.b + self.b_u[:,np.newaxis] + self.b_i[np.newaxis:,] + self.P.dot(self.Q.T) # 使用示例 R = np.array([ [5, 3, 0, 1], [4, 0, 0, 1], [1, 1, 0, 5], [1, 0, 0, 4], [0, 1, 5, 4], ]) mf = MatrixFactorization(R, K=2, learning_rate=0.01, reg_param=0.01, epochs=100, verbose=True) mf.fit() print(mf.full_matrix()) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值