隐语义模型(LFM)实现电影推荐

1.推荐系统

1.1 协同过滤算法

1) 算法简介

协同过滤算法是一种比较常用的推荐算法,它基于对用户历史行为数据进行挖掘发现用户的喜好偏向,并预测用户可能喜好的产品进行推荐。它主要包括两种:基于用户的协同过滤和基于物品的协同过滤。具体如下:

  • 基于用户的协同过滤(User-based CF):该算法通过用户的历史数据发现用户对商品或内容的喜欢,并对这些喜好进行度量和打分,然后根据不同用户对相同商品或内容的偏好程度计算用户之间的相似度,在有相似偏好的用户之间推荐他们喜欢的商品。所以这个算法主要是寻找偏好相似的用户,构建用户相似度矩阵。我们在一些购物网站上看到的“购买了该商品的用户也喜欢”则是基于该种算法。
  • 基于物品的协同过滤(Item-based CF):该算法通过计算不同用户对不同物品的评分获得物品之间的相关度,基于物品间的关系对用户进行相似物品推荐。在这个算法中,我们需要构建物品相关度矩阵。我们看到的“猜你喜欢”则是基于这种算法。

2)相似性计算

相似度的计算需要根据数据的不同选择合适的相似度计算方法。这里只介绍几个常用的计算方法:

  • 欧式距离: 
d(x,y)=\sqrt{(x_{1}-y_{1})^{2}+(x_{2}-y_{2})^{2}+\cdots+(x_{n}-y_{n})^{2} }

欧式距离越小,偏好则越近。为了使相似性与数值呈正相关,通常会对求得的欧氏距离取个倒数,使用户键的距离越接近,数值越大。

  • 皮尔森相关系数
\rho _{X,Y}=\frac{cov(X,Y)}{\sigma_{X}\sigma_{Y} }=\frac{E(XY)-E(X)E(Y)}{\sqrt{E(X^{2})-(E(X))^{2}}\sqrt{E(Y^{2})-(E(Y))^{2}}}

皮尔森系数比欧氏距离的计算要复杂一些,但对于评分数据不规范时皮尔森相关系数能够给出更好的结果。

  • 夹角余弦

以二维空间向量A(x_{1},y_{1})与向量B(x_{2},y_{2})为例,其余弦公式为:

cos\theta =\frac{x_{1}x_{2}+y_{1}y_{2}}{\sqrt{​{x_{1}}^{2}+{y_{1}}^{2}}\sqrt{​{x_{2}}^{2}+{y_{2}}^2}}
  • 杰卡德相关系数:该系数其实就是集合的交集除并集
J(A,B)=\frac{\left |A\cap B \right |}{\left |A\cup B \right | }

3)矩阵分解和隐语义模型

基于物品或基于用户的协同过滤算法是基于近邻模型的。但近邻模型通常面临以下两个问题:

  • 计算物品或用户之间的相关性时,其信息量并不随着物品或用户的增加而线性增加。
  • 近邻模型计算的用户相似性矩阵及物品相似性矩阵通常存在稀疏问题,计算结果不稳定。

矩阵分解可以解决一下近邻模型无法解决的问题。矩阵分解就是把原来很大的一个矩阵,分解成小矩阵的乘积。而在矩阵的时候不再使用原来的大矩阵,转而使用小矩阵。

SVD算法包含多种矩阵分解算法。该算法把用户和物品映射到一个K维空间中,但这个K维空间我们不能直接拿到,通常将这个K维空间称为隐因子。这个K在工程开始的时候是无法确定的,所以SVD又叫隐语义模型(LFM)。

举个例子,假设用户电影的评分矩阵A是m\times n维,即一共有m个用户,n部电影。通过SVD分解技术可以得到三个矩阵U_{m\times m},S_{m\times n}V_{n\times n}, 并且A_{m\times n}= U_{m\times m}S_{m\times n}V_{n\times n}。 其中S是个对角线矩阵,也是个特征值矩阵。如果对于S矩阵,我们只取前k个大的特征值,即可实现降维。具体地,将原来的S矩阵变成k\times k维。U变成m\times k维,V变成n\times k维,而最后得到的A仍然是m\times n维。但是由于降维后的矩阵基本不包含之前缺失比例比较高的向量,因此A矩阵中对应位置的数值就是该行用户对该物品评分的估量值。

2.实验过程

实验采用MovieLens-100K数据,该数据包含了用户对电影的评分信息,用户信息、电影信息和表现信息等。MovieLens-100K数据集包含943个用户对1652部电影的100000个评分。这组数据集可以直接从网上下载。

1)读取数据集并划分训练集和测试集

具体代码如下:

另外需要说明一点,由于推荐系统中存在冷启动问题,即很难为那些尚未观看过一定数量电影的用户提供个性化服务。但这个数据中的每个用户观看过的电影数都在5部以上,所以这里无须删除用户。具体验证代码如下:

