diff --git a/DL/recommender_system/.gitignore b/DL/recommender_system/.gitignore
new file mode 100644
index 0000000..5084e53
--- /dev/null
+++ b/DL/recommender_system/.gitignore
@@ -0,0 +1,3 @@
+*.csv
+.ipynb_checkpoints
+*.pth
diff --git a/DL/recommender_system/nn.ipynb b/DL/recommender_system/nn.ipynb
new file mode 100644
index 0000000..0c8f839
--- /dev/null
+++ b/DL/recommender_system/nn.ipynb
@@ -0,0 +1,1954 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "29b5381a-72b4-4f81-9208-2075f7acad85",
+ "metadata": {},
+ "source": [
+ "# Recommender System using Neural Network"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cac03d32",
+ "metadata": {},
+ "source": [
+ "Configure the project. Indeed you create a dataset in csv format."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "6f480cda-8380-4355-998a-5c59d6203b05",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Archive: ./dataset/archive.zip\n",
+ " inflating: anime.csv \n",
+ " inflating: animelist.csv \n",
+ " inflating: anime_with_synopsis.csv \n",
+ " inflating: rating_complete.csv \n"
+ ]
+ }
+ ],
+ "source": [
+ "! rm -rf *.csv\n",
+ "! unzip ./dataset/archive.zip\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "db1f7e48",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "total 2.7G\n",
+ "-rw-r--r-- 1 andre andre 5.5M Jul 13 2021 anime.csv\n",
+ "-rw-r--r-- 1 andre andre 6.9M Jul 13 2021 anime_with_synopsis.csv\n",
+ "-rw-r--r-- 1 andre andre 1.9G Jul 13 2021 animelist.csv\n",
+ "-rw-r--r-- 1 andre andre 781M Jul 13 2021 rating_complete.csv\n",
+ "drwxr-xr-x 6 andre andre 4.0K Sep 14 12:48 ..\n",
+ "drwxr-xr-x 2 andre andre 4.0K Sep 25 18:58 dataset\n",
+ "-rw-r--r-- 1 andre andre 198K Sep 26 15:26 best_anime_model.pth\n",
+ "-rw-r--r-- 1 andre andre 11K Sep 27 00:50 nn.py\n",
+ "-rw-r--r-- 1 andre andre 195K Sep 27 01:09 best_model.pth\n",
+ "drwxr-xr-x 3 andre andre 4.0K Sep 27 01:11 .\n",
+ "-rw-r--r-- 1 andre andre 193K Sep 27 01:11 nn.ipynb\n"
+ ]
+ }
+ ],
+ "source": [
+ "! ls -ltrha"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52ec2f48",
+ "metadata": {},
+ "source": [
+ "Import needed libraries"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "dd17f780",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import torch\n",
+ "import torch.nn as nn\n",
+ "import torch.optim as optim\n",
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "from sklearn.preprocessing import StandardScaler\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from torch.utils.data import TensorDataset, DataLoader\n",
+ "import matplotlib.pyplot as plt\n",
+ "from tqdm import tqdm\n",
+ "\n",
+ "%matplotlib inline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "aec5c99e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Using device: cpu\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/andre/miniconda3/envs/venv/lib/python3.12/site-packages/torch/cuda/__init__.py:128: UserWarning: CUDA initialization: CUDA unknown error - this may be due to an incorrectly set up environment, e.g. changing env variable CUDA_VISIBLE_DEVICES after program start. Setting the available devices to be zero. (Triggered internally at ../c10/cuda/CUDAFunctions.cpp:108.)\n",
+ " return torch._C._cuda_getDeviceCount() > 0\n"
+ ]
+ }
+ ],
+ "source": [
+ "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
+ "print(f'Using device: {device}')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57b33a77",
+ "metadata": {},
+ "source": [
+ "Read data from csv files using pandas and store in data frame structure. Also shuffle data to have uniform distribution. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "a102a751",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "anime_df = pd.read_csv(\"anime.csv\")\n",
+ "anime_df = anime_df.sample(frac=1.0, random_state=42).reset_index(drop=True)\n",
+ "\n",
+ "anime_synopsis_df = pd.read_csv(\"anime_with_synopsis.csv\")\n",
+ "anime_synopsis_df = anime_synopsis_df.sample(frac=1.0, random_state=42).reset_index(drop=True)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "639afef8",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " MAL_ID | \n",
+ " Name | \n",
+ " Score | \n",
+ " Genres | \n",
+ " English name | \n",
+ " Japanese name | \n",
+ " Type | \n",
+ " Episodes | \n",
+ " Aired | \n",
+ " Premiered | \n",
+ " ... | \n",
+ " Score-10 | \n",
+ " Score-9 | \n",
+ " Score-8 | \n",
+ " Score-7 | \n",
+ " Score-6 | \n",
+ " Score-5 | \n",
+ " Score-4 | \n",
+ " Score-3 | \n",
+ " Score-2 | \n",
+ " Score-1 | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 40176 | \n",
+ " Miru Tights: Cosplay Satsuei Tights | \n",
+ " 6.53 | \n",
+ " Ecchi, School | \n",
+ " Unknown | \n",
+ " みるタイツ コスプレ撮影 タイツ | \n",
+ " Special | \n",
+ " 1 | \n",
+ " Aug 23, 2019 | \n",
+ " Unknown | \n",
+ " ... | \n",
+ " 875.0 | \n",
+ " 350.0 | \n",
+ " 762.0 | \n",
+ " 1526.0 | \n",
+ " 1542.0 | \n",
+ " 924.0 | \n",
+ " 384.0 | \n",
+ " 245.0 | \n",
+ " 162.0 | \n",
+ " 148.0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 13969 | \n",
+ " Thermae Romae x Yoyogi Animation Gakuin Collab... | \n",
+ " 6.29 | \n",
+ " Comedy, Historical, Seinen | \n",
+ " Unknown | \n",
+ " テルマエ・ロマエx代々木アニメーション学院企業コラボレーション | \n",
+ " Special | \n",
+ " 1 | \n",
+ " Jul 9, 2012 | \n",
+ " Unknown | \n",
+ " ... | \n",
+ " 35.0 | \n",
+ " 47.0 | \n",
+ " 114.0 | \n",
+ " 253.0 | \n",
+ " 240.0 | \n",
+ " 162.0 | \n",
+ " 63.0 | \n",
+ " 29.0 | \n",
+ " 10.0 | \n",
+ " 10.0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 13459 | \n",
+ " Ribbon-chan | \n",
+ " Unknown | \n",
+ " Comedy | \n",
+ " Unknown | \n",
+ " リボンちゃん | \n",
+ " TV | \n",
+ " 24 | \n",
+ " Apr 4, 2012 to Mar 27, 2013 | \n",
+ " Spring 2012 | \n",
+ " ... | \n",
+ " 7.0 | \n",
+ " Unknown | \n",
+ " Unknown | \n",
+ " 2.0 | \n",
+ " 2.0 | \n",
+ " 4.0 | \n",
+ " 1.0 | \n",
+ " Unknown | \n",
+ " 2.0 | \n",
+ " 7.0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 15617 | \n",
+ " Jinrui wa Suitai Shimashita Specials | \n",
+ " 7.23 | \n",
+ " Comedy, Fantasy, Seinen | \n",
+ " Humanity Has Declined Specials | \n",
+ " 人類は衰退しました | \n",
+ " Special | \n",
+ " 6 | \n",
+ " Sep 19, 2012 to Feb 20, 2013 | \n",
+ " Unknown | \n",
+ " ... | \n",
+ " 451.0 | \n",
+ " 885.0 | \n",
+ " 2432.0 | \n",
+ " 3038.0 | \n",
+ " 1388.0 | \n",
+ " 588.0 | \n",
+ " 130.0 | \n",
+ " 38.0 | \n",
+ " 22.0 | \n",
+ " 19.0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 19157 | \n",
+ " Youkai Watch | \n",
+ " 6.54 | \n",
+ " Comedy, Demons, Kids, Supernatural | \n",
+ " Yo-kai Watch | \n",
+ " 妖怪ウォッチ | \n",
+ " TV | \n",
+ " 214 | \n",
+ " Jan 8, 2014 to Mar 30, 2018 | \n",
+ " Winter 2014 | \n",
+ " ... | \n",
+ " 517.0 | \n",
+ " 532.0 | \n",
+ " 1141.0 | \n",
+ " 1912.0 | \n",
+ " 1636.0 | \n",
+ " 1196.0 | \n",
+ " 500.0 | \n",
+ " 228.0 | \n",
+ " 138.0 | \n",
+ " 125.0 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 17557 | \n",
+ " 32238 | \n",
+ " Watashi wa, Kairaku Izonshou | \n",
+ " 6.2 | \n",
+ " Hentai | \n",
+ " Unknown | \n",
+ " 私は、快楽依存症 | \n",
+ " OVA | \n",
+ " 2 | \n",
+ " Feb 26, 2016 to May 20, 2016 | \n",
+ " Unknown | \n",
+ " ... | \n",
+ " 117.0 | \n",
+ " 96.0 | \n",
+ " 197.0 | \n",
+ " 329.0 | \n",
+ " 363.0 | \n",
+ " 216.0 | \n",
+ " 110.0 | \n",
+ " 49.0 | \n",
+ " 52.0 | \n",
+ " 52.0 | \n",
+ "
\n",
+ " \n",
+ " 17558 | \n",
+ " 33552 | \n",
+ " Mameshiba Bangai-hen | \n",
+ " 5.75 | \n",
+ " Music, Comedy | \n",
+ " Unknown | \n",
+ " 豆しば番外編 | \n",
+ " Special | \n",
+ " 5 | \n",
+ " 2008 to Jun 20, 2019 | \n",
+ " Unknown | \n",
+ " ... | \n",
+ " 8.0 | \n",
+ " 2.0 | \n",
+ " 6.0 | \n",
+ " 8.0 | \n",
+ " 24.0 | \n",
+ " 47.0 | \n",
+ " 11.0 | \n",
+ " 6.0 | \n",
+ " 2.0 | \n",
+ " 12.0 | \n",
+ "
\n",
+ " \n",
+ " 17559 | \n",
+ " 8476 | \n",
+ " Otome Youkai Zakuro | \n",
+ " 7.47 | \n",
+ " Demons, Historical, Military, Romance, Seinen,... | \n",
+ " Zakuro | \n",
+ " おとめ妖怪 ざくろ | \n",
+ " TV | \n",
+ " 13 | \n",
+ " Oct 5, 2010 to Dec 28, 2010 | \n",
+ " Fall 2010 | \n",
+ " ... | \n",
+ " 3237.0 | \n",
+ " 5815.0 | \n",
+ " 12079.0 | \n",
+ " 12757.0 | \n",
+ " 5674.0 | \n",
+ " 2383.0 | \n",
+ " 688.0 | \n",
+ " 234.0 | \n",
+ " 99.0 | \n",
+ " 81.0 | \n",
+ "
\n",
+ " \n",
+ " 17560 | \n",
+ " 953 | \n",
+ " Jyu Oh Sei | \n",
+ " 7.26 | \n",
+ " Action, Sci-Fi, Adventure, Mystery, Drama, Shoujo | \n",
+ " Jyu-Oh-Sei:Planet of the Beast King | \n",
+ " 獣王星 | \n",
+ " TV | \n",
+ " 11 | \n",
+ " Apr 14, 2006 to Jun 23, 2006 | \n",
+ " Spring 2006 | \n",
+ " ... | \n",
+ " 2193.0 | \n",
+ " 3886.0 | \n",
+ " 7188.0 | \n",
+ " 8062.0 | \n",
+ " 4360.0 | \n",
+ " 2140.0 | \n",
+ " 934.0 | \n",
+ " 302.0 | \n",
+ " 172.0 | \n",
+ " 148.0 | \n",
+ "
\n",
+ " \n",
+ " 17561 | \n",
+ " 39769 | \n",
+ " Kimi ni Sekai | \n",
+ " 6.7 | \n",
+ " Sci-Fi, Music, Fantasy | \n",
+ " Unknown | \n",
+ " 君に世界 | \n",
+ " Music | \n",
+ " 1 | \n",
+ " Apr 20, 2019 | \n",
+ " Unknown | \n",
+ " ... | \n",
+ " 48.0 | \n",
+ " 42.0 | \n",
+ " 72.0 | \n",
+ " 181.0 | \n",
+ " 134.0 | \n",
+ " 64.0 | \n",
+ " 17.0 | \n",
+ " 13.0 | \n",
+ " 7.0 | \n",
+ " 4.0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
17562 rows × 35 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " MAL_ID Name Score \\\n",
+ "0 40176 Miru Tights: Cosplay Satsuei Tights 6.53 \n",
+ "1 13969 Thermae Romae x Yoyogi Animation Gakuin Collab... 6.29 \n",
+ "2 13459 Ribbon-chan Unknown \n",
+ "3 15617 Jinrui wa Suitai Shimashita Specials 7.23 \n",
+ "4 19157 Youkai Watch 6.54 \n",
+ "... ... ... ... \n",
+ "17557 32238 Watashi wa, Kairaku Izonshou 6.2 \n",
+ "17558 33552 Mameshiba Bangai-hen 5.75 \n",
+ "17559 8476 Otome Youkai Zakuro 7.47 \n",
+ "17560 953 Jyu Oh Sei 7.26 \n",
+ "17561 39769 Kimi ni Sekai 6.7 \n",
+ "\n",
+ " Genres \\\n",
+ "0 Ecchi, School \n",
+ "1 Comedy, Historical, Seinen \n",
+ "2 Comedy \n",
+ "3 Comedy, Fantasy, Seinen \n",
+ "4 Comedy, Demons, Kids, Supernatural \n",
+ "... ... \n",
+ "17557 Hentai \n",
+ "17558 Music, Comedy \n",
+ "17559 Demons, Historical, Military, Romance, Seinen,... \n",
+ "17560 Action, Sci-Fi, Adventure, Mystery, Drama, Shoujo \n",
+ "17561 Sci-Fi, Music, Fantasy \n",
+ "\n",
+ " English name Japanese name \\\n",
+ "0 Unknown みるタイツ コスプレ撮影 タイツ \n",
+ "1 Unknown テルマエ・ロマエx代々木アニメーション学院企業コラボレーション \n",
+ "2 Unknown リボンちゃん \n",
+ "3 Humanity Has Declined Specials 人類は衰退しました \n",
+ "4 Yo-kai Watch 妖怪ウォッチ \n",
+ "... ... ... \n",
+ "17557 Unknown 私は、快楽依存症 \n",
+ "17558 Unknown 豆しば番外編 \n",
+ "17559 Zakuro おとめ妖怪 ざくろ \n",
+ "17560 Jyu-Oh-Sei:Planet of the Beast King 獣王星 \n",
+ "17561 Unknown 君に世界 \n",
+ "\n",
+ " Type Episodes Aired Premiered ... \\\n",
+ "0 Special 1 Aug 23, 2019 Unknown ... \n",
+ "1 Special 1 Jul 9, 2012 Unknown ... \n",
+ "2 TV 24 Apr 4, 2012 to Mar 27, 2013 Spring 2012 ... \n",
+ "3 Special 6 Sep 19, 2012 to Feb 20, 2013 Unknown ... \n",
+ "4 TV 214 Jan 8, 2014 to Mar 30, 2018 Winter 2014 ... \n",
+ "... ... ... ... ... ... \n",
+ "17557 OVA 2 Feb 26, 2016 to May 20, 2016 Unknown ... \n",
+ "17558 Special 5 2008 to Jun 20, 2019 Unknown ... \n",
+ "17559 TV 13 Oct 5, 2010 to Dec 28, 2010 Fall 2010 ... \n",
+ "17560 TV 11 Apr 14, 2006 to Jun 23, 2006 Spring 2006 ... \n",
+ "17561 Music 1 Apr 20, 2019 Unknown ... \n",
+ "\n",
+ " Score-10 Score-9 Score-8 Score-7 Score-6 Score-5 Score-4 Score-3 \\\n",
+ "0 875.0 350.0 762.0 1526.0 1542.0 924.0 384.0 245.0 \n",
+ "1 35.0 47.0 114.0 253.0 240.0 162.0 63.0 29.0 \n",
+ "2 7.0 Unknown Unknown 2.0 2.0 4.0 1.0 Unknown \n",
+ "3 451.0 885.0 2432.0 3038.0 1388.0 588.0 130.0 38.0 \n",
+ "4 517.0 532.0 1141.0 1912.0 1636.0 1196.0 500.0 228.0 \n",
+ "... ... ... ... ... ... ... ... ... \n",
+ "17557 117.0 96.0 197.0 329.0 363.0 216.0 110.0 49.0 \n",
+ "17558 8.0 2.0 6.0 8.0 24.0 47.0 11.0 6.0 \n",
+ "17559 3237.0 5815.0 12079.0 12757.0 5674.0 2383.0 688.0 234.0 \n",
+ "17560 2193.0 3886.0 7188.0 8062.0 4360.0 2140.0 934.0 302.0 \n",
+ "17561 48.0 42.0 72.0 181.0 134.0 64.0 17.0 13.0 \n",
+ "\n",
+ " Score-2 Score-1 \n",
+ "0 162.0 148.0 \n",
+ "1 10.0 10.0 \n",
+ "2 2.0 7.0 \n",
+ "3 22.0 19.0 \n",
+ "4 138.0 125.0 \n",
+ "... ... ... \n",
+ "17557 52.0 52.0 \n",
+ "17558 2.0 12.0 \n",
+ "17559 99.0 81.0 \n",
+ "17560 172.0 148.0 \n",
+ "17561 7.0 4.0 \n",
+ "\n",
+ "[17562 rows x 35 columns]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "anime_df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "ac373668",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " MAL_ID | \n",
+ " Name | \n",
+ " Score | \n",
+ " Genres | \n",
+ " sypnopsis | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 1220 | \n",
+ " Hoshizora Kiseki | \n",
+ " 5.8 | \n",
+ " Romance, Sci-Fi | \n",
+ " Kozue is a girl who loves astronomy, particula... | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 38407 | \n",
+ " Ishii Hiroyuki x Saitou Souma Essay-shuu | \n",
+ " Unknown | \n",
+ " Space | \n",
+ " advertisement for a photo and essay collection... | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 2705 | \n",
+ " Bakusou Kyoudai Let's & Go | \n",
+ " 6.78 | \n",
+ " Adventure, Cars, Sports, Shounen | \n",
+ " Based on the manga by Tetsuhiro Koshita, Bakus... | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 18829 | \n",
+ " Hello Kitty no Shiawase no Aoi Hotaru | \n",
+ " Unknown | \n",
+ " Kids | \n",
+ " p to camping with Kitty and her class. | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 9014 | \n",
+ " Kuttsukiboshi | \n",
+ " 6.12 | \n",
+ " Romance, Supernatural, Drama, Shoujo Ai | \n",
+ " To Kiiko Kawakami, there was nothing in the wo... | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 16209 | \n",
+ " 38009 | \n",
+ " Re:Stage! Dream Days♪ | \n",
+ " 6.69 | \n",
+ " Music, School, Slice of Life | \n",
+ " ana Shikimiya has just transferred into Mareho... | \n",
+ "
\n",
+ " \n",
+ " 16210 | \n",
+ " 10348 | \n",
+ " Fireball Charming | \n",
+ " 6.8 | \n",
+ " Sci-Fi | \n",
+ " 3D computer animation about a female robot duc... | \n",
+ "
\n",
+ " \n",
+ " 16211 | \n",
+ " 979 | \n",
+ " Street Fighter Zero The Animation | \n",
+ " 6.55 | \n",
+ " Action, Drama, Martial Arts, Shounen, Super Power | \n",
+ " u, the current Street Fighter champion, must o... | \n",
+ "
\n",
+ " \n",
+ " 16212 | \n",
+ " 42826 | \n",
+ " Seijo no Maryoku wa Bannou Desu | \n",
+ " Unknown | \n",
+ " Romance, Fantasy | \n",
+ " Sei, a 20-year-old office worker, is whisked a... | \n",
+ "
\n",
+ " \n",
+ " 16213 | \n",
+ " 20047 | \n",
+ " Sakura Trick | \n",
+ " 7.02 | \n",
+ " Slice of Life, Comedy, Romance, School, Seinen... | \n",
+ " Having been best friends since middle school, ... | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
16214 rows × 5 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " MAL_ID Name Score \\\n",
+ "0 1220 Hoshizora Kiseki 5.8 \n",
+ "1 38407 Ishii Hiroyuki x Saitou Souma Essay-shuu Unknown \n",
+ "2 2705 Bakusou Kyoudai Let's & Go 6.78 \n",
+ "3 18829 Hello Kitty no Shiawase no Aoi Hotaru Unknown \n",
+ "4 9014 Kuttsukiboshi 6.12 \n",
+ "... ... ... ... \n",
+ "16209 38009 Re:Stage! Dream Days♪ 6.69 \n",
+ "16210 10348 Fireball Charming 6.8 \n",
+ "16211 979 Street Fighter Zero The Animation 6.55 \n",
+ "16212 42826 Seijo no Maryoku wa Bannou Desu Unknown \n",
+ "16213 20047 Sakura Trick 7.02 \n",
+ "\n",
+ " Genres \\\n",
+ "0 Romance, Sci-Fi \n",
+ "1 Space \n",
+ "2 Adventure, Cars, Sports, Shounen \n",
+ "3 Kids \n",
+ "4 Romance, Supernatural, Drama, Shoujo Ai \n",
+ "... ... \n",
+ "16209 Music, School, Slice of Life \n",
+ "16210 Sci-Fi \n",
+ "16211 Action, Drama, Martial Arts, Shounen, Super Power \n",
+ "16212 Romance, Fantasy \n",
+ "16213 Slice of Life, Comedy, Romance, School, Seinen... \n",
+ "\n",
+ " sypnopsis \n",
+ "0 Kozue is a girl who loves astronomy, particula... \n",
+ "1 advertisement for a photo and essay collection... \n",
+ "2 Based on the manga by Tetsuhiro Koshita, Bakus... \n",
+ "3 p to camping with Kitty and her class. \n",
+ "4 To Kiiko Kawakami, there was nothing in the wo... \n",
+ "... ... \n",
+ "16209 ana Shikimiya has just transferred into Mareho... \n",
+ "16210 3D computer animation about a female robot duc... \n",
+ "16211 u, the current Street Fighter champion, must o... \n",
+ "16212 Sei, a 20-year-old office worker, is whisked a... \n",
+ "16213 Having been best friends since middle school, ... \n",
+ "\n",
+ "[16214 rows x 5 columns]"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "anime_synopsis_df"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "75a968d7",
+ "metadata": {},
+ "source": [
+ "Define the neural network"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "ba2cb244",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class AnimeRecommendationNN(nn.Module):\n",
+ " def __init__(self, input_size):\n",
+ " super(AnimeRecommendationNN, self).__init__()\n",
+ " self.fc1 = nn.Linear(input_size, 256)\n",
+ " self.fc2 = nn.Linear(256, 128)\n",
+ " self.fc3 = nn.Linear(128, 64)\n",
+ " self.fc4 = nn.Linear(64, 32)\n",
+ " self.fc5 = nn.Linear(32, 1)\n",
+ " self.relu = nn.LeakyReLU(negative_slope=0.01)\n",
+ " self.dropout = nn.Dropout(0.3)\n",
+ " self.batch_norm1 = nn.BatchNorm1d(256)\n",
+ " self.batch_norm2 = nn.BatchNorm1d(128)\n",
+ " self.batch_norm3 = nn.BatchNorm1d(64)\n",
+ " self.batch_norm4 = nn.BatchNorm1d(32)\n",
+ "\n",
+ " def forward(self, x):\n",
+ " x = self.dropout(self.relu(self.batch_norm1(self.fc1(x))))\n",
+ " x = self.dropout(self.relu(self.batch_norm2(self.fc2(x))))\n",
+ " x = self.dropout(self.relu(self.batch_norm3(self.fc3(x))))\n",
+ " x = self.dropout(self.relu(self.batch_norm4(self.fc4(x))))\n",
+ " x = self.fc5(x)\n",
+ " return x"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "90f1197e",
+ "metadata": {},
+ "source": [
+ "Feature engineering"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "45c355f5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def clean_numeric_column(series):\n",
+ " series = series.astype(str)\n",
+ " series = series.replace(['Unknown', ''], np.nan)\n",
+ " series = pd.to_numeric(series, errors='coerce')\n",
+ " return series"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "28654be7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def engineer_features(df):\n",
+ " df = df.copy()\n",
+ " \n",
+ " df['genre_count'] = df['Genres'].str.count(',') + 1\n",
+ " df['synopsis_length'] = df['sypnopsis'].str.len().fillna(0)\n",
+ " \n",
+ " numeric_columns = ['Score', 'Episodes', 'Members', 'Popularity', 'Ranked']\n",
+ " \n",
+ " for col in numeric_columns:\n",
+ " df[col] = clean_numeric_column(df[col])\n",
+ " # Fill NaN with median without using inplace\n",
+ " median_value = df[col].median()\n",
+ " df[col] = df[col].fillna(median_value)\n",
+ " \n",
+ " return df[['MAL_ID', 'Score', 'Episodes', 'Members', 'Popularity', 'Ranked', 'genre_count', 'synopsis_length']]\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "65ee1094",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "anime_features = engineer_features(pd.merge(anime_df, anime_synopsis_df[['MAL_ID', 'sypnopsis']], on='MAL_ID', how='left'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "a35cb269",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "non_numeric_check = anime_features.drop('MAL_ID', axis=1).select_dtypes(exclude=[np.number])\n",
+ "if not non_numeric_check.empty:\n",
+ " print(\"Warning: Non-numeric data found in columns:\", non_numeric_check.columns)\n",
+ " print(\"Sample of non-numeric data:\")\n",
+ " print(non_numeric_check.head())\n",
+ " raise ValueError(\"Please check your data preprocessing steps.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "56cc96a6",
+ "metadata": {},
+ "source": [
+ "Normalize features"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "0072397d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scaler = StandardScaler()\n",
+ "anime_features_scaled = scaler.fit_transform(anime_features.drop('MAL_ID', axis=1))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "c8a66545",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X = anime_features_scaled\n",
+ "y = anime_features['Score'].values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "9cc83cb0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "0fdea965",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "train_dataset = TensorDataset(torch.FloatTensor(X_train), torch.FloatTensor(y_train))\n",
+ "val_dataset = TensorDataset(torch.FloatTensor(X_val), torch.FloatTensor(y_val))\n",
+ "\n",
+ "batch_size = 512\n",
+ "train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n",
+ "val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f6e2b4c3",
+ "metadata": {},
+ "source": [
+ "Training"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "bc6fad2c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "input_size = X_train.shape[1]\n",
+ "model = AnimeRecommendationNN(input_size).to(device)\n",
+ "optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-5)\n",
+ "scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=5, factor=0.5, min_lr=1e-6)\n",
+ "criterion = nn.MSELoss()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "3cf30295",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "num_epochs = 100\n",
+ "patience = 15\n",
+ "best_val_loss = float('inf')\n",
+ "no_improve = 0\n",
+ "\n",
+ "train_losses = []\n",
+ "val_losses = []"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "de45215b",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 2%|▏ | 2/100 [00:00<00:20, 4.73it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [1/100], Train Loss: 35.1908, Val Loss: 34.1363\n",
+ "Epoch [2/100], Train Loss: 28.4761, Val Loss: 26.1533\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 4%|▍ | 4/100 [00:00<00:14, 6.71it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [3/100], Train Loss: 22.8870, Val Loss: 20.3565\n",
+ "Epoch [4/100], Train Loss: 18.0055, Val Loss: 15.7408\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 6%|▌ | 6/100 [00:00<00:12, 7.81it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [5/100], Train Loss: 13.4245, Val Loss: 11.4652\n",
+ "Epoch [6/100], Train Loss: 9.5039, Val Loss: 7.3833\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 8%|▊ | 8/100 [00:01<00:12, 7.19it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [7/100], Train Loss: 6.0797, Val Loss: 4.0210\n",
+ "Epoch [8/100], Train Loss: 3.4364, Val Loss: 1.7301\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 10%|█ | 10/100 [00:01<00:11, 7.98it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [9/100], Train Loss: 1.8735, Val Loss: 0.3324\n",
+ "Epoch [10/100], Train Loss: 1.3259, Val Loss: 0.0896\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 12%|█▏ | 12/100 [00:01<00:10, 8.41it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [11/100], Train Loss: 1.1793, Val Loss: 0.0788\n",
+ "Epoch [12/100], Train Loss: 1.1421, Val Loss: 0.0493\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 14%|█▍ | 14/100 [00:01<00:09, 8.67it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [13/100], Train Loss: 1.0728, Val Loss: 0.0493\n",
+ "Epoch [14/100], Train Loss: 1.0055, Val Loss: 0.0373\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 15%|█▌ | 15/100 [00:02<00:09, 8.75it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [15/100], Train Loss: 0.9540, Val Loss: 0.0340\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 17%|█▋ | 17/100 [00:02<00:11, 7.42it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [16/100], Train Loss: 0.9143, Val Loss: 0.0470\n",
+ "Epoch [17/100], Train Loss: 0.8634, Val Loss: 0.0281\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 19%|█▉ | 19/100 [00:02<00:10, 7.40it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [18/100], Train Loss: 0.8607, Val Loss: 0.0362\n",
+ "Epoch [19/100], Train Loss: 0.8161, Val Loss: 0.0189\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 21%|██ | 21/100 [00:02<00:09, 7.97it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [20/100], Train Loss: 0.7852, Val Loss: 0.0166\n",
+ "Epoch [21/100], Train Loss: 0.7763, Val Loss: 0.0257\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 23%|██▎ | 23/100 [00:03<00:08, 8.60it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [22/100], Train Loss: 0.7352, Val Loss: 0.0183\n",
+ "Epoch [23/100], Train Loss: 0.7398, Val Loss: 0.0281\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 25%|██▌ | 25/100 [00:03<00:08, 9.11it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [24/100], Train Loss: 0.7096, Val Loss: 0.0287\n",
+ "Epoch [25/100], Train Loss: 0.7122, Val Loss: 0.0163\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 27%|██▋ | 27/100 [00:03<00:08, 8.19it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [26/100], Train Loss: 0.6918, Val Loss: 0.0232\n",
+ "Epoch [27/100], Train Loss: 0.6863, Val Loss: 0.0228\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 29%|██▉ | 29/100 [00:03<00:08, 8.61it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [28/100], Train Loss: 0.6635, Val Loss: 0.0170\n",
+ "Epoch [29/100], Train Loss: 0.6679, Val Loss: 0.0171\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 30%|███ | 30/100 [00:03<00:08, 8.75it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [30/100], Train Loss: 0.6446, Val Loss: 0.0272\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 32%|███▏ | 32/100 [00:04<00:09, 7.44it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [31/100], Train Loss: 0.6492, Val Loss: 0.0337\n",
+ "Epoch [32/100], Train Loss: 0.6390, Val Loss: 0.0221\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 34%|███▍ | 34/100 [00:04<00:08, 8.14it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [33/100], Train Loss: 0.6460, Val Loss: 0.0324\n",
+ "Epoch [34/100], Train Loss: 0.6318, Val Loss: 0.0180\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 36%|███▌ | 36/100 [00:04<00:07, 8.85it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [35/100], Train Loss: 0.6359, Val Loss: 0.0235\n",
+ "Epoch [36/100], Train Loss: 0.6204, Val Loss: 0.0253\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 38%|███▊ | 38/100 [00:04<00:06, 9.30it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [37/100], Train Loss: 0.6167, Val Loss: 0.0258\n",
+ "Epoch [38/100], Train Loss: 0.6130, Val Loss: 0.0227\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 40%|████ | 40/100 [00:05<00:06, 9.36it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [39/100], Train Loss: 0.6214, Val Loss: 0.0161\n",
+ "Epoch [40/100], Train Loss: 0.6209, Val Loss: 0.0237\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 42%|████▏ | 42/100 [00:05<00:07, 8.24it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [41/100], Train Loss: 0.6044, Val Loss: 0.0238\n",
+ "Epoch [42/100], Train Loss: 0.6016, Val Loss: 0.0171\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 44%|████▍ | 44/100 [00:05<00:06, 8.61it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [43/100], Train Loss: 0.6160, Val Loss: 0.0218\n",
+ "Epoch [44/100], Train Loss: 0.6252, Val Loss: 0.0178\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 45%|████▌ | 45/100 [00:05<00:06, 8.85it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [45/100], Train Loss: 0.6161, Val Loss: 0.0247\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 47%|████▋ | 47/100 [00:05<00:07, 7.50it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [46/100], Train Loss: 0.5884, Val Loss: 0.0257\n",
+ "Epoch [47/100], Train Loss: 0.6001, Val Loss: 0.0157\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 49%|████▉ | 49/100 [00:06<00:06, 8.01it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [48/100], Train Loss: 0.6033, Val Loss: 0.0279\n",
+ "Epoch [49/100], Train Loss: 0.6040, Val Loss: 0.0180\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 51%|█████ | 51/100 [00:06<00:05, 8.17it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [50/100], Train Loss: 0.6089, Val Loss: 0.0159\n",
+ "Epoch [51/100], Train Loss: 0.5913, Val Loss: 0.0169\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 53%|█████▎ | 53/100 [00:06<00:05, 8.48it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [52/100], Train Loss: 0.6020, Val Loss: 0.0197\n",
+ "Epoch [53/100], Train Loss: 0.5963, Val Loss: 0.0158\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 55%|█████▌ | 55/100 [00:06<00:05, 8.78it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [54/100], Train Loss: 0.5993, Val Loss: 0.0205\n",
+ "Epoch [55/100], Train Loss: 0.5912, Val Loss: 0.0193\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 57%|█████▋ | 57/100 [00:07<00:04, 9.02it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [56/100], Train Loss: 0.5841, Val Loss: 0.0203\n",
+ "Epoch [57/100], Train Loss: 0.5937, Val Loss: 0.0202\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 59%|█████▉ | 59/100 [00:07<00:04, 9.17it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [58/100], Train Loss: 0.6112, Val Loss: 0.0150\n",
+ "Epoch [59/100], Train Loss: 0.5767, Val Loss: 0.0172\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 60%|██████ | 60/100 [00:07<00:05, 7.97it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [60/100], Train Loss: 0.5896, Val Loss: 0.0179\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 62%|██████▏ | 62/100 [00:07<00:05, 7.05it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [61/100], Train Loss: 0.5894, Val Loss: 0.0130\n",
+ "Epoch [62/100], Train Loss: 0.5865, Val Loss: 0.0131\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 64%|██████▍ | 64/100 [00:08<00:04, 8.05it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [63/100], Train Loss: 0.5908, Val Loss: 0.0180\n",
+ "Epoch [64/100], Train Loss: 0.5949, Val Loss: 0.0164\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 66%|██████▌ | 66/100 [00:08<00:03, 8.66it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [65/100], Train Loss: 0.5909, Val Loss: 0.0197\n",
+ "Epoch [66/100], Train Loss: 0.5723, Val Loss: 0.0174\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 68%|██████▊ | 68/100 [00:08<00:03, 8.79it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [67/100], Train Loss: 0.5814, Val Loss: 0.0222\n",
+ "Epoch [68/100], Train Loss: 0.5995, Val Loss: 0.0202\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 70%|███████ | 70/100 [00:08<00:03, 8.57it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [69/100], Train Loss: 0.5859, Val Loss: 0.0246\n",
+ "Epoch [70/100], Train Loss: 0.5812, Val Loss: 0.0132\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 72%|███████▏ | 72/100 [00:08<00:03, 8.19it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [71/100], Train Loss: 0.5821, Val Loss: 0.0183\n",
+ "Epoch [72/100], Train Loss: 0.5841, Val Loss: 0.0206\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 74%|███████▍ | 74/100 [00:09<00:02, 8.78it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [73/100], Train Loss: 0.5871, Val Loss: 0.0192\n",
+ "Epoch [74/100], Train Loss: 0.5782, Val Loss: 0.0155\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Epochs: 75%|███████▌ | 75/100 [00:09<00:03, 8.00it/s]"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Epoch [75/100], Train Loss: 0.5961, Val Loss: 0.0175\n",
+ "Epoch [76/100], Train Loss: 0.5817, Val Loss: 0.0208\n",
+ "Early stopping triggered after 76 epochs\n",
+ "Training completed.\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "/tmp/ipykernel_307086/1420535760.py:64: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
+ " model.load_state_dict(torch.load('best_model.pth'))\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "AnimeRecommendationNN(\n",
+ " (fc1): Linear(in_features=7, out_features=256, bias=True)\n",
+ " (fc2): Linear(in_features=256, out_features=128, bias=True)\n",
+ " (fc3): Linear(in_features=128, out_features=64, bias=True)\n",
+ " (fc4): Linear(in_features=64, out_features=32, bias=True)\n",
+ " (fc5): Linear(in_features=32, out_features=1, bias=True)\n",
+ " (relu): LeakyReLU(negative_slope=0.01)\n",
+ " (dropout): Dropout(p=0.3, inplace=False)\n",
+ " (batch_norm1): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
+ " (batch_norm2): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
+ " (batch_norm3): BatchNorm1d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
+ " (batch_norm4): BatchNorm1d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
+ ")"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "for epoch in tqdm(range(num_epochs), desc=\"Epochs\"):\n",
+ " model.train()\n",
+ " train_loss = 0\n",
+ " total_train_loss = 0\n",
+ " train_batch_count = 0\n",
+ "\n",
+ " for batch_X, batch_y in train_loader:\n",
+ " batch_X, batch_y = batch_X.to(device), batch_y.to(device)\n",
+ "\n",
+ " optimizer.zero_grad()\n",
+ " outputs = model(batch_X)\n",
+ " loss = criterion(outputs.squeeze(), batch_y)\n",
+ " loss.backward()\n",
+ " \n",
+ " torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n",
+ " \n",
+ " optimizer.step()\n",
+ "\n",
+ " total_train_loss += loss.item()\n",
+ " train_batch_count += 1\n",
+ " train_loss += loss.item()\n",
+ "\n",
+ " train_loss /= len(train_loader)\n",
+ " train_losses.append(train_loss)\n",
+ "\n",
+ " avg_train_loss = total_train_loss / train_batch_count\n",
+ "\n",
+ " # Validation phase\n",
+ " model.eval()\n",
+ " total_val_loss = 0\n",
+ " val_batch_count = 0\n",
+ "\n",
+ " with torch.no_grad():\n",
+ " for batch_X, batch_y in val_loader:\n",
+ " batch_X, batch_y = batch_X.to(device), batch_y.to(device)\n",
+ " outputs = model(batch_X)\n",
+ " val_loss = criterion(outputs.squeeze(), batch_y)\n",
+ " total_val_loss += val_loss.item()\n",
+ " val_batch_count += 1\n",
+ "\n",
+ " avg_val_loss = total_val_loss / val_batch_count\n",
+ " val_losses.append(avg_val_loss) # Changed from val_loss to avg_val_loss\n",
+ "\n",
+ " tqdm.write(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, Val Loss: {avg_val_loss:.4f}')\n",
+ " \n",
+ " # Learning rate scheduling\n",
+ " scheduler.step(avg_val_loss)\n",
+ " \n",
+ " # Early stopping\n",
+ " if avg_val_loss < best_val_loss:\n",
+ " best_val_loss = avg_val_loss\n",
+ " no_improve = 0\n",
+ " torch.save(model.state_dict(), 'best_model.pth')\n",
+ " else:\n",
+ " no_improve += 1\n",
+ " if no_improve == patience:\n",
+ " print(f\"Early stopping triggered after {epoch+1} epochs\")\n",
+ " break\n",
+ "\n",
+ "print(\"Training completed.\")\n",
+ "\n",
+ "# Load the best model for inference\n",
+ "model.load_state_dict(torch.load('best_model.pth'))\n",
+ "model.eval()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "0aaef025",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def predict_anime_score(anime_features_dict):\n",
+ " feature_order = anime_features.columns.tolist()\n",
+ " feature_order.remove('MAL_ID') # Remove MAL_ID as it's not used for prediction \n",
+ " features_list = [anime_features_dict.get(feature, 0) for feature in feature_order]\n",
+ " \n",
+ " model.eval()\n",
+ " with torch.no_grad():\n",
+ " features = torch.FloatTensor(scaler.transform([features_list])).to(device)\n",
+ " prediction = model(features)\n",
+ " return prediction.item()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "338fa304",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Predicted score for the new anime: 1.48\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/andre/miniconda3/envs/venv/lib/python3.12/site-packages/sklearn/base.py:493: UserWarning: X does not have valid feature names, but StandardScaler was fitted with feature names\n",
+ " warnings.warn(\n"
+ ]
+ }
+ ],
+ "source": [
+ "new_anime_features = {\n",
+ " 'Score': 0,\n",
+ " 'Episodes': 12,\n",
+ " 'Members': 1000000,\n",
+ " 'Popularity': 1000,\n",
+ " 'Ranked': 500,\n",
+ " 'genre_count': 3,\n",
+ " 'synopsis_length': 150\n",
+ "}\n",
+ "\n",
+ "predicted_score = predict_anime_score(new_anime_features)\n",
+ "print(f\"Predicted score for the new anime: {predicted_score:.2f}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "224e985a",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Validation MSE: 0.0130\n",
+ "Validation RMSE: 0.1140\n"
+ ]
+ }
+ ],
+ "source": [
+ "model.eval()\n",
+ "val_predictions = []\n",
+ "val_true_scores = []\n",
+ "\n",
+ "with torch.no_grad():\n",
+ " for batch_X, batch_y in val_loader:\n",
+ " batch_X, batch_y = batch_X.to(device), batch_y.to(device)\n",
+ " outputs = model(batch_X)\n",
+ " val_predictions.extend(outputs.squeeze().cpu().numpy())\n",
+ " val_true_scores.extend(batch_y.cpu().numpy())\n",
+ "\n",
+ "val_predictions = np.array(val_predictions)\n",
+ "val_true_scores = np.array(val_true_scores)\n",
+ "\n",
+ "# Calculate MSE and RMSE\n",
+ "mse = np.mean((val_predictions - val_true_scores) ** 2)\n",
+ "rmse = np.sqrt(mse)\n",
+ "\n",
+ "print(f\"Validation MSE: {mse:.4f}\")\n",
+ "print(f\"Validation RMSE: {rmse:.4f}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "36e94621",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0EAAAIjCAYAAADFthA8AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACpuklEQVR4nOzdd3hUZfrG8e+ZPukJKSQhtNCbUhQVBJWm2DtW7Lr2wu7q6orYsHdXUX9iZe19VQS7iIKiKAhC6CSQQkgmddo5vz8iAyG0hIQEcn+ui2uZ95w555nAYu6873lew7IsCxERERERkVbC1twFiIiIiIiI7EkKQSIiIiIi0qooBImIiIiISKuiECQiIiIiIq2KQpCIiIiIiLQqCkEiIiIiItKqKASJiIiIiEirohAkIiIiIiKtikKQiIiIiIi0KgpBIiK7oGPHjpx33nmR11999RWGYfDVV181W01b27pGqb/DDjuMww47rNnubxgGt912W7PdX0SktVAIEpEW74UXXsAwjMgvj8dDt27duPLKK8nPz2/u8url448/bjXf5C5atCjy51VSUtLg69x999289957jVZXYwqHw2RkZGAYBp988klzl9MkPvzwQ4YPH05qaipRUVF07tyZ0047jU8//bS5SxMRaTCFIBHZa9x+++28/PLLPPHEExxyyCE89dRTHHzwwVRWVu7xWoYNG0ZVVRXDhg2r1/s+/vhjJk2a1ERVtSyvvPIKbdu2BeCtt95q8HVacgj64osvWLduHR07duTVV1/d7etVVVVxyy23NEJljeOBBx7guOOOwzAMbrrpJh5++GFOPvlkli5dymuvvdbc5YmINJijuQsQEdlVRx11FIMGDQLgoosuok2bNjz00EO8//77nHHGGdt8T0VFBdHR0Y1ei81mw+PxNPp19xWWZTFt2jTOPPNMVqxYwauvvspFF13U3GU1uldeeYUBAwYwfvx4/vWvf+3237eW9HcqFApxxx13MGrUKD777LM6xwsKCvZYLaZpEggEWtTXR0T2bpoJEpG91hFHHAHAihUrADjvvPOIiYlh2bJljB07ltjYWM466yyg5puoRx55hN69e+PxeEhLS+PSSy9l48aNta5pWRZ33nkn7dq1IyoqisMPP5yFCxfWuff2ngn68ccfGTt2LImJiURHR9OvXz8effTRSH1PPvkkQK3lfZs0do1bCwaDJCUlcf7559c55vP58Hg8TJgwITL2+OOP07t3b6KiokhMTGTQoEFMmzZtp/cBmDVrFitXrmTcuHGMGzeOb775hrVr19Y5zzRNHn30Ufr27YvH4yElJYUjjzySn376KfJ1qqio4MUXX4x8vTY993TeeefRsWPHOte87bbban1dAaZOncoRRxxBamoqbrebXr168dRTT+3SZ9meqqoq3n33XcaNG8dpp51GVVUV77//fp3zNv29zM3N5YQTTiAmJoaUlBQmTJhAOByude7WzwRt+ixLlizh7LPPJj4+npSUFP79739jWRZr1qzh+OOPJy4ujrZt2/Lggw/Wub/f72fixIl06dIFt9tNVlYW//jHP/D7/Tv8fEVFRfh8PoYMGbLN46mpqbVeV1dXc9ttt9GtWzc8Hg/p6emcdNJJLFu2LHJORUUFN9xwA1lZWbjdbrp3784DDzyAZVl1vg5XXnklr776Kr1798btdkeW3+Xm5nLBBReQlpaG2+2md+/ePP/883Xq252/vyKy79NMkIjstTZ9c9WmTZvIWCgUYsyYMQwdOpQHHniAqKgoAC699FJeeOEFzj//fK6++mpWrFjBE088wS+//MKsWbNwOp0A3Hrrrdx5552MHTuWsWPHMm/ePEaPHk0gENhpPTNmzOCYY44hPT2da665hrZt27Jo0SI++ugjrrnmGi699FLy8vKYMWMGL7/8cp33N3WNTqeTE088kXfeeYcpU6bgcrkix9577z38fj/jxo0D4Nlnn+Xqq6/mlFNO4ZprrqG6uprffvuNH3/8kTPPPHOnX4tXX32V7OxsDjjgAPr06UNUVBT//e9/+fvf/17rvAsvvJAXXniBo446iosuuohQKMS3337LDz/8wKBBg3j55Ze56KKLOPDAA7nkkksAyM7O3un9t/bUU0/Ru3dvjjvuOBwOBx9++CGXX345pmlyxRVX1Pt6AB988AHl5eWMGzeOtm3bcthhh/Hqq69u8+sTDocZM2YMgwcP5oEHHmDmzJk8+OCDZGdn87e//W2n9zr99NPp2bMn99xzD//73/+48847SUpKYsqUKRxxxBHce++9vPrqq0yYMIEDDjggskzTNE2OO+44vvvuOy655BJ69uzJ77//zsMPP8ySJUt2uMwwNTUVr9fLhx9+yFVXXUVSUtJ2zw2HwxxzzDF8/vnnjBs3jmuuuYaysjJmzJjBggULyM7OxrIsjjvuOL788ksuvPBC9t9/f6ZPn87f//53cnNzefjhh2td84svvuCNN97gyiuvJDk5mY4dO5Kfn89BBx0UCUkpKSl88sknXHjhhfh8Pq699lpg9//+ikgrYImItHBTp061AGvmzJlWYWGhtWbNGuu1116z2rRpY3m9Xmvt2rWWZVnW+PHjLcC68cYba73/22+/tQDr1VdfrTX+6aef1hovKCiwXC6XdfTRR1umaUbO+9e//mUB1vjx4yNjX375pQVYX375pWVZlhUKhaxOnTpZHTp0sDZu3FjrPlte64orrrC29U9vU9S4LdOnT7cA68MPP6w1PnbsWKtz586R18cff7zVu3fvHV5rewKBgNWmTRvr5ptvjoydeeaZ1n777VfrvC+++MICrKuvvrrONbb8bNHR0dv8XOPHj7c6dOhQZ3zixIl1vsaVlZV1zhszZkytz2xZljV8+HBr+PDh2/hUdR1zzDHWkCFDIq+feeYZy+FwWAUFBXXqBKzbb7+91nj//v2tgQMH1hoDrIkTJ9b5LJdccklkLBQKWe3atbMMw7DuueeeyPjGjRstr9db62v18ssvWzabzfr2229r3efpp5+2AGvWrFk7/Iy33nqrBVjR0dHWUUcdZd11113Wzz//XOe8559/3gKshx56qM6xTX+W7733ngVYd955Z63jp5xyimUYhpWTk1Pr62Cz2ayFCxfWOvfCCy+00tPTraKiolrj48aNs+Lj4yN/zrvz91dEWgcthxORvcbIkSNJSUkhKyuLcePGERMTw7vvvktmZmat87b+yfqbb75JfHw8o0aNoqioKPJr4MCBxMTE8OWXXwIwc+ZMAoEAV111Va3lVJt+urwjv/zyCytWrODaa68lISGh1rGtl2Zty56oEWqWECYnJ/P6669HxjZu3MiMGTM4/fTTI2MJCQmsXbuWuXPn7tJ1t/TJJ5+wYcOGWs9pnXHGGcyfP7/Wsr23334bwzCYOHFinWvsytesPrxeb+T3paWlFBUVMXz4cJYvX05paWm9r7dhwwamT59e6zOefPLJGIbBG2+8sc33XHbZZbVeH3rooSxfvnyX7rfl81R2u51BgwZhWRYXXnhhZDwhIYHu3bvXuuabb75Jz5496dGjR62/V5uWkm76e7U9kyZNYtq0afTv35/p06dz8803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P/54jj32WA4//HBuvvlmVq5cyX777cdnn33G+++/z7XXXrtLrc/vuecevvzySwYPHszFF19Mr169KC4uZt68ecycOZPi4mKgYX9/RaSVaY6WdCIi9bGpRfbcuXN3eN748eOt6Ojo7R5/5plnrIEDB1per9eKjY21+vbta/3jH/+w8vLyIueEw2Fr0qRJVnp6uuX1eq3DDjvMWrBggdWhQ4cdtsje5LvvvrNGjRplxcbGWtHR0Va/fv2sxx9/PHI8FApZV111lZWSkmIZhlGnlXNj1rgjpmlaWVlZ22xZbFmWNWXKFGvYsGFWmzZtLLfbbWVnZ1t///vfrdLS0u1e88EHH7QA6/PPP9/uOS+88IIFWO+//37k63H//fdbPXr0sFwul5WSkmIdddRRtdowL1682Bo2bJjl9XrrtAH/7LPPrD59+lgul8vq3r279corr2yzRfYHH3xg9evXz/J4PFbHjh2te++9N9LWecWKFZHzdtYi++eff7YA69///vd2z1m5cqUFWNddd51lWdv/e7mtOtlOi+zCwsJa523vmsOHD6/TGjoQCFj33nuv1bt3b8vtdluJiYnWwIEDrUmTJu3wzzMYDFrPPvusdcIJJ1gdOnSw3G63FRUVZfXv39+6//77Lb/fX+v8yspK6+abb7Y6depkOZ1Oq23bttYpp5xiLVu2LHJOWVmZdd1111kZGRmW0+m0unbtat1///21WqJv+jpcccUV26wrPz/fuuKKK6ysrKzIfUaMGGE988wzkXMa8vdXRFoXw7K22qZZRERERERkH6ZngkREREREpFVRCBIRERERkVZFIUhERERERFoVhSAREREREWlVFIJERERERKRVUQgSEREREZFWZa/eLNU0TfLy8oiNjcUwjOYuR0REREREmollWZSVlZGRkYHNtuO5nr06BOXl5W13x24REREREWl91qxZQ7t27XZ4zl4dgmJjY4GaDxoXF9fM1YiIiIiISHPx+XxkZWVFMsKO7NUhaNMSuLi4OIUgERERERHZpcdk1BhBRERERERaFYUgERERERFpVRSCRERERESkVVEIEhERERGRVkUhSEREREREWhWFIBERERERaVUUgkREREREpFVRCBIRERERkVZFIUhERERERFoVhSAREREREWlVFIJERERERKRVUQgSEREREZFWRSFIRERERERaFYUgERERERFpVRSCRERERESkVVEIEhERERGRVkUhSERERERE6i83FxYvbu4qGkQhSEREREREdp3fD/feC927w7nngmk2d0X1phAkIiIiIiK75uOPoW9fuPFGqKiAuXPhpZeau6p6czR3ASIiIiIi0sLl5MB118FHH20es9ngssvguOOar64GUggSEREREZHte+01GD8eAoHNY4ceCo8/Dvvt13x17QYthxMRERERke076KCaWR+AjAyYNg2+/nqvDUCgmSAREREREdlSZSVERW1+3bEj3Hor+Hxw880QE9NspTUWhSAREREREYGNG2vCzgcfwMKFtcPOTTc1X11NQMvhRERERERas3AYnn0WunWDJ56A1avhrruau6om1awhqKysjGuvvZYOHTrg9Xo55JBDmDt3bnOWJCIiIiLSesyeDYMHwyWXQFFRzVhUFCQnN29dTaxZQ9BFF13EjBkzePnll/n9998ZPXo0I0eOJDc3tznLEhERERHZt61fX9Px7ZBD4OefN4+fcQb8+SfccEPz1bYHGJZlWc1x46qqKmJjY3n//fc5+uijI+MDBw7kqKOO4s4776zzHr/fj9/vj7z2+XxkZWVRWlpKXFzcHqlbRERERGSvFQjAY4/B7bdDWdnm8X79alpeDxvWfLXtJp/PR3x8/C5lg2abCQqFQoTDYTweT61xr9fLd999t833TJ48mfj4+MivrKysPVGqiIiIiMi+YcMGmDRpcwBKSKh5Dujnn/fqAFRfzRaCYmNjOfjgg7njjjvIy8sjHA7zyiuvMHv2bNatW7fN99x0002UlpZGfq1Zs2YPVy0iIiIishdLT4d//xsMo+Y5oKVL4YorwNG6mkY36zNBL7/8MpZlkZmZidvt5rHHHuOMM87AZtt2WW63m7i4uFq/RERERERkGyora7q8lZTUHr/22pqZnylT9vkGCNvTrCEoOzubr7/+mvLyctasWcOcOXMIBoN07ty5OcsSEREREdl7WRa89Rb07Am33AK33Vb7uMsF/fs3S2ktRYvYJyg6Opr09HQ2btzI9OnTOf7445u7JBERERGRvc/ChTByJJx6as1+PwDPPLO5/bUAzRyCpk+fzqeffsqKFSuYMWMGhx9+OD169OD8889vzrJERERERPYuJSU1y9z22w+++GLz+JgxMG9eq132tj3N+gRUaWkpN910E2vXriUpKYmT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pnHnnXfSrVs35s2bp4XhTejtt9/mm2++0S/eJnj00UeZPn06119/PUVFRaSmpnLttddyxx13mF1azCgtLWXatGl89913JCUlMWbMGGbPnk1cXJzZpTUp7RMkIiIiIiIxRWuCREREREQkpigEiYiIiIhITFEIEhERERGRmKIQJCIiIiIiMUUhSEREREREYopCkIiIiIiIxBSFIBERERERiSkKQSIiIiIiElMUgkREpEWxWCwsW7bM7DJERKQFUwgSEZEGffDBB9hsNkaNGnXEr+3atSvz5s07+kUdhuLiYq677jo6d+6M0+nkmGOOYcSIEaxdu9aUekREpPmxm12AiIg0T4sWLWLSpEksWrSIgoICUlNTzS7psIwZM4ZAIMBTTz1FRkYGhYWFvPPOO+zZs6fRPjMQCOBwOBrt/UVE5OjSTJCIiBykoqKCF198keuuu45Ro0bx5JNPHnTO66+/zoABA3C5XLRv357zzjsPgKFDh/L1119z4403YrFYsFgsAMycOZPjjz8+6j3mzZtH165d675ft24dw4cPp3379vh8Pk455RQ++eSTw667pKSE999/n3vuuYdTTz2VLl268Ktf/Ypp06bx29/+Nuq8a6+9lo4dO+JyuejTpw/Lly+vO/7KK6+QnZ2N0+mka9euPPDAA1Gf07VrV2bNmsUVV1xBYmIi11xzDQBr1qzh5JNPxu12k56ezuTJk6msrKx73YIFC8jKysLlctGxY0cuuOCCw742ERE5ehSCRETkIC+99BK9evWiZ8+eXH755fz973/HMIy64//3f//Heeedx1lnncWGDRt45513+NWvfgXAP//5Tzp16sSdd97Jrl272LVr12F/bnl5OePGjWPNmjV8+OGHZGVlcdZZZ1FeXn5Yr/d4PHg8HpYtW0ZNTU2D54TDYUaOHMnatWtZsmQJmzdvZu7cudhsNgA+/vhjLrroIi655BI+++wzZs6cyfTp0w8Kgvfffz/HHXccGzZsYPr06ezYsYMzzzyTMWPG8Omnn/Liiy+yZs0abrjhBgDWr1/P5MmTufPOO9myZQv/+te/GDJkyGHfGxEROYoMERGRAwwaNMiYN2+eYRiGUVtba7Rv395477336o4PHDjQGDt27CFf36VLF+Ohhx6KGpsxY4Zx3HHHRY099NBDRpcuXQ75PqFQyPB6vcbrr79eNwYYS5cuPeRrXn75ZaNt27aGy+UyBg0aZEybNs3YtGlT3fHc3FzDarUaW7ZsafD1l112mTF8+PCosVtvvdXo3bt31PWde+65UedcffXVxjXXXBM19v777xtWq9Worq42XnnlFSMxMdEoKys7ZO0iItI0NBMkIiJRtmzZwkcffcSll14KgN1u5+KLL2bRokV152zcuJHTTz/9qH92YWEh//M//0NWVhY+n4/ExEQqKir45ptvDvs9xowZQ0FBAa+99hpnnnkmK1eupF+/fnUzORs3bqRTp0706NGjwdd/8cUXDB48OGps8ODBbNu2jVAoVDfWv3//qHM2bdrEk08+WTcb5fF4GDFiBOFwmC+//JLhw4fTpUsXMjIy+N3vfsezzz5LVVXVYV+XiIgcPWqMICIiURYtWkQwGIxqhGAYBk6nk/nz5+Pz+XC73Uf8vlarNeqROoDa2tqo78eNG8eePXt4+OGH6dKlC06nk4EDBxIIBI7os1wuF8OHD2f48OFMnz6dCRMmMGPGDK688sqfVXtDEhISor6vqKjg2muvZfLkyQed27lzZxwOB5988gkrV67kzTff5I477mDmzJmsW7eONm3aHJWaRETk8GgmSERE6gSDQZ5++mkeeOABNm7cWPe1adMmUlNTef755wHIycnhnXfeOeT7OByOqFkTgA4dOrB79+6oILRx48aoc9auXcvkyZM566yz6hoTfP/997/4unr37l3XoCAnJ4fvvvuOrVu3Nnjusccee1A77bVr19KjR4+6dUMN6devH5s3byYzM/Ogr32d4+x2O8OGDePee+/l008/5auvvuLdd9/9xdcnIiJHRjNBIiJSZ/ny5fzwww9cffXV+Hy+qGNjxoxh0aJF/P73v2fGjBmcfvrpdO/enUsuuYRgMMgbb7zBbbfdBkS6p61evZpLLrkEp9NJ+/btGTp0KMXFxdx7771ccMEF/Otf/2LFihUkJibWfUZWVhbPPPMM/fv3p6ysjFtvvfWIZm727NnDhRdeyFVXXUVOTg5er5f169dz7733Mnr0aABOOeUUhgwZwpgxY3jwwQfJzMzkv//9LxaLhTPPPJObb76ZAQMGMGvWLC6++GI++OAD5s+fz4IFC370s2+77TZ+/etfc8MNNzBhwgQSEhLYvHkzb731FvPnz2f58uXs3LmTIUOG0LZtW9544w3C4TA9e/Y87OsTEZGjxOQ1SSIi0oycffbZxllnndXgsf/85z8GUNdk4JVXXjGOP/54w+FwGO3btzfOP//8unM/+OADIycnx3A6ncb+/6lZuHChkZ6ebiQkJBhXXHGFMXv27KjGCJ988onRv39/w+VyGVlZWcY//vGPg5os8CONEfx+vzF16lSjX79+hs/nM+Lj442ePXsaf/7zn42qqqq68/bs2WOMHz/eaNeuneFyuYw+ffoYy5cvrzv+8ssvG7179zbi4uKMzp07G/fdd1/U5zTU+MEwDOOjjz4yhg8fbng8HiMhIcHIyckxZs+ebRhGpEnCKaecYrRt29Zwu91GTk6O8eKLLzZ4HSIi0rgshnHAA9oiIiIiIiKtmNYEiYiIiIhITFEIEhERERGRmKIQJCIiIiIiMUUhSEREREREYopCkIiIiIiIxBSFIBERERERiSkKQSIiIiIiElMUgkREREREJKYoBImIiIiISExRCBIRERERkZiiECQiIiIiIjHl/wFttAD0tUCgeQAAAABJRU5ErkJggg==",
+ "text/plain": [
+ "