Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions cornac/models/ncf/backend_pt.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import torch
import torch.nn as nn


optimizer_dict = {
"sgd": torch.optim.SGD,
"adam": torch.optim.Adam,
Expand All @@ -16,7 +15,7 @@
"selu": nn.SELU(),
"relu": nn.ReLU(),
"relu6": nn.ReLU6(),
"leakyrelu": nn.LeakyReLU(),
"leaky_relu": nn.LeakyReLU(),
}


Expand Down
46 changes: 24 additions & 22 deletions cornac/models/ncf/recom_neumf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

import numpy as np

from .recom_ncf_base import NCFBase
from ...exception import ScoreException
from .recom_ncf_base import NCFBase


class NeuMF(NCFBase):
Expand Down Expand Up @@ -59,13 +59,13 @@ class NeuMF(NCFBase):

backend: str, optional, default: 'tensorflow'
Backend used for model training: tensorflow, pytorch

early_stopping: {min_delta: float, patience: int}, optional, default: None
If `None`, no early stopping. Meaning of the arguments:
If `None`, no early stopping. Meaning of the arguments:

- `min_delta`: the minimum increase in monitored value on validation set to be considered as improvement, \
i.e. an increment of less than min_delta will count as no improvement.

- `patience`: number of epochs with no improvement after which training should be stopped.

name: string, optional, default: 'NeuMF'
Expand Down Expand Up @@ -159,12 +159,13 @@ def from_pretrained(self, pretrained_gmf, pretrained_mlp, alpha=0.5):
########################
def _build_model_tf(self):
import tensorflow as tf

from .backend_tf import GMFLayer, MLPLayer

# Define inputs
user_input = tf.keras.layers.Input(shape=(1,), dtype=tf.int32, name="user_input")
item_input = tf.keras.layers.Input(shape=(1,), dtype=tf.int32, name="item_input")

# GMF layer
gmf_layer = GMFLayer(
num_users=self.num_users,
Expand All @@ -175,7 +176,7 @@ def _build_model_tf(self):
seed=self.seed,
name="gmf_layer"
)

# MLP layer
mlp_layer = MLPLayer(
num_users=self.num_users,
Expand All @@ -186,72 +187,72 @@ def _build_model_tf(self):
seed=self.seed,
name="mlp_layer"
)

# Get embeddings and element-wise product
gmf_vector = gmf_layer([user_input, item_input])
mlp_vector = mlp_layer([user_input, item_input])

# Concatenate GMF and MLP vectors
concat_vector = tf.keras.layers.Concatenate(axis=-1)([gmf_vector, mlp_vector])

# Output layer
logits = tf.keras.layers.Dense(
1,
kernel_initializer=tf.keras.initializers.LecunUniform(seed=self.seed),
name="logits"
)(concat_vector)

prediction = tf.keras.layers.Activation('sigmoid', name="prediction")(logits)

# Create model
model = tf.keras.Model(
inputs=[user_input, item_input],
outputs=prediction,
name="NeuMF"
)

# Handle pretrained models
if self.pretrained:
# Get GMF and MLP models
gmf_model = self.pretrained_gmf.model
mlp_model = self.pretrained_mlp.model

# Copy GMF embeddings
model.get_layer('gmf_layer').user_embedding.set_weights(
gmf_model.get_layer('gmf_layer').user_embedding.get_weights()
)
model.get_layer('gmf_layer').item_embedding.set_weights(
gmf_model.get_layer('gmf_layer').item_embedding.get_weights()
)

# Copy MLP embeddings and layers
model.get_layer('mlp_layer').user_embedding.set_weights(
mlp_model.get_layer('mlp_layer').user_embedding.get_weights()
)
model.get_layer('mlp_layer').item_embedding.set_weights(
mlp_model.get_layer('mlp_layer').item_embedding.get_weights()
)

# Copy dense layers in MLP
for i, layer in enumerate(model.get_layer('mlp_layer').dense_layers):
layer.set_weights(mlp_model.get_layer('mlp_layer').dense_layers[i].get_weights())

# Combine weights for output layer
gmf_logits_weights = gmf_model.get_layer('logits').get_weights()
mlp_logits_weights = mlp_model.get_layer('logits').get_weights()

# Combine kernel weights
combined_kernel = np.concatenate([
self.alpha * gmf_logits_weights[0],
(1.0 - self.alpha) * mlp_logits_weights[0]
], axis=0)

# Combine bias weights
combined_bias = self.alpha * gmf_logits_weights[1] + (1.0 - self.alpha) * mlp_logits_weights[1]

# Set combined weights to output layer
model.get_layer('logits').set_weights([combined_kernel, combined_bias])

return model

#####################
Expand All @@ -264,6 +265,7 @@ def _build_model_pt(self):
num_users=self.num_users,
num_items=self.num_items,
layers=self.layers,
num_factors=self.num_factors,
act_fn=self.act_fn,
)
if self.pretrained:
Expand Down
Loading