1.LFM模型通过隐含特征联系用户与物品

2.LFM模型主要思想是对物品的兴趣进行分类,对于某个用户,首先得到他的兴趣     分类,再从分类中挑选他可能喜欢的物品

3.负采样样本数目要平衡且尽可能选择热门且用户没有行为的物品

4.LFM模型一般采用SGD求解

1.LFM模型介绍

隐语义模型(Latent Factor Model,LFM)属于机器学习算法,它通过隐含特征联系用户与物品。主要思想是:对物品的兴趣进行分类,对于某个用户,首先得到他的兴趣分类,再从分类中挑选他可能喜欢的物品。

隐语义模型将矩阵R分解为P和Q的乘积,即通过矩阵中的物品类别将用户User和物品Item联系起来。实际上需要根据用户当前的物品偏好信息R进行计算,得到相应的矩阵P和矩阵Q.

  • R矩阵表示用户对物品的偏好信息,Rij代表User i对Item j的兴趣度

  • P矩阵表示用户对各物品类别的一个偏好信息,Pij代表User i对Class j的兴趣度

  • Q矩阵表示各个物品归属到各个类别的信息,Qij代表Item j在类别Class i的权重或概率

从隐语义模型可以得到用户对物品兴趣度公式:

2.LFM模型样本

推荐系统的用户行为分为显性反馈数据集(评分数据)隐性反馈数据集。LFM在显性反馈数据上很好解决了评分预测问题(这里没有正负样本之分)。

而在隐性反馈数据集上,有正负样本之分。因为对于热门推荐而用户没有浏览或表达过偏好的商品,用户很大概率是看到的,但却没有行为,说明用户不喜欢这一类商品。人们发现,对于负采样应该遵循以下原则:

对每个用户,要保证正负样本的平衡(数目相似);

对每个用户采样负样本时,要选取那些很热门而用户没有行为的物品

3.LFM模型求解

一般采用最优化损失函数求解P和Q:

该函数意义:用户u对物品i的真实兴趣度与推算出来的兴趣度的误差平方和。如果使得模型最优,则误差平方和必然应该最小。

求解该损失函数一般使用梯度下降法,最常用的是随机梯度下降法(SGD)

对两组未知参数求导,

迭代计算,直至收敛

这里需要设置四个参数:

K:隐分类个数

alpha:梯度下降步长(学习速率)

lambda:损失惩罚函数的惩罚因子

ratio:正反馈样本和负反馈样本数的比例

4.LFM模型代码实现

LFM模型算法实现步骤:

1.基于【用户,项目,评分】划分训练集与测试集

2.以比例ratio对训练数据集进行负采样,有过评分的项目打标签为1,负样本(没有过评分)打标签为0

3.生成初始用户物品偏好矩阵R(user-item)

4.设定隐分类个数K,迭代次数,学习速率和惩罚因子

5.生成初始矩阵P,Q

6.利用梯度下降公式更新P和Q

7.输出PQ,即更新后的用户物品偏好矩阵

小编用的是电影数据集进行算法实现。

数据集介绍

1.ratings.dat UserID:用户id MovieId:电影id Rating:评分 Timestamp:时间戳

2.movies.dat 电影id 电影名字 电影类别

3.users.dat 用户id 用户性别 年龄 职业 压缩编码

定义评测指标

def Recall_Precison(train,test):''':param train: 字典形式,训练集上给用户推荐的物品列表:param test: 字典形式,测试集上用户的行为列表:return:返回精准率和召回率'''hit = 0hit = 0Ru_total = 0 Tu_total = 0for user in train.keys():Tu = set(test[user])Ru = set(train[user])hit = hit + len(Ru&Tu)Ru_total = Ru_total + len(Ru)Tu_total = Tu_total + len(Tu)recall = hit/Tu_totalprecision = hit/Ru_totalreturn precision,recalldef Coverage(train,I):''':param train: 字典形式,训练集上给用户推荐的物品列表:param I: 测试集上所有的物品个数:return:返回覆盖率'''hit = 0 total = 0R = set() #推荐系统能够推荐出来的物品集合for user in train.keys():Ru = set(train[user])R = R|Rureturn len(R)/Idef Popularity(train,Popularity_Di):''':param train: 字典形式,训练集上给用户推荐的物品列表:param Popularity_Di: 字典形式,物品流行度:return:返回推荐列表的物品平均流行度'''R = set() #推荐系统能够推荐出来的物品集合for user in train.keys():Ru = set(train[user])R = R|RuP = {key:Popularity_Di[key] for key in Popularity_Di if key in R}return sum(P.values())/len(R)

