class_docstr: Neural Collaborative Filtering (NCF) implementation
  
  :Citation:
  
      He, Xiangnan, Lizi Liao, Hanwang Zhang, Liqiang Nie, Xia Hu, and Tat-Seng Chua. "Neural collaborative filtering."
      In Proceedings of the 26th International Conference on World Wide Web, pp. 173-182. International World Wide Web
      Conferences Steering Committee, 2017. Link: https://www.comp.nus.edu.sg/~xiangnan/papers/ncf.pdf
class_docstr_tok: ["Neural","Collaborative","Filtering","(","NCF",")","implementation",":","Citation",":","He",",","Xiangnan",",","Lizi","Liao",",","Hanwang","Zhang",",","Liqiang","Nie",",","Xia","Hu",",","and","Tat-Seng","Chua",".","``","Neural","collaborative","filtering",".","''","In","Proceedings","of","the","26th","International","Conference","on","World","Wide","Web",",","pp",".","173-182.","International","World","Wide","Web","Conferences","Steering","Committee",",","2017",".","Link",":","https",":","\/\/www.comp.nus.edu.sg\/~xiangnan\/papers\/ncf.pdf"]
code: def _create_model(
      self,
  ):
      # reset graph
      tf.compat.v1.reset_default_graph()
  
      with tf.compat.v1.variable_scope(
          "input_data", reuse=tf.compat.v1.AUTO_REUSE
      ):
          # input: index of users, items and ground truth
          self.user_input = tf.compat.v1.placeholder(
              tf.int32, shape=[None, 1]
          )
          self.item_input = tf.compat.v1.placeholder(
              tf.int32, shape=[None, 1]
          )
          self.labels = tf.compat.v1.placeholder(
              tf.float32, shape=[None, 1]
          )
  
      with tf.compat.v1.variable_scope(
          "embedding", reuse=tf.compat.v1.AUTO_REUSE
      ):
          # set embedding table
          self.embedding_gmf_P = tf.Variable(
              tf.random.truncated_normal(
                  shape=[self.n_users, self.n_factors],
                  mean=0.0,
                  stddev=0.01,
                  seed=self.seed,
              ),
              name="embedding_gmf_P",
              dtype=tf.float32,
          )
  
          self.embedding_gmf_Q = tf.Variable(
              tf.random.truncated_normal(
                  shape=[self.n_items, self.n_factors],
                  mean=0.0,
                  stddev=0.01,
                  seed=self.seed,
              ),
              name="embedding_gmf_Q",
              dtype=tf.float32,
          )
  
          # set embedding table
          self.embedding_mlp_P = tf.Variable(
              tf.random.truncated_normal(
                  shape=[self.n_users, int(self.layer_sizes[0] / 2)],
                  mean=0.0,
                  stddev=0.01,
                  seed=self.seed,
              ),
              name="embedding_mlp_P",
              dtype=tf.float32,
          )
  
          self.embedding_mlp_Q = tf.Variable(
              tf.random.truncated_normal(
                  shape=[self.n_items, int(self.layer_sizes[0] / 2)],
                  mean=0.0,
                  stddev=0.01,
                  seed=self.seed,
              ),
              name="embedding_mlp_Q",
              dtype=tf.float32,
          )
  
      with tf.compat.v1.variable_scope(
          "gmf", reuse=tf.compat.v1.AUTO_REUSE
      ):
          # get user embedding p and item embedding q
          self.gmf_p = tf.reduce_sum(
              input_tensor=tf.nn.embedding_lookup(
                  params=self.embedding_gmf_P, ids=self.user_input
              ),
              axis=1,
          )
          self.gmf_q = tf.reduce_sum(
              input_tensor=tf.nn.embedding_lookup(
                  params=self.embedding_gmf_Q, ids=self.item_input
              ),
              axis=1,
          )
  
          # get gmf vector
          self.gmf_vector = self.gmf_p * self.gmf_q
  
      with tf.compat.v1.variable_scope(
          "mlp", reuse=tf.compat.v1.AUTO_REUSE
      ):
          # get user embedding p and item embedding q
          self.mlp_p = tf.reduce_sum(
              input_tensor=tf.nn.embedding_lookup(
                  params=self.embedding_mlp_P, ids=self.user_input
              ),
              axis=1,
          )
          self.mlp_q = tf.reduce_sum(
              input_tensor=tf.nn.embedding_lookup(
                  params=self.embedding_mlp_Q, ids=self.item_input
              ),
              axis=1,
          )
  
          # concatenate user and item vector
          output = tf.concat([self.mlp_p, self.mlp_q], 1)
  
          # MLP Layers
          for layer_size in self.layer_sizes[1:]:
              output = slim.layers.fully_connected(
                  output,
                  num_outputs=layer_size,
                  activation_fn=tf.nn.relu,
                  weights_initializer=tf.compat.v1.keras.initializers.VarianceScaling(
                      scale=1.0,
                      mode="fan_avg",
                      distribution="uniform",
                      seed=self.seed,
                  ),
              )
          self.mlp_vector = output
  
          # self.output = tf.sigmoid(tf.reduce_sum(self.mlp_vector, axis=1, keepdims=True))
  
      with tf.compat.v1.variable_scope(
          "ncf", reuse=tf.compat.v1.AUTO_REUSE
      ):
          if self.model_type == "gmf":
              # GMF only
              output = slim.layers.fully_connected(
                  self.gmf_vector,
                  num_outputs=1,
                  activation_fn=None,
                  biases_initializer=None,
                  weights_initializer=tf.compat.v1.keras.initializers.VarianceScaling(
                      scale=1.0,
                      mode="fan_avg",
                      distribution="uniform",
                      seed=self.seed,
                  ),
              )
              self.output = tf.sigmoid(output)
  
          elif self.model_type == "mlp":
              # MLP only
              output = slim.layers.fully_connected(
                  self.mlp_vector,
                  num_outputs=1,
                  activation_fn=None,
                  biases_initializer=None,
                  weights_initializer=tf.compat.v1.keras.initializers.VarianceScaling(
                      scale=1.0,
                      mode="fan_avg",
                      distribution="uniform",
                      seed=self.seed,
                  ),
              )
              self.output = tf.sigmoid(output)
  
          elif self.model_type == "neumf":
              # concatenate GMF and MLP vector
              self.ncf_vector = tf.concat(
                  [self.gmf_vector, self.mlp_vector], 1
              )
              # get predicted rating score
              output = slim.layers.fully_connected(
                  self.ncf_vector,
                  num_outputs=1,
                  activation_fn=None,
                  biases_initializer=None,
                  weights_initializer=tf.compat.v1.keras.initializers.VarianceScaling(
                      scale=1.0,
                      mode="fan_avg",
                      distribution="uniform",
                      seed=self.seed,
                  ),
              )
              self.output = tf.sigmoid(output)
  
      with tf.compat.v1.variable_scope(
          "loss", reuse=tf.compat.v1.AUTO_REUSE
      ):
          # set loss function
          self.loss = tf.compat.v1.losses.log_loss(
              self.labels, self.output
          )
  
      with tf.compat.v1.variable_scope(
          "optimizer", reuse=tf.compat.v1.AUTO_REUSE
      ):
          # set optimizer
          self.optimizer = tf.compat.v1.train.AdamOptimizer(
              learning_rate=self.learning_rate
          ).minimize(self.loss)
  
file_path: recommenders/recommenders/models/ncf/ncf_singlenode.py
imports: import os
  import numpy
  import tensorflow
  import tf_slim
  from time import time
  import logging
label_desc: Use image node_id 2 for calling the NCF obj's underlying member method code with example usage: obj._create_model() without return types