{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The autoreload extension is already loaded. To reload it, use:\n",
      "  %reload_ext autoreload\n",
      "Found 2 sessions\n",
      "Session 'Beaver_01' at folder: /home/kleinsteuber/vscode/ResizedSessions256_NoBackup/VIELAAS_Spring_Session01-VIELAAS_Beaver_01\n",
      "Loaded scans.\n"
     ]
    }
   ],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "import numpy as np\n",
    "from sklearn.neighbors import KernelDensity\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "import pandas as pd\n",
    "import torch\n",
    "from glob import glob\n",
    "\n",
    "from py.Dataset import Dataset\n",
    "from py.FileUtils import load\n",
    "from py.PlotUtils import plot_roc_curve, get_percentiles\n",
    "from py.PyTorchData import get_log, create_dataloader, model_output_to_image\n",
    "from py.Labels import LABELS\n",
    "from py.Autoencoder2 import Autoencoder\n",
    "from py.ImageUtils import display_images\n",
    "\n",
    "DIR = '/home/kleinsteuber/vscode/ResizedSessions256_NoBackup' # dataset directory\n",
    "SESSION = \"beaver_01\"\n",
    "TRAIN_NAME = \"ae2_deep_noise_sparse\"\n",
    "\n",
    "ds = Dataset(DIR)\n",
    "session = ds.create_session(SESSION)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20536 characters]",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "its, losses = get_log(TRAIN_NAME, display=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Autoencoder(\n",
       "  (encoder): Sequential(\n",
       "    (0): Dropout(p=0.1, inplace=False)\n",
       "    (1): Conv2d(3, 32, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))\n",
       "    (2): ReLU(inplace=True)\n",
       "    (3): Dropout(p=0.1, inplace=False)\n",
       "    (4): Conv2d(32, 64, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2))\n",
       "    (5): ReLU(inplace=True)\n",
       "    (6): Dropout(p=0.1, inplace=False)\n",
       "    (7): Conv2d(64, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
       "    (8): ReLU(inplace=True)\n",
       "    (9): Dropout(p=0.1, inplace=False)\n",
       "    (10): Conv2d(64, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
       "    (11): ReLU(inplace=True)\n",
       "    (12): Dropout(p=0.1, inplace=False)\n",
       "    (13): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
       "    (14): ReLU(inplace=True)\n",
       "    (15): Dropout(p=0.1, inplace=False)\n",
       "    (16): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
       "    (17): ReLU(inplace=True)\n",
       "    (18): Dropout(p=0.1, inplace=False)\n",
       "    (19): Conv2d(128, 32, kernel_size=(3, 3), stride=(1, 1), padding=same)\n",
       "    (20): ReLU(inplace=True)\n",
       "  )\n",
       "  (decoder): Sequential(\n",
       "    (0): Dropout(p=0.1, inplace=False)\n",
       "    (1): Conv2d(32, 128, kernel_size=(3, 3), stride=(1, 1), padding=same)\n",
       "    (2): ReLU(inplace=True)\n",
       "    (3): Dropout(p=0.1, inplace=False)\n",
       "    (4): ConvTranspose2d(128, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))\n",
       "    (5): ReLU(inplace=True)\n",
       "    (6): Dropout(p=0.1, inplace=False)\n",
       "    (7): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))\n",
       "    (8): ReLU(inplace=True)\n",
       "    (9): Dropout(p=0.1, inplace=False)\n",
       "    (10): ConvTranspose2d(64, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))\n",
       "    (11): ReLU(inplace=True)\n",
       "    (12): Dropout(p=0.1, inplace=False)\n",
       "    (13): ConvTranspose2d(64, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))\n",
       "    (14): ReLU(inplace=True)\n",
       "    (15): Dropout(p=0.1, inplace=False)\n",
       "    (16): ConvTranspose2d(64, 32, kernel_size=(6, 6), stride=(2, 2), padding=(2, 2))\n",
       "    (17): ReLU(inplace=True)\n",
       "    (18): Dropout(p=0.1, inplace=False)\n",
       "    (19): ConvTranspose2d(32, 16, kernel_size=(8, 8), stride=(2, 2), padding=(3, 3))\n",
       "    (20): ReLU(inplace=True)\n",
       "    (21): Dropout(p=0.1, inplace=False)\n",
       "    (22): Conv2d(16, 3, kernel_size=(3, 3), stride=(1, 1), padding=same)\n",
       "    (23): Tanh()\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_path = sorted(glob(f\"./ae_train_NoBackup/{TRAIN_NAME}/model_*.pth\"))[-1]\n",
    "model = Autoencoder()\n",
    "model.load_state_dict(torch.load(model_path, map_location=torch.device(\"cpu\")))\n",
    "model.eval()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "695 files found\n"
     ]
    }
   ],
   "source": [
    "def labeler(filename: str) -> int:\n",
    "    is_normal = (int(filename[10:-4]) in LABELS[session.name][\"normal\"])\n",
    "    return 0 if is_normal else 1\n",
    "\n",
    "def is_labeled(filename: str) -> bool:\n",
    "    return int(filename[10:-4]) <= LABELS[session.name][\"max\"]\n",
    "\n",
    "test_dl = create_dataloader(session.get_motion_folder(), shuffle=False, labeler=labeler, filter=is_labeled, skip_transforms=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Feature batch shape: torch.Size([32, 3, 256, 256])\n",
      "Labels batch shape: torch.Size([32])\n"
     ]
    }
   ],
   "source": [
    "features, labels = next(iter(test_dl))\n",
    "print(f\"Feature batch shape: {features.size()}\")\n",
    "print(f\"Labels batch shape: {labels.size()}\")\n",
    "input_imgs = model_output_to_image(features).detach()\n",
    "output_imgs = model_output_to_image(model(features)).detach()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 4008404 characters]",
      "text/plain": [
       "<Figure size 1152x2304 with 32 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dimgs = []\n",
    "dlbls = []\n",
    "only_normals = False\n",
    "for i in range(32 if only_normals else 16):\n",
    "    if only_normals and labels[i] == 1:\n",
    "        continue\n",
    "    lbl = \"anomalous\" if labels[i] == 1 else \"normal\"\n",
    "    dimgs += [np.einsum(\"ijk->jki\", input_imgs[i]), np.einsum(\"ijk->jki\", output_imgs[i])]\n",
    "    dlbls += [f\"In {i} ({lbl})\", f\"Out {i}\"]\n",
    "display_images(dimgs, dlbls, size=(4, 4), row_size=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "lapse_losses, lapse_encodings, lapse_labels = load(f\"./ae_train_NoBackup/{TRAIN_NAME}/eval/{session.name}_lapse.pickle\")\n",
    "motion_losses, motion_encodings, motion_labels = load(f\"./ae_train_NoBackup/{TRAIN_NAME}/eval/{session.name}_motion.pickle\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "kde = KernelDensity(kernel=\"gaussian\", bandwidth=0.2).fit(lapse_encodings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "preds = kde.score_samples(motion_encodings)\n",
    "y_anom = preds[motion_labels == 1]\n",
    "y_norm = preds[motion_labels == 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "count    7.400000e+01\n",
       "mean    -2.073727e+07\n",
       "std      6.007246e+07\n",
       "min     -3.089760e+08\n",
       "25%     -1.017565e+07\n",
       "50%     -7.924425e+06\n",
       "75%     -2.720522e+06\n",
       "max      3.167954e+02\n",
       "dtype: float64"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.Series(y_norm).describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "count    6.210000e+02\n",
       "mean    -2.110057e+08\n",
       "std      3.090626e+08\n",
       "min     -1.801623e+09\n",
       "25%     -1.874621e+08\n",
       "50%     -7.601582e+07\n",
       "75%     -4.367579e+07\n",
       "max     -7.580517e+05\n",
       "dtype: float64"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.Series(y_anom).describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "mode = \"kde\"\n",
    "\n",
    "if mode == \"kde\":\n",
    "    y_anom = preds[motion_labels == 1]\n",
    "    y_norm = preds[motion_labels == 0]\n",
    "    X = np.concatenate([y_norm, y_anom]).reshape((-1, 1))\n",
    "    y = np.concatenate([-np.ones_like(y_norm), np.ones_like(y_anom)])\n",
    "elif mode == \"loss\":\n",
    "    y_anom = motion_losses[motion_labels == 1]\n",
    "    y_norm = motion_losses[motion_labels == 0]\n",
    "    X = np.concatenate([y_norm, y_anom]).reshape((-1, 1))\n",
    "    y = np.concatenate([-np.ones_like(y_norm), np.ones_like(y_anom)])\n",
    "else:\n",
    "    raise ValueError(\"unknown mode\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 22324 characters]",
      "text/plain": [
       "<Figure size 576x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9 percentile : TPR = 0.9050, FPR = 0.1486 <-> TNR = 0.8514 @ thresh 17550323.86403683\n",
      "0.95 percentile : TPR = 0.9517, FPR = 0.3108 <-> TNR = 0.6892 @ thresh 8964006.018924074\n",
      "0.98 percentile : TPR = 0.9807, FPR = 0.6892 <-> TNR = 0.3108 @ thresh 2973684.7084381217\n",
      "0.99 percentile : TPR = 0.9903, FPR = 0.8784 <-> TNR = 0.1216 @ thresh 1865040.012273987\n"
     ]
    }
   ],
   "source": [
    "fpr, tpr, thresholds, auc_score = plot_roc_curve(y, -X[:,0], f\"Autoencoder {mode}\", savefile=f\"plots/approach4/roc_curves/{session.name}_{mode}\")\n",
    "get_percentiles(fpr, tpr, thresholds)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## AUC Scores\n",
    "\n",
    "### Beaver_01\n",
    "\n",
    "| Mode | AUC |\n",
    "| --- | ---: |\n",
    "| Loss | 0.5549 |\n",
    "| KDE | 0.9209 |\n",
    "| KDE + Loss | 0.9209 |\n",
    "\n",
    "### Marten_01\n",
    "\n",
    "| Mode | AUC |\n",
    "| --- | ---: |\n",
    "| Loss | 0.8499 |\n",
    "| KDE | 1.0 |\n",
    "| KDE + Loss | 1.0 |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.4 ('pytorch-gpu')",
   "language": "python",
   "name": "python3"
  },
  "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.10.4"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "17cd5c528a3345b75540c61f907eece919c031d57a2ca1e5653325af249173c9"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