训练测试集划分

import random
from sklearn.model_selection import KFolddef splitdata(data):kf = KFold(n_splits=5,random_state=0,shuffle=True) #把数据集分成5等份train,test = pd.DataFrame(),pd.DataFrame()for user in set(data['userId']):items = data[data['userId'] == user].reset_index(drop=True)k_groups = []for index in kf.split(items): #因为是5等分,即5折交叉,一共循环5次#index[0]是每一折的训练集,index[1]是每一折的测试集k_groups.append(index)i = random.randint(0,4) #随机选取一份作为测试集训练集train = pd.concat([train,items.loc[k_groups[i][0],:]],axis=0)test = pd.concat([test,items.loc[k_groups[i][1],:]],axis=0)return train,test

负样本采样

def SampleSelect(data,Popularity,ratio):''':param User:用户电影评分数据集:param Popularity:字典形式,物品流行度:param ratio:负样本比例(负样本:正样本):return:字典形式,用户采样物品。用户id:{物品id:1,..,物品id:0},1代表正样本,0代表负样本'''Sample = dict()popular_items = [i[0] for i in sorted(Popularity.items(),key=lambda x:x[1],reverse=True)] #热门商品降序排列user_list = set(data['userId'])for user in user_list:PositiveSample = list(data[data['userId'] == user]['movieId'])N = len(PositiveSample)*ratioSelectSample = popular_items[:(N+len(PositiveSample))]NegativeSamlpe = [i for i in SelectSample if i not in PositiveSample][:N] #得到采样负样本positive_di = dict.fromkeys(PositiveSample,1) #正样本标记为1negative_di = dict.fromkeys(NegativeSamlpe,0) #负样本标记为0positive_di.update(negative_di)Sample.setdefault(user,positive_di) #把正负样本写进字典return Sample

编写核心算法(隐性反馈)

def LFM_algorithm(Sample,R,K,alpha,lamda,max_iter=1000):''':param Sample: 采样集合,字典形式:param R: 用户-物品评分矩阵:param k: 隐特征个数:param alpha: 学习速率:param lamda: 正则化参数:param max_iter: 最大迭代次数:return:用户特征矩阵P(用户与k隐类的关系),规模M*K;物品特征矩阵Q(k隐类与物品的关系),规模K*N'''item_list = [i[1] for i in R.columns]user_list = [i for i in R.index]R = R.valuesM = R.shape[0] #用户数N = R.shape[1] #物品数#随机初始化特征矩阵P、QP = np.random.rand(M,K)Q = np.random.rand(K,N)for n in range(max_iter):for u in range(M):for i in range(N):if Sample[user_list[u]].get(item_list[i],-1) != -1:#找到用户u的正负样本eui = R[u,i] - 1/(1+np.exp(-np.dot(P[u,:],Q[:,i])))#梯度下降更新Pu,Qifor k in range(K):P[u,k] = P[u,k] + alpha*(Q[k,i]*eui - lamda*P[u,k])Q[k,i] = Q[k,i] + alpha*(P[u,k]*eui - lamda*Q[k,i])alpha *= 0.9 #每次迭代降低学习率#计算损失函数值cost = 0for u in range(M):for i in range(N):if Sample[user_list[u]].get(item_list[i],-1) != -1:cost += (R[u,i] - 1/(1+np.exp(-np.dot(P[u,:],Q[:,i]))))**2
# for k in range(K): #计算正则项
# cost += lamda*(P[u,k]**2 + Q[k,i]**2)# if cost < 0.1*:
# breakR_new = pd.DataFrame(1/(1+np.exp(-np.dot(P,Q))),index=user_list,columns=item_list)return R_new,cost

编写推荐函数

