{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# default_exp models.tf.vncf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VNCF\n",
    "> Variational Neural Collaborative Filtering."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#hide\n",
    "from nbdev.showdoc import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras.models import Model, Sequential\n",
    "from tensorflow.keras.layers import Embedding, Flatten, Input, Dropout, Dense, Concatenate, Lambda\n",
    "from tensorflow.keras import backend as K\n",
    "\n",
    "\n",
    "class VNCF:\n",
    "    \"\"\"Variational Neural Collaborative Filtering.\n",
    "    \"\"\"\n",
    "    def __init__(self, num_users, num_items, latent_dim=20, batch_size=32):\n",
    "        self.num_users = num_users\n",
    "        self.num_items = num_items\n",
    "        self.latent_dim = latent_dim\n",
    "        self.batch_size = batch_size\n",
    "\n",
    "    def sampling(self, qargs):\n",
    "        z_mean, z_var = qargs\n",
    "        epsilon = K.random_normal(shape=(self.batch_size, self.latent_dim), mean=0., stddev=1)\n",
    "        return z_mean + K.exp(z_var) * epsilon\n",
    "\n",
    "    def build(self):\n",
    "        user_input = Input(shape=[1])\n",
    "        user_embedding = Embedding(self.num_users, self.latent_dim)(user_input)\n",
    "        user_embedding_mean = Dense(self.latent_dim)(user_embedding)\n",
    "        user_embedding_var = Dense(self.latent_dim)(user_embedding)\n",
    "        user_embedding_z = Lambda(self.sampling)([user_embedding_mean, user_embedding_var])\n",
    "        user_vec = Flatten()(user_embedding_z)\n",
    "\n",
    "        item_input = Input(shape=[1])\n",
    "        item_embedding = Embedding(self.num_items + 1, self.latent_dim)(item_input)\n",
    "        item_embedding_mean = Dense(self.latent_dim)(item_embedding)\n",
    "        item_embedding_var = Dense(self.latent_dim)(item_embedding)\n",
    "        item_embedding_z = Lambda(self.sampling)([item_embedding_mean, item_embedding_var], self.latent_dim)\n",
    "        item_vec = Flatten()(item_embedding_z)\n",
    "\n",
    "        concat = Concatenate(axis=1)([item_vec, user_vec])\n",
    "\n",
    "        fc_1 = Dense(80, name='fc-1', activation='relu')(concat)\n",
    "        fc_1_dropout = Dropout(0.6, name='fc-1-dropout')(fc_1)\n",
    "        fc_2 = Dense(25, name='fc-2', activation='relu')(fc_1_dropout)\n",
    "        fc_2_dropout = Dropout(0.4, name='fc-2-dropout')(fc_2)\n",
    "        fc_3 = Dense(1, name='fc-3', activation='relu')(fc_2_dropout)\n",
    "\n",
    "        model = Model([user_input, item_input], fc_3)\n",
    "        return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Author: Sparsh A.\n",
      "\n",
      "Last updated: 2021-12-17 07:21:33\n",
      "\n",
      "Compiler    : GCC 7.5.0\n",
      "OS          : Linux\n",
      "Release     : 5.4.104+\n",
      "Machine     : x86_64\n",
      "Processor   : x86_64\n",
      "CPU cores   : 2\n",
      "Architecture: 64bit\n",
      "\n",
      "tensorflow: 2.7.0\n",
      "IPython   : 5.5.0\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#hide\n",
    "!pip install -q watermark\n",
    "%reload_ext watermark\n",
    "%watermark -a \"Sparsh A.\" -m -iv -u -t -d"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
