Showing preview only (1,073K chars total). Download the full file or copy to clipboard to get everything.
Repository: rposhala/Recommender-System-on-MovieLens-dataset
Branch: main
Commit: 7e9b1dce2acf
Files: 6
Total size: 1.0 MB
Directory structure:
gitextract_6b3qicba/
├── Images/
│ └── .gitkeep
├── Item_based_Collaborative_Recommender_System_using_KNN.ipynb
├── Knowledge_based_Recommender_System.ipynb
├── README.md
├── Recommender_System_using_SVD.ipynb
└── Recommender_System_using_Softmax_DNN.ipynb
================================================
FILE CONTENTS
================================================
================================================
FILE: Images/.gitkeep
================================================
================================================
FILE: Item_based_Collaborative_Recommender_System_using_KNN.ipynb
================================================
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Item-based-Collaborative-Recommender-System-using-KNN.ipynb",
"provenance": [],
"collapsed_sections": [
"jVJu1rsTx0F3"
],
"authorship_tag": "ABX9TyM1K937XEBtUiFWogHB4DtZ",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/rposhala/Recommender-System-on-MovieLens-dataset/blob/main/Item_based_Collaborative_Recommender_System_using_KNN.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"metadata": {
"id": "bwSPLalV6Rca"
},
"source": [
"import os\n",
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"from scipy.sparse import csr_matrix\n",
"from sklearn.neighbors import NearestNeighbors"
],
"execution_count": 113,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "HKw5H628aSY9"
},
"source": [
"DATASET_LINK='http://files.grouplens.org/datasets/movielens/ml-100k.zip'"
],
"execution_count": 114,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "gavevc8waXW_",
"outputId": "138b5e41-3605-4838-f1f7-9eac9315c9c6",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 67
}
},
"source": [
"!wget -nc http://files.grouplens.org/datasets/movielens/ml-100k.zip\n",
"!unzip -n ml-100k.zip"
],
"execution_count": 115,
"outputs": [
{
"output_type": "stream",
"text": [
"File ‘ml-100k.zip’ already there; not retrieving.\n",
"\n",
"Archive: ml-100k.zip\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "d4WNkFXcauZ3"
},
"source": [
"## Loading MovieLens dataset"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3jZ7lU8RafYz"
},
"source": [
"Loading u.info -- The number of users, items, and ratings in the u data set."
]
},
{
"cell_type": "code",
"metadata": {
"id": "dEj5ZJQzaX-7",
"outputId": "b73df5ec-cf04-491f-ad79-e2b9a8c26b16",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"overall_stats = pd.read_csv('ml-100k/u.info', header=None)\n",
"print(\"Details of users, items and ratings involved in the loaded movielens dataset: \",list(overall_stats[0]))"
],
"execution_count": 116,
"outputs": [
{
"output_type": "stream",
"text": [
"Details of users, items and ratings involved in the loaded movielens dataset: ['943 users', '1682 items', '100000 ratings']\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "aFzpbJ_Hap8V"
},
"source": [
"Loading u.data -- The full u data set, 100000 ratings by 943 users on 1682 items.\n",
"\n",
"---\n",
"\n",
"\n",
"\n",
" Each user has rated at least 20 movies. Users and items are\n",
" numbered consecutively from 1. The data is randomly ordered. This is a tab separated list of \n",
"\t user id | item id | rating | timestamp. \n",
" The time stamps are unix seconds since 1/1/1970 UTC "
]
},
{
"cell_type": "code",
"metadata": {
"id": "NXg9Sj7ralr4",
"outputId": "0c8ac301-e92f-4682-df49-9c21c137dcd0",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 195
}
},
"source": [
"## same item id is same as movie id, item id column is renamed as movie id\n",
"column_names1 = ['user id','movie id','rating','timestamp']\n",
"dataset = pd.read_csv('ml-100k/u.data', sep='\\t',header=None,names=column_names1)\n",
"dataset.head() "
],
"execution_count": 117,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>user id</th>\n",
" <th>movie id</th>\n",
" <th>rating</th>\n",
" <th>timestamp</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>196</td>\n",
" <td>242</td>\n",
" <td>3</td>\n",
" <td>881250949</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>186</td>\n",
" <td>302</td>\n",
" <td>3</td>\n",
" <td>891717742</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>22</td>\n",
" <td>377</td>\n",
" <td>1</td>\n",
" <td>878887116</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>244</td>\n",
" <td>51</td>\n",
" <td>2</td>\n",
" <td>880606923</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>166</td>\n",
" <td>346</td>\n",
" <td>1</td>\n",
" <td>886397596</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" user id movie id rating timestamp\n",
"0 196 242 3 881250949\n",
"1 186 302 3 891717742\n",
"2 22 377 1 878887116\n",
"3 244 51 2 880606923\n",
"4 166 346 1 886397596"
]
},
"metadata": {
"tags": []
},
"execution_count": 117
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "M2lYi6toa9tA",
"outputId": "01b6797c-12cf-479f-fc6e-1889e088e8af",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"len(dataset), max(dataset['movie id']),min(dataset['movie id'])"
],
"execution_count": 118,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"(100000, 1682, 1)"
]
},
"metadata": {
"tags": []
},
"execution_count": 118
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9C9qVRfcbE0k"
},
"source": [
"Loading u.item -- Information about the items (movies); this is a tab separated\n",
"\n",
" list of\n",
" movie id | movie title | release date | video release date |\n",
" IMDb URL | unknown | Action | Adventure | Animation |\n",
" Children's | Comedy | Crime | Documentary | Drama | Fantasy |\n",
" Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi |\n",
" Thriller | War | Western |\n",
" The last 19 fields are the genres, a 1 indicates the movie\n",
" is of that genre, a 0 indicates it is not; movies can be in\n",
" several genres at once.\n",
" The movie ids are the ones used in the u.data data set.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ZaMNuf9fbA0V",
"outputId": "d0d0ced1-9bfb-404a-d0d4-e168cddc6ea0",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 420
}
},
"source": [
"d = 'movie id | movie title | release date | video release date | IMDb URL | unknown | Action | Adventure | Animation | Children | Comedy | Crime | Documentary | Drama | Fantasy | Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi | Thriller | War | Western'\n",
"column_names2 = d.split(' | ')\n",
"column_names2"
],
"execution_count": 119,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['movie id',\n",
" 'movie title',\n",
" 'release date',\n",
" 'video release date',\n",
" 'IMDb URL',\n",
" 'unknown',\n",
" 'Action',\n",
" 'Adventure',\n",
" 'Animation',\n",
" 'Children',\n",
" 'Comedy',\n",
" 'Crime',\n",
" 'Documentary',\n",
" 'Drama',\n",
" 'Fantasy',\n",
" 'Film-Noir',\n",
" 'Horror',\n",
" 'Musical',\n",
" 'Mystery',\n",
" 'Romance',\n",
" 'Sci-Fi',\n",
" 'Thriller',\n",
" 'War',\n",
" 'Western']"
]
},
"metadata": {
"tags": []
},
"execution_count": 119
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "Cv_sboAHbMp7",
"outputId": "db4cb56c-afa3-4ad4-bef6-fd6937eaddf1",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 758
}
},
"source": [
"items_dataset = pd.read_csv('ml-100k/u.item', sep='|',header=None,names=column_names2,encoding='latin-1')\n",
"items_dataset"
],
"execution_count": 120,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>movie id</th>\n",
" <th>movie title</th>\n",
" <th>release date</th>\n",
" <th>video release date</th>\n",
" <th>IMDb URL</th>\n",
" <th>unknown</th>\n",
" <th>Action</th>\n",
" <th>Adventure</th>\n",
" <th>Animation</th>\n",
" <th>Children</th>\n",
" <th>Comedy</th>\n",
" <th>Crime</th>\n",
" <th>Documentary</th>\n",
" <th>Drama</th>\n",
" <th>Fantasy</th>\n",
" <th>Film-Noir</th>\n",
" <th>Horror</th>\n",
" <th>Musical</th>\n",
" <th>Mystery</th>\n",
" <th>Romance</th>\n",
" <th>Sci-Fi</th>\n",
" <th>Thriller</th>\n",
" <th>War</th>\n",
" <th>Western</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>Toy Story (1995)</td>\n",
" <td>01-Jan-1995</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?Toy%20Story%2...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>GoldenEye (1995)</td>\n",
" <td>01-Jan-1995</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?GoldenEye%20(...</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>Four Rooms (1995)</td>\n",
" <td>01-Jan-1995</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?Four%20Rooms%...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4</td>\n",
" <td>Get Shorty (1995)</td>\n",
" <td>01-Jan-1995</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?Get%20Shorty%...</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5</td>\n",
" <td>Copycat (1995)</td>\n",
" <td>01-Jan-1995</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?Copycat%20(1995)</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1677</th>\n",
" <td>1678</td>\n",
" <td>Mat' i syn (1997)</td>\n",
" <td>06-Feb-1998</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?Mat%27+i+syn+...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1678</th>\n",
" <td>1679</td>\n",
" <td>B. Monkey (1998)</td>\n",
" <td>06-Feb-1998</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?B%2E+Monkey+(...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1679</th>\n",
" <td>1680</td>\n",
" <td>Sliding Doors (1998)</td>\n",
" <td>01-Jan-1998</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/Title?Sliding+Doors+(1998)</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1680</th>\n",
" <td>1681</td>\n",
" <td>You So Crazy (1994)</td>\n",
" <td>01-Jan-1994</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?You%20So%20Cr...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1681</th>\n",
" <td>1682</td>\n",
" <td>Scream of Stone (Schrei aus Stein) (1991)</td>\n",
" <td>08-Mar-1996</td>\n",
" <td>NaN</td>\n",
" <td>http://us.imdb.com/M/title-exact?Schrei%20aus%...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>1682 rows × 24 columns</p>\n",
"</div>"
],
"text/plain": [
" movie id movie title ... War Western\n",
"0 1 Toy Story (1995) ... 0 0\n",
"1 2 GoldenEye (1995) ... 0 0\n",
"2 3 Four Rooms (1995) ... 0 0\n",
"3 4 Get Shorty (1995) ... 0 0\n",
"4 5 Copycat (1995) ... 0 0\n",
"... ... ... ... .. ...\n",
"1677 1678 Mat' i syn (1997) ... 0 0\n",
"1678 1679 B. Monkey (1998) ... 0 0\n",
"1679 1680 Sliding Doors (1998) ... 0 0\n",
"1680 1681 You So Crazy (1994) ... 0 0\n",
"1681 1682 Scream of Stone (Schrei aus Stein) (1991) ... 0 0\n",
"\n",
"[1682 rows x 24 columns]"
]
},
"metadata": {
"tags": []
},
"execution_count": 120
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "VFhUx9zsbQpD",
"outputId": "d6bf0a5a-4dd8-4923-9b91-c50a04bef417",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 195
}
},
"source": [
"movie_dataset = items_dataset[['movie id','movie title']]\n",
"movie_dataset.head()"
],
"execution_count": 121,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>movie id</th>\n",
" <th>movie title</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>Toy Story (1995)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>GoldenEye (1995)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>Four Rooms (1995)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4</td>\n",
" <td>Get Shorty (1995)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5</td>\n",
" <td>Copycat (1995)</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" movie id movie title\n",
"0 1 Toy Story (1995)\n",
"1 2 GoldenEye (1995)\n",
"2 3 Four Rooms (1995)\n",
"3 4 Get Shorty (1995)\n",
"4 5 Copycat (1995)"
]
},
"metadata": {
"tags": []
},
"execution_count": 121
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Wr2cmp5impC7"
},
"source": [
"Looking at length of original items_dataset and length of unique combination of rows in items_dataset after removing movie id column"
]
},
{
"cell_type": "code",
"metadata": {
"id": "iIwj68LWGeQX",
"outputId": "1df25549-276e-49fc-950f-139f79f493e2",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"## looking at length of original items_dataset and length of unique combination of rows in items_dataset after removing movie id column\n",
"len(items_dataset.groupby(by=column_names2[1:])),len(items_dataset)"
],
"execution_count": 122,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"(1664, 1682)"
]
},
"metadata": {
"tags": []
},
"execution_count": 122
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "AfBNIWO7mqjc"
},
"source": [
"We can see there are 18 extra movie id's for already mapped movie title and the same duplicate movie id is assigned to the user in the user-item dataset."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nwdvxUdkbiPK"
},
"source": [
"## Merging required datasets"
]
},
{
"cell_type": "code",
"metadata": {
"id": "-fKazhqFbcAq",
"outputId": "636990d0-c78b-4b1e-f269-dec12c317de3",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 195
}
},
"source": [
"merged_dataset = pd.merge(dataset, movie_dataset, how='inner', on='movie id')\n",
"merged_dataset.head()"
],
"execution_count": 123,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>user id</th>\n",
" <th>movie id</th>\n",
" <th>rating</th>\n",
" <th>timestamp</th>\n",
" <th>movie title</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>196</td>\n",
" <td>242</td>\n",
" <td>3</td>\n",
" <td>881250949</td>\n",
" <td>Kolya (1996)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>63</td>\n",
" <td>242</td>\n",
" <td>3</td>\n",
" <td>875747190</td>\n",
" <td>Kolya (1996)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>226</td>\n",
" <td>242</td>\n",
" <td>5</td>\n",
" <td>883888671</td>\n",
" <td>Kolya (1996)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>154</td>\n",
" <td>242</td>\n",
" <td>3</td>\n",
" <td>879138235</td>\n",
" <td>Kolya (1996)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>306</td>\n",
" <td>242</td>\n",
" <td>5</td>\n",
" <td>876503793</td>\n",
" <td>Kolya (1996)</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" user id movie id rating timestamp movie title\n",
"0 196 242 3 881250949 Kolya (1996)\n",
"1 63 242 3 875747190 Kolya (1996)\n",
"2 226 242 5 883888671 Kolya (1996)\n",
"3 154 242 3 879138235 Kolya (1996)\n",
"4 306 242 5 876503793 Kolya (1996)"
]
},
"metadata": {
"tags": []
},
"execution_count": 123
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ELmLkEQBnxv1"
},
"source": [
"A dataset is created from the existing merged dataset by grouping the unique user id and movie title combination and the ratings by a user to the same movie in different instances (timestamps) are averaged and stored in the new dataset."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "zd2jR0cFouee"
},
"source": [
"Example of a multiple rating scenario by an user to a specific movie:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "HQ6owSOikYMq",
"outputId": "496ac596-719b-4ad3-bf8f-79cae6e0e88d",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 106
}
},
"source": [
"merged_dataset[(merged_dataset['movie title'] == 'Chasing Amy (1997)') & (merged_dataset['user id'] == 894)]"
],
"execution_count": 124,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>user id</th>\n",
" <th>movie id</th>\n",
" <th>rating</th>\n",
" <th>timestamp</th>\n",
" <th>movie title</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>4800</th>\n",
" <td>894</td>\n",
" <td>246</td>\n",
" <td>4</td>\n",
" <td>882404137</td>\n",
" <td>Chasing Amy (1997)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>22340</th>\n",
" <td>894</td>\n",
" <td>268</td>\n",
" <td>3</td>\n",
" <td>879896041</td>\n",
" <td>Chasing Amy (1997)</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" user id movie id rating timestamp movie title\n",
"4800 894 246 4 882404137 Chasing Amy (1997)\n",
"22340 894 268 3 879896041 Chasing Amy (1997)"
]
},
"metadata": {
"tags": []
},
"execution_count": 124
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "p5XS_3dPhCVb",
"outputId": "f122409a-556b-4dd7-eeb0-1c98b280c81d",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 195
}
},
"source": [
"refined_dataset = merged_dataset.groupby(by=['user id','movie title'], as_index=False).agg({\"rating\":\"mean\"})\n",
"\n",
"refined_dataset.head()"
],
"execution_count": 125,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>user id</th>\n",
" <th>movie title</th>\n",
" <th>rating</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>101 Dalmatians (1996)</td>\n",
" <td>2.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1</td>\n",
" <td>12 Angry Men (1957)</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1</td>\n",
" <td>20,000 Leagues Under the Sea (1954)</td>\n",
" <td>3.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1</td>\n",
" <td>2001: A Space Odyssey (1968)</td>\n",
" <td>4.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1</td>\n",
" <td>Abyss, The (1989)</td>\n",
" <td>3.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" user id movie title rating\n",
"0 1 101 Dalmatians (1996) 2.0\n",
"1 1 12 Angry Men (1957) 5.0\n",
"2 1 20,000 Leagues Under the Sea (1954) 3.0\n",
"3 1 2001: A Space Odyssey (1968) 4.0\n",
"4 1 Abyss, The (1989) 3.0"
]
},
"metadata": {
"tags": []
},
"execution_count": 125
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "W_HNZ2j9dP5O"
},
"source": [
"## Exploratory data analysis\n",
"\n",
"* Plot the counts of each rating\n",
"* Plot rating frequency of each movie"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "i_cInoHOrk4o"
},
"source": [
"**Plot the counts of each rating**\n",
"\n",
"we first need to get the counts of each rating from ratings data"
]
},
{
"cell_type": "code",
"metadata": {
"id": "qkoNLoyabl42",
"outputId": "e71b61e0-1106-4cc1-f4af-b4cbce4d6400",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 50
}
},
"source": [
"# num_users = len(refined_dataset.rating.unique())\n",
"# num_items = len(refined_dataset.movieId.unique())\n",
"num_users = len(refined_dataset['user id'].value_counts())\n",
"num_items = len(refined_dataset['movie title'].value_counts())\n",
"print('Unique number of users in the dataset: {}'.format(num_users))\n",
"print('Unique number of movies in the dataset: {}'.format(num_items))\n"
],
"execution_count": 126,
"outputs": [
{
"output_type": "stream",
"text": [
"Unique number of users in the dataset: 943\n",
"Unique number of movies in the dataset: 1664\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "Ea3fORd-r24Z",
"outputId": "1aed76ea-4851-436e-943a-1eb45473905b",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 343
}
},
"source": [
"rating_count_df = pd.DataFrame(refined_dataset.groupby(['rating']).size(), columns=['count'])\n",
"rating_count_df"
],
"execution_count": 127,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>count</th>\n",
" </tr>\n",
" <tr>\n",
" <th>rating</th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1.0</th>\n",
" <td>6083</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1.5</th>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2.0</th>\n",
" <td>11334</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2.5</th>\n",
" <td>6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3.0</th>\n",
" <td>27060</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3.5</th>\n",
" <td>19</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4.0</th>\n",
" <td>34042</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4.5</th>\n",
" <td>16</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5.0</th>\n",
" <td>21130</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" count\n",
"rating \n",
"1.0 6083\n",
"1.5 3\n",
"2.0 11334\n",
"2.5 6\n",
"3.0 27060\n",
"3.5 19\n",
"4.0 34042\n",
"4.5 16\n",
"5.0 21130"
]
},
"metadata": {
"tags": []
},
"execution_count": 127
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "BbcBMiiC0GIl",
"outputId": "b777075a-17f1-44a5-d239-808d729274a4",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 539
}
},
"source": [
"ax = rating_count_df.reset_index().rename(columns={'index': 'rating score'}).plot('rating','count', 'bar',\n",
" figsize=(12, 8),\n",
" title='Count for Each Rating Score',\n",
" fontsize=12)\n",
"\n",
"ax.set_xlabel(\"movie rating score\")\n",
"ax.set_ylabel(\"number of ratings\")"
],
"execution_count": 128,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"Text(0, 0.5, 'number of ratings')"
]
},
"metadata": {
"tags": []
},
"execution_count": 128
},
{
"output_type": "display_data",
"data": {
"image/png": "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jq/rNOA0gIULF9amHZ0kSZIGMffNF2/R/V333mdt0f1tilNOOYWXvvSl3O9+99vsfU317RJnMvEc87FQvF1VraQ35WVBX/sCYGm3vLS/LcmO3T6XDtBXkiRJ08zZZ5/NAQccwIIFC3jZy17Gddddx9Oe9jQOOOAADj30UH7yk58AcMwxx/Cv//qv9/SbPbs3GePyyy/nqU99Ki984QuZN28eRx11FFXFqaeeyg033MAhhxzCIYccstl1Di2YJ3lAkiOSzE4yI8kzgJcAX0xyUJJHJNkuyW7AqcDlVTU2BeVs4IQku3QXdR4LnNm1XQg8OsnhSWYBbweWVNW1A/SVJEnSNLJ06VJOOukkvvSlL7F48WL+7u/+jje84Q0cffTRLFmyhKOOOorjjz9+0v18+9vf5pRTTuG73/0uP/rRj7jyyis5/vjjedCDHsRll13GZZddttm1DnPEvIDXANcDK4EPAH9SVRcBDwUuoTfF5L/ozTt/SV/fd9C7oHMZ8GXg5LHbHVbVcuBw4N3dfg8CjhikryRJkqaXL33pS7zoRS9i9913B2DXXXfl61//OkceeSQAL3vZy7jiiism3c/jH/949t57b7bbbjsOPPBArrvuui1e69DmmHcB+inraTsXOHcDfdcBr+heE7VfCsxbT9sG+0qSJEkTmTlzJnfffTcAd999N7fffvs9bTvssMM9yzNmzODOOyd6FM/mmeo55pIkSdKUedrTnsb555/PihW951v+4he/4IlPfCL/8i//AsA555zDwQcfDMDcuXO56qqrALjooou44447Jt3/nDlzWL16wvuMbLQpuSuLJEmSNArz58/nrW99K095ylOYMWMGv/3bv83f//3f8/KXv5yTTz6ZPfbYg49//OMAHHvssTzvec9jwYIFHHbYYey4446T7v+4447jsMMOu2eu+eZIlXcJhN7tEhctWjT5hpIkSRrINddcwyMf+chRlzEyEx1/kquqauFE2zuVRZIkSWqAwVySJElqgMFckiRJaoAXf0qSpM2ypR+zviW08Kh29VQVSUZdxpTblOs4HTGXJEnSUMyaNYsVK1ZsUkjdmlUVK1asYNasWRvVzxFzSZIkDcXee+/N9ddfz/Lly0ddypSbNWsWe++990b1MZhLkiRpKLbffnse8pCHjLqMrYZTWSRJkqQGGMwlSZKkBhjMJUmSpAYY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\n",
"text/plain": [
"<Figure size 864x576 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "zM7NoOXG1vYU"
},
"source": [
"We can see that number of 1.5, 2.5, 3.5, 4.5 ratings by the users are comparitively negligible."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cXYlt0OFxP1z"
},
"source": [
"Ratings for the movies not seen by a user is by default considered as 0. Lets calculate and add it to the existing dataframe."
]
},
{
"cell_type": "code",
"metadata": {
"id": "lgyPInMAwQAv",
"outputId": "10191306-986d-469f-dd46-5be593208c7f",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"total_count = num_items * num_users\n",
"zero_count = total_count-refined_dataset.shape[0]\n",
"zero_count"
],
"execution_count": 129,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"1469459"
]
},
"metadata": {
"tags": []
},
"execution_count": 129
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "avyj8_8ewjA_",
"outputId": "8e6b1763-1ea6-45ed-e86c-8ec1216e1fe4",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 343
}
},
"source": [
"# append counts of zero rating to df_ratings_cnt\n",
"rating_count_df = rating_count_df.append(\n",
" pd.DataFrame({'count': zero_count}, index=[0.0]),\n",
" verify_integrity=True,\n",
").sort_index()\n",
"rating_count_df"
],
"execution_count": 130,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>count</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0.0</th>\n",
" <td>1469459</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1.0</th>\n",
" <td>6083</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1.5</th>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2.0</th>\n",
" <td>11334</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2.5</th>\n",
" <td>6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3.0</th>\n",
" <td>27060</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3.5</th>\n",
" <td>19</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4.0</th>\n",
" <td>34042</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4.5</th>\n",
" <td>16</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5.0</th>\n",
" <td>21130</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" count\n",
"0.0 1469459\n",
"1.0 6083\n",
"1.5 3\n",
"2.0 11334\n",
"2.5 6\n",
"3.0 27060\n",
"3.5 19\n",
"4.0 34042\n",
"4.5 16\n",
"5.0 21130"
]
},
"metadata": {
"tags": []
},
"execution_count": 130
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Ofd8LQcVxvYA"
},
"source": [
"Number of times no rating was given (forged as 0 in this case) is a lot more than other ratings."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "f7ngnrerysBV"
},
"source": [
"So let's take log transform for count values and then we can plot them to compare"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ACZx4jhKxtGH",
"outputId": "43772624-dd68-4665-dab7-776df6fb0200",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 343
}
},
"source": [
"# add log count\n",
"rating_count_df['log_count'] = np.log(rating_count_df['count'])\n",
"rating_count_df"
],
"execution_count": 131,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>count</th>\n",
" <th>log_count</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0.0</th>\n",
" <td>1469459</td>\n",
" <td>14.200405</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1.0</th>\n",
" <td>6083</td>\n",
" <td>8.713253</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1.5</th>\n",
" <td>3</td>\n",
" <td>1.098612</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2.0</th>\n",
" <td>11334</td>\n",
" <td>9.335562</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2.5</th>\n",
" <td>6</td>\n",
" <td>1.791759</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3.0</th>\n",
" <td>27060</td>\n",
" <td>10.205812</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3.5</th>\n",
" <td>19</td>\n",
" <td>2.944439</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4.0</th>\n",
" <td>34042</td>\n",
" <td>10.435350</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4.5</th>\n",
" <td>16</td>\n",
" <td>2.772589</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5.0</th>\n",
" <td>21130</td>\n",
" <td>9.958449</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" count log_count\n",
"0.0 1469459 14.200405\n",
"1.0 6083 8.713253\n",
"1.5 3 1.098612\n",
"2.0 11334 9.335562\n",
"2.5 6 1.791759\n",
"3.0 27060 10.205812\n",
"3.5 19 2.944439\n",
"4.0 34042 10.435350\n",
"4.5 16 2.772589\n",
"5.0 21130 9.958449"
]
},
"metadata": {
"tags": []
},
"execution_count": 131
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "J2LE9usIy1Mz",
"outputId": "b0bd7926-7d36-4e9d-ec5b-f9f090ef228d",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 343
}
},
"source": [
"rating_count_df = rating_count_df.reset_index().rename(columns={'index': 'rating score'})\n",
"rating_count_df"
],
"execution_count": 132,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>rating score</th>\n",
" <th>count</th>\n",
" <th>log_count</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0.0</td>\n",
" <td>1469459</td>\n",
" <td>14.200405</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1.0</td>\n",
" <td>6083</td>\n",
" <td>8.713253</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1.5</td>\n",
" <td>3</td>\n",
" <td>1.098612</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2.0</td>\n",
" <td>11334</td>\n",
" <td>9.335562</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2.5</td>\n",
" <td>6</td>\n",
" <td>1.791759</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>3.0</td>\n",
" <td>27060</td>\n",
" <td>10.205812</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>3.5</td>\n",
" <td>19</td>\n",
" <td>2.944439</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>4.0</td>\n",
" <td>34042</td>\n",
" <td>10.435350</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>4.5</td>\n",
" <td>16</td>\n",
" <td>2.772589</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>5.0</td>\n",
" <td>21130</td>\n",
" <td>9.958449</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" rating score count log_count\n",
"0 0.0 1469459 14.200405\n",
"1 1.0 6083 8.713253\n",
"2 1.5 3 1.098612\n",
"3 2.0 11334 9.335562\n",
"4 2.5 6 1.791759\n",
"5 3.0 27060 10.205812\n",
"6 3.5 19 2.944439\n",
"7 4.0 34042 10.435350\n",
"8 4.5 16 2.772589\n",
"9 5.0 21130 9.958449"
]
},
"metadata": {
"tags": []
},
"execution_count": 132
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "vb5wAmR4zg7s",
"outputId": "8b822e7a-4e99-460e-e78f-2e4fa97bf9af",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 539
}
},
"source": [
"ax = rating_count_df.plot('rating score', 'log_count', 'bar', figsize=(12, 8),\n",
" title='Count for Each Rating Score (in Log Scale)',\n",
" logy=True,\n",
" fontsize=12,)\n",
"\n",
"ax.set_xlabel(\"movie rating score\")\n",
"ax.set_ylabel(\"number of ratings\")"
],
"execution_count": 133,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"Text(0, 0.5, 'number of ratings')"
]
},
"metadata": {
"tags": []
},
"execution_count": 133
},
{
"output_type": "display_data",
"data": {
"image/png": "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XWTZWrs+yRP79/zvdJ/3cRv4vrNqrV2c5Mx04enf0100eWm6YQk3ZfUhBx/r/7u8qjZmOrcXpBvnuzzdz/Gk9MNRZnFdut77H6QbTvCOJEe01lb9nF+UblzvN5NclW6Melp3MeqbkvxLuuB4/3QXts6qtXZ+klekuwj0p+kuvHvJOj7DcUlesEbP8e3xvCQ/H3l8d13nWn++/Va6oTvX9vt9Mmtvx58leWe68+aadOOvn9Va+14/ZOTQdL3KP0hyebqpGZPuQuB90/3l4vQkJ6/jM7w73YW0/1FV16e7iHL0H38vSBfAgTlSqw8VA2Ahqu6mMN9srf3JpGvZEFX1z+kuODxlvTvPg6r6UpL3tdb+cdK1rKmq7p5u6sKHttbWNU4duB2Ea4AFqKr2T/KTJJcleVK6v1D8emvtaxMtbMpU1WPSzWhyTWZ6he/XD5cBFiCzhQAsTPdIN7zgLumGIBwhWG+UB6Ubl33HJN9L8mzBGhY2PdcAADAQFzQCAMBAhGsAABjIZjPm+q53vWtbunTppMsAAGAz95WvfOWa1trdZtu22YTrpUuX5vzzz590GQAAbOaqaq03YjIsBAAABiJcAwDAQIRrAAAYyGYz5hoAYKH75S9/mcsvvzw33eQO90NYvHhxdt5552y11VZjv0a4BgDYTFx++eXZfvvts3Tp0lTVpMuZaq21LF++PJdffnl23XXXsV9nWAgAwGbipptuyl3uchfBegBVlbvc5S4b/FcA4RoAYDMiWA9nY9pSuAYAgIEYcw0AsJlaevTpgx5v2bFPXe8+2223XW644YZB33cunXLKKXngAx+YPffcc5Dj6bkGAGDBOuWUU/L1r399sOMJ1wAADK61lqOOOiq/9mu/lr322isnnXRSkmTlypU58sgjs/vuu+eJT3xinvKUp+TjH//4Wo9z3nnn5ZGPfGT23nvvHHDAAbn++utz00035aUvfWn22muvPPShD83nPve5JMnxxx+fV7/61be99pBDDsnnP//5JF2P+hvf+MbsvffeecQjHpErr7wy55xzTk499dQcddRR2WefffLd7373dn9uw0IAABjcySefnAsuuCAXXnhhrrnmmuy///559KMfnbPPPjvLli3L17/+9Vx11VXZY4898rKXvWzWY9x888057LDDctJJJ2X//ffPddddl2233Tbvfve7U1W5+OKL881vfjNPetKTcumll66znhtvvDGPeMQj8ra3vS1/+Id/mPe///055phj8rSnPS2HHHJInv3sZw/yufVcAwAwuLPOOivPe97zsuWWW2annXbKYx7zmJx33nk566yz8pznPCdbbLFF7nGPe+Rxj3vcWo/xrW99K/e85z2z//77J0l22GGHLFq0KGeddVZe+MIXJkl233333Pe+911vuN56661zyCGHJEke9rCHZdmyZcN80DUI1wAAbBYWLVqUlStX3rY8Okf1VlttddvUeltuuWVuueWWOalBuAYAYHAHHXRQTjrppNx66625+uqrc+aZZ+aAAw7IgQcemH/5l3/JypUrc+WVV942Jno2D3rQg3LFFVfkvPPOS5Jcf/31ueWWW3LQQQflhBNOSJJceuml+cEPfpAHPehBWbp0aS644IKsXLkyP/zhD/PlL395vXVuv/32uf766wf5zIkx1wAAm61xps6bK8985jNz7rnnZu+9905V5R3veEfucY975FnPelY++9nPZs8998x97nOf7LvvvlmyZMmsx9h6661z0kkn5TWveU1+/vOfZ9ttt80ZZ5yRI488MkcccUT22muvLFq0KMcff3y22WabHHjggdl1112z5557Zo899si+++673jqf+9zn5hWveEXe85735OMf/3juf//7367PXa2123WATcV+++3Xzj///EmXAQAwMd/4xjeyxx57TLqM9brhhhuy3XbbZfny5TnggANy9tln5x73uMeky5rVbG1aVV9pre032/56rgEAmFeHHHJIrr322tx8881505vetMkG640hXI8Y+i5GG2OSf74BAJgPs42zfuYzn5nLLrtstXVvf/vbc/DBB89TVcMQrgEAmLhPfOITky5hEGYLAQDYjGwu19NtCjamLYVrAIDNxOLFi7N8+XIBewCttSxfvjyLFy/eoNcZFgIAsJnYeeedc/nll+fqq6+edCmbhcWLF2fnnXfeoNcI1wAAm4mtttoqu+6666TLWNAMCwEAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEsmnQBAMDmZ+nRp0+6hCw79qmTLoEFaJPsua6qJVX15aq6oap+bdL1AADAODbJcJ3kZ0memuTjky4EAADGtUmG69baL1trV0+6DgAA2BBzOua6ql6d5CVJ9kpyYmvtJSPbdkzygSRPSnJNkv/VWvvnuawHgOEZWwswY64vaPxxkrcmOTjJtmtse2+Sm5PslGSfJKdX1YWttUvmuCYAAJgTczospLV2cmvtlCTLR9dX1R2TPCvJm1prN7TWzkpyapIXzWU9AAAwlyY15vqBSW5prV06su7CJA9etVBVn0o3ZOT9VfWS2Q5SVYdX1flVdf7VVxuiDQDAZE1qnuvtkly3xroVSbZftdBae8r6DtJaOy7JcUmy3377tSELBABgWAvhGo1J9VzfkGSHNdbtkOT6CdQCAACDmFS4vjTJoqp6wMi6vZO4mBEAgKk1p+G6qhZV1eIkWybZsqoWV9Wi1tqNSU5O8paqumNVHZjk6Uk+Mpf1AADAXJrrnutjkvw8ydFJXtg/P6bfdmS66fmuSnJikiNMwwcAwDSb0wsaW2tvTvLmtWz7SZJnzOX7AwDAfNokb38OAADTSLgGAICBCNcAADAQ4RoAAAYyqTs0AlNoIdxZCwBuDz3XAAAwEOEaAAAGIlwDAMBAhGsAABjI1Ifrqjq0qo5bsWLFpEsBAGCBm/pw3Vo7rbV2+JIlSyZdCgAAC9zUh2sAANhUCNcAADAQ4RoAAAbiDo3Myp34AAA2nJ5rAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxk6sN1VR1aVcetWLFi0qUAALDATX24bq2d1lo7fMmSJZMuBQCABW7qwzUAAGwqhGsAABiIcA0AAAMRrgEAYCDCNQAADES4BgCAgQjXAAAwEOEaAAAGIlwDAMBAhGsAABiIcA0AAAMRrgEAYCDCNQAADES4BgCAgQjXAAAwEOEaAAAGIlwDAMBAhGsAABiIcA0AAAOZ+nBdVYdW1XErVqyYdCkAACxwUx+uW2untdYOX7JkyaRLAQBggZv6cA0AAJsK4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIFMfrqvq0Ko6bsWKFZMuBQCABW7qw3Vr7bTW2uFLliyZdCkAACxwUx+uAQBgUyFcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYyAaF66q6c1U9ZK6KAQCAabbecF1Vn6+qHapqxyRfTfL+qvqruS8NAACmyzg910taa9cl+a0kH26tPTzJE+a2LAAAmD7jhOtFVXXPJL+d5JNzXA8AAEytccL1W5L8e5LvtNbOq6r7Jfn23JYFAADTZ9H6dmitfSzJx0aWv5fkWXNZFAAATKP1huuqes8sq1ckOb+19q/DlwQAANNpnGEhi5Psk24oyLeTPCTJzkleXlXvmsPaxlJVh1bVcStWrJh0KQAALHDr7blOF6YPbK3dmiRV9XdJvpDkUUkunsPaxtJaOy3Jafvtt98rJl0LAAAL2zg913dOst3I8h2T7NiH7V/MSVUAADCFxum5fkeSC6rq80kqyaOT/FlV3THJGXNYGwAATJVxZgv5QFV9KskB/ao3tNZ+3D8/as4qAwCAKTPOsJBV+12d5KdJdquqR89dSQAAMJ3GmYrv7UkOS3JJkpX96pbkzDmsCwAAps44Y66fkeRBrTUXLwIAwDqMMyzke0m2mutCAABg2o3Tc/2zdLOFfDYjU++11l47Z1UBAMAUGidcn9o/AACAdRhnKr4PzUchAAAw7dYarqvqo621366qi9PNDrKa1tpD5rQyAACYMuvquf69/r+HzEchAAAw7dY6W0hr7Yr+6ZGtte+PPpIcOT/lAQDA9BhnKr4nzrLuyUMXAgAA025dY66PSNdDfb+qumhk0/ZJzp7rwgAAYNqsa8z1Pyf5tyR/nuTokfXXt9Z+MqdVAQDAFFpruG6trUiyIsnzkqSq7p5kcZLtqmq71toP5qdEAACYDusdc11Vh1bVt5NcluS/kixL16MNAACMGOeCxrcmeUSSS1truyZ5fJIvzmlVAAAwhcYJ179srS1PskVVbdFa+1yS/ea4LgAAmDrrvf15kmurarskZyY5oaquSnLj3JYFAADTZ5ye66cn+VmSP0jy6STfTXLoXBYFAADTaJ0911W1ZZJPttYel2Rlkg/NS1UAADCF1tlz3Vq7NcnKqloyT/UAAMDUGmfM9Q1JLq6qz2RkrHVr7bVzVhUAAEyhccL1yf0DAABYh/WG69aacdYAADCGcWYLAQAAxiBcAwDAQNYarqvqI/1/f2/+ygEAgOm1rp7rh1XVvZK8rKruXFU7jj7mq0AAAJgW67qg8X1JPpvkfkm+kqRGtrV+PQAA0Ftrz3Vr7T2ttT2SfLC1dr/W2q4jD8EaAADWMM5UfEdU1d5JDupXndlau2huyxpfVR2a5NDddttt0qUAALDArXe2kKp6bZITkty9f5xQVa+Z68LG1Vo7rbV2+JIl7tAOAMBkjXOHxt9N8vDW2o1JUlVvT3Jukv8zl4UBAMC0GWee60py68jyrVn94kYAACDj9Vz/Y5IvVdUn+uVnJPnA3JUEAADTaZwLGv+qqj6f5FH9qpe21r42p1UBAMAUGqfnOq21ryb56hzXAgAAU22cMdcAAMAYhGsAABjIOsN1VW1ZVZ+br2IAAGCarTNct9ZuTbKyqtyhBQAA1mOcCxpvSHJxVX0myY2rVrbWXjtnVQEAwBQaJ1yf3D8AAIB1GGee6w9V1bZJdmmtfWseagIAgKm03tlCqurQJBck+XS/vE9VnTrXhQEAwLQZZyq+Nyc5IMm1SdJauyDJ/eawJgAAmErjhOtfttZWrLFu5VwUAwAA02ycCxovqarnJ9myqh6Q5LVJzpnbsgAAYPqM03P9miQPTvKLJCcmuS7J789lUQAAMI3GmS3kZ0neWFVv7xbb9XNfFgAATJ9xZgvZv6ouTnJRupvJXFhVD5v70gAAYLqMM+b6A0mObK19IUmq6lFJ/jHJQ+ayMAAAmDbjjLm+dVWwTpLW2llJbpm7kgAAYDqttee6qvbtn/5XVf19uosZW5LDknx+7ksDAIDpsq5hIe9cY/lPRp63OagFAACm2lrDdWvtcfNZCAAATLv1XtBYVXdK8jtJlo7u31p77dyVBQAA02ec2UI+leSLSS6O254DAMBajROuF7fWXjfnlQAAwJQbZyq+j1TVK6rqnlW146rHnFcGAABTZpye65uT/EWSN2ZmlpCW5H5zVRQAAEyjccL1/0yyW2vtmrkuBgAAptk4w0K+k+Rnc10IAABMu3F6rm9MckFVfS7JL1atNBUfAACsbpxwfUr/AAAA1mG94bq19qH5KAQAAKbdOHdovCwzs4TcprVmthAAABgxzrCQ/UaeL07ynCTmuQYAgDWsd7aQ1trykcePWmvvSvLUeagNAACmyjjDQvYdWdwiXU/2OD3eAACwoIwTkt858vyWJMuS/PacVAMAAFNsnNlCHjcfhQAAwLQbZ1jINkmelWTp6P6ttbfMXVkAADB9xhkW8q9JViT5Skbu0AgAAKxunHC9c2vtN+e8ko1UVYcmOXS33XabdCkAACxw652KL8k5VbXXnFeykVprp7XWDl+yZMmkSwEAYIEbp+f6UUle0t+p8RdJKklrrT1kTisDAIApM064fvKcVwEAm4GlR58+6RKy7Fj3eYNJGmcqvu/PRyEAADDtxhlzDQAAjEG4BgCAgQjXAAAwEOEaAAAGIlwDAMBAhGsAABiIcA0AAAMZ5yYyAABsJDcXWlj0XAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGMjUh+uqOrSqjluxYsWkSwEAYIGb+nDdWjuttXb4kiVLJl0KAAAL3NSHawAA2FQI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxEuAYAgIEI1wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgiyZdAMA0Wnr06ZMuIcuOfeqkSwBgDXquAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGALwJDxkAAA5+SURBVICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMRLgGAICBCNcAADAQ4RoAAAYiXAMAwECEawAAGIhwDQAAAxGuAQBgIMI1AAAMZNGkC4BN3dKjT590CVl27FMnXQIAMAY91wAAMBDhGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAxkkw3XVfX2qvpCVX2kqraadD0AALA+m2S4rqq9k9y7tXZQkm8mefaESwIAgPXaJMN1kkcm+Y/++aeTHDjBWgAAYCxzGq6r6tVVdX5V/aKqjl9j245V9YmqurGqvl9Vzx/ZfOck1/XPVyTZcS7rBACAISya4+P/OMlbkxycZNs1tr03yc1JdkqyT5LTq+rC1tolSa5NskO/35IkP5njOgEA4Hab057r1trJrbVTkiwfXV9Vd0zyrCRvaq3d0Fo7K8mpSV7U73JOkif0zw9OcvZc1gkAAEOY1JjrBya5pbV26ci6C5M8OElaaxckubKqvtCv+5f5LxEAADbMXA8LWZvtMjOmepUVSbZftdBaO2p9B6mqw5McniS77LLLkPUBAMAGm1TP9Q2ZGVO9yg5Jrt+Qg7TWjmut7dda2+9ud7vbYMUBAMDGmFS4vjTJoqp6wMi6vZNcMqF6AADgdpvrqfgWVdXiJFsm2bKqFlfVotbajUlOTvKWqrpjVR2Y5OlJPjKX9QAAwFya657rY5L8PMnRSV7YPz+m33Zkuun5rkpyYpIj+mn4AABgKlVrbdI1DKKqrk7y/UnXkeSuSa6ZdBGbCG0xQ1vM0BYztMUMbTFDW3S0wwxtMWNTaYv7ttZmveBvswnXm4qqOr+1tt+k69gUaIsZ2mKGtpihLWZoixnaoqMdZmiLGdPQFpO6oBEAADY7wjUAAAxEuB7ecZMuYBOiLWZoixnaYoa2mKEtZmiLjnaYoS1mbPJtYcw1AAAMRM81AAAMRLgGAICBCNcAADCQRZMuANj8VdWdk2yf5PrW2k8nXQ+bBucFsDnSc307VNXhVXVOVa2oqlv7/55TVa+YdG2TVFV3rqpd+i9OFqiq2qqq/qyqrkh3N61lSa6pqh9X1duqaqvJVjh/qurRI8+3qKo/qqrzqur8qjqmqracZH3zyXkxw3mxOt+pSVUtXWP5sKr6WFV9vKpeOJmqJmsazwvheiNV1bFJfi/JPyT5jSQPSvK4fvn3qurPJ1jevPOF2fFluZq/S/LrSV6Q5O5Jtk5ytyQvTPKIfvtC8cmR529I8jtJ/jLJXyQ5LMkxkyhqQpwXM5wXPd+pt7lo1ZOqemWSv05yfpIvJzm2ql41qcImYVrPC1PxbaSqujrJQ1prV8yy7V5JLmqt3XX+K5uMqvqHJPdP8r+TXJhkRZIdkuyT5I1JLmut/e7kKpwfVXVda22H/vkxSZ6X5C395mOSfLy19qeTqm8+VdW1Se7bWlsxy7Y7JVnWWrvT/Fc2/6rq+tba9v3zbyZ5Vmvtkn559ySfbK3tNska54vzYobzYobv1M4a58TFSQ5vrZ3bLx+Q5PjW2p6TrHE+Tet5Ycz1xqvbuX1z8+z86hfmT5L8Z1V9NV1P9mYfrrP6z/2FWf3L8sJ0PVULIlwn+XmSe6b7h9aa7pnkpvktZ6JGezF2XHVOJElr7ZtVtdMEapoU58UM58UM36md0XPinkm+eNuG1r5cVTvPf0kTNZXnhXC98T6QLji+M6v31O6d5HVJ3j/B2ibBF2bHl+WMdyT5XFV9IL/6O/LyJMdOsLb5doeqOrN/vm1V3be19v0kqaq7J7lxcqXNO+fFDOfFDN+pncVV9eH++ZZJdkry38ltf9m5eVKFTchUnhfC9UZqrf1RVX0vyUuTPDjJdkluSHJJkve01v5+kvVNgC/Mji/LXmvtr6vq6+nGkR6S1X9HXtpa+/dJ1jfPXr7G8mhvy75JPjKPtUyU82I1zoue79TbvG3k+buS3Cl9uE7y6CT/Me8VTdC0nhfGXDOYqjo43Rfmmr8AH14oX5hV9eI1Vv1Xa21Zv+03kzy+tXbUvBcGAMwL4RqYiKraubV2+aTr2BRoixnaYoa2gOlkKr45UlXXTbqGTckCvAhjVtphNV+fdAGbkG9MuoBNiPNihrbo+U7taIfVbartIVzPnadMuoBNjPDQ0Q4zHjzpAjYhC2ZqrTE4L2Zoixm+UzvaYXWbZHsYFnI7VNUeSV6U7n+A2ye5Pt0Y44+01oSoEVV1n9baDyddx6QttHaoql2SPCzJJa21S9fY9rzW2omTqWz+aYsZVfXQdPPifyrJL5Ic0S+f0Vo7fZK1zTdtsW5VdX6SJ7XWfjLpWiZJO3Sqatd0gbqSfLq19p0JlzQr4XojVdXz0t1J7NT86uwYT0vyytbaSZOrcNPR35Xwja21t6x3583YQmuH/gLOjya5LMkDkhyf5DWttVv77bfdcGdzpy1mVNXLk7w13bSVP05ycpL7pJu96rlJfq+19sHJVTh/tMWMkenn1vTsdPcHuKm19jvzWNJEaIfVVdU3Wmt79M8fk+S0JGen+505KMnTW2v/OcESZyVcb6SquizJC1trZ8+y7cAkJ7TWls57YZugqtomyc9aawvp1t+/YqG1Q3/zoDe11k7v5/f+p3Q9c7/VWrt59E5kmzttMaO/E+HT0vU8fSPJo1pr5/TbDk7yjtba3hMscd5oixlV9fN0t/j+bFafkvD1Sd6X5IaFcHdb7bC6Ne5Y+YUk72+tfbhffkGSV7XWHjnJGmcjXG+kqrohyd1aaz+fZdsdklzVWttu/iubjKpaV+/KoiQvWAihUjvMqKoVrbUlI8uL0oXKu6YLFFcuoECpLXqjbVFVNybZrvVfRFW1RZKfLKDbn2uLXlU9IMnfJPlpkte11n7cr78iyd6ttasmWd980Q6rG/2rXlVdleTerbVf9stbJrm6tbbjJGucjQsaN95nknywqu4/urJffn+/fSF5frq7NP5olsdCmkpKO8z4aVXdZ9VCa+2WJM9L8oMkZ6S7+9hCoS1m3FhVW/XPj2+r9/Bsm2TlBGqaFG3Ra619u7V2cJJT0t2Q7PX9P0IXVA+gdvgVW1XVS6vqZenaYOuRbYuyif6/0x0aN97Lkvxtkq9X1S+TXJduzPWidOPmXjbB2ibh4iT/3lo7dc0NVbU4ydHzX9JEaIcZZ6S7q9ZtY8z78PCyqnpfkkdMqrAJ0BYzPptktyTfaK29ao1thyS5aP5LmhhtsYbW2v+tqk+l+125IN1kAQuOdrjNl9LdnC7ppqbcM8l5/fJjknxrEkWtj2Eht1M/BOSBmbkj4aWttZ9Ntqr5V1WvSvKj1tops2zbMskxC2GcmHaYUVVbJ1m0tt+HqtqltfaDeS5rIrTFeKrqbun+3XHNpGuZNG2RVNU+6QLU37fWbpp0PZOiHWZXVUuSbLUp/o4I1wAAMBBjrgEAYCDCNQAADES4BthEVdUrq2rwG0ZU1dKqev7I8n5V9Z6h3wdgITLmGmAzVFWL+in/Ztv22CSvb60dMr9Vbbiq2nLVnSwBpoGea4Dbqe8J/mZVHV9Vl1bVCVX1hKo6u6q+XVUH9PvtWFWnVNVFVfXFqnpIVW1RVcuq6k4jx/t2Ve1UVW+uqtf36+5fVZ+uqq9U1ReqavdZ6nhzVX2kqs5O8pG+ri9U1Vf7x6o7mR2b5KCquqCq/qCqHltVnxw5xger6vNV9b2qeu3I8d9UVd+qqrOq6sRVta1Rw3Oq6v9V1YVVdWa/bsuq+st+/UVV9Zp+/eOr6mtVdXH/ntv065dV1duru7Plc6rqSVV1bv8ZPlZVC+YGXcD0Ea4BhrFbkncm2b1/PD/Jo9LdtvgN/T5/muRrrbWH9Os+3FpbmeRfkzwzSarq4Um+31q7co3jH5fkNa21h/XH/Nu11LFnkie01p6X5KokT2yt7ZvksCSrhn4cneQLrbV9Wmt/Pcsxdk9ycJIDkvxJVW1VVfsneVaSvZM8Ocl+a3n/P05ycH/b7qf16w5PsjTJPv1nP6Gf9/34JIe11vZKd4+AI0aOs7yv+4wkx/Sfad8k5yd53VreG2Di3EQGYBiXtdYuTpKquiTJZ1trraouThcsky5sPytJWmv/WVV3qaodkpyULpT+Y5Ln9su36XtqH5nkY1W1avU2a6nj1Nbaz/vnWyX5m36e3FvTzck/jtNba79I8ov+lsM7JTkwyb/28+zeVFWnreW1Zyc5vqo+mu6GWknyhCTvWzVMpbX2k6raO12bXdrv86Ekr0ryrn55VRs8It0/GM7uP/vWSc4d83MAzDvhGmAYvxh5vnJkeWXW///ac5Ps1t845BlJ3rrG9i2SXNta22eMOm4cef4HSa5M19u8RZJxb0Ax+lluzQZ8V7TWXtn3vj81yVeq6mHjvnYNqz5HJflM3xMPsMkzLARg/nwhyQuS2y4qvKa1dl1/K/RPJPmrdLfCXj76otbadUkuq6rn9K+tvud3fZYkuaIfevKiJFv266/Pht9O+ewkh1bV4r4nfdaLIavq/q21L7XW/jjJ1Unuk+QzSf5HVS3q99kx3W2Ll1bVbv1LX5Tkv2Y55BeTHLhqv6q6Y1WN2wMPMO+Ea4D58+YkD6uqi9JdVPjikW0nJXlh1hgSMuIFSV5eVRcmuSTJ08d4v79N8uL+Nbtnpjf4oiS39hcd/sE4hbfWzktyav/af0tycZIVs+z6F/0Fiv8vyTlJLkzyD0l+kOSivpbn98NLXppuqMvF6Xr43zfL+16d5CVJTuzb7dz+swBskkzFB8BYqmq71toNVXWHJGcmOby19tVJ1wWwKTHmGoBxHVdVeyZZnORDgjXAr9JzDQAAAzHmGgAABiJcAwDAQIRrAAAYiHANAAADEa4BAGAgwjUAAAzk/wMTBMoPutQUjwAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 864x576 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "J5oRl9LZ2KiW"
},
"source": [
"We have already observed from the before bar plot that ratings 3 and 4 are given in more numbers by the users. Even the above graph suggests the same.\n",
"\n",
" Take away from this plot is by the number of missing ratings, we can estimate the level of sparsity in the matrix we are going to form. "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ezYrpsCM2LC7"
},
"source": [
"**Plot rating frequency of all movies**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "YqfWKYCEz782",
"outputId": "93b3ac8c-a39f-44e5-9c2f-39ce2d9b6b55",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 195
}
},
"source": [
"refined_dataset.head()"
],
"execution_count": 134,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>user id</th>\n",
" <th>movie title</th>\n",
" <th>rating</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>101 Dalmatians (1996)</td>\n",
" <td>2.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1</td>\n",
" <td>12 Angry Men (1957)</td>\n",
" <td>5.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1</td>\n",
" <td>20,000 Leagues Under the Sea (1954)</td>\n",
" <td>3.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1</td>\n",
" <td>2001: A Space Odyssey (1968)</td>\n",
" <td>4.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1</td>\n",
" <td>Abyss, The (1989)</td>\n",
" <td>3.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" user id movie title rating\n",
"0 1 101 Dalmatians (1996) 2.0\n",
"1 1 12 Angry Men (1957) 5.0\n",
"2 1 20,000 Leagues Under the Sea (1954) 3.0\n",
"3 1 2001: A Space Odyssey (1968) 4.0\n",
"4 1 Abyss, The (1989) 3.0"
]
},
"metadata": {
"tags": []
},
"execution_count": 134
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "oTe-A4D156Ry",
"outputId": "f64f656a-b218-4ab1-95a3-e01641fbe434",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 225
}
},
"source": [
"# get rating frequency\n",
"movies_count_df = pd.DataFrame(refined_dataset.groupby('movie title').size(), columns=['count'])\n",
"movies_count_df.head()"
],
"execution_count": 135,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>count</th>\n",
" </tr>\n",
" <tr>\n",
" <th>movie title</th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>'Til There Was You (1997)</th>\n",
" <td>9</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1-900 (1994)</th>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>101 Dalmatians (1996)</th>\n",
" <td>109</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12 Angry Men (1957)</th>\n",
" <td>125</td>\n",
" </tr>\n",
" <tr>\n",
" <th>187 (1997)</th>\n",
" <td>41</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" count\n",
"movie title \n",
"'Til There Was You (1997) 9\n",
"1-900 (1994) 5\n",
"101 Dalmatians (1996) 109\n",
"12 Angry Men (1957) 125\n",
"187 (1997) 41"
]
},
"metadata": {
"tags": []
},
"execution_count": 135
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "2PZxHmrq6MTz",
"outputId": "e2b555d2-c2f9-44db-de48-8e57efe3e4c5",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 533
}
},
"source": [
"# plot rating frequency of all movies\n",
"ax = movies_count_df \\\n",
" .sort_values('count', ascending=False) \\\n",
" .reset_index(drop=True) \\\n",
" .plot(\n",
" figsize=(12, 8),\n",
" title='Rating Frequency of All Movies',\n",
" fontsize=12\n",
" )\n",
"ax.set_xlabel(\"movie Id\")\n",
"ax.set_ylabel(\"number of ratings\")"
],
"execution_count": 136,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"Text(0, 0.5, 'number of ratings')"
]
},
"metadata": {
"tags": []
},
"execution_count": 136
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 864x576 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PyCcV_0j6yUw"
},
"source": [
"**As the size of MovieLens dataset picked for this project is small. There is no need of removing rarely rated movies or users who has given rating for fewer movies.**\n",
"\n",
"**Also because the dataset considered is small, we do not see the long-tail property which will be the scenario with the distribution of ratings.**\n",
"\n",
"*If the dataset is larger, then* (this can be referred when we do similar kind of tasks with a larger dataset, just for future reference)\n",
"\n",
"The distribution of ratings among movies often satisfies a property in real-world settings, which is referred to as the long-tail property. According to this property, only a small fraction of the items are rated frequently. Such items are referred to as popular items. The vast majority of items are rated rarely. This results in a highly skewed distribution of the underlying ratings."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PZD27ZLM8IN7"
},
"source": [
"# Training KNN model to build item-based collaborative Recommender System."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5omV7GyNTITK"
},
"source": [
"**Reshaping the dataframe**\n",
"\n",
"We need to transform (reshape in this case) the data in such a way that each row of the dataframe represents a movie and each column represents a different user. So we want the data to be [movies, users] array if movie is the subject where similar movies must be found and [users, movies] array for reverse.\n",
"\n",
"To reshape the dataframe, we will pivot the dataframe to the wide format with movies as rows and users as columns. As we know that not all users watch all the movies, we can expect a lot of missing values. We will have to fill those missing observations with 0s since we are going to perform linear algebra operations (calculating distances between vectors). \n",
"\n",
"Finally, we transform the values of the dataframe into a scipy sparse matrix for most efficient calculations.\n",
"\n",
"This dataframe is then fed into a KNN model."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IyvX84Lm6ToE"
},
"source": [
"## Movie Recommendation using KNN with Input as **User id**, Number of similar users should the model pick and Number of movies you want to get recommended:"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3qJCE3l3f2mY"
},
"source": [
"1. Reshaping model in such a way that each user has n-dimensional rating space where n is total number of movies\n",
"\n",
" We will train the KNN model inorder to find the closely matching similar users to the user we give as input and we recommend the top movies which would interest the input user."
]
},
{
"cell_type": "code",
"metadata": {
"id": "pVjDfpRvWVhw",
"outputId": "d4e854fb-2020-4c7e-88c4-57b2e5d638cb",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 391
}
},
"source": [
"# pivot and create movie-user matrix\n",
"user_to_movie_df = refined_dataset.pivot(\n",
" index='user id',\n",
" columns='movie title',\n",
" values='rating').fillna(0)\n",
"\n",
"user_to_movie_df.head()"
],
"execution_count": 138,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th>movie title</th>\n",
" <th>'Til There Was You (1997)</th>\n",
" <th>1-900 (1994)</th>\n",
" <th>101 Dalmatians (1996)</th>\n",
" <th>12 Angry Men (1957)</th>\n",
" <th>187 (1997)</th>\n",
" <th>2 Days in the Valley (1996)</th>\n",
" <th>20,000 Leagues Under the Sea (1954)</th>\n",
" <th>2001: A Space Odyssey (1968)</th>\n",
" <th>3 Ninjas: High Noon At Mega Mountain (1998)</th>\n",
" <th>39 Steps, The (1935)</th>\n",
" <th>8 1/2 (1963)</th>\n",
" <th>8 Heads in a Duffel Bag (1997)</th>\n",
" <th>8 Seconds (1994)</th>\n",
" <th>A Chef in Love (1996)</th>\n",
" <th>Above the Rim (1994)</th>\n",
" <th>Absolute Power (1997)</th>\n",
" <th>Abyss, The (1989)</th>\n",
" <th>Ace Ventura: Pet Detective (1994)</th>\n",
" <th>Ace Ventura: When Nature Calls (1995)</th>\n",
" <th>Across the Sea of Time (1995)</th>\n",
" <th>Addams Family Values (1993)</th>\n",
" <th>Addicted to Love (1997)</th>\n",
" <th>Addiction, The (1995)</th>\n",
" <th>Adventures of Pinocchio, The (1996)</th>\n",
" <th>Adventures of Priscilla, Queen of the Desert, The (1994)</th>\n",
" <th>Adventures of Robin Hood, The (1938)</th>\n",
" <th>Affair to Remember, An (1957)</th>\n",
" <th>African Queen, The (1951)</th>\n",
" <th>Afterglow (1997)</th>\n",
" <th>Age of Innocence, The (1993)</th>\n",
" <th>Aiqing wansui (1994)</th>\n",
" <th>Air Bud (1997)</th>\n",
" <th>Air Force One (1997)</th>\n",
" <th>Air Up There, The (1994)</th>\n",
" <th>Airheads (1994)</th>\n",
" <th>Akira (1988)</th>\n",
" <th>Aladdin (1992)</th>\n",
" <th>Aladdin and the King of Thieves (1996)</th>\n",
" <th>Alaska (1996)</th>\n",
" <th>Albino Alligator (1996)</th>\n",
" <th>...</th>\n",
" <th>Whole Wide World, The (1996)</th>\n",
" <th>Widows' Peak (1994)</th>\n",
" <th>Wife, The (1995)</th>\n",
" <th>Wild America (1997)</th>\n",
" <th>Wild Bill (1995)</th>\n",
" <th>Wild Bunch, The (1969)</th>\n",
" <th>Wild Reeds (1994)</th>\n",
" <th>Wild Things (1998)</th>\n",
" <th>William Shakespeare's Romeo and Juliet (1996)</th>\n",
" <th>Willy Wonka and the Chocolate Factory (1971)</th>\n",
" <th>Window to Paris (1994)</th>\n",
" <th>Wings of Courage (1995)</th>\n",
" <th>Wings of Desire (1987)</th>\n",
" <th>Wings of the Dove, The (1997)</th>\n",
" <th>Winnie the Pooh and the Blustery Day (1968)</th>\n",
" <th>Winter Guest, The (1997)</th>\n",
" <th>Wishmaster (1997)</th>\n",
" <th>With Honors (1994)</th>\n",
" <th>Withnail and I (1987)</th>\n",
" <th>Witness (1985)</th>\n",
" <th>Wizard of Oz, The (1939)</th>\n",
" <th>Wolf (1994)</th>\n",
" <th>Woman in Question, The (1950)</th>\n",
" <th>Women, The (1939)</th>\n",
" <th>Wonderful, Horrible Life of Leni Riefenstahl, The (1993)</th>\n",
" <th>Wonderland (1997)</th>\n",
" <th>Wooden Man's Bride, The (Wu Kui) (1994)</th>\n",
" <th>World of Apu, The (Apur Sansar) (1959)</th>\n",
" <th>Wrong Trousers, The (1993)</th>\n",
" <th>Wyatt Earp (1994)</th>\n",
" <th>Yankee Zulu (1994)</th>\n",
" <th>Year of the Horse (1997)</th>\n",
" <th>You So Crazy (1994)</th>\n",
" <th>Young Frankenstein (1974)</th>\n",
" <th>Young Guns (1988)</th>\n",
" <th>Young Guns II (1990)</th>\n",
" <th>Young Poisoner's Handbook, The (1995)</th>\n",
" <th>Zeus and Roxanne (1997)</th>\n",
" <th>unknown</th>\n",
" <th>Á köldum klaka (Cold Fever) (1994)</th>\n",
" </tr>\n",
" <tr>\n",
" <th>user id</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>2.0</td>\n",
" <td>5.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>5.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>5.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>5.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>2.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>2.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>5.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>5.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>2.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>0.0</td>\n",
" <td>2.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>5.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>5.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 1664 columns</p>\n",
"</div>"
],
"text/plain": [
"movie title 'Til There Was You (1997) ... Á köldum klaka (Cold Fever) (1994)\n",
"user id ... \n",
"1 0.0 ... 0.0\n",
"2 0.0 ... 0.0\n",
"3 0.0 ... 0.0\n",
"4 0.0 ... 0.0\n",
"5 0.0 ... 0.0\n",
"\n",
"[5 rows x 1664 columns]"
]
},
"metadata": {
"tags": []
},
"execution_count": 138
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "NzGiLk_P6ZPU",
"outputId": "ce7e1849-a29d-456b-9eb7-a17190231787",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 50
}
},
"source": [
"# transform matrix to scipy sparse matrix\n",
"user_to_movie_sparse_df = csr_matrix(user_to_movie_df.values)\n",
"user_to_movie_sparse_df"
],
"execution_count": 139,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<943x1664 sparse matrix of type '<class 'numpy.float64'>'\n",
"\twith 99693 stored elements in Compressed Sparse Row format>"
]
},
"metadata": {
"tags": []
},
"execution_count": 139
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_lmFFozScX9B"
},
"source": [
"**Fitting K-Nearest Neighbours model to the scipy sparse matrix:**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "T-C_KVvkglZZ",
"outputId": "fa672186-a2c4-478a-9e26-5a8d9eaa8334",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 67
}
},
"source": [
"knn_model = NearestNeighbors(metric='cosine', algorithm='brute')\n",
"knn_model.fit(user_to_movie_sparse_df)"
],
"execution_count": 140,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"NearestNeighbors(algorithm='brute', leaf_size=30, metric='cosine',\n",
" metric_params=None, n_jobs=None, n_neighbors=5, p=2,\n",
" radius=1.0)"
]
},
"metadata": {
"tags": []
},
"execution_count": 140
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "GznTZhlIcPCI"
},
"source": [
"## function to find top n similar users of the given input user \n",
"def get_similar_users(user, n = 5):\n",
" ## input to this function is the user and number of top similar users you want.\n",
"\n",
" knn_input = np.asarray([user_to_movie_df.values[user-1]]) #.reshape(1,-1)\n",
" # knn_input = user_to_movie_df.iloc[0,:].values.reshape(1,-1)\n",
" distances, indices = knn_model.kneighbors(knn_input, n_neighbors=n+1)\n",
" \n",
" print(\"Top\",n,\"users who are very much similar to the User-\",user, \"are: \")\n",
" print(\" \")\n",
" for i in range(1,len(distances[0])):\n",
" print(i,\". User:\", indices[0][i]+1, \"separated by distance of\",distances[0][i])\n",
" return indices.flatten()[1:] + 1, distances.flatten()[1:]\n"
],
"execution_count": 141,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "UzD2cOe361JX"
},
"source": [
"**Specify User id and Number of similar users we want to consider here**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ZAc5xnl2mZp3",
"outputId": "9f9a1dd7-2877-4cdc-fd5f-e6282ac42a3e",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 319
}
},
"source": [
"from pprint import pprint\n",
"user_id = 778\n",
"print(\" Few of movies seen by the User:\")\n",
"pprint(list(refined_dataset[refined_dataset['user id'] == user_id]['movie title'])[:10])\n",
"similar_user_list, distance_list = get_similar_users(user_id,5)"
],
"execution_count": 142,
"outputs": [
{
"output_type": "stream",
"text": [
" Few of movies seen by the User:\n",
"['Amityville Horror, The (1979)',\n",
" 'Angels in the Outfield (1994)',\n",
" 'Apocalypse Now (1979)',\n",
" 'Apollo 13 (1995)',\n",
" 'Austin Powers: International Man of Mystery (1997)',\n",
" 'Babe (1995)',\n",
" 'Back to the Future (1985)',\n",
" 'Blues Brothers, The (1980)',\n",
" 'Chasing Amy (1997)',\n",
" 'Clerks (1994)']\n",
"Top 5 users who are very much similar to the User- 778 are: \n",
" \n",
"1 . User: 124 separated by distance of 0.4586649429539592\n",
"2 . User: 933 separated by distance of 0.5581959868865324\n",
"3 . User: 56 separated by distance of 0.5858413112292744\n",
"4 . User: 738 separated by distance of 0.5916272517988691\n",
"5 . User: 653 separated by distance of 0.5991479757406326\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LDtU_DkCqLl6"
},
"source": [
"**With the help of the KNN model built, we could get desired number of top similar users.**\n",
"\n",
"**Now we will have to pick the top movies to recommend.**\n",
"\n",
"**One way would be by taking the average of the existing ratings given by the similar users and picking the top 10 or 15 movies to recommend to our current user.**\n",
"\n",
"**But I feel recommendation would be more effective if we define weights to ratings by each similar user based on the thier distance from the input user. Defining these weights would give us the accurate recommendations by eliminating the chance of decision manipulation by the users who are relatively very far from the input user.**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "3JNvsjkzhXj4",
"outputId": "d8f1e6b9-9d26-4415-8ad9-f5b4b5049aec",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 50
}
},
"source": [
"similar_user_list, distance_list"
],
"execution_count": 143,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"(array([124, 933, 56, 738, 653]),\n",
" array([0.45866494, 0.55819599, 0.58584131, 0.59162725, 0.59914798]))"
]
},
"metadata": {
"tags": []
},
"execution_count": 143
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "7de9PUuitY5p",
"outputId": "360455f1-412d-4b07-ed51-c704da2d788c",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"weightage_list = distance_list/np.sum(distance_list)\n",
"weightage_list"
],
"execution_count": 144,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array([0.16419139, 0.19982119, 0.20971757, 0.2117888 , 0.21448105])"
]
},
"metadata": {
"tags": []
},
"execution_count": 144
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lCX18TkDtnz8"
},
"source": [
"Getting ratings of all movies by derived similar users"
]
},
{
"cell_type": "code",
"metadata": {
"id": "VEh6O0oAtv_F",
"outputId": "140cf5f4-a9fb-47a7-8365-6fab2d732462",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 101
}
},
"source": [
"mov_rtngs_sim_users = user_to_movie_df.values[similar_user_list]\n",
"mov_rtngs_sim_users"
],
"execution_count": 145,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array([[0., 0., 0., ..., 0., 0., 0.],\n",
" [0., 0., 2., ..., 0., 0., 0.],\n",
" [0., 0., 3., ..., 0., 0., 0.],\n",
" [0., 0., 0., ..., 0., 0., 0.],\n",
" [0., 0., 0., ..., 0., 0., 0.]])"
]
},
"metadata": {
"tags": []
},
"execution_count": 145
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "nhty6LqMur17",
"outputId": "d49cf83a-3e2c-4092-c477-77f81b285735",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 202
}
},
"source": [
"movies_list = user_to_movie_df.columns\n",
"movies_list"
],
"execution_count": 146,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"Index([''Til There Was You (1997)', '1-900 (1994)', '101 Dalmatians (1996)',\n",
" '12 Angry Men (1957)', '187 (1997)', '2 Days in the Valley (1996)',\n",
" '20,000 Leagues Under the Sea (1954)', '2001: A Space Odyssey (1968)',\n",
" '3 Ninjas: High Noon At Mega Mountain (1998)', '39 Steps, The (1935)',\n",
" ...\n",
" 'Yankee Zulu (1994)', 'Year of the Horse (1997)', 'You So Crazy (1994)',\n",
" 'Young Frankenstein (1974)', 'Young Guns (1988)',\n",
" 'Young Guns II (1990)', 'Young Poisoner's Handbook, The (1995)',\n",
" 'Zeus and Roxanne (1997)', 'unknown',\n",
" 'Á köldum klaka (Cold Fever) (1994)'],\n",
" dtype='object', name='movie title', length=1664)"
]
},
"metadata": {
"tags": []
},
"execution_count": 146
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "c_nwkKwhvQ7Y",
"outputId": "bed4129d-df39-4742-8906-b24469f36cbf",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 67
}
},
"source": [
"print(\"Weightage list shape:\", len(weightage_list))\n",
"print(\"mov_rtngs_sim_users shape:\", mov_rtngs_sim_users.shape)\n",
"print(\"Number of movies:\", len(movies_list))"
],
"execution_count": 147,
"outputs": [
{
"output_type": "stream",
"text": [
"Weightage list shape: 5\n",
"mov_rtngs_sim_users shape: (5, 1664)\n",
"Number of movies: 1664\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oMgSULlTx71x"
},
"source": [
"**Broadcasting weightage matrix to similar user rating matrix. so that it gets compatible for matrix operations**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "0WF66O37x7WH",
"outputId": "8f6b8c87-d797-4485-8468-48b6802439d1",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"weightage_list = weightage_list[:,np.newaxis] + np.zeros(len(movies_list))\n",
"weightage_list.shape"
],
"execution_count": 148,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"(5, 1664)"
]
},
"metadata": {
"tags": []
},
"execution_count": 148
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "RI6iizTIx7SO",
"outputId": "e31a105c-d826-4928-ec93-15cf58e2cd42",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 50
}
},
"source": [
"new_rating_matrix = weightage_list*mov_rtngs_sim_users\n",
"mean_rating_list = new_rating_matrix.sum(axis =0)\n",
"mean_rating_list"
],
"execution_count": 149,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array([0. , 0. , 1.02879509, ..., 0. , 0. ,\n",
" 0. ])"
]
},
"metadata": {
"tags": []
},
"execution_count": 149
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "jasA8xEWu3Sj"
},
"source": [
"from pprint import pprint\n",
"def recommend_movies(n):\n",
" n = min(len(mean_rating_list),n)\n",
" # print(np.argsort(mean_rating_list)[::-1][:n])\n",
" pprint(list(movies_list[np.argsort(mean_rating_list)[::-1][:n]]))\n",
"\n"
],
"execution_count": 150,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "4ix_nK1I33WS",
"outputId": "64cfee5b-3f39-4616-81f3-d7a044706504",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 202
}
},
"source": [
"print(\"Movies recommended based on similar users are: \")\n",
"recommend_movies(10)"
],
"execution_count": 151,
"outputs": [
{
"output_type": "stream",
"text": [
"Movies recommended based on similar users are: \n",
"['Star Wars (1977)',\n",
" 'Terminator, The (1984)',\n",
" \"Schindler's List (1993)\",\n",
" 'Fugitive, The (1993)',\n",
" 'Forrest Gump (1994)',\n",
" 'Princess Bride, The (1987)',\n",
" 'Empire Strikes Back, The (1980)',\n",
" 'Pulp Fiction (1994)',\n",
" 'Die Hard (1988)',\n",
" 'Monty Python and the Holy Grail (1974)']\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MZh3ID7NgwD7"
},
"source": [
"It had been observed that, this recommendation system built can be made more efficient as it has few drawbacks.\n",
"\n",
"**Drawbacks:**\n",
"\n",
"**1.** But this recommendation system has a drawback, it also **recommends movies which are already seen by the given input User.**\n",
"\n",
"**2.** And also there is a possibility of recommending the **movies which are not at all seen by any of the similar users.**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cMOC4pKzkKiQ"
},
"source": [
"**Above drawbacks are addressed and a new recommender system with modification is built**\n",
"\n",
"Below function is defined to remove the movies which are already seen the current user and not at all seen by any of the similar users."
]
},
{
"cell_type": "code",
"metadata": {
"id": "cC5fgG3-iXei"
},
"source": [
"\n",
"def filtered_movie_recommendations(n):\n",
" \n",
" first_zero_index = np.where(mean_rating_list == 0)[0][-1]\n",
" sortd_index = np.argsort(mean_rating_list)[::-1]\n",
" sortd_index = sortd_index[:list(sortd_index).index(first_zero_index)]\n",
" n = min(len(sortd_index),n)\n",
" movies_watched = list(refined_dataset[refined_dataset['user id'] == user_id]['movie title'])\n",
" filtered_movie_list = list(movies_list[sortd_index])\n",
" count = 0\n",
" final_movie_list = []\n",
" for i in filtered_movie_list:\n",
" if i not in movies_watched:\n",
" count+=1\n",
" final_movie_list.append(i)\n",
" if count == n:\n",
" break\n",
" if count == 0:\n",
" print(\"There are no movies left which are not seen by the input users and seen by similar users. May be increasing the number of similar users who are to be considered may give a chance of suggesting an unseen good movie.\")\n",
" else:\n",
" pprint(final_movie_list)\n"
],
"execution_count": 152,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "hhk_3V2QyeNz",
"outputId": "d47981dd-3691-4255-a783-7b8fb2ce5d03",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 185
}
},
"source": [
"filtered_movie_recommendations(10)"
],
"execution_count": 153,
"outputs": [
{
"output_type": "stream",
"text": [
"['Star Wars (1977)',\n",
" \"Schindler's List (1993)\",\n",
" 'Princess Bride, The (1987)',\n",
" 'Empire Strikes Back, The (1980)',\n",
" 'Return of the Jedi (1983)',\n",
" 'Fargo (1996)',\n",
" 'Dances with Wolves (1990)',\n",
" 'Toy Story (1995)',\n",
" 'Braveheart (1995)',\n",
" 'Star Trek: First Contact (1996)']\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MI7T25n6ZOEf"
},
"source": [
"Coding up all of the above individual cells into a function.\n",
"\n",
"Giving Input as **User id, Number of similar Users to be considered, Number of top movie we want to recommend**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "GQ4UfrTM33hF"
},
"source": [
"from pprint import pprint\n",
"\n",
"def recommender_system(user_id, n_similar_users, n_movies): #, user_to_movie_df, knn_model):\n",
" \n",
" print(\"Movie seen by the User:\")\n",
" pprint(list(refined_dataset[refined_dataset['user id'] == user_id]['movie title']))\n",
" print(\"\")\n",
"\n",
" # def get_similar_users(user, user_to_movie_df, knn_model, n = 5):\n",
" def get_similar_users(user, n = 5):\n",
" \n",
" knn_input = np.asarray([user_to_movie_df.values[user-1]])\n",
" \n",
" distances, indices = knn_model.kneighbors(knn_input, n_neighbors=n+1)\n",
" \n",
" print(\"Top\",n,\"users who are very much similar to the User-\",user, \"are: \")\n",
" print(\" \")\n",
"\n",
" for i in range(1,len(distances[0])):\n",
" print(i,\". User:\", indices[0][i]+1, \"separated by distance of\",distances[0][i])\n",
" print(\"\")\n",
" return indices.flatten()[1:] + 1, distances.flatten()[1:]\n",
"\n",
"\n",
" def filtered_movie_recommendations(n = 10):\n",
" \n",
" first_zero_index = np.where(mean_rating_list == 0)[0][-1]\n",
" sortd_index = np.argsort(mean_rating_list)[::-1]\n",
" sortd_index = sortd_index[:list(sortd_index).index(first_zero_index)]\n",
" n = min(len(sortd_index),n)\n",
" movies_watched = list(refined_dataset[refined_dataset['user id'] == user_id]['movie title'])\n",
" filtered_movie_list = list(movies_list[sortd_index])\n",
" count = 0\n",
" final_movie_list = []\n",
" for i in filtered_movie_list:\n",
" if i not in movies_watched:\n",
" count+=1\n",
" final_movie_list.append(i)\n",
" if count == n:\n",
" break\n",
" if count == 0:\n",
" print(\"There are no movies left which are not seen by the input users and seen by similar users. May be increasing the number of similar users who are to be considered may give a chance of suggesting an unseen good movie.\")\n",
" else:\n",
" pprint(final_movie_list)\n",
"\n",
" similar_user_list, distance_list = get_similar_users(user_id,n_similar_users)\n",
" weightage_list = distance_list/np.sum(distance_list)\n",
" mov_rtngs_sim_users = user_to_movie_df.values[similar_user_list]\n",
" movies_list = user_to_movie_df.columns\n",
" weightage_list = weightage_list[:,np.newaxis] + np.zeros(len(movies_list))\n",
" new_rating_matrix = weightage_list*mov_rtngs_sim_users\n",
" mean_rating_list = new_rating_matrix.sum(axis =0)\n",
" print(\"\")\n",
" print(\"Movies recommended based on similar users are: \")\n",
" print(\"\")\n",
" filtered_movie_recommendations(n_movies)"
],
"execution_count": 233,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "ZhQI_qBL33dj",
"outputId": "fae03002-e4c8-46d9-b4ef-e5f0bcdb1781",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 1000
}
},
"source": [
"print(\"Enter user id\")\n",
"user_id= int(input())\n",
"print(\"number of similar users to be considered\")\n",
"sim_users = int(input())\n",
"print(\"Enter number of movies to be recommended:\")\n",
"n_movies = int(input())\n",
"recommender_system(user_id,sim_users,n_movies)\n",
"# recommender_system(300, 15,15)"
],
"execution_count": 234,
"outputs": [
{
"output_type": "stream",
"text": [
"Enter user id\n",
"307\n",
"number of similar users to be considered\n",
"15\n",
"Enter number of movies to be recommended:\n",
"15\n",
"Movie seen by the User:\n",
"['12 Angry Men (1957)',\n",
" '2001: A Space Odyssey (1968)',\n",
" 'Abyss, The (1989)',\n",
" 'Alien (1979)',\n",
" 'Apollo 13 (1995)',\n",
" 'Back to the Future (1985)',\n",
" 'Barbarella (1968)',\n",
" 'Batman (1989)',\n",
" 'Beauty and the Beast (1991)',\n",
" 'Blade Runner (1982)',\n",
" 'Blues Brothers, The (1980)',\n",
" 'Boot, Das (1981)',\n",
" 'Brady Bunch Movie, The (1995)',\n",
" 'Braveheart (1995)',\n",
" 'Brazil (1985)',\n",
" 'Casablanca (1942)',\n",
" 'Close Shave, A (1995)',\n",
" 'Contact (1997)',\n",
" 'Crying Game, The (1992)',\n",
" 'Dead Poets Society (1989)',\n",
" 'Dial M for Murder (1954)',\n",
" 'Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb (1963)',\n",
" 'Dragonheart (1996)',\n",
" 'E.T. the Extra-Terrestrial (1982)',\n",
" 'Empire Strikes Back, The (1980)',\n",
" 'English Patient, The (1996)',\n",
" 'Englishman Who Went Up a Hill, But Came Down a Mountain, The (1995)',\n",
" 'Escape from L.A. (1996)',\n",
" 'Fargo (1996)',\n",
" 'Fast, Cheap & Out of Control (1997)',\n",
" 'Field of Dreams (1989)',\n",
" 'Fish Called Wanda, A (1988)',\n",
" 'Four Weddings and a Funeral (1994)',\n",
" 'Fried Green Tomatoes (1991)',\n",
" 'Full Monty, The (1997)',\n",
" 'Gandhi (1982)',\n",
" 'Ghost (1990)',\n",
" 'Graduate, The (1967)',\n",
" 'Grand Day Out, A (1992)',\n",
" 'Grumpier Old Men (1995)',\n",
" 'Harold and Maude (1971)',\n",
" 'Heathers (1989)',\n",
" 'Heavy Metal (1981)',\n",
" 'Highlander (1986)',\n",
" 'Home Alone (1990)',\n",
" 'How to Make an American Quilt (1995)',\n",
" 'Hudsucker Proxy, The (1994)',\n",
" 'Hunt for Red October, The (1990)',\n",
" 'Independence Day (ID4) (1996)',\n",
" 'Indiana Jones and the Last Crusade (1989)',\n",
" 'Jurassic Park (1993)',\n",
" 'Koyaanisqatsi (1983)',\n",
" 'Lawnmower Man, The (1992)',\n",
" 'Lawrence of Arabia (1962)',\n",
" 'Like Water For Chocolate (Como agua para chocolate) (1992)',\n",
" 'Lion King, The (1994)',\n",
" 'Mary Poppins (1964)',\n",
" 'Mask, The (1994)',\n",
" \"McHale's Navy (1997)\",\n",
" 'Men in Black (1997)',\n",
" \"Microcosmos: Le peuple de l'herbe (1996)\",\n",
" 'Monty Python and the Holy Grail (1974)',\n",
" \"Monty Python's Life of Brian (1979)\",\n",
" 'Mrs. Doubtfire (1993)',\n",
" 'Much Ado About Nothing (1993)',\n",
" 'Muppet Treasure Island (1996)',\n",
" 'My Left Foot (1989)',\n",
" 'My Life as a Dog (Mitt liv som hund) (1985)',\n",
" 'Mystery Science Theater 3000: The Movie (1996)',\n",
" 'Nightmare Before Christmas, The (1993)',\n",
" 'Pink Floyd - The Wall (1982)',\n",
" 'Pretty Woman (1990)',\n",
" 'Princess Bride, The (1987)',\n",
" 'Psycho (1960)',\n",
" 'Pulp Fiction (1994)',\n",
" 'Raiders of the Lost Ark (1981)',\n",
" 'Real Genius (1985)',\n",
" 'Return of the Jedi (1983)',\n",
" 'Return of the Pink Panther, The (1974)',\n",
" 'Right Stuff, The (1983)',\n",
" 'Road to Wellville, The (1994)',\n",
" 'Robin Hood: Men in Tights (1993)',\n",
" 'Rumble in the Bronx (1995)',\n",
" 'Secret of Roan Inish, The (1994)',\n",
" 'Sex, Lies, and Videotape (1989)',\n",
" 'Shadowlands (1993)',\n",
" 'Shawshank Redemption, The (1994)',\n",
" 'Shining, The (1980)',\n",
" 'Sneakers (1992)',\n",
" 'Snow White and the Seven Dwarfs (1937)',\n",
" 'Sound of Music, The (1965)',\n",
" 'Stand by Me (1986)',\n",
" 'Star Trek III: The Search for Spock (1984)',\n",
" 'Star Trek IV: The Voyage Home (1986)',\n",
" 'Star Trek V: The Final Frontier (1989)',\n",
" 'Star Trek VI: The Undiscovered Country (1991)',\n",
" 'Star Trek: First Contact (1996)',\n",
" 'Star Trek: Generations (1994)',\n",
" 'Star Trek: The Motion Picture (1979)',\n",
" 'Star Trek: The Wrath of Khan (1982)',\n",
" 'Star Wars (1977)',\n",
" 'Stargate (1994)',\n",
" 'Tank Girl (1995)',\n",
" 'Terminator, The (1984)',\n",
" 'This Is Spinal Tap (1984)',\n",
" 'Titanic (1997)',\n",
" 'To Kill a Mockingbird (1962)',\n",
" 'Top Gun (1986)',\n",
" 'Toy Story (1995)',\n",
" 'Wallace & Gromit: The Best of Aardman Animation (1996)',\n",
" 'Wizard of Oz, The (1939)',\n",
" 'Wrong Trousers, The (1993)']\n",
"\n",
"Top 15 users who are very much similar to the User- 307 are: \n",
" \n",
"1 . User: 70 separated by distance of 0.4560883724650484\n",
"2 . User: 738 separated by distance of 0.4846662001127756\n",
"3 . User: 922 separated by distance of 0.503221313979523\n",
"4 . User: 407 separated by distance of 0.5038250337403114\n",
"5 . User: 514 separated by distance of 0.5060750098353226\n",
"6 . User: 44 separated by distance of 0.5160506271876224\n",
"7 . User: 660 separated by distance of 0.5165826487301209\n",
"8 . User: 5 separated by distance of 0.5211146313938015\n",
"9 . User: 457 separated by distance of 0.5309167131718452\n",
"10 . User: 23 separated by distance of 0.5316197783536492\n",
"11 . User: 843 separated by distance of 0.5324703658288387\n",
"12 . User: 64 separated by distance of 0.53318921205275\n",
"13 . User: 198 separated by distance of 0.535682894616484\n",
"14 . User: 815 separated by distance of 0.5416036160331636\n",
"15 . User: 95 separated by distance of 0.5468066886836396\n",
"\n",
"\n",
"Movies recommended based on similar users are: \n",
"\n",
"[\"Schindler's List (1993)\",\n",
" 'Liar Liar (1997)',\n",
" 'When Harry Met Sally... (1989)',\n",
" 'Leaving Las Vegas (1995)',\n",
" 'Silence of the Lambs, The (1991)',\n",
" 'Dead Man Walking (1995)',\n",
" 'Trainspotting (1996)',\n",
" 'Forrest Gump (1994)',\n",
" 'Scream (1996)',\n",
" 'Twelve Monkeys (1995)',\n",
" 'Jerry Maguire (1996)',\n",
" 'Raising Arizona (1987)',\n",
" 'Godfather, The (1972)',\n",
" 'Rock, The (1996)',\n",
" 'Fugitive, The (1993)']\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9i5m2wO4iQUW"
},
"source": [
"## Movie Recommendation using KNN with Input as **Movie Name** and Number of movies you want to get recommended:"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XaQLSI1ni_qS"
},
"source": [
"2. Reshaping model in such a way that each movie has n-dimensional rating space where n is total number of users who could rate.\n",
"\n",
" We will train the KNN model inorder to find the closely matching similar movies to the movie we give as input and we recommend the top movies which would more closely align to the movie we have given."
]
},
{
"cell_type": "code",
"metadata": {
"id": "pKgkHLCN33ZT",
"outputId": "9b3ac3a7-2436-47ef-f6a6-fb39fc62c515",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 391
}
},
"source": [
"# pivot and create movie-user matrix\n",
"movie_to_user_df = refined_dataset.pivot(\n",
" index='movie title',\n",
" columns='user id',\n",
" values='rating').fillna(0)\n",
"\n",
"movie_to_user_df.head()"
],
"execution_count": 157,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th>user id</th>\n",
" <th>1</th>\n",
" <th>2</th>\n",
" <th>3</th>\n",
" <th>4</th>\n",
" <th>5</th>\n",
" <th>6</th>\n",
" <th>7</th>\n",
" <th>8</th>\n",
" <th>9</th>\n",
" <th>10</th>\n",
" <th>11</th>\n",
" <th>12</th>\n",
" <th>13</th>\n",
" <th>14</th>\n",
" <th>15</th>\n",
" <th>16</th>\n",
" <th>17</th>\n",
" <th>18</th>\n",
" <th>19</th>\n",
" <th>20</th>\n",
" <th>21</th>\n",
" <th>22</th>\n",
" <th>23</th>\n",
" <th>24</th>\n",
" <th>25</th>\n",
" <th>26</th>\n",
" <th>27</th>\n",
" <th>28</th>\n",
" <th>29</th>\n",
" <th>30</th>\n",
" <th>31</th>\n",
" <th>32</th>\n",
" <th>33</th>\n",
" <th>34</th>\n",
" <th>35</th>\n",
" <th>36</th>\n",
" <th>37</th>\n",
" <th>38</th>\n",
" <th>39</th>\n",
" <th>40</th>\n",
" <th>...</th>\n",
" <th>904</th>\n",
" <th>905</th>\n",
" <th>906</th>\n",
" <th>907</th>\n",
" <th>908</th>\n",
" <th>909</th>\n",
" <th>910</th>\n",
" <th>911</th>\n",
" <th>912</th>\n",
" <th>913</th>\n",
" <th>914</th>\n",
" <th>915</th>\n",
" <th>916</th>\n",
" <th>917</th>\n",
" <th>918</th>\n",
" <th>919</th>\n",
" <th>920</th>\n",
" <th>921</th>\n",
" <th>922</th>\n",
" <th>923</th>\n",
" <th>924</th>\n",
" <th>925</th>\n",
" <th>926</th>\n",
" <th>927</th>\n",
" <th>928</th>\n",
" <th>929</th>\n",
" <th>930</th>\n",
" <th>931</th>\n",
" <th>932</th>\n",
" <th>933</th>\n",
" <th>934</th>\n",
" <th>935</th>\n",
" <th>936</th>\n",
" <th>937</th>\n",
" <th>938</th>\n",
" <th>939</th>\n",
" <th>940</th>\n",
" <th>941</th>\n",
" <th>942</th>\n",
" <th>943</th>\n",
" </tr>\n",
" <tr>\n",
" <th>movie title</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>'Til There Was You (1997)</th>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
"
gitextract_6b3qicba/ ├── Images/ │ └── .gitkeep ├── Item_based_Collaborative_Recommender_System_using_KNN.ipynb ├── Knowledge_based_Recommender_System.ipynb ├── README.md ├── Recommender_System_using_SVD.ipynb └── Recommender_System_using_Softmax_DNN.ipynb
Condensed preview — 6 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,125K chars).
[
{
"path": "Images/.gitkeep",
"chars": 1,
"preview": "\n"
},
{
"path": "Item_based_Collaborative_Recommender_System_using_KNN.ipynb",
"chars": 239472,
"preview": "{\n \"nbformat\": 4,\n \"nbformat_minor\": 0,\n \"metadata\": {\n \"colab\": {\n \"name\": \"Item-based-Collaborative-Recomme"
},
{
"path": "Knowledge_based_Recommender_System.ipynb",
"chars": 602372,
"preview": "{\n \"nbformat\": 4,\n \"nbformat_minor\": 0,\n \"metadata\": {\n \"colab\": {\n \"name\": \"Knowledge-based-Recommender-Syst"
},
{
"path": "README.md",
"chars": 40639,
"preview": "## [Unrelated post - Connect with me on LinkedIn] \n[09-01-2023] It's been almost three years since I completed this proj"
},
{
"path": "Recommender_System_using_SVD.ipynb",
"chars": 75205,
"preview": "{\n \"nbformat\": 4,\n \"nbformat_minor\": 0,\n \"metadata\": {\n \"colab\": {\n \"name\": \"Recommender-System-using-SVD.ipy"
},
{
"path": "Recommender_System_using_Softmax_DNN.ipynb",
"chars": 114018,
"preview": "{\n \"nbformat\": 4,\n \"nbformat_minor\": 0,\n \"metadata\": {\n \"colab\": {\n \"name\": \"Recommender-System-using-Softmax"
}
]
About this extraction
This page contains the full source code of the rposhala/Recommender-System-on-MovieLens-dataset GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 6 files (1.0 MB), approximately 481.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.