def LFM_Recommand(user, R, N):''':param user: 用户id:param R: 训练好的用户物品评分矩阵:param N: 推荐物品长度:return:推荐列表,字典形式。物品id:评分'''
# NegativeSample = [i[0] for i in Sample[user].items() if i[1] == 0]ser = R.loc[user,:].sort_values(ascending=False)[:N]Recommend = dict(zip(ser.index, ser)) #物品id:兴趣度return list(Recommend.keys())

主函数

#加载并导入数据
path = r'F:\推荐系统\推荐系统开发实战\ml-1m'file_path = os.path.join(path,'ratings.dat')
rating_dt = pd.read_table(file_path,header=None,sep="::",names=['userId','movieId','rate','timesamp'],engine='python')file_path = os.path.join(path,'movies.dat')
movie_dt = pd.read_table(file_path,header=None,sep="::",names=['movieId','name','type'],engine='python')file_path = os.path.join(path,'users.dat')
user_dt = pd.read_table(file_path,header=None,sep="::",names=['userId','sex','age','job','code'],engine='python')D = rating_dt[['userId','movieId','rate']]
#物品流行度:有多少用户为某物品评分
ser = D['movieId'].value_counts()/100
Popularity_Di = dict(zip(ser.index,ser.values)) #物品流行度字典,物品id:流行度#训练测试集划分
train,test = splitdata(D)
user_train = {}
user_test = {}
for user in set(test['userId']):user_train[user] = list(train[train['userId'] == user]['movieId'])user_test[user] = list(test[test['userId'] == user]['movieId'])#计算原始user-item矩阵
R = pd.pivot_table(train,index=['userId'],columns=['movieId'],values=['rate'],aggfunc=np.alen,fill_value=0) #隐性评分
import time
import random
user_train_list = random.sample(list(set(train['userId'])),300)
# user_train_list = list(set(train['userId']))K = 100
alpha = 0.02
lamda = 0.01
LFM_li = []
for ratio in [1,2,3,5,10,20]:user_recommond = dict()Sample = SampleSelect(train,Popularity_Di,ratio)t = time.time()R_train = LFM_algorithm(Sample,R,K,alpha,lamda,max_iter=5)print('ratio {} cost time:{:.4}s,the cost function is:{:.5}'.format(ratio,(time.time() - t),R_train[1]))for user in user_train_list:user_recommond[user] = LFM_Recommand(user,R_train[0],20)r = Recall_Precison(user_recommond,user_test)cov = Coverage(user_recommond,len(set(test['movieId'])))p = Popularity(user_recommond,Popularity_Di)LFM_li.append([ratio,r[0],r[1],cov,p])LFM = pd.DataFrame(LFM_li,columns=['ratio','precision','recall','coverage','popularity'])
LFM

这里,由于本地电脑算力实在有限,小编只随机推荐了300个用户,耗时还是很长的,来看看结果:

随着负样本的增加,覆盖率会降低,而流行度会上升

