--- title: Factorization keywords: fastai sidebar: home_sidebar summary: "Matrix Factorization algorithmic modules for recommender systems." description: "Matrix Factorization algorithmic modules for recommender systems." nb_path: "nbs/models/models.factorization.ipynb" ---
{% raw %}
{% endraw %} {% raw %}
{% endraw %} {% raw %}

class MF[source]

MF(num_users, num_items, emb_size=100) :: Module

Base class for all neural network modules.

Your models should also subclass this class.

Modules can also contain other Modules, allowing to nest them in a tree structure. You can assign the submodules as regular attributes::

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

Submodules assigned in this way will be registered, and will have their parameters converted too when you call :meth:to, etc.

:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool

{% endraw %} {% raw %}
{% endraw %} {% raw %}

class BiasedMF[source]

BiasedMF(num_users, num_items, emb_size=100) :: Module

Base class for all neural network modules.

Your models should also subclass this class.

Modules can also contain other Modules, allowing to nest them in a tree structure. You can assign the submodules as regular attributes::

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

Submodules assigned in this way will be registered, and will have their parameters converted too when you call :meth:to, etc.

:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool

{% endraw %} {% raw %}
{% endraw %} {% raw %}

class NeuMF[source]

NeuMF(args, num_users, num_items) :: Module

Base class for all neural network modules.

Your models should also subclass this class.

Modules can also contain other Modules, allowing to nest them in a tree structure. You can assign the submodules as regular attributes::

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

Submodules assigned in this way will be registered, and will have their parameters converted too when you call :meth:to, etc.

:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool

{% endraw %} {% raw %}
{% endraw %} {% raw %}

class GMF[source]

GMF(args, num_users, num_items) :: Module

Base class for all neural network modules.

Your models should also subclass this class.

Modules can also contain other Modules, allowing to nest them in a tree structure. You can assign the submodules as regular attributes::

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

Submodules assigned in this way will be registered, and will have their parameters converted too when you call :meth:to, etc.

:ivar training: Boolean represents whether this module is in training or evaluation mode. :vartype training: bool

{% endraw %} {% raw %}
{% endraw %} {% raw %}
# import torch.nn.functional as F

# from recohut.datasets.synthetic import Synthetic
# from recohut.transforms.split import chrono_split
# from recohut.transforms.encode import label_encode as le
# from recohut.models.dnn import CollabFNet

# # generate synthetic implicit data
# synt = Synthetic()
# df = synt.implicit()

# # drop duplicates
# df = df.drop_duplicates()

# # chronological split
# df_train, df_valid = chrono_split(df)
# print(f"Train set:\n\n{df_train}\n{'='*100}\n")
# print(f"Validation set:\n\n{df_valid}\n{'='*100}\n")

# # label encoding
# df_train, uid_maps = le(df_train, col='USERID')
# df_train, iid_maps = le(df_train, col='ITEMID')
# df_valid = le(df_valid, col='USERID', maps=uid_maps)
# df_valid = le(df_valid, col='ITEMID', maps=iid_maps)

# # event implicit to rating conversion
# event_weights = {'click':1, 'add':2, 'purchase':4}
# event_maps = dict({'EVENT_TO_IDX':event_weights})
# df_train = le(df_train, col='EVENT', maps=event_maps)
# df_valid = le(df_valid, col='EVENT', maps=event_maps)
# print(f"Processed Train set:\n\n{df_train}\n{'='*100}\n")
# print(f"Processed Validation set:\n\n{df_valid}\n{'='*100}\n")

# # get number of unique users and items
# num_users = len(df_train.USERID.unique())
# num_items = len(df_train.ITEMID.unique())
# print(f"There are {num_users} users and {num_items} items.\n{'='*100}\n")

# # training and testing related helper functions
# def train_epocs(model, epochs=10, lr=0.01, wd=0.0, unsqueeze=False):
#     optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=wd)
#     model.train()
#     for i in range(epochs):
#         users = torch.LongTensor(df_train.USERID.values) # .cuda()
#         items = torch.LongTensor(df_train.ITEMID.values) #.cuda()
#         ratings = torch.FloatTensor(df_train.EVENT.values) #.cuda()
#         if unsqueeze:
#             ratings = ratings.unsqueeze(1)
#         y_hat = model(users, items)
#         loss = F.mse_loss(y_hat, ratings)
#         optimizer.zero_grad()
#         loss.backward()
#         optimizer.step()
#         print(loss.item()) 
#     test_loss(model, unsqueeze)

