GMF模型

1.从深度学习的视角可以理解为矩阵分解模型,其中矩阵分解层的用户隐向量和物品隐向量可以看做是一种Embedding方法,然后将Embedding后的向量进行点积 最后通过一个线性层输出
2.模型结构如下

所以输入的模型中的数据有num_users(user的数量),num_items(item的数量),embed_dim(Embedding的维度)

模型需要输入的数据inputs里面应该为[userId,itemID]
该模型的特点:

  1. 点积:让用户和物品向量进行交互为了进一步让向量在个维度上进行充分的交叉。
    代码如下:
import datetime
import numpy as np
import pandas as pd
from collections import Counter
import heapqimport torch
from torch.utils.data import DataLoader, Dataset, TensorDatasetimport torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import warnings
warnings.filterwarnings('ignore')
from torchsummary import summary
# 一些超参数设置
topK = 10
num_factors = 8
num_negatives = 4
batch_size = 64
lr = 0.001
# 数据在processed Data里面
train = np.load('ProcessedData/train.npy', allow_pickle=True).tolist()
testRatings = np.load('ProcessedData/testRatings.npy').tolist()
testNegatives = np.load('ProcessedData/testNegatives.npy').tolist()
num_users, num_items = train.shape
# 制作数据   用户打过分的为正样本, 用户没打分的为负样本, 负样本这里采用的采样的方式
def get_train_instances(train, num_negatives):user_input, item_input, labels = [], [], []num_items = train.shape[1]for (u, i) in train.keys():  # train.keys()是打分的用户和商品# positive instanceuser_input.append(u)item_input.append(i)labels.append(1)# negative instancefor t in range(num_negatives):j = np.random.randint(num_items)while (u, j) in train:j = np.random.randint(num_items)#print(u, j)user_input.append(u)item_input.append(j)labels.append(0)return user_input, item_input, labels
user_input, item_input, labels = get_train_instances(train, num_negatives)
train_x = np.vstack([user_input, item_input]).T
labels = np.array(labels)
# 构建成Dataset和DataLoader
train_dataset = TensorDataset(torch.tensor(train_x), torch.tensor(labels).float())
dl_train = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
class GMF(nn.Module):def __init__(self,num_users,num_items,embed_dim,reg=[0,0]):super(GMF,self).__init__()self.MF_Embedding_User=nn.Embedding(num_embeddings=num_users,embedding_dim=embed_dim)self.MF_Embedding_Item=nn.Embedding(num_embeddings=num_items,embedding_dim=embed_dim)self.linear=nn.Linear(embed_dim,1)self.sigmoid=nn.Sigmoid()def forward(self,input):input=input.long()MF_Embedding_User=self.MF_Embedding_User(input[:, 0])MF_Embedding_Item=self.MF_Embedding_Item(input[:, 1])predict=torch.mul(MF_Embedding_User,MF_Embedding_Item)linear=self.linear(predict)output=self.sigmoid(linear)output=output.squeeze(-1)return output
# Global variables that are shared across processes
_model = None
_testRatings = None
_testNegatives = None
_K = None# HitRation
def getHitRatio(ranklist, gtItem):for item in ranklist:if item == gtItem:return 1return 0# NDCG
def getNDCG(ranklist, gtItem):for i in range(len(ranklist)):item = ranklist[i]if item == gtItem:return np.log(2) / np.log(i+2)return 0def eval_one_rating(idx):   # 一次评分预测rating = _testRatings[idx]items = _testNegatives[idx]u = rating[0]gtItem = rating[1]items.append(gtItem)# Get prediction scoresmap_item_score = {}users = np.full(len(items), u, dtype='int32')test_data = torch.tensor(np.vstack([users, np.array(items)]).T)predictions = _model(test_data)for i in range(len(items)):item = items[i]map_item_score[item] = predictions[i].data.numpy()items.pop()# Evaluate top rank listranklist = heapq.nlargest(_K, map_item_score, key=lambda k: map_item_score[k])  # heapq是堆排序算法, 取前K个hr = getHitRatio(ranklist, gtItem)ndcg = getNDCG(ranklist, gtItem)return hr, ndcgdef evaluate_model(model, testRatings, testNegatives, K):"""Evaluate the performance (Hit_Ratio, NDCG) of top-K recommendationReturn: score of each test rating."""global _modelglobal _testRatingsglobal _testNegativesglobal _K_model = model_testNegatives = testNegatives_testRatings = testRatings_K = Khits, ndcgs = [], []for idx in range(len(_testRatings)):(hr, ndcg) = eval_one_rating(idx)hits.append(hr)ndcgs.append(ndcg)return hits, ndcgs
# 训练参数设置
loss_func = nn.BCELoss()
optimizer = torch.optim.Adam(params=net.parameters(), lr=lr)
# 计算出初始的评估
(hits, ndcgs) = evaluate_model(net, testRatings, testNegatives, topK)
hr, ndcg = np.array(hits).mean(), np.array(ndcgs).mean()
print('Init: HR=%.4f, NDCG=%.4f' %(hr, ndcg))
# 模型训练
best_hr, best_ndcg, best_iter = hr, ndcg, -1epochs = 20
log_step_freq = 10000
print('开始训练')
for epoch in range(epochs):# 训练阶段net.train()loss_sum = 0.0for step, (features, labels) in enumerate(dl_train, 1):features, labels = features, labels# 梯度清零optimizer.zero_grad()# 正向传播predictions = net(features)loss = loss_func(predictions, labels)# 反向传播求梯度loss.backward()optimizer.step()# 打印batch级别日志loss_sum += loss.item()loss_list=[]if step % log_step_freq == 0:loss_list.append(loss_sum/step)print(("[step = %d] loss: %.3f") %(step, loss_sum/step))# 验证阶段net.eval()(hits, ndcgs) = evaluate_model(net, testRatings, testNegatives, topK)hr, ndcg = np.array(hits).mean(), np.array(ndcgs).mean()if hr > best_hr:best_hr, best_ndcg, best_iter = hr, ndcg, epochtorch.save(net.state_dict(), 'Pre_train/m1-1m_GMF.pkl')  loss_list=[]loss_list.append(loss_sum/step)hr_list=[]hr_list.append(hr)NDCG_list=[]NDCG_list.append(ndcg)info = (epoch, loss_sum/step, hr, ndcg)print(("\nEPOCH = %d, loss = %.3f, hr = %.3f, ndcg = %.3f") %info)
print('Finished Training...')