推荐算法之隐语义模型相关推荐

  1. 推荐算法之隐语义模型(LFM)矩阵分解梯度下降算法实现

    推荐算法之隐语义模型(LFM)矩阵分解梯度下降算法实现 基于协同过滤的推荐一般分为基于近邻的推荐和基于模型的推荐,其中,基于近邻是指预测时直接使用用户已有的偏好数据,通过近邻数据来预测新物品的偏好.而 ...

  2. Python推荐系统学习笔记(1)基于协同过滤的个性化推荐算法实战---隐语义模型

    一.相关概念: 1.隐语义模型(LFM) 通过矩阵分解建立用户和隐类之间的关系,物品和隐类之间的关系,最终得到用户对物品的偏好关系. 假设我们想要发现 F 个隐类, 我们的任务就是找到两个矩阵 U 和 ...

  3. 模型算法_推荐算法之隐语义模型

    1.LFM模型通过隐含特征联系用户与物品 2.LFM模型主要思想是对物品的兴趣进行分类,对于某个用户,首先得到他的兴趣     分类,再从分类中挑选他可能喜欢的物品 3.负采样样本数目要平衡且尽可能选 ...

  4. 电商推荐系统(上):推荐系统架构、数据模型、离线统计与机器学习推荐、历史热门商品、最近热门商品、商品平均得分统计推荐、基于隐语义模型的协同过滤推荐、用户商品推荐列表、商品相似度矩阵、模型评估和参数选取

    文章目录 第1章 项目体系架构设计 1.1 项目系统架构 1.2 项目数据流程 1.3 数据模型 第2章 工具环境搭建 2.1 MongoDB(单节点)环境配置 2.2 Redis(单节点)环境配置 ...

  5. 推荐算法!基于隐语义模型的协同过滤推荐之用户商品推荐列表

    项目采用ALS作为协同过滤算法,根据MongoDB中的用户评分表计算离线的用户商品推荐列表以及商品相似度矩阵. 通过ALS训练出来的Model来计算所有当前用户商品的推荐列表,主要思路如下: 1. u ...

  6. 基于SVD++隐语义模型的信任网络推荐算法

    点击上方蓝字关注我们 基于SVD++隐语义模型的信任网络推荐算法 陈佩武1, 束方兴2 1 平安科技(深圳)有限公司,广东 深圳 518031 2 北京大学互联网研究院(深圳),广东 深圳 51805 ...

  7. 基于隐语义模型的个性化推荐算法综述-笔记整理

    1. 前期知识 均方根值(RMS)+ 均方根误差(RMSE)+标准差(Standard Deviation) 1.均方根值(RMS)也称作为效值,它的计算方法是先平方.再平均.然后开方. 2.均方根误 ...

  8. 电商推荐系统四: 基于隐语义模型的协同过滤推荐

    四.离线推荐服务建设(基于隐语义模型的协同过滤推荐) 目录 四.离线推荐服务建设(基于隐语义模型的协同过滤推荐) 4.1 离线推荐服务 4.2 离线统计服务 4.3 基于隐语义模型的协同过滤推荐 4. ...

  9. 隐语义模型(LFM)-----------电影推荐算法

    隐语义模型(LFM) LFM 降维方法 -- 矩阵因子分解 LFM 的进一步理解 矩阵因子分解 模型的求解算法--ALS ALS算法具体过程如下: 算法实现代码如下: 用隐语义模型来进行协同过滤的目标 ...

最新文章

  1. python复合数据类型_python—组合数据类型
  2. Oracle PL/SQL之令人不解的提示(nls_date_format)
  3. 文件格式用Latex排版论文(1)如何将Visio画图文件转换成Latex支持的.eps文件
  4. 【Android工具】最新测试谷歌play耗电情况,各种品牌安装谷歌play方法,GooglePlay...
  5. 拷贝目录: 将D:\course拷贝到C盘根下.... 需要使用到: FileInputStream FileOutputStream
  6. Redux简介以及Redux应用程序中的状态更新方式
  7. 3 Sum Closest
  8. C++中成员初始化列表的使用
  9. 【python基础知识】python输出时出错,UnicodeEncodeError: 'gbk' codec can't encode character '\ue4bf.....
  10. list vue 添加数据方法_一篇文章教会你创建vue项目和使用vue.js实现数据增删改查...
  11. STM32DMA搬运ADC只搬了一半数据的原因。
  12. Nginx二级目录反向代理网站
  13. 基于SSM的驾校网站
  14. USB免驱NFC读写器 Android系统中NFC读写范例
  15. python 去除文本空行
  16. 用户行为序列推荐模型
  17. 魔兽十区服务器人最多,十区毁灭计划 新一轮wow大服务器实装公告
  18. 手机上好用的记事本工具
  19. Mac装机必备软件2020最全下载集合
  20. C语言编程:求水仙花数。输入一个正整数n,计算n位水仙花数。

热门文章

  1. 为什么 Go 的负载因子是 6.5?
  2. 加速mq消费的方式一
  3. JavaScript基础 - 字符串倒序输出
  4. Java开发LBS地图新婚红包系统
  5. SPI + DMA
  6. java rpc框架 hsf_分布式服务框架HSF学习
  7. IDEA 常用格式化快捷键记录
  8. 老夫花了 3 天时间整理了一份史上最强 Java 学习路线图,送给有缘人!
  9. 使用 neovim 的浮动窗口让你再次爱上 fzf
  10. StringUtils里面的 isEmpty方法和isBlank方法的区别