理论:其实就是追求参数的最大后验概率

数据集:movie_len的格式

import numpy as np
import pandas as pd
import scipy.sparse as sp
import torch.utils.data as data
import torch
import torch.nn as nn
import os
import time
dataset = 'ml-1m'
main_path = './Data/'
train_rating = main_path + '{}.train.rating'.format(dataset)
test_rating = main_path + '{}.test.rating'.format(dataset)
test_negative = main_path + '{}.test.negative'.format(dataset)
model_path = './models/'
BPR_model_path = model_path + 'BPR.pth'# 1、训练集
train_data = pd.read_csv(train_rating, sep='\t', header=None, names=['user', 'item'], usecols=[0, 1], dtype={0: np.int32, 1: np.int32})user_num = train_data['user'].max() + 1
item_num = train_data['item'].max() + 1
train_data = train_data.values.tolist()
# 2、训练样本转换为稀疏矩阵
train_mat = sp.dok_matrix((user_num, item_num), dtype=np.float32) # 其实就是以字典形式存储,对应位置的横纵坐标是index,value就是矩阵中的值
for x in train_data:train_mat[x[0], x[1]] = 1.0# 3、测试集数据读取,即为每个用户赋值99个没评分过的item。 1个评分过的+99个未评分的。
test_data = []
with open(test_negative, 'r') as fd:line = fd.readline()while line != None and line != '':arr = line.split('\t')u = eval(arr[0])[0]test_data.append([u, eval(arr[0])[1]])for i in arr[1:]:test_data.append([u, int(i)])line = fd.readline()# 根据继承pytorch的Dataset类定义BPR数据类
class BPRData(data.Dataset):def __init__(self, features,num_item, train_mat=None, num_ng=0, is_training=None):"""features=train_data,num_item=item_num,train_mat,稀疏矩阵,num_ng,训练阶段默认为4,即采样4-1个负样本对应一个评分过的数据。"""super(BPRData, self).__init__()""" Note that the labels are only useful when training, we thus add them in the ng_sample() function."""self.features = featuresself.num_item = num_itemself.train_mat = train_matself.num_ng = num_ngself.is_training = is_trainingdef ng_sample(self): # 平时写dataloader不会写采样,这里一次返回5个,就是一组,对应负采样的形式,这里不像tensorflow的现成的lossassert self.is_training, 'no need to sampling when testing'self.features_fill = []for x in self.features:u, i = x[0], x[1]for t in range(self.num_ng):j = np.random.randint(self.num_item)while (u, j) in self.train_mat:j = np.random.randint(self.num_item)self.features_fill.append([u, i, j])def __len__(self):return self.num_ng * len(self.features) if \self.is_training else len(self.features)def __getitem__(self, idx):features = self.features_fill if \self.is_training else self.featuresuser = features[idx][0]item_i = features[idx][1]item_j = features[idx][2] if \self.is_training else features[idx][1]return user, item_i, item_j# 定义BPR模型
class BPR(nn.Module):def __init__(self, user_num, item_num, factor_num):super(BPR, self).__init__()"""user_num: number of users;item_num: number of items;factor_num: number of predictive factors."""self.embed_user = nn.Embedding(user_num, factor_num)self.embed_item = nn.Embedding(item_num, factor_num)nn.init.normal_(self.embed_user.weight, std=0.01)nn.init.normal_(self.embed_item.weight, std=0.01)def forward(self, user, item_i, item_j):user = self.embed_user(user)item_i = self.embed_item(item_i)item_j = self.embed_item(item_j)prediction_i = (user * item_i).sum(dim=-1)prediction_j = (user * item_j).sum(dim=-1)return prediction_i, prediction_j
model = BPR(user_num, item_num, 16)
model.cuda()# 定义一些指标
import torch.optim as optim
lamb = 0.001
lr = 0.01
optimizer = optim.SGD(model.parameters(), lr=lr, weight_decay=lamb)def hit(gt_item, pred_items):if gt_item in pred_items:return 1return 0def ndcg(gt_item, pred_items):if gt_item in pred_items:index = pred_items.index(gt_item)return np.reciprocal(np.log2(index+2))return 0def metrics(model, test_loader, top_k):HR, NDCG = [], []for user, item_i, item_j in test_loader:user = user.cuda()item_i = item_i.cuda()item_j = item_j.cuda() # not useful when testingprediction_i, prediction_j = model(user, item_i, item_j)_, indices = torch.topk(prediction_i, top_k)recommends = torch.take(item_i, indices).cpu().numpy().tolist()gt_item = item_i[0].item()HR.append(hit(gt_item, recommends))NDCG.append(ndcg(gt_item, recommends))return np.mean(HR), np.mean(NDCG) # 6、训练过程,根据公式得到后验概率,然后求导,更新两个矩阵的值。
import os
epochs = 50
top_k = 10
best_hr = 0 # 记录命中率。
import time
for epoch in range(epochs):model.train() # 在使用pytorch构建神经网络的时候,训练过程中会在程序上方添加一句model.train(),作用是启用batch normalization和drop out。start_time = time.time()train_loader.dataset.ng_sample() # 训练阶段,这一步生成真正的训练样本for user,item_i,item_j in train_loader:user = user.cuda()item_i = item_i.cuda()item_j = item_j.cuda()model.zero_grad()prediction_i,prediction_j = model(user,item_i,item_j) # 调用forward()方法loss = -(prediction_i-prediction_j).sigmoid().log().sum() # 这里是最小化取了负号后对应的对数后验估计函数。可以使用梯度下降。其实这里本身是想让二者差距足够大,但是为了梯度下降,这里使用了负号loss.backward() # 在这里得到梯度optimizer.step() # 根据上面得到的梯度进行梯度回传。# 一个epoch训练结束,开始测试model.eval() # 测试过程中会使用model.eval(),这时神经网络会沿用batch normalization的值,并不使用drop out。HR, NDCG = metrics(model, test_loader, top_k)elapsed_time = time.time() - start_timeprint("The time elapse of epoch {:03d}".format(epoch) + " is: " +time.strftime("%H: %M: %S", time.gmtime(elapsed_time)))print("HR: {:.3f}\tNDCG: {:.3f}".format(np.mean(HR), np.mean(NDCG)))if HR > best_hr:best_hr,best_ndcg,best_epoch = HR,NDCG,epochif not os.path.exists(model_path):os.mkdir(model_path)torch.save(model,'{}BPR.pt'.format(model_path))
print("End. Best epoch {:03d}: HR = {:.3f}, NDCG = {:.3f}".format(best_epoch, best_hr, best_ndcg))