NCF模型

打字字母啥的太费劲了 直接看手写笔记吧

import datetime
import numpy as np
import pandas as pd
from collections import Counter
import heapqimport torch
from torch.utils.data import DataLoader, Dataset, TensorDatasetimport torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import warnings
warnings.filterwarnings('ignore')
from torchsummary import summary
# 一些超参数设置
topK = 10
num_factors = 8
num_negatives = 4
batch_size = 64
lr = 0.001
# 数据在processed Data里面
train = np.load('ProcessedData/train.npy', allow_pickle=True).tolist()
testRatings = np.load('ProcessedData/testRatings.npy').tolist()
testNegatives = np.load('ProcessedData/testNegatives.npy').tolist()
num_users, num_items = train.shape
# 制作数据   用户打过分的为正样本, 用户没打分的为负样本, 负样本这里采用的采样的方式
def get_train_instances(train, num_negatives):user_input, item_input, labels = [], [], []num_items = train.shape[1]for (u, i) in train.keys():  # train.keys()是打分的用户和商品# positive instanceuser_input.append(u)item_input.append(i)labels.append(1)# negative instancefor t in range(num_negatives):j = np.random.randint(num_items)while (u, j) in train:j = np.random.randint(num_items)#print(u, j)user_input.append(u)item_input.append(j)labels.append(0)return user_input, item_input, labels
user_input, item_input, labels = get_train_instances(train, num_negatives)
train_x = np.vstack([user_input, item_input]).T
labels = np.array(labels)
# 构建成Dataset和DataLoader
train_dataset = TensorDataset(torch.tensor(train_x), torch.tensor(labels).float())
dl_train = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)class MLP(nn.Module):def __init__(self, num_users, num_items, layers=[20, 64, 32, 16], regs=[0, 0]):super(MLP, self).__init__()self.MF_Embedding_User = nn.Embedding(num_embeddings=num_users, embedding_dim=layers[0]//2)self.MF_Embedding_Item = nn.Embedding(num_embeddings=num_items, embedding_dim=layers[0]//2)# 全连接网络self.dnn_network = nn.ModuleList([nn.Linear(layer[0], layer[1]) for layer in list(zip(layers[:-1], layers[1:]))])self.linear = nn.Linear(layers[-1], 1)self.sigmoid = nn.Sigmoid()def forward(self, inputs):# 这个inputs是一个批次的数据, 所以后面的操作切记写成inputs[0], [1]这种, 这是针对某个样本了, 我们都是对列进行的操作# 先把输入转成long类型inputs = inputs.long()# MF的前向传播  用户和物品的embeddingMF_Embedding_User = self.MF_Embedding_User(inputs[:, 0])  # 这里踩了个坑, 千万不要写成[0], 我们这里是第一列MF_Embedding_Item = self.MF_Embedding_Item(inputs[:, 1])# 两个隐向量堆叠起来x = torch.cat([MF_Embedding_User, MF_Embedding_Item], dim=-1)# l全连接网络for linear in self.dnn_network:x = linear(x)x = F.relu(x)x = self.linear(x)output = self.sigmoid(x)output=output.squeeze(-1)return output
# 看一下这个网络
model = MLP(1, 1, [20, 64, 32, 16, 8])    # 全连接网络可以随意扩展
summary(model, input_size=(2,))
## 设置
layers = [num_factors*2, 64, 32, 16, 8]
model = MLP(num_users, num_items, layers)
# Global variables that are shared across processes
_model = None
_testRatings = None
_testNegatives = None
_K = None# HitRation
def getHitRatio(ranklist, gtItem):for item in ranklist:if item == gtItem:return 1return 0# NDCG
def getNDCG(ranklist, gtItem):for i in range(len(ranklist)):item = ranklist[i]if item == gtItem:return np.log(2) / np.log(i+2)return 0def eval_one_rating(idx):   # 一次评分预测rating = _testRatings[idx]items = _testNegatives[idx]u = rating[0]gtItem = rating[1]items.append(gtItem)# Get prediction scoresmap_item_score = {}users = np.full(len(items), u, dtype='int32')test_data = torch.tensor(np.vstack([users, np.array(items)]).T)predictions = _model(test_data)for i in range(len(items)):item = items[i]map_item_score[item] = predictions[i].data.numpy()items.pop()# Evaluate top rank listranklist = heapq.nlargest(_K, map_item_score, key=lambda k: map_item_score[k])  # heapq是堆排序算法, 取前K个hr = getHitRatio(ranklist, gtItem)ndcg = getNDCG(ranklist, gtItem)return hr, ndcgdef evaluate_model(model, testRatings, testNegatives, K):"""Evaluate the performance (Hit_Ratio, NDCG) of top-K recommendationReturn: score of each test rating."""global _modelglobal _testRatingsglobal _testNegativesglobal _K_model = model_testNegatives = testNegatives_testRatings = testRatings_K = Khits, ndcgs = [], []for idx in range(len(_testRatings)):(hr, ndcg) = eval_one_rating(idx)hits.append(hr)ndcgs.append(ndcg)return hits, ndcgs
# 训练参数设置
loss_func = nn.BCELoss()
optimizer = torch.optim.Adam(params=model.parameters(), lr=lr)# 计算出初始的评估
(hits, ndcgs) = evaluate_model(model, testRatings, testNegatives, topK)
# 模型训练
best_hr, best_ndcg, best_iter = hr, ndcg, -1epochs = 20
log_step_freq = 10000for epoch in range(epochs):# 训练阶段model.train()loss_sum = 0.0for step, (features, labels) in enumerate(dl_train, 1):features, labels = features, labels# 梯度清零optimizer.zero_grad()# 正向传播predictions = model(features)loss = loss_func(predictions, labels)# 反向传播求梯度loss.backward()optimizer.step()# 打印batch级别日志loss_sum += loss.item()if step % log_step_freq == 0:print(("[step = %d] loss: %.3f") % (step, loss_sum/step))# 验证阶段model.eval()(hits, ndcgs) = evaluate_model(model, testRatings, testNegatives, topK)hr, ndcg = np.array(hits).mean(), np.array(ndcgs).mean()if hr > best_hr:best_hr, best_ndcg, best_iter = hr, ndcg, epochtorch.save(model.state_dict(), 'Pre_train/m1-1m_MLP.pkl')  info = (epoch, loss_sum/step, hr, ndcg)print(("\nEPOCH = %d, loss = %.3f, hr = %.3f, ndcg = %.3f") %info)
print('Finished Training...') 训练结果
start  training....
[step = 10000] loss: 0.290
[step = 20000] loss: 0.290
[step = 30000] loss: 0.290
[step = 40000] loss: 0.291
[step = 50000] loss: 0.291
[step = 60000] loss: 0.291
[step = 70000] loss: 0.291EPOCH = 0, loss = 0.291, hr = 0.575, ndcg = 0.324
[0.5751655629139073]
[0.3239830483525621]
[0.29118310283853677]
[step = 10000] loss: 0.289
[step = 20000] loss: 0.289
[step = 30000] loss: 0.289
[step = 40000] loss: 0.290
[step = 50000] loss: 0.290
[step = 60000] loss: 0.290
[step = 70000] loss: 0.290EPOCH = 1, loss = 0.291, hr = 0.577, ndcg = 0.322
[0.5771523178807947]
[0.3217358813225827]
[0.29051399411566703]
[step = 10000] loss: 0.288
[step = 20000] loss: 0.288
[step = 30000] loss: 0.289
[step = 40000] loss: 0.289
[step = 50000] loss: 0.289
[step = 60000] loss: 0.289
[step = 70000] loss: 0.290EPOCH = 2, loss = 0.290, hr = 0.571, ndcg = 0.322[step = 10000] loss: 0.288
[step = 20000] loss: 0.288
[step = 30000] loss: 0.289
[step = 40000] loss: 0.289
[step = 50000] loss: 0.289
[step = 60000] loss: 0.289
[step = 70000] loss: 0.289EPOCH = 3, loss = 0.289, hr = 0.573, ndcg = 0.321[step = 10000] loss: 0.287
[step = 20000] loss: 0.288
[step = 30000] loss: 0.288
[step = 40000] loss: 0.288
[step = 50000] loss: 0.289
[step = 60000] loss: 0.289
[step = 70000] loss: 0.289EPOCH = 4, loss = 0.289, hr = 0.575, ndcg = 0.324[step = 10000] loss: 0.287
[step = 20000] loss: 0.287
[step = 30000] loss: 0.288
[step = 40000] loss: 0.288
[step = 50000] loss: 0.288
[step = 60000] loss: 0.288
[step = 70000] loss: 0.288EPOCH = 5, loss = 0.288, hr = 0.577, ndcg = 0.324[step = 10000] loss: 0.287
[step = 20000] loss: 0.287
[step = 30000] loss: 0.288
[step = 40000] loss: 0.288
[step = 50000] loss: 0.288
[step = 60000] loss: 0.288
[step = 70000] loss: 0.288EPOCH = 6, loss = 0.288, hr = 0.575, ndcg = 0.325[step = 10000] loss: 0.285
[step = 20000] loss: 0.286
[step = 30000] loss: 0.286
[step = 40000] loss: 0.287
[step = 50000] loss: 0.287
[step = 60000] loss: 0.287
[step = 70000] loss: 0.287EPOCH = 7, loss = 0.288, hr = 0.578, ndcg = 0.326
[0.578476821192053]
[0.3256224358082742]
[0.2875433361290872]
[step = 10000] loss: 0.286
[step = 20000] loss: 0.286
[step = 30000] loss: 0.286
[step = 40000] loss: 0.287
[step = 50000] loss: 0.287
[step = 60000] loss: 0.287
[step = 70000] loss: 0.287EPOCH = 8, loss = 0.287, hr = 0.577, ndcg = 0.324[step = 10000] loss: 0.285
[step = 20000] loss: 0.285
[step = 30000] loss: 0.286
[step = 40000] loss: 0.286
[step = 50000] loss: 0.286
[step = 60000] loss: 0.287
[step = 70000] loss: 0.287EPOCH = 9, loss = 0.287, hr = 0.575, ndcg = 0.325
[]
[]
[]
[step = 10000] loss: 0.285
[step = 20000] loss: 0.286
[step = 30000] loss: 0.286
[step = 40000] loss: 0.286
[step = 50000] loss: 0.286
[step = 60000] loss: 0.286
[step = 70000] loss: 0.286EPOCH = 10, loss = 0.286, hr = 0.577, ndcg = 0.326
[]
[]
[]
[step = 10000] loss: 0.284
[step = 20000] loss: 0.285
[step = 30000] loss: 0.285
[step = 40000] loss: 0.285
[step = 50000] loss: 0.286
[step = 60000] loss: 0.286
[step = 70000] loss: 0.286EPOCH = 11, loss = 0.286, hr = 0.577, ndcg = 0.323
[]
[]
[]
[step = 10000] loss: 0.284
[step = 20000] loss: 0.284
[step = 30000] loss: 0.284
[step = 40000] loss: 0.284
[step = 50000] loss: 0.285
[step = 60000] loss: 0.285
[step = 70000] loss: 0.286EPOCH = 12, loss = 0.286, hr = 0.584, ndcg = 0.331
[0.5839403973509933]
[0.3306596866817331]
[0.2857730609305933]
[step = 10000] loss: 0.284
[step = 20000] loss: 0.284
[step = 30000] loss: 0.284
[step = 40000] loss: 0.285
[step = 50000] loss: 0.285
[step = 60000] loss: 0.285
[step = 70000] loss: 0.285EPOCH = 13, loss = 0.286, hr = 0.579, ndcg = 0.325
[]
[]
[]
[step = 10000] loss: 0.284
[step = 20000] loss: 0.284
[step = 30000] loss: 0.284
[step = 40000] loss: 0.284
[step = 50000] loss: 0.285
[step = 60000] loss: 0.285
[step = 70000] loss: 0.285EPOCH = 14, loss = 0.285, hr = 0.585, ndcg = 0.329
[0.5846026490066225]
[0.32850985491245704]
[0.28524806334910374]
[step = 10000] loss: 0.283
[step = 20000] loss: 0.283
[step = 30000] loss: 0.283
[step = 40000] loss: 0.284
[step = 50000] loss: 0.284
[step = 60000] loss: 0.285
[step = 70000] loss: 0.285EPOCH = 15, loss = 0.285, hr = 0.576, ndcg = 0.323
[]
[]
[]
[step = 10000] loss: 0.284
[step = 20000] loss: 0.284
[step = 30000] loss: 0.284
[step = 40000] loss: 0.284
[step = 50000] loss: 0.284
[step = 60000] loss: 0.285
[step = 70000] loss: 0.285EPOCH = 16, loss = 0.285, hr = 0.581, ndcg = 0.327
[]
[]
[]
[step = 10000] loss: 0.283
[step = 20000] loss: 0.283
[step = 30000] loss: 0.283
[step = 40000] loss: 0.284
[step = 50000] loss: 0.284
[step = 60000] loss: 0.284
[step = 70000] loss: 0.284EPOCH = 17, loss = 0.285, hr = 0.584, ndcg = 0.328
[]
[]
[]
[step = 10000] loss: 0.284
[step = 20000] loss: 0.284
[step = 30000] loss: 0.284
[step = 40000] loss: 0.284
[step = 50000] loss: 0.284
[step = 60000] loss: 0.284
[step = 70000] loss: 0.284EPOCH = 18, loss = 0.285, hr = 0.580, ndcg = 0.324
[]
[]
[]
[step = 10000] loss: 0.283
[step = 20000] loss: 0.283
[step = 30000] loss: 0.284
[step = 40000] loss: 0.284
[step = 50000] loss: 0.284
[step = 60000] loss: 0.284
[step = 70000] loss: 0.284EPOCH = 19, loss = 0.284, hr = 0.582, ndcg = 0.327Finished Training...

GMF+MLP模型

这个模型非常好理解了
个人的理解的区别为

  1. .Embedding层:把输入的User 和Item 进行MF向量的Embedding 和MLP的Embedding
  2. 然后将MF的Embedding向量进行点积操作 ,将MLP的EMbedding进行合并然后将合并的向量送入多层神经网络中。
  3. 最后将点积的MF向量 和多层神经网络输出的向量进行合并 最后将合并之后的向量输入到线性层中进行预测

代码如下:

import datetime
import numpy as np
import pandas as pd
from collections import Counter
import heapqimport torch
from torch.utils.data import DataLoader, Dataset, TensorDatasetimport torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import warnings
warnings.filterwarnings('ignore')
from torchsummary import summary# 一些超参数设置
topK = 10
num_factors = 8
num_negatives = 4
batch_size = 64
lr = 0.001# 数据在processed Data里面
train = np.load('ProcessedData/train.npy', allow_pickle=True).tolist()
testRatings = np.load('ProcessedData/testRatings.npy').tolist()
testNegatives = np.load('ProcessedData/testNegatives.npy').tolist()
# 制作数据   用户打过分的为正样本, 用户没打分的为负样本, 负样本这里采用的采样的方式
def get_train_instances(train, num_negatives):user_input, item_input, labels = [], [], []num_items = train.shape[1]for (u, i) in train.keys():  # train.keys()是打分的用户和商品# positive instanceuser_input.append(u)item_input.append(i)labels.append(1)# negative instancefor t in range(num_negatives):j = np.random.randint(num_items)while (u, j) in train:j = np.random.randint(num_items)#print(u, j)user_input.append(u)item_input.append(j)labels.append(0)return user_input, item_input, labelsuser_input, item_input, labels = get_train_instances(train, num_negatives)train_x = np.vstack([user_input, item_input]).T
labels = np.array(labels)
# 构建成Dataset和DataLoader
train_dataset = TensorDataset(torch.tensor(train_x), torch.tensor(labels).float())
dl_train = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
class NeuralMF(nn.Module):def __init__(self,num_users,num_items,mf_embed_dim,layers):super(NeuralMF,self).__init__()#Embedding 层self.MF_Embedding_User=nn.Embedding(num_embeddings=num_users,embedding_dim=mf_embed_dim)self.MF_Embedding_Item=nn.Embedding(num_embeddings=num_items,embedding_dim=mf_embed_dim)self.MLP_Embedding_User=nn.Embedding(num_embeddings=num_users,embedding_dim=layers[0]//2)self.MLP_Embedding_Item=nn.Embedding(num_embeddings=num_items,embedding_dim=layers[0]//2)#全连接层self.dnn_network = nn.ModuleList([nn.Linear(layer[0], layer[1]) for layer in list(zip(layers[:-1], layers[1:]))])self.linear = nn.Linear(layers[-1], mf_embed_dim)#线性层self.linear2=nn.Linear(2*mf_embed_dim,1)self.sigmod=nn.Sigmoid()def forward(self,inputs):inputs=inputs.long()MF_Embedding_User=self.MF_Embedding_User(inputs[:,0])MF_Embedding_Item=self.MF_Embedding_Item(inputs[:,1])MF_vec=torch.mul(MF_Embedding_User,MF_Embedding_Item)MLP_Embedding_User=self.MLP_Embedding_User(inputs[:,0])MLP_Embedding_Item=self.MLP_Embedding_Item(inputs[:,1])#将向量进行拼接后然后将其送入到全连接层x=torch.cat([MLP_Embedding_User,MLP_Embedding_Item],dim=-1)for linear in self.dnn_network:x=linear(x)x=F.relu(x)MLP_vec=self.linear(x)#将两个合并vector=torch.cat([MF_vec,MLP_vec],dim=-1)#预测层 线性层linear=self.linear2(vector)output=self.sigmod(linear)output=output.squeeze(-1)return output
num_users,num_items=train.shape
## 设置
layers = [num_factors*2, 64, 32, 16]
model = NeuralMF(num_users, num_items, num_factors, layers)
# Global variables that are shared across processes
_model = None
_testRatings = None
_testNegatives = None
_K = None# HitRation
def getHitRatio(ranklist, gtItem):for item in ranklist:if item == gtItem:return 1return 0# NDCG
def getNDCG(ranklist, gtItem):for i in range(len(ranklist)):item = ranklist[i]if item == gtItem:return np.log(2) / np.log(i+2)return 0def eval_one_rating(idx):   # 一次评分预测rating = _testRatings[idx]items = _testNegatives[idx]u = rating[0]gtItem = rating[1]items.append(gtItem)# Get prediction scoresmap_item_score = {}users = np.full(len(items), u, dtype='int32')test_data = torch.tensor(np.vstack([users, np.array(items)]).T)predictions = _model(test_data)for i in range(len(items)):item = items[i]map_item_score[item] = predictions[i].data.numpy()items.pop()# Evaluate top rank listranklist = heapq.nlargest(_K, map_item_score, key=lambda k: map_item_score[k])  # heapq是堆排序算法, 取前K个hr = getHitRatio(ranklist, gtItem)ndcg = getNDCG(ranklist, gtItem)return hr, ndcgdef evaluate_model(model, testRatings, testNegatives, K):"""Evaluate the performance (Hit_Ratio, NDCG) of top-K recommendationReturn: score of each test rating."""global _modelglobal _testRatingsglobal _testNegativesglobal _K_model = model_testNegatives = testNegatives_testRatings = testRatings_K = Khits, ndcgs = [], []for idx in range(len(_testRatings)):(hr, ndcg) = eval_one_rating(idx)hits.append(hr)ndcgs.append(ndcg)return hits, ndcgs
# 训练参数设置
loss_func = nn.BCELoss()
optimizer = torch.optim.Adam(params=model.parameters(), lr=lr)
# 计算出初始的评估
(hits, ndcgs) = evaluate_model(model, testRatings, testNegatives, topK)
hr, ndcg = np.array(hits).mean(), np.array(ndcgs).mean()
print('Init: HR=%.4f, NDCG=%.4f' %(hr, ndcg))
# 模型训练
best_hr, best_ndcg, best_iter = hr, ndcg, -1
print('start  training....')
epochs = 20
log_step_freq = 10000for epoch in range(epochs):# 训练阶段model.train()loss_sum = 0.0for step, (features, labels) in enumerate(dl_train, 1):features, labels = features, labels# 梯度清零optimizer.zero_grad()# 正向传播predictions = model(features)loss = loss_func(predictions, labels)# 反向传播求梯度loss.backward()optimizer.step()# 打印batch级别日志loss_sum += loss.item()if step % log_step_freq == 0:print(("[step = %d] loss: %.3f") % (step, loss_sum/step))# 验证阶段model.eval()hr_list=[]ndcg_list=[]loss_list=[](hits, ndcgs) = evaluate_model(model, testRatings, testNegatives, topK)hr, ndcg = np.array(hits).mean(), np.array(ndcgs).mean()if hr > best_hr:best_hr, best_ndcg, best_iter = hr, ndcg, epochhr_list.append(hr)ndcg_list.append(ndcg)loss_list.append(loss_sum/step)torch.save(model.state_dict(), 'Pre_train/m1-1m_MLP.pkl')  info = (epoch, loss_sum/step, hr, ndcg)print(("\nEPOCH = %d, loss = %.3f, hr = %.3f, ndcg = %.3f") %info)print(hr_list)print(ndcg_list)print(loss_list)
print('Finished Training...') 训练结果
start  training....
[step = 10000] loss: 0.371
[step = 20000] loss: 0.368
[step = 30000] loss: 0.366
[step = 40000] loss: 0.364
[step = 50000] loss: 0.364
[step = 60000] loss: 0.363
[step = 70000] loss: 0.362EPOCH = 0, loss = 0.362, hr = 0.446, ndcg = 0.247
[0.4461920529801324]
[0.24665692194874442]
[0.3615081424313008]
[step = 10000] loss: 0.356
[step = 20000] loss: 0.355
[step = 30000] loss: 0.355
[step = 40000] loss: 0.354
[step = 50000] loss: 0.354
[step = 60000] loss: 0.354
[step = 70000] loss: 0.354EPOCH = 1, loss = 0.354, hr = 0.450, ndcg = 0.251
[0.45049668874172183]
[0.25060382488628974]
[0.35396337600438554]
[step = 10000] loss: 0.350
[step = 20000] loss: 0.350
[step = 30000] loss: 0.351
[step = 40000] loss: 0.351
[step = 50000] loss: 0.350
[step = 60000] loss: 0.350
[step = 70000] loss: 0.349EPOCH = 2, loss = 0.348, hr = 0.472, ndcg = 0.258
[0.47218543046357614]
[0.2581062288833335]
[0.3481580679601909]
[step = 10000] loss: 0.335
[step = 20000] loss: 0.334
[step = 30000] loss: 0.333
[step = 40000] loss: 0.331
[step = 50000] loss: 0.330
[step = 60000] loss: 0.328
[step = 70000] loss: 0.326EPOCH = 3, loss = 0.325, hr = 0.502, ndcg = 0.278
[0.5024834437086093]
[0.27812582380637824]
[0.325182699872265]
[step = 10000] loss: 0.306
[step = 20000] loss: 0.305
[step = 30000] loss: 0.304
[step = 40000] loss: 0.303
[step = 50000] loss: 0.303
[step = 60000] loss: 0.302
[step = 70000] loss: 0.301EPOCH = 4, loss = 0.301, hr = 0.541, ndcg = 0.301
[0.5408940397350993]
[0.301453770482002]
[0.30071208906625324]
[step = 10000] loss: 0.288
[step = 20000] loss: 0.288
[step = 30000] loss: 0.287
[step = 40000] loss: 0.287
[step = 50000] loss: 0.287
[step = 60000] loss: 0.287
[step = 70000] loss: 0.287EPOCH = 5, loss = 0.287, hr = 0.569, ndcg = 0.320
[0.5690397350993377]
[0.3197982144366359]
[0.28653216629144124]
[step = 10000] loss: 0.278
[step = 20000] loss: 0.278
[step = 30000] loss: 0.278
[step = 40000] loss: 0.278
[step = 50000] loss: 0.278
[step = 60000] loss: 0.278
[step = 70000] loss: 0.278EPOCH = 6, loss = 0.278, hr = 0.591, ndcg = 0.333
[0.5913907284768212]
[0.3329951807529053]
[0.2780010957392207]
[step = 10000] loss: 0.270
[step = 20000] loss: 0.272
[step = 30000] loss: 0.272
[step = 40000] loss: 0.272
[step = 50000] loss: 0.272
[step = 60000] loss: 0.273
[step = 70000] loss: 0.273EPOCH = 7, loss = 0.273, hr = 0.600, ndcg = 0.341
[0.5996688741721854]
[0.3412463814496145]
[0.2726059490596333]
[step = 10000] loss: 0.268
[step = 20000] loss: 0.268
[step = 30000] loss: 0.268
[step = 40000] loss: 0.268
[step = 50000] loss: 0.269
[step = 60000] loss: 0.269
[step = 70000] loss: 0.269EPOCH = 8, loss = 0.269, hr = 0.610, ndcg = 0.346
[0.6099337748344371]
[0.3455881971393328]
[0.2691765811218056]
[step = 10000] loss: 0.264
[step = 20000] loss: 0.265
[step = 30000] loss: 0.266
[step = 40000] loss: 0.266
[step = 50000] loss: 0.266
[step = 60000] loss: 0.267
[step = 70000] loss: 0.267EPOCH = 9, loss = 0.267, hr = 0.614, ndcg = 0.349
[0.6142384105960265]
[0.3488014429028774]
[0.2670171557082331]
[step = 10000] loss: 0.262
[step = 20000] loss: 0.263
[step = 30000] loss: 0.264
[step = 40000] loss: 0.264
[step = 50000] loss: 0.265
[step = 60000] loss: 0.265
[step = 70000] loss: 0.265EPOCH = 10, loss = 0.266, hr = 0.615, ndcg = 0.352
[0.614569536423841]
[0.3520316801750179]
[0.2655882040162689]
[step = 10000] loss: 0.261
[step = 20000] loss: 0.262
[step = 30000] loss: 0.263
[step = 40000] loss: 0.263
[step = 50000] loss: 0.264
[step = 60000] loss: 0.265
[step = 70000] loss: 0.265EPOCH = 11, loss = 0.265, hr = 0.616, ndcg = 0.354
[0.615728476821192]
[0.3540029758631938]
[0.2647231956259677]
[step = 10000] loss: 0.261
[step = 20000] loss: 0.262
[step = 30000] loss: 0.263
[step = 40000] loss: 0.263
[step = 50000] loss: 0.264
[step = 60000] loss: 0.264
[step = 70000] loss: 0.264EPOCH = 12, loss = 0.264, hr = 0.618, ndcg = 0.353
[0.6175496688741722]
[0.35274068000467834]
[0.26397280253223415]
[step = 10000] loss: 0.260
[step = 20000] loss: 0.261
[step = 30000] loss: 0.261
[step = 40000] loss: 0.262
[step = 50000] loss: 0.262
[step = 60000] loss: 0.262
[step = 70000] loss: 0.263EPOCH = 13, loss = 0.263, hr = 0.622, ndcg = 0.357
[0.6218543046357616]
[0.35705638777070575]
[0.2628108871733074]
[step = 10000] loss: 0.260
[step = 20000] loss: 0.260
[step = 30000] loss: 0.261
[step = 40000] loss: 0.261
[step = 50000] loss: 0.261
[step = 60000] loss: 0.262
[step = 70000] loss: 0.262EPOCH = 14, loss = 0.262, hr = 0.627, ndcg = 0.359
[0.6271523178807947]
[0.3586146519427854]
[0.262244005493884]
[step = 10000] loss: 0.257
[step = 20000] loss: 0.259
[step = 30000] loss: 0.260
[step = 40000] loss: 0.261
[step = 50000] loss: 0.261
[step = 60000] loss: 0.261
[step = 70000] loss: 0.262EPOCH = 15, loss = 0.262, hr = 0.631, ndcg = 0.362
[0.6307947019867549]
[0.3624748399043986]
[0.261853505862301]
[step = 10000] loss: 0.259
[step = 20000] loss: 0.260
[step = 30000] loss: 0.260
[step = 40000] loss: 0.261
[step = 50000] loss: 0.261
[step = 60000] loss: 0.261
[step = 70000] loss: 0.261EPOCH = 16, loss = 0.262, hr = 0.625, ndcg = 0.358[step = 10000] loss: 0.260
[step = 20000] loss: 0.259
[step = 30000] loss: 0.261
[step = 40000] loss: 0.261
[step = 50000] loss: 0.261
[step = 60000] loss: 0.261
[step = 70000] loss: 0.262EPOCH = 17, loss = 0.262, hr = 0.624, ndcg = 0.357
[]
[]
[]
[step = 10000] loss: 0.259
[step = 20000] loss: 0.260
[step = 30000] loss: 0.261
[step = 40000] loss: 0.261
[step = 50000] loss: 0.261
[step = 60000] loss: 0.261
[step = 70000] loss: 0.262EPOCH = 18, loss = 0.262, hr = 0.629, ndcg = 0.359
[step = 10000] loss: 0.260
[step = 20000] loss: 0.260
[step = 30000] loss: 0.261
[step = 40000] loss: 0.261
[step = 50000] loss: 0.262
[step = 60000] loss: 0.262
[step = 70000] loss: 0.262
EPOCH = 19, loss = 0.262, hr = 0.632, ndcg = 0.360

*从训练的结果来看 GMF+MLP的结果是比GMF 和MLP好的
*
NCF的局限性:仅仅是引入了用户ID向量和物品ID向量 但是在数据集中还有很多有价值的信息。

深度学习撞上推荐系统——02 GFM MLP NCF Pytorch代码实现相关推荐

  1. 桌游玩的好也能发NeurIPS!当深度学习撞上阿瓦隆!

    在遥远神秘的阿瓦隆,正义与邪恶展开激烈的争斗. 亚瑟王手下的圆桌骑士派西维尔率队完成三次艰巨的任务,然而在众多的人选中隐藏着邪恶的力量,为了避免失败,他需要挑选出绝对忠诚的伙伴帮助他尽快完成任务. 梅 ...

  2. 深度学习中一些注意力机制的介绍以及pytorch代码实现

    文章目录 前言 注意力机制 软注意力机制 代码实现 硬注意力机制 多头注意力机制 代码实现 参考 前言 因为最近看论文发现同一个模型用了不同的注意力机制计算方法,因此懵了好久,原来注意力机制也是多种多 ...

  3. 什么是深度学习?kears简介,深度学习常用的三大模型,MLP(多层感知机),CNN(卷积神经网络),RNN(循环神经网络)

    什么是深度学习? 简单理解深度学习就是人类容易做的事情,机器不容易完成的事情.(实例:人脸识别,这个例子很好的证明了这句话.假如你识别一个人 ,今天这个人长这个样子,明天脸上有一块伤口,我们人是不是还 ...

  4. 华为在深度学习平台上的优化实践

    "Kubernetes Meetup 中国 2017"--北京站3.18落幕啦!本次分享嘉宾彭靖田来自华为,他的分享题目是<华为在深度学习平台上的优化实践>.实录将从深 ...

  5. 基于深度学习的音乐推荐系统

    ♚ 作者:沂水寒城,CSDN博客专家,个人研究方向:机器学习.深度学习.NLP.CV Blog: http://yishuihancheng.blog.csdn.net 推荐系统在我们日常生活中发挥着 ...

  6. Hulu(北京)推荐算法负责人周涵宁:怎样应对基于深度学习的视频推荐系统...

    本文仅用于学习和交流目的,不得用于商业目的.非商业转载请注明作译者.出处,并保留本文的原始链接:http://www.ituring.com.cn/art... 周涵宁,本科毕业于清华大学自动化系,于 ...

  7. 基于深度学习的商品推荐系统(Web)

    基于深度学习的商品推荐系统(ECRS_Web) 项目简介 技术栈 项目用到的技术如下: 语言:Python3 Java Web端:Layui,Flask,Nginx,Gevent,Flask_Cach ...

  8. 一文回顾深度学习发展史上最重要经典模型

    这篇文章的目的是回顾经过时间考验的,被广泛采用的想法.我将介绍一小部分技术,这些技术涵盖了解现代深度学习研究所必需的许多基本知识.如果你是该领域的新手,那么这是一个很好的起点. 深度学习是一个瞬息万变 ...

  9. 当深度学习遇上异构并行计算

    当深度学习遇上异构并行计算 近几年来,以深度神经网络(DNN)为代表的深度学习如火如荼,深度学习的研究领域从开始的图像识别(如imagenet比赛)到现在的自然语言处理,几乎有席卷一切机器学习研究领域 ...

最新文章

  1. 控制~Matlab非线性模型分析
  2. Socket accept failed
  3. [html] const nums1 = [1, 2, 2, 1], nums2 = [2] 交集是什么?
  4. 在elementUI中使用 el-autocomplete 实现远程搜索的下拉框
  5. 计算机控制中mcu,MCU学习1:单片机控制应用很广,它在智能控制中起什么作用?...
  6. 使用PostgREST的RestAPI操作之安装教程
  7. SQL 一次插入多条记录
  8. labview与单片机正弦信号_LabVIEW小白入门——低通滤波器
  9. php 添加cdata,PHP cdata 处理 PHP cdata 处理(仔细讲解)
  10. adadelta算法_自适应学习率调整:AdaDelta
  11. 航空三字代码表_目前最全的航空城市三字代码表
  12. php swfupload,ThinkPHP+swfupload多图上传实例 经典实用的php多图上传
  13. 五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程
  14. 程序猿面试八股文分享~
  15. 量化择业 银行vs券商vs公募vs私募?(行内人深度分享)
  16. 【第17周复盘】拿到红本本喽!
  17. 浏览器有新消息之后,图标在电脑任务栏闪烁提示
  18. VCC AVCC VDD AVDD区别(转载)
  19. 免费ARP(gratuitousARP)
  20. 邻接矩阵与拉普拉斯矩阵

热门文章

  1. 微创机器人上市收涨背后:新股热情或回暖,下一个是谁?
  2. 知识图谱课程报告-关系抽取文献综述
  3. 边际效应与边际生产力理论
  4. 兼职币圈代言人?特斯拉CEO:加密货币是我的安全词
  5. 概率论笔记1.1.3事件间的关系
  6. 信息学奥赛一本通 细胞
  7. 计算机网络拓扑应用于,基于复杂网络理论的计算机网络拓扑研究
  8. Molecular Psychiatry:海马及其相关网络在电休克抗抑郁中的机制研究
  9. 哈工大赛尔 | 事理图谱:事件演化的规律和模式
  10. 论文中参考文献的引用