Coverage for hopwise/model/general_recommender/multidae.py: 90%
49 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-09-30 13:25 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-09-30 13:25 +0000
1# @Time : 2020/12/14
2# @Author : Yihong Guo
3# @Email : gyihong@hotmail.com
5r"""MultiDAE
6################################################
7Reference:
8 Dawen Liang et al. "Variational Autoencoders for Collaborative Filtering." in WWW 2018.
10"""
12import torch
13import torch.nn.functional as F
14from torch import nn
16from hopwise.model.abstract_recommender import AutoEncoderMixin, GeneralRecommender
17from hopwise.model.init import xavier_normal_initialization
18from hopwise.model.layers import MLPLayers
19from hopwise.utils import InputType
22class MultiDAE(GeneralRecommender, AutoEncoderMixin):
23 r"""MultiDAE is an item-based collaborative filtering model that simultaneously ranks all items for each user.
25 We implement the the MultiDAE model with only user dataloader.
26 """
28 input_type = InputType.USERWISE
30 def __init__(self, config, dataset):
31 super().__init__(config, dataset)
33 self.layers = config["mlp_hidden_size"]
34 self.lat_dim = config["latent_dimension"]
35 self.drop_out = config["dropout_prob"]
37 self.build_histroy_items(dataset)
39 self.encode_layer_dims = [self.n_items] + self.layers + [self.lat_dim]
40 self.decode_layer_dims = [self.lat_dim] + self.encode_layer_dims[::-1][1:]
42 self.encoder = MLPLayers(self.encode_layer_dims, activation="tanh")
43 self.decoder = self.mlp_layers(self.decode_layer_dims)
45 # parameters initialization
46 self.apply(xavier_normal_initialization)
48 def mlp_layers(self, layer_dims):
49 mlp_modules = []
50 for i, (d_in, d_out) in enumerate(zip(layer_dims[:-1], layer_dims[1:])):
51 mlp_modules.append(nn.Linear(d_in, d_out))
52 if i != len(layer_dims[:-1]) - 1:
53 mlp_modules.append(nn.Tanh())
54 return nn.Sequential(*mlp_modules)
56 def forward(self, rating_matrix):
57 h = F.normalize(rating_matrix)
59 h = F.dropout(h, self.drop_out, training=self.training)
61 h = self.encoder(h)
62 return self.decoder(h)
64 def calculate_loss(self, interaction):
65 user = interaction[self.USER_ID]
67 rating_matrix = self.get_rating_matrix(user)
69 z = self.forward(rating_matrix)
71 # CE loss
72 ce_loss = -(F.log_softmax(z, 1) * rating_matrix).sum(1).mean()
74 return ce_loss
76 def predict(self, interaction):
77 user = interaction[self.USER_ID]
78 item = interaction[self.ITEM_ID]
80 rating_matrix = self.get_rating_matrix(user)
82 scores = self.forward(rating_matrix)
84 return scores[[torch.arange(len(item)).to(self.device), item]]
86 def full_sort_predict(self, interaction):
87 user = interaction[self.USER_ID]
89 rating_matrix = self.get_rating_matrix(user)
91 scores = self.forward(rating_matrix)
93 return scores.view(-1)