2)基于隐语义构建评价矩阵

3)评价指标

这里使用Top-N accuracy metrics(Top-N推荐的准确性指标),用来评价给用户推荐的电影的准确性。其评估过程如下:

  • 对于每个用户
    • 对于测试集中该用户已经观看过的每一部电影:
      • 1) 取样该用户从未观看过的100部电影。假定用户没有看过某部电影等于用户与该电影没有关联关系,即感兴趣程度低;
      • 2) 推荐系统基于该用户从未观看过的100部电影+测试集中该用户已经观看过的电影,生成按照推荐度从高到低排名的物品列表。取Top-N作为推荐列表
      • 3) 计算推荐给用户的Top-N推荐的准确性。即如果测试集用户已经观看过的这1部电影出现在TOP-N推荐中,则计1. 最后统计出一个比例
      • 4) 对每个用的TOP-N推荐的准确性进行整合,形成一个总指标。

召回率(Recall)计算公式如下:

Recall=\frac{\sum_{u\in U}\left | R(u)\cap T(u) \right |}{\sum _{u\in U}\left | T(u) \right |}

其中,分母为测试集中实际交互过的物品数量。R(u)为针对每个用户在测试集中观看过的电影所形成的Top-N推荐。本次的TOP-N选择10。具体代码如下:

最后的召回率计算如下:

最后:

  • topN的计算方式会影响最后的召回率计算
  •  在对数据进行SVD分解之前还可以对先对Rating字段进行log平滑。具体代码如下:

### 隐语义 LFM 模型 Python 代码实现 隐语义模型(Latent Factor Model, LFM)通过引入潜在因子来表示用户和物品之间的关系,从而能够更好地捕捉数据中的隐藏模式。下面是一个基于矩阵分解方法的简单隐语义模型实现。 #### 数据准备 为了训练LFM模型,通常需要一个评分矩阵作为输入。这里假设有一个简单的用户-项目评分表: ```python import numpy as np from sklearn.metrics.pairwise import cosine_similarity ratings = { 'Alice': {'Item1': 5, 'Item2': 3}, 'Bob': {'Item1': 4, 'Item3': 2}, 'Charlie': {'Item2': 1, 'Item3': 5} } # 将字典转换成稀疏矩阵形式 users = list(ratings.keys()) items = set() for user in ratings.values(): items.update(user.keys()) n_users = len(users) n_items = len(items) item_indices = {item: i for i, item in enumerate(sorted(items))} user_indices = {user: i for i, user in enumerate(users)} rating_matrix = np.zeros((n_users, n_items)) for user, scores in ratings.items(): uid = user_indices[user] for item, score in scores.items(): rating_matrix[uid][item_indices[item]] = score ``` #### 训练LFM模型 接下来定义并训练LFM模型函数,该过程涉及初始化随机权重向量P和Q,并利用梯度下降法更新这些参数直到收敛为止。 ```python def lfm_train(R, K=2, steps=5000, alpha=0.0002, beta=0.02): """ 使用显式反馈的数据集训练LFM模型 参数: R -- 用户-项目的评分矩阵 (m x n), m代表用户的数量,n代表商品的数量. K -- 主成分个数(即隐含特征维度). steps -- 迭代次数. alpha -- 学习速率. beta -- 正则项系数. 返回值: P,Q -- 分解后的两个低秩矩阵(m×K 和 K×n),它们相乘可以近似原始R矩阵. """ N = len(R) # Number of users M = len(R[0]) # Number of movies/items P = np.random.rand(N,K) Q = np.random.rand(M,K) for step in range(steps): eij_sum_square_error = 0 for u in range(len(R)): for i in range(len(R[u])): if R[u][i]>0: eui=R[u][i]-np.dot(P[u,:],Q[i,:].T) for k in range(K): P[u][k]=P[u][k]+alpha*(eui*Q[i][k]-beta*P[u][k]) Q[i][k]=Q[i][k]+alpha*(eui*P[u][k]-beta*Q[i][k]) eij_sum_square_error += pow(eui, 2) if eij_sum_square_error<0.001: break return P, Q.T ``` 此部分实现了基本版的LFM算法,在实际应用中可能还需要考虑更多因素如偏置项、时间衰减效应等以提高预测精度[^3]。 #### 应用LFM进行推荐 一旦获得了P和Q这两个矩阵之后就可以用来做个性化推荐了: ```python P, Qt = lfm_train(rating_matrix) predicted_ratings = np.dot(P,Qt) print("Predicted Ratings:\n", predicted_ratings) ``` 上述代码展示了如何构建一个基础版本的隐语义模型以及怎样运用它来进行电影或其他产品的推荐服务。当然这只是一个非常简化例子,在真实场景下还需加入更多的优化措施和技术细节处理。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值