# def test_loss(model, unsqueeze=False):
#     model.eval()
#     users = torch.LongTensor(df_valid.USERID.values) #.cuda()
#     items = torch.LongTensor(df_valid.ITEMID.values) #.cuda()
#     ratings = torch.FloatTensor(df_valid.EVENT.values) #.cuda()
#     if unsqueeze:
#         ratings = ratings.unsqueeze(1)
#     y_hat = model(users, items)
#     loss = F.mse_loss(y_hat, ratings)
#     print("test loss %.3f " % loss.item())

# # training MF model
# model = MF(num_users, num_items, emb_size=100) # .cuda() if you have a GPU
# print(f"Training MF model:\n")
# train_epocs(model, epochs=10, lr=0.1)
# print(f"\n{'='*100}\n")

# # training MF with bias model
# model = MF_bias(num_users, num_items, emb_size=100) #.cuda()
# print(f"Training MF+bias model:\n")
# train_epocs(model, epochs=10, lr=0.05, wd=1e-5)
# print(f"\n{'='*100}\n")

# # training MLP model
# model = CollabFNet(num_users, num_items, emb_size=100) #.cuda()
# print(f"Training MLP model:\n")
# train_epocs(model, epochs=15, lr=0.05, wd=1e-6, unsqueeze=True)
# print(f"\n{'='*100}\n")


# """
# Train set:
#     USERID  ITEMID     EVENT   TIMESTAMP
# 0        1       1     click  2000-01-01
# 2        1       2     click  2000-01-02
# 5        2       1     click  2000-01-01
# 6        2       2  purchase  2000-01-01
# 7        2       1       add  2000-01-03
# 8        2       2  purchase  2000-01-03
# 10       3       3     click  2000-01-01
# 11       3       3     click  2000-01-03
# 12       3       3       add  2000-01-03
# 13       3       3  purchase  2000-01-03
# ====================================================================================================
# Validation set:
#     USERID  ITEMID     EVENT   TIMESTAMP
# 4        1       2  purchase  2000-01-02
# 9        2       3  purchase  2000-01-03
# 14       3       1     click  2000-01-04
# ====================================================================================================
# Processed Train set:
#     USERID  ITEMID  EVENT   TIMESTAMP
# 0        0       0      1  2000-01-01
# 2        0       1      1  2000-01-02
# 5        1       0      1  2000-01-01
# 6        1       1      4  2000-01-01
# 7        1       0      2  2000-01-03
# 8        1       1      4  2000-01-03
# 10       2       2      1  2000-01-01
# 11       2       2      1  2000-01-03
# 12       2       2      2  2000-01-03
# 13       2       2      4  2000-01-03
# ====================================================================================================
# Processed Validation set:
#     USERID  ITEMID  EVENT   TIMESTAMP
# 4        0       1      4  2000-01-02
# 9        1       2      4  2000-01-03
# 14       2       0      1  2000-01-04
# ====================================================================================================
# There are 3 users and 3 items.
# ====================================================================================================
# Training MF model:
# 5.836816787719727
# 1.993103265762329
# 4.549840450286865
# 1.5779536962509155
# 1.285771131515503
# 1.926152229309082
# 2.242276191711426
# 2.270019054412842
# 2.3635096549987793
# 2.272618055343628
# test loss 9.208 
# ====================================================================================================
# Training MF+bias model:
# 5.8399200439453125
# 3.7661311626434326
# 1.8716331720352173
# 1.6015545129776
# 1.5306222438812256
# 1.2995147705078125
# 1.1046849489212036
# 1.1331274509429932
# 1.2109991312026978
# 1.2451963424682617
# test loss 5.625 
# ====================================================================================================
# Training MLP model:
# 4.953568458557129
# 9.649873733520508
# 1.1805670261383057
# 2.54287052154541
# 2.6113314628601074
# 2.1839144229888916
# 1.4144573211669922
# 0.8893814086914062
# 0.7603365182876587
# 1.240354061126709
# 1.1316341161727905
# 0.8014519810676575
# 0.7997692823410034
# 0.8474739789962769
# 0.9691768884658813
# test loss 5.207 
# ====================================================================================================
# """
{% endraw %}