{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# default_exp models.mlp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# MLP\n",
    "> Multi-layer Perceptron for Recommendations."
   ]
  },
  {
   "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 torch\n",
    "from torch import nn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#export\n",
    "class MLP(nn.Module):\n",
    "    def __init__(self, args, num_users, num_items):\n",
    "        super(MLP, self).__init__()\n",
    "        self.num_users = num_users\n",
    "        self.num_items = num_items\n",
    "        self.factor_num = args.factor_num\n",
    "        self.layers = args.layers\n",
    "\n",
    "        self.embedding_user = nn.Embedding(num_embeddings=self.num_users, embedding_dim=self.factor_num)\n",
    "        self.embedding_item = nn.Embedding(num_embeddings=self.num_items, embedding_dim=self.factor_num)\n",
    "\n",
    "        self.fc_layers = nn.ModuleList()\n",
    "        for idx, (in_size, out_size) in enumerate(zip(self.layers[:-1], self.layers[1:])):\n",
    "            self.fc_layers.append(nn.Linear(in_size, out_size))\n",
    "\n",
    "        self.affine_output = nn.Linear(in_features=self.layers[-1], out_features=1)\n",
    "        self.logistic = nn.Sigmoid()\n",
    "\n",
    "    def forward(self, user_indices, item_indices):\n",
    "        user_embedding = self.embedding_user(user_indices)\n",
    "        item_embedding = self.embedding_item(item_indices)\n",
    "        vector = torch.cat([user_embedding, item_embedding], dim=-1)  # the concat latent vector\n",
    "        for idx, _ in enumerate(range(len(self.fc_layers))):\n",
    "            vector = self.fc_layers[idx](vector)\n",
    "            vector = nn.ReLU()(vector)\n",
    "            # vector = nn.BatchNorm1d()(vector)\n",
    "            # vector = nn.Dropout(p=0.5)(vector)\n",
    "        logits = self.affine_output(vector)\n",
    "        rating = self.logistic(logits)\n",
    "        return rating\n",
    "\n",
    "    def init_weight(self):\n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0.4265],\n",
       "        [0.4298]], grad_fn=<SigmoidBackward0>)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class Args:\n",
    "    factor_num = 4\n",
    "    layers = [8,4,2]\n",
    "args = Args()\n",
    "\n",
    "model = MLP(args, num_users=5, num_items=5)\n",
    "model.forward(torch.tensor([0,1]), torch.tensor([1,3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Author: Sparsh A.\n",
      "\n",
      "Last updated: 2021-12-26 04:53:14\n",
      "\n",
      "recohut: 0.0.7\n",
      "\n",
      "Compiler    : GCC 7.5.0\n",
      "OS          : Linux\n",
      "Release     : 5.4.144+\n",
      "Machine     : x86_64\n",
      "Processor   : x86_64\n",
      "CPU cores   : 2\n",
      "Architecture: 64bit\n",
      "\n",
      "torch  : 1.10.0+cu111\n",
      "IPython: 5.5.0\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#hide\n",
    "%reload_ext watermark\n",
    "%watermark -a \"Sparsh A.\" -m -iv -u -t -d -p recohut"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
