从这一篇开始,咱们开始学习深度学习推荐模型,与传统的机器学习相比,深度学习模型的表达能力更强,而且更可以挖掘出数据中潜藏的模式。另外。深度学习模型结构也很是灵活,可以根据业务场景和数据结构进行调整。仍是原来的样子,我会按照原理以及代码实现,再就是一些优缺点进行逐一介绍。python
AutoRec能够说是最小的深度学习推荐系统了,它是一种单隐层神经网络推荐模型,将自编码器与协同过滤相结合。那么什么是自编码器呢?自编码器能够看作是一种压缩维度的工具,不管是图像、音频、仍是文本,都可以经过自编码器转换成向量形式进行表达,假设咱们的输入(不管是图像、音频等等)的数据向量是\(r\),那么但愿经过自编码器的输出向量尽量接近原来的数据输入\(r\)。git
如下是论文原文github
Our aim in this work is to design an item-based (user-based) autoencoder which can take as input each partially observed, project it into a low-dimensional latent (hidden) space, and then reconstruct in the output space to predict missing ratings for purposes of recommendation.网络
假设自编码器的重建函数是\(h(r;\theta)\),那么自编码器的目标函数是:数据结构
其中的\(S\)就是全部数据输入的向量结合。机器学习
通常来讲,重建函数\(h(r;\theta)\)的参数量远远小于输入向量的维度,因此自编码器至关于完成了数据压缩和降维的工做。而且,经过自编码器生成的输出向量,使得自编码器的编码过程有必定的泛化能力,能够预测丢失的维度信息,这也是自编码器可以用于推荐系统的缘由。函数
在以前的文章中咱们介绍了协同过滤的关键——共现矩阵。就是由于由\(m\)个用户以及\(n\)的物品造成的\(m\times n\)的共现矩阵维度过高,因此咱们须要使用一个重建函数对共现矩阵里面的评分向量进行压缩,而后通过评分预估以及排序以后造成最终的排序列表。AutoRec使用了单隐层神经网络结构来实现自编码器的功能。以下图所示。
蓝色神经元表明模型的\(k\)维单隐层,也就是压缩以后的向量,\(V\)以及\(W\)表明从输入到隐层、从隐层到输出层的参数矩阵。那么写成重建函数的形式就是工具
\(f(\cdot)\)以及\(g(\cdot)\)为输出层和隐层神经元的激活函数。为了防止重构函数(单隐层神经网络、或者说三层神经网络)的过拟合,再加上\(L2\)正则化项,那么AutoRec的目标函数就是学习
\(||\cdot||_F\)为Frobenius范数.ui
当输入物品\(i\)的评分向量\(r^{(i)}\)时,获得的模型输出向量\(h(r;\theta)\)就是全部用户对物品\(i\)的评分预测。其中第\(u\)维就是用户\(u\)对物品\(i\)的预测评分\(\hat{R}_{ui}\)。那么再遍历一遍物品向量就能够获得该用户对全部物品的评分预测,而后进行排序就能够获得推荐列表。这种以物品评分向量做为输入的被称为I-AutoRec(Item based AutoRec),另一种就是以用户评分向量做为输入的就是U-AutoRec(User based AutoRec)。U-Auto相比较于I-Auto优点是仅输入一次目标用户的用户向量就能够重建用户对全部物品的评分向量,也就是说仅需一次推断就能够获得用户的推荐列表,可是用户向量的稀疏性可能会影响模型推荐效果。
没法进行特征交叉,表达能力相对于后面更复杂的深度学习模型仍是表达能力不足。因为AutoRec的简单明了,做为入门的深度学习推荐模型再合适不过了。
## 模型部分 class Autorec(nn.Module): def __init__(self,args, num_items): super(Autorec, self).__init__() self.args = args #self.num_users = num_users self.num_items = num_items self.hidden_units = args.hidden_units self.lambda_value = args.lambda_value self.encoder = nn.Sequential( nn.Linear(self.num_items, self.hidden_units), nn.Sigmoid() ) self.decoder = nn.Sequential( nn.Linear(self.hidden_units, self.num_items), ) def forward(self,torch_input): encoder = self.encoder(torch_input) decoder = self.decoder(encoder) return decoder ## 损失函数部分 def loss(self, decoder, input, optimizer, mask_input): cost = 0 temp2 = 0 cost += ((decoder - input) * mask_input).pow(2).sum() rmse = cost for i in optimizer.param_groups: for j in i['params']: # print(type(j.data), j.shape,j.data.dim()) if j.data.dim() == 2: temp2 += torch.t(j.data).pow(2).sum() cost += temp2 * self.lambda_value * 0.5 return cost, rmse
AutoRec: Autoencoders Meet Collaborative Filtering
Github:NeWnIx5991/AutoRec-for-CF