模型算法_推荐算法之隐语义模型
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 = 0 hit = 0 Ru_total = 0 Tu_total = 0 for 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_total precision = hit/Ru_total
return precision,recall
def Coverage(train,I): ''' :param train: 字典形式,训练集上给用户推荐的物品列表 :param I: 测试集上所有的物品个数 :return:返回覆盖率 ''' hit = 0 total = 0 R = set() #推荐系统能够推荐出来的物品集合 for user in train.keys(): Ru = set(train[user]) R = R|Ru
return len(R)/I
def Popularity(train,Popularity_Di): ''' :param train: 字典形式,训练集上给用户推荐的物品列表 :param Popularity_Di: 字典形式,物品流行度 :return:返回推荐列表的物品平均流行度 ''' R = set() #推荐系统能够推荐出来的物品集合 for user in train.keys(): Ru = set(train[user]) R = R|Ru
P = {key:Popularity_Di[key] for key in Popularity_Di if key in R} return sum(P.values())/len(R)
训练测试集划分
import randomfrom sklearn.model_selection import KFold
def 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)*ratio SelectSample = popular_items[:(N+len(PositiveSample))] NegativeSamlpe = [i for i in SelectSample if i not in PositiveSample][:N] #得到采样负样本 positive_di = dict.fromkeys(PositiveSample,1) #正样本标记为1 negative_di = dict.fromkeys(NegativeSamlpe,0) #负样本标记为0 positive_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.values M = R.shape[0] #用户数 N = R.shape[1] #物品数 #随机初始化特征矩阵P、Q P = 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,Qi for 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 = 0 for 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*:# break
R_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()/100Popularity_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 timeimport randomuser_train_list = random.sample(list(set(train['userId'])),300)# user_train_list = list(set(train['userId']))
K = 100alpha = 0.02lamda = 0.01LFM_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章 项目体系架构设计 1.1 项目系统架构 1.2 项目数据流程 1.3 数据模型 第2章 工具环境搭建 2.1 MongoDB(单节点)环境配置 2.2 Redis(单节点)环境配置 ...
- Python推荐系统学习笔记(1)基于协同过滤的个性化推荐算法实战---隐语义模型
一.相关概念: 1.隐语义模型(LFM) 通过矩阵分解建立用户和隐类之间的关系,物品和隐类之间的关系,最终得到用户对物品的偏好关系. 假设我们想要发现 F 个隐类, 我们的任务就是找到两个矩阵 U 和 ...
- 基于SVD++隐语义模型的信任网络推荐算法
点击上方蓝字关注我们 基于SVD++隐语义模型的信任网络推荐算法 陈佩武1, 束方兴2 1 平安科技(深圳)有限公司,广东 深圳 518031 2 北京大学互联网研究院(深圳),广东 深圳 51805 ...
- 基于隐语义模型的个性化推荐算法综述-笔记整理
1. 前期知识 均方根值(RMS)+ 均方根误差(RMSE)+标准差(Standard Deviation) 1.均方根值(RMS)也称作为效值,它的计算方法是先平方.再平均.然后开方. 2.均方根误 ...
- 电商推荐系统四: 基于隐语义模型的协同过滤推荐
四.离线推荐服务建设(基于隐语义模型的协同过滤推荐) 目录 四.离线推荐服务建设(基于隐语义模型的协同过滤推荐) 4.1 离线推荐服务 4.2 离线统计服务 4.3 基于隐语义模型的协同过滤推荐 4. ...
- 隐语义模型( LFM )
基于模型的协同过滤思想 ●基本思想 -用户具有一定的特征,决定着他的偏好选择; -物品具有一定的特征,影响着用户需是否选 ...
- 隐语义模型 VS 协同过滤
隐语义模型 从数据出发,进行个性化推荐 用户和数据之间有着隐含的联系 隐含因子让计算机能理解就好 将用户和物品通过中介隐含因子联系起来 分解-组合 F隐藏因子 隐语义模型求解 梯度下降方向 迭代求解 ...
- 推荐算法!基于隐语义模型的协同过滤推荐之用户商品推荐列表
项目采用ALS作为协同过滤算法,根据MongoDB中的用户评分表计算离线的用户商品推荐列表以及商品相似度矩阵. 通过ALS训练出来的Model来计算所有当前用户商品的推荐列表,主要思路如下: 1. u ...
- 隐语义模型(LFM)-----------电影推荐算法
隐语义模型(LFM) LFM 降维方法 -- 矩阵因子分解 LFM 的进一步理解 矩阵因子分解 模型的求解算法--ALS ALS算法具体过程如下: 算法实现代码如下: 用隐语义模型来进行协同过滤的目标 ...
最新文章
- C++_typedef名字
- mysql复制的配置
- flume的概述和运行机制
- 中国金融出版社出版的2016版《个人贷款》
- 强健程序员体魄————减脂原理
- Qt维基文档翻译:D-指针,D-Pointer
- 吴恩达|机器学习作业2.1正则化的Logistic回归
- Spring与策略模式
- snmptrap发送消息到服务器,我试图通过snmptrap发送snmp消息
- 八爪鱼批量爬取html中的数据,批量采集网页数据 - 八爪鱼采集器
- php 语句以句号结尾,短句末尾是否用句号
- 玩转电脑|电脑回收站还能这么玩,自定义图标让你的回收站与众不同
- apk一般放服务器哪个位置,apk放在服务器
- 盘点2022年爆火的小程序游戏
- 查看电脑开机关机记录
- 茶有真香 | 一款茶好不好喝自己说了才算
- phpcms下载页直接显示下载真实地址方法
- 英语六级高频词汇速记 + 2018-12-1听力 Day03
- 根据面阵相机拍摄的速度和传送带运动的速度将拍摄的实物图片的每一帧进行无缝拼接使其成为一张完整的图片的全部流程以及c++代码
- 【亲测可用】云里黑白第十三回——解决出现问题,你的PIN不可用,单击以重新设置PIN,诊断启动,禁用服务
热门文章
- dll 重新加密打包的问题
- 思科交换机MST配置命令步骤-实例讲解
- 分形图案c语言源程序,Mandlbrot集图形的一个C语言实现
- 使用java如何访问报表服务器_Java访问远程http服务器上数据的简便方法
- visio防火墙可以连接什么_画流程图,就是要用Visio软件!
- comment.html手机文件,comment.html
- 计算机科技作品大赛,世界编程大赛一等奖作品
- python 二维列表切片_Python中mutable与immutable和二维列表的初始化问题
- android+统计功能,React Native 轻松集成统计功能(Android 篇)
- java多线程生产者与消费者案例_多线程操作实例——生产者与消费者