awarebayes/RecNN

View on GitHub
examples/1. Vanilla RL/1. Anomaly Detection.ipynb

Summary

Maintainability
Test Coverage
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Anomaly detection using an autoencoder"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### **Note on this tutorials:**\n",
    "**They mostly contain low level implementations explaining what is going on inside the library.**\n",
    "\n",
    "**Most of the stuff explained here is already available out of the box for your usage.**\n",
    "\n",
    "This is a utility network mainly used for debuggning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "import torch_optimizer as optim\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from tqdm import tqdm_notebook as tqdm\n",
    "import pickle\n",
    "import json\n",
    "\n",
    "# == recnn ==\n",
    "import sys\n",
    "sys.path.append(\"../../\")\n",
    "import recnn\n",
    "\n",
    "from jupyterthemes import jtplot\n",
    "jtplot.style(theme='grade3')\n",
    "\n",
    "cuda = torch.device('cuda')\n",
    "frame_size = 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# https://drive.google.com/open?id=1kTyu05ZmtP2MA33J5hWdX8OyUYEDW4iI\n",
    "movies = pickle.load(open('../../data/embeddings/ml20_pca128.pkl', 'rb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in movies.keys():\n",
    "    movies[i] = movies[i].to(cuda)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class AnomalyDetector(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(AnomalyDetector, self).__init__()\n",
    "        self.ae = nn.Sequential(\n",
    "            nn.Linear(128, 64),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm1d(64),\n",
    "            nn.Linear(64, 32),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm1d(32),\n",
    "            nn.Linear(32, 64),\n",
    "            nn.ReLU(),\n",
    "            nn.BatchNorm1d(64),\n",
    "            nn.Linear(64, 128),\n",
    "            nn.ReLU(),\n",
    "        )\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return self.ae(x)\n",
    "    \n",
    "    def rec_error(self, x):\n",
    "        error = torch.sum((x - self.ae(x)) ** 2, 1)\n",
    "        if x.size(1) != 1:\n",
    "            return error.detach()\n",
    "        return error.item()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = torch.stack(list(movies.values())).to(cuda)\n",
    "data = data[torch.randperm(data.size()[0])] # shuffle rows\n",
    "data_test = data[-100:]\n",
    "data = data[:-100]\n",
    "n_epochs = 5000\n",
    "batch_size = 15000\n",
    "\n",
    "model = AnomalyDetector().to(cuda)\n",
    "criterion = nn.MSELoss()\n",
    "optimizer = optim.Ranger(model.parameters(), lr=1e-4, weight_decay=1e-2)\n",
    "run_loss = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "<ipython-input-8-422c8195285b>:5: TqdmDeprecationWarning: This function will be removed in tqdm==5.0.0\n",
      "Please use `tqdm.notebook.tqdm` instead of `tqdm.tqdm_notebook`\n",
      "  for epoch in tqdm(range(n_epochs)):\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "414758e42cd541919db127e6287ff954",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "HBox(children=(FloatProgress(value=0.0, max=5000.0), HTML(value='')))"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/mikew/anaconda3/envs/recnn/lib/python3.8/site-packages/pytorch_ranger/ranger.py:172: UserWarning: This overload of addcmul_ is deprecated:\n",
      "\taddcmul_(Number value, Tensor tensor1, Tensor tensor2)\n",
      "Consider using one of the following signatures instead:\n",
      "\taddcmul_(Tensor tensor1, Tensor tensor2, *, Number value) (Triggered internally at  /opt/conda/conda-bld/pytorch_1595629395347/work/torch/csrc/utils/python_arg_parser.cpp:766.)\n",
      "  exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "test_loss = []\n",
    "rec_loss = []\n",
    "test_rec_loss = []\n",
    "\n",
    "for epoch in tqdm(range(n_epochs)):\n",
    "    for batch in data.split(batch_size):\n",
    "        optimizer.zero_grad()\n",
    "        batch = batch\n",
    "        output = model(batch).float()\n",
    "        loss = criterion(output, batch)\n",
    "        test_loss.append(criterion(model(data_test).float(), data_test).item())\n",
    "        rec_loss.append(model.rec_error(batch))\n",
    "        test_rec_loss.append(model.rec_error(data_test))\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        run_loss.append(loss.item())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "plt.plot(run_loss)\n",
    "plt.plot(test_loss)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[224.92099 585.77966 528.3213  ... 215.87817 337.97443 397.52893]\n"
     ]
    }
   ],
   "source": [
    "# real movies\n",
    "def calc_art_score(x):\n",
    "    return model.rec_error(x)  + (1 / x.var() * 5)\n",
    "\n",
    "model.eval()\n",
    "train_scores = model.rec_error(data).detach().cpu().numpy()\n",
    "print(train_scores)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Now lets see what our autoencoder can do\n",
    "Here you can see test scores reconstruction errors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAD6CAYAAACs/ECRAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAoEUlEQVR4nO3dfZAc9X3n8ffurFa7rFa7q5WEHlgLx6xhCTIIG3IQNIysksY2D3YRIs4pc85dkbLLGOlsHDDYUDqTowwxjsVDyk6Iw1GV3PFg10WYcsaES9/Ihcuxoxts2YMQ2MirB0Crp12kXUbb2/dHz0izs9Pz2DPTD59X1ZRW/eue6d/0b/r7e+ruNsuyEBGR8Gpv9Q6IiEhrKRCIiIScAoGISMgpEIiIhJwCgYhIyHW0egeqdeuX7m0DzgHGW70vIiI+sxDY99g3vjZruqjvAgF2EPhdq3dCRMSn3gOM5i/wYyAYB7jvK1+ku6urqg1N0ySdTjMyMkIkEmnIznlRGPOtPIcjzxDOfNeS58mpKe7579+EIr0pfgwEAHR3ddHdXX0g6OycR3d3V2gKDIQz38pzOPIM4cy323nWYLGISMgpEIiIhJwCgYhIyCkQiIiEnAKBiEgVxsYz/OSVo4yNZ1q9K67x7awhEZFme2rHQbY9t5dp06Ij0saW61Zx09rlrd6tuqlFICJSgbHxzOkgADBtWmx7bm8gWgYKBCIiFdhz4MTpIJAzbVrsOXCiRXvkHgUCEZEKDK/ooSPSNmtZR6SN4RU9Ldoj9ygQiIhUYPHCTrZct+p0MMiNESxe2NniPaufBotFRCp009rlrL94kD0HTjC8oicQQQAUCEREqrJ4YWdgAkCOuoZEREJOgUBEJOQUCEREQk6BQEQk5BQIRERCToFARCTkFAhEREJOgUBEJOQUCEREQk6BQEQk5BQIRERCrqJ7DcWi8U3AZuASYMxIJs7NS+sAHgJuxg4s3wNuNZKJKTfSRUSksSptERwFHgW+UiTtbmAdsBoYBi4EHnQxXUREGqiiFoGRTLwAEIvGP1Ek+RbgDiOZ2J9dZyvwTCwa/4KRTJgupBdlmiam6ZjsuE3+v2ERxnwrz+ERxnzXkudS69Z1G+pYNN4PDAGpvMU7gV7g3Fg0friedOB1p89Op9N0ds6rab/T6XRN2/ldGPOtPIdHGPNdTZ4zmVOOafU+j6A3+++xvGXH8tIydaY7GhkZobu7q8LdtJmmSTqdZmRkhEgkUtW2fhbGfCvP4cgzhDPfteR5cnIK2F40rd5AMJH9tw94M/t3f15avemOIpFIzQe9nm39LIz5Vp7DI4z5ribPpdara/qokUwcA0axZxPlrME+ib9Rb3o9+yYiIpWpdPpoBJiXfbXFovEuwDKSiXeBx4G7YtH4DuAUsBV4Im+gt950CZGx8Uzgngcr4nWVdg3dDPx93v8ngb3YA7r3A4uBX2G3MJ4F7sxbt950CYmndhxk23N7mTYtOiJtbLluFTetXd7q3RIJvEqnjz4BPOGQNo19sdnmRqRLOIyNZ04HAYBp02Lbc3tZf/GgWgYiDaZbTIgn7Dlw4nQQyJk2LfYcONGiPRIJDwUC8YThFT10RNpmLeuItDG8oqdFeyQSHgoEUpOx8Qw/eeUoY+OZ8itXYPHCTrZct+p0MMiNEahbSKTx6r2OQEKoUYO6N61dzvqLBzVrSKTJ1CKQqjgN6rrZMrjiggEFAZEmUiCQqmhQVyR4FAikKhrUFQkeBQKpigZ1RYJHg8VSNQ3qigSLAoHUZPHCTgUAkYBQ15CISMgpEIiIhJwCgYhIyCkQiIiEnAKBiEjIKRCIiIScAoGISMgpEIiIhJwCgYhIyCkQiIiEnAKBiEjIKRCIiIScAoGIh7j9LGiRSujuoyIe0ahnQYuUoxaBSIFW1Mob/SxokVLUIhDJ06paealnQeu5D9JorgSCWDS+HHgUuBpoA3YAnzeSiX2xaLwDeAi4GbsF8j3gViOZmMpuWzJdpFmcauXrLx5s+Mk49yzo/GCgZ0FLs7jVNfTXQCfwXmAIOAF8N5t2N7AOWA0MAxcCD+ZtWy5dpClK1cobTc+CllZyKxC8D3jGSCYmjGTiJPCPwAeyabcA9xvJxH4jmTgEbAX+NBaNRypMF2mKXK08XzNr5TetXc72r17Ktj+7gO1fvVQDxQHnpRlibo0RfBO4MRaNbwdM7G6e52LReD92CyGVt+5OoBc4NxaNHy6VDrzu9IGmaWKaZlU7mVu/2u38Loz5riXPAz0RbrtmiEeeHz09RrD52iEGeiJN++4GeiJcPrwQqP54hfE4gz/z/fSP35xVzm67ZohNVy2rePta8lxqXbcCwY+B/wIcASzgF8BG7BM6wLG8dXN/9wKZMumO0uk0nZ3zatrZdDpd03Z+F8Z8V5vnC/vh6zd0MXpkhqFF7fR1j7Fr11hjdq5BwnicwT/5PnbS4uEfTGLO2P+fNi0e/sHvWDn/EH3dbaU3LlBNnjOZU45pdQeCWDTeDvwL8H3gY9gtgjsAA4hlV+sD3sz+3Z/9dyL7KpXuaGRkhO7urqr21TRN0uk0IyMjRCLh6XkKY76V53DkGfyX75/sPoY58+qsZeYMtC8c4qLz+yt6j1ryPDk5BWwvmuZGi2ARsAp42Egm3gGIRePfxO7rHwRGgUuA3dn112Cf5N8wkgkzFo07ppf60EgkUvNBr2dbPwtjvpXn8PBLvi84p7foDLELzumtev+ryXOp9eoOBEYyMRaLxl8Dbo1F4/ditwi2AEexT+aPA3fFovEdwCnsAPGEkUzkOqzKpYuIBEZuhljh9SqtnCHm1hjBx7EHjPdhz0TaBVxrJBNTsWj8fmAx8Kts2rPAnXnblksXEQmUm9YuZ/3Fg+w5cILhFT0tnybsSiAwkolfAx9xSJsGNmdfVaeLiATR4oWdLQ8AObrXkIhIyCkQ+JiXLkgREf/STecKjI1nPNNvV4puWSwiblEgyOOXk2srb44mIsGjrqEsP90PvpU3RxOR4FEgyPLTybXVN0eT+ml8R7xEXUNZjbgffKPGG7x4QYpUzi9dkBIeCgRZbp9cG/1j99oFKV7mpQkAGt8RL1IgyOPWydXtH7vTicxLF6R4VeHtfltd+9YjKcWLQhUIDk9k2LXfZPmqDEv7u4uu48bJ1c0fu7oRanfspHU6CIA3at96JKV4UWgGi5/acZBP3P8y2158l0/c/zJP7TjYsM9yazDXTzOZvGjf0RnPTQDQIynFi0LRImh2v6xb4w3qRqjP0KJ2T9a+Nb4jXhOKQNCKE6obP3Z1I9Snr7ttzqMnvVL71viOeEkoAkGrTqj1/tg1TbR+m65axoY1S5pa+/bSLCWRSoQiEPj5hKpuhPo1s/atwf3KKWB6RygCAdgn1HWr+3nhpTQbrhxxnDXkRepG8AddI1A5BUxvCc2sIYDB3k4uWhlhsFc/SnGfn25T0kqaDec9oQoEIo2ke0BVRgHTexQIRFyiawQqo4DpPaEZI5DSNHDnDg3ul+fnyRtBpUBQg6CdNDVw5y4N7pengOktCgRVCtpJUzNdpFUUML1DYwRVCOJsBw3c1U4Pl5GgUIugCkG8949uY1GboLUMJdzUIqhCEGc7aKZL9YLYMpRwU4ugCkGd7aCBu+oEsWUo4eZaIIhF49cA9wHnAxPAQ0Yy8ZexaLwDeAi4GbsF8j3gViOZmMpuVzLda4J60gzCwF3+bK6BnkjDPkfdaRI0rgSCWDS+Efgb4D8B/xc4C3hPNvluYB2wGsgA24EHgc0VpntOEE6aQVPYZ3/bNUNc2N+Yz/J7yzBo05+lfm61CO4D7jOSiRez/x8HdmX/vgW4w0gm9gPEovGtwDOxaPwLRjJhVpAuDRKUE0KxPvtHnh/l6zd0Newz/doy1CC3FFN3IIhF4z3AZcAPY9H4K8AA8FNgC3AUGAJSeZvsBHqBc2PR+OFS6cDrTp9rmiamWV2cyK1f7XZ+VyzfhQ91v+2aITZdtaxVu1iXV/ZNFO2zHz0y09BjPdAT4fLhhYA3ylS58u00yL1udb+vb8QYxt91LXkuta4bLYIBoA34I+AjwNvAt4DvA9dn1zmWt37u717srqBS6Y7S6TSdnfNq2uF0Os3xSftEMbSonb7utvIbBUA6nQbsh7o//INJzBl7+bRp8fAPfsfK+Yd8+V3MTFpE2jmdH4BIu/2oylyew8Qpz7v2m0UD5gsvpbloZePGVJpFx7q0TOaUY5obgWAi++82I5l4AyAWjd8NHMIOEAB9wJvZv/vztpsok+5oZGSE7u7qmv6maZJOp9l1ZJDHfrgvELXhSuTyPTIyQiQS4Se7j2HOvDp7nRloXzjERef3t2Yn67T53dktnM9/7Bz6ug+fznMYFB7nQstXZXjMeHnOIPeGK0d83yIole8gqiXPk5NT2EOwc9UdCIxk4ngsGt8LWA6rjAKXALuz/1+DfZJ/w0gmzFg07phe6nMjkUhNB/3YSet0EIAz/ckb1iypuZ/XL33tue/sgnN6i856ueCcXt/+kD559cpZj6Qc6Imwa9fhmsuJnznleWl/d9FBbj89pKkUHevy6zpxa7D428CWWDT+I+yWwH3AvxvJxO9i0fjjwF2xaHwHcArYCjyRNxBcLt1V+47OuDoH3I+Db36f9eIkfzZXmPqLq+HXQW5pLLcCwYPYYwU7sa8F+DFwQzbtfmAx8Kts2rPAnXnblkt31dCidtfmgPv5hm06IYSXpj9LIVcCgZFMzGCfvOecwI1kYhr7moCi1wWUS3dbX7c9JpDfn1xrbdjvV5jqhCAiENJbTGy6atms/uRaT4a6wlQayS9jT+J/oQwE4E5t2Et97TppBIsfx57Ev0IbCNzihb52nTSCxc9jT36jCpRNgcAFrexr10kjePw+9uQXpSpQYQsQCgQ+p5NG8GjsqfFKVaBefPlw6FrYejCNzwXxYTlhp4cFNZ5TBernrx0P5UOH1CLwmcImq5cGrMU9Xhh7CjKnVhcQyha2AoGPOPVp6qQRTLrOo3GcKlAfOq8vlN1yCgQtUMtAVLlBYZ00RKrjVIEKYwtbgaDJap3qqUFhEfcVq0CFsYWtweImcqrVVzIQpUFhkeZZvLCTKy4YCEUQAAWCpipVqy9HM0lEpFHUNdRE9c4PD2OTVUQaTy2CJnKjVh+2JquINJ5aBE2Smym0/uJB1epFxFMUCJpAN4UTkUq14j5HCgQNppvCSTlhu8GZOGtVpVGBoME0/19KUWtRclpZadRgcYNp/r84qee6EgmeeqaX10uBoME0/1+ctPKHL97TykqjuoaaQPP/pRg9d0DytfJOwgoETRLkm8JpsLM2uoW4FGpVpVGBQOqiwc7KFQuYai1KoVZUGhUIpGaaGlu5UgEzyK1F8QcNFgfQ2HiGn7xytOGzTzTYWRnNDhKvU4sgYIrVPG+8cmlDPkuDnZXx+7UkGgMKPlcDQSwa7wZ+CSwzkokF2WUdwEPAzdgtkO8BtxrJxFQl6VI5p5rnutX9Dfm8coOdOoHY/BwwNQYUDm63CL4G7AWW5S27G1gHrAYywHbgQWBzhemB5ubJ0qnm+eqBk/TW9c7OnAY7dQI5w6+zgzQGFB6uBYJYNP5B4CPA7cD385JuAe4wkon92fW2As/EovEvGMmEWUF6YLl9snSqeb5/xVkc3OvGHhdXONipE8hcfpwd5PcuLamcK4Eg273zt8Ct5A1Ax6LxfmAISOWtvhPoBc6NReOHS6UDrzt9prl/P+b8bGFsa4Ply2F6Gt5+e/aKixZBVxccOoQ5NUXH229jjo5CT4+dduIEHD8+e5vly8Gy4M03Zy/v74ezzoLDh+Hdd88s7+yExYthchKOHp29zdlnQyQCBw7MWnyYLrY9t5fuE8eZP22/1z/8z0N8eNkHWPR759jvf/jw7PdasgTmzbP3a2bmzPKeHujrY2D6He74g3l898UDTJsW7ZEIn/qPl9A/b4ZDuXxHIvY2g4Mwf779fU1Pn3mv7m4YGIB33oHx8dmfv2IFmCa89dbs5QMD9nZjY5DJ8JvXj9N//G1ORTo53t3H/FNT9L4zwW92vsrA+/rsbZYts4/bwYOz36uvz87PkSMwldc7OG+enf+pKTst39Kl0NFhv5dln7hM06T9xAlM04Rjx+DkyTPrRyL2cclk7H3Ot3ixfTzfesvOa85ZZ9nHf2LCfuVUWPY4dYoB4PIe4N1pTNP9smeOjZ0p37k8Fil7LFwICxbYZXVy8szyjg77u8yWvWErw7LJMaZNi6PdA5iRDpZOHmHYOoI5+o69Tbbscfy4nZ+c9nb7GJ86Zec/n8tlz+zsJHL06OzyPX++/TknT9rHP1+Dyx4Avb32q0FlzzRNOg4dsst3BWUPwHy3xOQEy7Lqfl29duNdV6/d+HfZv2NXr934TvbvoavXbrSuXrtxWd6687LLLimXXuyzPnf7PX2fu/0e62TnfMuyv3presECK5VKWb/evv30stzrN9u2WalUynpn9epZy49u3GilUilr9MtfnrNN6mc/s36xY8ec5Xu3brVSqZR1LBqdtXz88sutVCplvfHAA3O22fWjH1mpVMqa6eiYtXznf95sXfbFl6ztv/+xWcuPnHuelUqlrNe+85057/XK009bqVTKyixZMmv5W5/+tJVKpay3Pv3pWcunFi+2UqmU9crTT895r9e+8x0rlUpZJ4eHZy0/fP31ViqVsvZv2TJr+UxHh5VKpaxdP/rRnPd644EHrFQqZY1ffvms5cnf+0Prsi++ZP23jXfP2eYXO3ZYqZ/9bM7y0S9/2UqlUtbRjRtnLX9n9WorlUpZv9m2bc42v96+3UqlUtb0ggWzlh/8zGesVCplHbrpptnfy9CQlUqlrFeffHLOe7365JNWKpWypoaGZi0/dNNNViqVsg5+5jOzlvux7O3fssVKpVLW4euvn7X85PCwY9n75M1PWv/hSy9ZE/2LKyp7mSVLHMveyw9/u+Fl71g0aqVSKWvv1q0qe7nj2znf+tzt91ifu/2evsLzaptlWc5RogKxaPw84EVgjZFMHIlF4zHgB0YysSDbIjgKXGAkE7uz6y8B3gbOAw6XSjeSiTktglu/dG8fcOyBz36a7hpaBHv27GF4eJhIi1sER9q6+PjDr89qEXRE2vi7L9TeInCqlZlTU+x56SU7301oEQA8929v821jjCOdC+mZeZcta3u57rK82UtNaBHsPnCA8z/0ISITE55oEZzW1dWQsmeOjZ0p3y60CHKOvpNhd6aH4VV9DJ44UlXZy7UInvu3t0+3VE/09PPZj7+PTe9vd61F8OpLL/H+c889U75b3CI4wnx2T0Q4vyfDova8PLrYItjz2msMR6NELKuisjf5boY7v/0/APof+8bXZhU8N7qGrgLOBl6NReMA84CeWDQ+BtwAjAKXALuz668BJoA3jGTCjEXjjumlPjSyciWR7q6ChREYGiq+wbJlYJpMHz9OZGjoTIFZuNB+FeP0XksdpmMuWGC/KnivJcCW66bZ9txeJvLGCJYMZ8cIzjrLfhWzcmXx5YsW2a9CXV1ML106O985yx3GJPr67FehUt/x2Wef/vMTQ0NctaH8QPhY39nF11mypPhn9PTYr2LOOefM36bJzPHjRCIRIoOD9kmhUHe3c15WrCi+vL/ffhUqV/aKcbvsdXfPLd+l3mvx4uLLC8re4uwLgP4qy14kwljf2Tz40/1Md5/5vEeeH2XDmkuLl4tqy55pYg4MFC/fuS6aYpy+lzrLnj3295vSY3/1lr3cuSwSsfNcQdmLTDpPxHQjEDwN/Eve/68AnsA+uR8CHgfuikXjO4BTwFbgibyB4HLpgeXHAcRqlLtiVjOLwqGSQeegTDUuN1HCq/msOxAYycRJ4HS7OxaNHwIsI5nYl/3//dgVil9hDyQ/C9yZ9xbl0gMtrLcX0Myi8Ch3HUWQKgSlgt6LLx/2bD5dv7LYSCYMYEHe/6exrwkoel1AuXQJJk1NrJ1Xa5VOSl1HEbQKgVPQG+zt5Pbv7vZsPnWLCWkJP19t20p+rT07dYMGrULgFPQOT2Q8nU8FAmkJv15t20p+rz0X6wYNYoWgWNAbG894Op8KBNIyQR8sd1vQas9Qe4Ugv3tsoCdSct1WKAx6Xq/4KBBISY3uj27lYLnf+tqDWHuG0hWCYseosHvstmuGuLC/RTtfBS9XfBQIxJGb/dFeO+n6sa/d67XKehSrEBQ7RusvHpzTPfbI86N8/YauYm/rOV6dJahAIEW52R/ttZOun/vavVyrdJPTMerr6SjaPTZ6ZKbY2zSV1yo71VAgkKLc6o/24knX733tXq1VusnpGLVB0e6xoUWtfdii1yo71dKjKqWoXH90vlr6o734OEu38iaN43SMPnheH1uuW3U6rSPSxuZrh+jrbiv2NkW5/SjXIDyKVIEgBA5PZNi13+TwROUFM9cfnf+Dq6U/2osn3Xry1qznQbeaW/ms9X1KHaOb1i5n+1cvZdufXcD2r17KH/+hw72cinhqx0Gu/4udbPnbV7j+L3by1I6D5Tcqw4uVnWqpayjg8pusjxkvV9VkdaM/2qsDnLXkze/N/0q5lc9636fUMcrvHjPNym5L1qhuymbN5mrklFkFggr5cSDIjYLvRn+0Vwc4K8lb7rgP9nZ6bqzDDYXl2q2TpVvv4+Z4SKPGhppR2Wn0lFkFggr4tSbopUFRPw5w5h/39vbZt+EHfw0wF1OsXL9nSZcrZcZLZS+nkTX3RlZ2igVVt6fMaoygDD8PBHmxf94vCo97YRAAb3yXtfbBO5XrwYWdrpQZL5Y9t8a98uV//4sXdnLFBQM1vV+p4+gUVN2cMqsWQRlerNlUyqv9882QGyBfvirD0v7uqrcvdtwBIu1gzrhzEqlXPd0FTuX68HjGlTLj1bLnZs29WWMpTi0ZN6fMKhCU4ffL+m9au5x1q/t54aU0G64cqemk6Df1DJDnOB33J/7rag6PZ1o+1lFvd0Gpcn3FBQOunCz9PDZUTjPHUooFVXvK7Fipt66KuobKqLY56cXphYO9nVy0MsJgrzd+iI3kVlee03F/f/ZE2eqTWr3dBeXKdSXdHJWU9Xq6S2r5vGZxa8pope9Tz5TZSqhFUIFKazZ+HVSulFdmTpXaDze78qqp0Tb7u3Gju6CeGnuzy3q9n+f28XGrp6Ca96llymylFAgqVK456cVbKdSqkjs+NiPI1bIfbnflVdKNUGqfGhUg3OouqKWbpNllvZrPa1bZdWsMxCtjKQoELvHzoHK+Su/4WM0PsZn70ewfVqmTVKOfUVtYox/oibBrl3v9xk6aXdYr/bynf/wmjzw/WnPZrZZbYyBeGEtRIHCJ3weVofo7Phb+EN2qedW7H80cIHc6Sf38teNNqTU3srvASbPLeiWfd+ykdToIQPVlplZuXR/T6utsNFiMO4NQjZij3Gzl7viYr/CH6Ob1FvXsR06zBsid5ssDrgwmelGzy3oln7fv6EzdZaZRvDTI7ST0LQI3+w+90MSrh1PNK3fHx1LdLW52F9SzH83m1BX1ofP6fN9CLKXZZb3c5w0tavdkmfHLBJJQB4JGDHq1uolXj1L96+V+iNV0F5QbRyi2H7dsWMmeAydYf/Gg54Kt03fj5gmolrGXarepdv1GlXWn/Sj1eX3d9gV1+WMErS4zfppAEupA4LUBXi9Mz6z0jo+FKh2krbSGlL8fvx49weMv7PN0rarYd+NWrbnS7yz/aup//eWxqmqiXqm51rMfm65axoY1SzxTZrx2fikl1IHASwO8XvkhQu01vXInvmprSLllt393t2u1qmYH23przZV+Z/nl59F/TWFZMJMt1uW+M6/UXN26Wy7UVma8eq1BM4R6sNgrA7zFfgDf2v4G/7zzkKcHmIopdSVpLVdjuvnQj0Y8lKTRKsl/YfkxZ84Egfxttv/0rapuatbsge1a96PwwUu1vE8jyoZXzi+VqLtFEIvG5wOPAuuBJcBB4BEjmXgkm94BPATcjB14vgfcaiQTU5WkN5oXBniLFVxzBu79h9da3jpwUy01JLdqVV6p9Varkvw73SCv0Lf/eR+Pv7C/4Rfh1aqW/Sh2X6n1Fw9W9T6NLBteOL9Uwo0WQQfwJrAR6AM2AV+NReObsul3A+uA1cAwcCHwYN725dIbzs37odSi2BTEnHqmYXpNLTWkcttUOjXPK7XealXynRUrP+1t0NE+t0wVK09eqblWux9OJ3CgqvdpdNlo9fmlEnW3CIxk4gRwT96iVCwa3w5cBTwN3ALcYSQT+wFi0fhW4JlYNP4FI5kwK0gPvMKB1kJeHWCqRS01JKdtqhlX8UqttxblvjOngfr1Fw+y/adv8e1/3jdrfaeL8LxQc61mP0qdwKt5Hz+XDbe4Plgci8bnAWuBb8Si8X5gCEjlrbIT6AXOjUXjh0ulA687fY5pmlVfSZlbv1lXYFbjxiuXsm51Pz9/bZy/eOq3TM/MLpTvW9ZV8357Ld8DPREuH14IVL5Phds41QbXre5nsLdzTp4HeiJzphduvnaIgZ4Ipmn3L7964CTvX3GWJ+/SWu47u/HKpUQvXMj/+eluPvwH57O0374d9bWXLebxF/bPOckVK0+1HJdGqHQ/3resq+gJPJe3St+nXNnwolp+06XWbcSsoUeBCeBJ4OzssmN56bm/e4FMmXRH6XSazs55Ne1gOp2uabtmWDkPbvxgB8/8+ynMGftBKDde2sHBva9S7/CVl/NdrV37zaK1wRdeSnPRyjMP9s7P84X98PUbuhg9MsPQonb6usfYtWuMF9OnZn3ff/zBeawfqa1stdpFKyO8ve813s5rBNx4aWPKkxe4lTenspFzfNLKSyvejdsK1fymM5lTjmmuBoJYNP5N4Argw0YykYlF4xPZpD7scQSA/uy/E9lXqXRHIyMjdHdX98xO0zRJp9OMjIwQiUTKrt+qWuJFF8GnPuLeZ1ebbz9YvirDY8bLc2qDG64cOd0iqCTPY+MZnv2HlzGzt/E3Z+DZndN86iO/78mWQSlOeXa7PJXTzN/NRRfBJzdMzWkJuanwZna3XTPEpqvcfR6AE6fvspbf9OTkFLC9aJprgSAWjX8Le+bQh41kYgzASCaOxaLxUeASYHd21TXYJ/k3jGTCLJVe6vMikUjNJ7VKtm31vP6l/d2u3yytnu/Ma5b2dxftFy/8zsrl+TdvTRVtWbz+5pRvn+ZWLM+NKE/FtOJ3s7S/i4tWRlja3+V6+R4bz8y5md0jz4+yYc2Sho+jVPJdVvObLrWeK4EgFo0/DHwYWGckE4cKkh8H7opF4zuAU8BW4Im8geBy6U3n16mGYePGAKcGCt0TxN9Nq64ObvZ36cZ1BKuA24B3gd/GovFc0g4jmfgocD+wGPgV9nTVZ4E7896iXHrT+enS8LCr98rdZj+/IMiC+LtpVUWh2d+lG9NH9wKOoydGMjENbM6+qk5vBdUSw8UrUyf9bGw8w/jJaTra2+bMePPz76ZVFYVmn4NCfa8hJ6olho+f7xrbavl92e1t9sVsM5a3b6lQjVZUFJp9DlIgcKBaokh5hX3ZM5Y9jfNrf3IeHzqvLzC/m1ZUFJp5DlIgKEG1RJHSnO6T1XdWh347LmjWOSjUdx8Vkfo4ParTz+MCYaRAICI188oN66Q+6hoSkbpoPM3/FAhCxguPw5Tg0XiavykQhEjhPVOC8sAbEamPxghC4thJa849U4LywBsRqY8CQUjsOzrjyyd0iUjjKRCExNCidk3zE5GiFAhCoq/bvo+6pvmJSCENFofIpquWsWHNEs0aEpFZFAhCRtP8RKSQuoZEREJOgUBEJOQUCEREQk6BQEQk5BQIRERCToFARCTkFAhEREJOgUBEJOQUCEREQk6BQEQk5BQIRKRiY+MZfvLKUT3HImB0ryERqchTOw6y7bm9esJdAHkiEMSi8Q7gIeBm7FbK94BbjWRiqqU7JiKA3RLIBQE484S79RcP6iaGAeCVrqG7gXXAamAYuBB4sKV7JCKn7TlwQk+4CzCvBIJbgPuNZGK/kUwcArYCfxqLxiOt3S0RARhe0aMn3AVYy7uGYtF4PzAEpPIW7wR6gXOB14ttZ5ompmlW9Vm59avdzu/CmG/l2V0DPRFuu2aIR54fPT1GsPnaIQZ6Ii3/jnWsq9ummJYHAuwTPsCxvGXHCtLmSKfTdHbOq+kD0+l0Tdv5XRjzrTy758J++PoNXYwemWFoUTt93WPs2jXWkM+qhY51aZnMKcc0LwSCiey/fcCb2b/7C9LmGBkZobu7q6oPMk2TdDrNyMgIkUh4ep3CmG/lORx5hnDmu5Y8T05OAduLprU8EBjJxLFYND4KXALszi5egx0E3nDaLhKJ1HzQ69nWz8KYb+U5PMKY72ryXGq9lgeCrMeBu2LR+A7gFPZg8RNGMhGeTj8RkRbxSiC4H1gM/Ap7JtOzwJ0t3SMRkZDwRCAwkolpYHP2JSIiTeSJQFCLyanqLzo2TZNM5hSTk1Oh6ksMY76V53DkGcKZ71ryXOqc2WZZlmOiF936pXuHgN+1ej9ERHzqPY9942uj+Qv82CLYB7wHGG/1joiI+MxC7HPoLL5rEYiIiLu8cq8hERFpEQUCEZGQUyAQEQk5BQIRkZDz46yhmgT9KWixaHw+8CiwHlgCHAQeMZKJR7Lpgc4/QCwa7wZ+CSwzkokF2WWBzXcsGr8GuA84H/veXA8ZycRfBjzPy7HL+dVAG7AD+LyRTOwLSr5j0fgm7ItrLwHGjGTi3Ly0knms9TsIU4sg6E9B68C+e+tG7Du5bgK+mi1UEPz8A3wN2FuwLJD5jkXjG4G/Af4c+3i/H/hhNjmQec76a6ATeC/2c0xOAN/NpgUl30exg91XiqSVy2NN30GYAkGgn4JmJBMnjGTiHiOZeM1IJmaMZCKFfc/Zq7KrBDr/sWj8g8BHgAcKkoKa7/uA+4xk4kUjmZg2kolxI5nYlU0Lap4B3gc8YyQTE0YycRL4R+AD2bRA5NtIJl4wkon/xdxKDZTPY03fQSi6hmp9CpqfxaLxecBa4BtBz3+2Ofy3wK3kVW6Cmu9YNN4DXAb8MBaNvwIMAD8FtmDXJgOX5zzfBG6MRePbARO7C+S5oB7rfOXyGIvGD5dKp8R3EJYWQU1PQfO5R7H7jZ8k+Pn/c+D/GclEsmB5UPM9gN0//kfYraD3YncLfp/g5jnnx9gPrjqCna/zsbtDgp5vKJ/Hmr+DsASC/Keg5fQXpAVGLBr/JnAF8FEjmcgQ4PzHovHzgM9iB4NCQc13bt+3GcnEG9kukruxBxdzT5gPWp6JRePtwL8AP8e+VcIC4H8DBpAbDA1cvvOUK881l/dQBAIjmTgG5J6CllP2KWh+FIvGvwVsANYbycQYBD7/VwFnA6/GovEx4J+AnuzfHyCA+TaSiePY/cdO94cJXJ6zFgGrgIeNZOIdI5mYxO4quhAYJLj5Bsr/juv5nYfmXkOxaPxe4AbgY9hPQfsn4OdGMhGYZyDEovGHgQ8D67IDRflpgcx/LBo/C/sEkXMF8AR2l8Eh7AccBTHfXwb+BLgGO59/BVxmJBMfCuqxBohF43uwWwH3Yo8R3AF8EViR/dv3+c4O7M4DrgO+gV2WLSOZeLfcsa312IdisDgr0E9Bi0Xjq4DbgHeB38ai8VzSDiOZ+CgBzX+2W+Rk7v+xaPwQ9o9mX/b/gcw39pTAAezBwHbsvvMbsmlBzTPAx7FbAfuw87YLuNZIJqYCdKxvBv4+7/+T2C3Acyl/bGv6DkLTIhARkeJCMUYgIiLOFAhEREJOgUBEJOQUCEREQk6BQEQk5BQIRERCToFARCTkFAhEREJOgUBEJOT+P+1C0S/zenFQAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "test_scores = model.rec_error(data_test)\n",
    "scores = test_scores.detach().cpu().numpy()\n",
    "plt.plot(scores, 'o')\n",
    "plt.axhline(y=np.mean(scores), label='mean', linestyle='--', color='red')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "22.486663584980334"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from scipy import stats\n",
    "# test from train doesn't seem to be that far off!\n",
    "stats.wasserstein_distance(train_scores, scores)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### This example shows randomly generated movies \n",
    "drawn from ~ Normal(0, 0.2):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "scores = model.rec_error(torch.tensor(np.random.normal(0, 0.2, [100, 128])).to(cuda).float())\n",
    "scores = scores.detach().cpu().numpy()\n",
    "plt.plot(scores, 'o')\n",
    "plt.axhline(y=np.mean(scores), label='mean', linestyle='--', color='red')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "399.0211505168499"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stats.wasserstein_distance(train_scores, scores) # something doesnt quiet match here"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Here is that nasty -1 tensor\n",
    "Normal distro was used to add some of variance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([136.6106], device='cuda:0')"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.rec_error(torch.tensor([-1] * 128).unsqueeze(0).to(cuda).float())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "scores = model.rec_error(torch.tensor(np.random.normal(-1, 0.2, [100, 128])).to(cuda).float())\n",
    "scores = scores.detach().cpu().numpy()\n",
    "plt.plot(scores, 'o')\n",
    "plt.axhline(y=np.mean(scores), label='mean', linestyle='--', color='red')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "264.0437043496098"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stats.wasserstein_distance(train_scores, scores) # oh oh! Look at the number at the bottom!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## As you can see it works just fine!\n",
    "The key thing here is to use the WS distance as the metric and not just look at the scores.\n",
    "Anyway, as in any neural networks setup, our actor will be acting in batches. We will sample the generated films batch, feed it into the autoencoder, perform MSE with the ground truth and get the reconstruction score distribution. Then we will see how closely it resembles the real one using Wasserstein-Gromov metric.\n",
    "### Anyway here are some cool KDE visualizations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_scores = model.rec_error(data).detach().cpu().numpy()\n",
    "train_kernel = stats.gaussian_kde(train_scores)\n",
    "test_scores = model.rec_error(data_test).detach().cpu().numpy()\n",
    "test_kernel = stats.gaussian_kde(test_scores)\n",
    "x = np.linspace(0,1000, 100)\n",
    "probs_train = train_kernel(x)\n",
    "probs_test = test_kernel(x)\n",
    "plt.plot(x, probs_train, '-b', label='train dist')\n",
    "plt.plot(x, probs_test, '-r', label='test dist')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "count    27178.000000\n",
      "mean       405.222748\n",
      "std        202.811554\n",
      "min          5.092957\n",
      "25%        259.896370\n",
      "50%        341.583618\n",
      "75%        506.556114\n",
      "max       4608.396973\n",
      "dtype: float64\n",
      "count     100.000000\n",
      "mean      396.920502\n",
      "std       211.813919\n",
      "min        12.653063\n",
      "25%       244.549824\n",
      "50%       315.021576\n",
      "75%       536.957306\n",
      "max      1110.174561\n",
      "dtype: float64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "print(pd.Series(train_scores).describe())\n",
    "print(pd.Series(test_scores).describe())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "torch.save(model.state_dict(), \"../../models/anomaly.pt\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.8.5 64-bit",
   "language": "python",
   "name": "python38564bitfba12b29602d49fd94d253df959599f4"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}