推荐系统经典-BPR算法相关推荐

  1. 推荐系统之 BPR 算法及 Librec的BPR算法实现【1】

    [推荐系统之 BPR 算法] 1.关于BPR的论文原文: BPR: Bayesian Personalized Ranking from Implicit Feedback 2.参考1:论文快读 - ...

  2. 推荐系统-经典协同过滤算法【基于记忆的协同过滤算法、基于模型的协同过滤算法】

    推荐系统-经典协同过滤理论基础实践 1.协同过滤推荐方法CF简介 协同过滤CF 基于记忆的协同过滤 ---- 用户和物品的相似度矩阵 用户相似度的推荐 物品相似度推荐 UserCF用户协同过滤算法 I ...

  3. 推荐系统遇上深度学习(二十一)--贝叶斯个性化排序(BPR)算法原理及实战

    笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值,找寻数据的秘密,笔者认为,数据的价值不仅仅只体现在企业中,个人也可以体会到数据的魅力,用技术力量探索行为密码,让大数据 ...

  4. 贝叶斯个性化排序(BPR)算法

    在推荐系统中的经典矩阵分解技术中,我们讨论过像funkSVD之类的矩阵分解方法如何用于推荐.今天我们讲另一种在实际产品中用的比较多的推荐算法:贝叶斯个性化排序(Bayesian Personalize ...

  5. 《转》推荐系统经典论文文献及业界应用

    转载自http://semocean.com 列了一些之前设计开发百度关键词搜索推荐引擎时, 参考过的论文, 书籍, 以及调研过的推荐系统相关的工具:同时给出参加过及未参加过的业界推荐引擎应用交流资料 ...

  6. slope one matlab代码,经典推荐算法之 Slope one

    title: 经典推荐算法之 Slope one date: 2017/5/16 15:29:24 tags: 推荐系统 Machine Learning categories: 推荐系统 Slope ...

  7. 再看经典推荐算法之召回算法

    在学习和应用推荐算法的过程中,发现越来越多的文章在描述深度学习应用在推荐系统上的方法,不可否认深度学习的发展给推荐系统带来了巨大的进步,但是传统的经典算法仍然是非常值得学习的,毕竟可以作为一个比较高的 ...

  8. 推荐系统经典论文文献及业界应用

    作者:百度关键词搜索推荐系统maker 列了一些之前设计开发百度关键词搜索推荐引擎时, 参考过的论文, 书籍, 以及调研过的推荐系统相关的工具:同时给出参加过及未参加过的业界推荐引擎应用交流资料(有我 ...

  9. 推荐系统的常用算法,选择,漫谈,推荐系统开源软件汇总

    推荐系统的常用算法概述 前一阵子准备毕业论文的开题,一直在看推荐系统相关的论文.对推荐系统有了一个更加清晰和理性的认识,也对推荐算法有了深入了解.借此机会总结分享一下,大家多多拍砖. 推荐系统的出现 ...

最新文章

  1. 区块链的爆炸式增长使其成为第二大热门需求技能
  2. 如何去掉Silverlight应用程序在浏览器中的滚动条
  3. 硬币游戏 (博弈入门)
  4. 计算机键盘为啥要这样分布,你知道电脑键盘为什么这么排列吗?
  5. 【Python基础】Python高级特性:切片、迭代、列表生成式、生成器与迭代器
  6. 2d fft matlab,证明2D-FFT能够拆分成两个1D-FFT
  7. [mount]linux 挂载时 mount: wrong fs type, bad option, bad superblock on /dev/sdb
  8. Android 系统(229)---Android与h5交互专题
  9. netdevice - 底层访问 Linux 网络设备
  10. JAVA分布式(一)——了解分布式
  11. java stream list转map
  12. 虚拟机win7系统安装vmtool
  13. 插图详解Python解决汉诺塔问题
  14. 查重有风险,小心论文被买卖!——iThenticate官方论文查重系统登录中国!
  15. 玩转Luat 进阶篇③——远程升级实现过程详解
  16. 半加器、全加器的FPGA实现
  17. 第一个小项目:学生成绩管理系统
  18. PotPlayer 和 VLC 播放器的书签
  19. 《Unity游戏优化》笔记(4)[21/02/05_周五][P29_46]
  20. xp如何开启远程服务器,XP系统打开远程桌面与修改3389端口的操作步骤

热门文章

  1. java 重定向下载_Java 获取网络302重定向URL的方法
  2. 架构师之修炼内功篇-系统性能优化 .
  3. 能通话的Apple Watch,为什么只有联通可以首发?
  4. 【视频转图片】用python-opencv实现视频连续逐帧截图自动生成图片方法
  5. MacBOOK AIR PRO MAC 安装第三方软件 允许未知来源
  6. 思维导图怎样绘制?适合小学生画思维导图的软件有哪些
  7. 文件怎么转换成pdf格式?只需这个一键转换神器
  8. Oracle列转行unpivot函数的使用
  9. 你不了解的贵阳:正在成为“大数据”之城
  10. 华为真的注册鸿蒙,熙伦国际:“鸿蒙”真的来了!华为注册了整本山海经?