workshops_recommender_systems/P4. Matrix Factorization.ipynb

1404 lines
73 KiB
Plaintext
Raw Normal View History

2020-05-21 13:42:50 +02:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Self made SVD"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import helpers\n",
"import pandas as pd\n",
"import numpy as np\n",
"import scipy.sparse as sparse\n",
"from collections import defaultdict\n",
"from itertools import chain\n",
"import random\n",
"\n",
"train_read=pd.read_csv('./Datasets/ml-100k/train.csv', sep='\\t', header=None)\n",
"test_read=pd.read_csv('./Datasets/ml-100k/test.csv', sep='\\t', header=None)\n",
"train_ui, test_ui, user_code_id, user_id_code, item_code_id, item_id_code = helpers.data_to_csr(train_read, test_read)"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 2,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [],
"source": [
"# Done similarly to https://github.com/albertauyeung/matrix-factorization-in-python\n",
"from tqdm import tqdm\n",
"\n",
"class SVD():\n",
" \n",
" def __init__(self, train_ui, learning_rate, regularization, nb_factors, iterations):\n",
" self.train_ui=train_ui\n",
" self.uir=list(zip(*[train_ui.nonzero()[0],train_ui.nonzero()[1], train_ui.data]))\n",
" \n",
" self.learning_rate=learning_rate\n",
" self.regularization=regularization\n",
" self.iterations=iterations\n",
" self.nb_users, self.nb_items=train_ui.shape\n",
" self.nb_ratings=train_ui.nnz\n",
" self.nb_factors=nb_factors\n",
" \n",
" self.Pu=np.random.normal(loc=0, scale=1./self.nb_factors, size=(self.nb_users, self.nb_factors))\n",
" self.Qi=np.random.normal(loc=0, scale=1./self.nb_factors, size=(self.nb_items, self.nb_factors))\n",
"\n",
" def train(self, test_ui=None):\n",
" if test_ui!=None:\n",
" self.test_uir=list(zip(*[test_ui.nonzero()[0],test_ui.nonzero()[1], test_ui.data]))\n",
" \n",
" self.learning_process=[]\n",
" pbar = tqdm(range(self.iterations))\n",
" for i in pbar:\n",
" pbar.set_description(f'Epoch {i} RMSE: {self.learning_process[-1][1] if i>0 else 0}. Training epoch {i+1}...')\n",
" np.random.shuffle(self.uir)\n",
" self.sgd(self.uir)\n",
" if test_ui==None:\n",
" self.learning_process.append([i+1, self.RMSE_total(self.uir)])\n",
" else:\n",
" self.learning_process.append([i+1, self.RMSE_total(self.uir), self.RMSE_total(self.test_uir)])\n",
" \n",
" def sgd(self, uir):\n",
" \n",
" for u, i, score in uir:\n",
" # Computer prediction and error\n",
" prediction = self.get_rating(u,i)\n",
" e = (score - prediction)\n",
" \n",
" # Update user and item latent feature matrices\n",
" Pu_update=self.learning_rate * (e * self.Qi[i] - self.regularization * self.Pu[u])\n",
" Qi_update=self.learning_rate * (e * self.Pu[u] - self.regularization * self.Qi[i])\n",
" \n",
" self.Pu[u] += Pu_update\n",
" self.Qi[i] += Qi_update\n",
" \n",
" def get_rating(self, u, i):\n",
" prediction = self.Pu[u].dot(self.Qi[i].T)\n",
" return prediction\n",
" \n",
" def RMSE_total(self, uir):\n",
" RMSE=0\n",
" for u,i, score in uir:\n",
" prediction = self.get_rating(u,i)\n",
" RMSE+=(score - prediction)**2\n",
" return np.sqrt(RMSE/len(uir))\n",
" \n",
" def estimations(self):\n",
" self.estimations=\\\n",
" np.dot(self.Pu,self.Qi.T)\n",
"\n",
" def recommend(self, user_code_id, item_code_id, topK=10):\n",
" \n",
" top_k = defaultdict(list)\n",
" for nb_user, user in enumerate(self.estimations):\n",
" \n",
" user_rated=self.train_ui.indices[self.train_ui.indptr[nb_user]:self.train_ui.indptr[nb_user+1]]\n",
" for item, score in enumerate(user):\n",
" if item not in user_rated and not np.isnan(score):\n",
" top_k[user_code_id[nb_user]].append((item_code_id[item], score))\n",
" result=[]\n",
" # Let's choose k best items in the format: (user, item1, score1, item2, score2, ...)\n",
" for uid, item_scores in top_k.items():\n",
" item_scores.sort(key=lambda x: x[1], reverse=True)\n",
" result.append([uid]+list(chain(*item_scores[:topK])))\n",
" return result\n",
" \n",
" def estimate(self, user_code_id, item_code_id, test_ui):\n",
" result=[]\n",
" for user, item in zip(*test_ui.nonzero()):\n",
" result.append([user_code_id[user], item_code_id[item], \n",
" self.estimations[user,item] if not np.isnan(self.estimations[user,item]) else 1])\n",
" return result"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 3,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
2020-05-21 16:20:12 +02:00
"Epoch 39 RMSE: 0.7480082047970615. Training epoch 40...: 100%|██████████| 40/40 [01:21<00:00, 2.05s/it]\n"
2020-05-21 13:42:50 +02:00
]
}
],
"source": [
"model=SVD(train_ui, learning_rate=0.005, regularization=0.02, nb_factors=100, iterations=40)\n",
"model.train(test_ui)"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 5,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
2020-05-21 16:20:12 +02:00
"<matplotlib.legend.Legend at 0x7f77ab510e48>"
2020-05-21 13:42:50 +02:00
]
},
2020-05-21 16:20:12 +02:00
"execution_count": 5,
2020-05-21 13:42:50 +02:00
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
2020-05-21 16:20:12 +02:00
"image/png": "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
2020-05-21 13:42:50 +02:00
"text/plain": [
2020-05-21 16:20:12 +02:00
"<matplotlib.figure.Figure at 0x7f77a9afdba8>"
2020-05-21 13:42:50 +02:00
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"df=pd.DataFrame(model.learning_process).iloc[:,:2]\n",
"df.columns=['epoch', 'train_RMSE']\n",
"plt.plot('epoch', 'train_RMSE', data=df, color='blue')\n",
"plt.legend()"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 6,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
2020-05-21 16:20:12 +02:00
"<matplotlib.legend.Legend at 0x7f774c4e3fd0>"
2020-05-21 13:42:50 +02:00
]
},
2020-05-21 16:20:12 +02:00
"execution_count": 6,
2020-05-21 13:42:50 +02:00
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
2020-05-21 16:20:12 +02:00
"image/png": "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
2020-05-21 13:42:50 +02:00
"text/plain": [
2020-05-21 16:20:12 +02:00
"<matplotlib.figure.Figure at 0x7f77a08e7748>"
2020-05-21 13:42:50 +02:00
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"df=pd.DataFrame(model.learning_process[10:], columns=['epoch', 'train_RMSE', 'test_RMSE'])\n",
"plt.plot('epoch', 'train_RMSE', data=df, color='blue')\n",
"plt.plot('epoch', 'test_RMSE', data=df, color='yellow', linestyle='dashed')\n",
"plt.legend()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Saving and evaluating recommendations"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 7,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [],
"source": [
"model.estimations()\n",
"\n",
"top_n=pd.DataFrame(model.recommend(user_code_id, item_code_id, topK=10))\n",
"\n",
"top_n.to_csv('Recommendations generated/ml-100k/Self_SVD_reco.csv', index=False, header=False)\n",
"\n",
"estimations=pd.DataFrame(model.estimate(user_code_id, item_code_id, test_ui))\n",
"estimations.to_csv('Recommendations generated/ml-100k/Self_SVD_estimations.csv', index=False, header=False)"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 8,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
2020-05-21 16:20:12 +02:00
"943it [00:00, 8982.19it/s]\n"
2020-05-21 13:42:50 +02:00
]
},
{
"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>RMSE</th>\n",
" <th>MAE</th>\n",
" <th>precision</th>\n",
" <th>recall</th>\n",
" <th>F_1</th>\n",
" <th>F_05</th>\n",
" <th>precision_super</th>\n",
" <th>recall_super</th>\n",
" <th>NDCG</th>\n",
" <th>mAP</th>\n",
" <th>MRR</th>\n",
" <th>LAUC</th>\n",
" <th>HR</th>\n",
" <th>Reco in test</th>\n",
" <th>Test coverage</th>\n",
" <th>Shannon</th>\n",
" <th>Gini</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
2020-05-21 16:20:12 +02:00
" <td>0.914856</td>\n",
" <td>0.718384</td>\n",
" <td>0.100424</td>\n",
" <td>0.040859</td>\n",
" <td>0.050523</td>\n",
" <td>0.067431</td>\n",
" <td>0.090665</td>\n",
" <td>0.068368</td>\n",
" <td>0.101328</td>\n",
" <td>0.047917</td>\n",
" <td>0.183792</td>\n",
" <td>0.517141</td>\n",
" <td>0.459173</td>\n",
" <td>0.860551</td>\n",
" <td>0.146465</td>\n",
" <td>3.853236</td>\n",
" <td>0.971798</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
2020-05-21 16:20:12 +02:00
" RMSE MAE precision recall F_1 F_05 \\\n",
"0 0.914856 0.718384 0.100424 0.040859 0.050523 0.067431 \n",
2020-05-21 13:42:50 +02:00
"\n",
2020-05-21 16:20:12 +02:00
" precision_super recall_super NDCG mAP MRR LAUC \\\n",
"0 0.090665 0.068368 0.101328 0.047917 0.183792 0.517141 \n",
2020-05-21 13:42:50 +02:00
"\n",
2020-05-21 16:20:12 +02:00
" HR Reco in test Test coverage Shannon Gini \n",
"0 0.459173 0.860551 0.146465 3.853236 0.971798 "
2020-05-21 13:42:50 +02:00
]
},
2020-05-21 16:20:12 +02:00
"execution_count": 8,
2020-05-21 13:42:50 +02:00
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import evaluation_measures as ev\n",
"\n",
"estimations_df=pd.read_csv('Recommendations generated/ml-100k/Self_SVD_estimations.csv', header=None)\n",
"reco=np.loadtxt('Recommendations generated/ml-100k/Self_SVD_reco.csv', delimiter=',')\n",
"\n",
"ev.evaluate(test=pd.read_csv('./Datasets/ml-100k/test.csv', sep='\\t', header=None),\n",
" estimations_df=estimations_df, \n",
" reco=reco,\n",
" super_reactions=[4,5])"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 11,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
2020-05-21 16:20:12 +02:00
"943it [00:00, 9603.22it/s]\n",
"943it [00:00, 8786.72it/s]\n",
"943it [00:00, 8141.95it/s]\n",
"943it [00:00, 8884.14it/s]\n",
"943it [00:00, 10117.77it/s]\n",
"943it [00:00, 8687.46it/s]\n",
"943it [00:00, 10361.84it/s]\n",
"943it [00:00, 10162.64it/s]\n",
"943it [00:00, 8493.19it/s]\n",
"943it [00:00, 9153.50it/s]\n"
2020-05-21 13:42:50 +02:00
]
},
{
"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>Model</th>\n",
" <th>RMSE</th>\n",
" <th>MAE</th>\n",
" <th>precision</th>\n",
" <th>recall</th>\n",
" <th>F_1</th>\n",
" <th>F_05</th>\n",
" <th>precision_super</th>\n",
" <th>recall_super</th>\n",
" <th>NDCG</th>\n",
" <th>mAP</th>\n",
" <th>MRR</th>\n",
" <th>LAUC</th>\n",
" <th>HR</th>\n",
" <th>Reco in test</th>\n",
" <th>Test coverage</th>\n",
" <th>Shannon</th>\n",
" <th>Gini</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_TopPop</td>\n",
" <td>2.508258</td>\n",
" <td>2.217909</td>\n",
" <td>0.188865</td>\n",
" <td>0.116919</td>\n",
" <td>0.118732</td>\n",
" <td>0.141584</td>\n",
" <td>0.130472</td>\n",
" <td>0.137473</td>\n",
" <td>0.214651</td>\n",
" <td>0.111707</td>\n",
" <td>0.400939</td>\n",
" <td>0.555546</td>\n",
" <td>0.765642</td>\n",
" <td>1.000000</td>\n",
" <td>0.038961</td>\n",
" <td>3.159079</td>\n",
" <td>0.987317</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_SVD</td>\n",
2020-05-21 16:20:12 +02:00
" <td>0.914856</td>\n",
" <td>0.718384</td>\n",
" <td>0.100424</td>\n",
" <td>0.040859</td>\n",
" <td>0.050523</td>\n",
" <td>0.067431</td>\n",
" <td>0.090665</td>\n",
" <td>0.068368</td>\n",
" <td>0.101328</td>\n",
" <td>0.047917</td>\n",
" <td>0.183792</td>\n",
" <td>0.517141</td>\n",
" <td>0.459173</td>\n",
" <td>0.860551</td>\n",
" <td>0.146465</td>\n",
" <td>3.853236</td>\n",
" <td>0.971798</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_Baseline</td>\n",
" <td>0.949459</td>\n",
" <td>0.752487</td>\n",
" <td>0.091410</td>\n",
" <td>0.037652</td>\n",
" <td>0.046030</td>\n",
" <td>0.061286</td>\n",
" <td>0.079614</td>\n",
" <td>0.056463</td>\n",
" <td>0.095957</td>\n",
" <td>0.043178</td>\n",
" <td>0.198193</td>\n",
" <td>0.515501</td>\n",
" <td>0.437964</td>\n",
" <td>1.000000</td>\n",
" <td>0.033911</td>\n",
" <td>2.836513</td>\n",
" <td>0.991139</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_GlobalAvg</td>\n",
" <td>1.125760</td>\n",
" <td>0.943534</td>\n",
" <td>0.061188</td>\n",
" <td>0.025968</td>\n",
" <td>0.031383</td>\n",
" <td>0.041343</td>\n",
" <td>0.040558</td>\n",
" <td>0.032107</td>\n",
" <td>0.067695</td>\n",
" <td>0.027470</td>\n",
" <td>0.171187</td>\n",
" <td>0.509546</td>\n",
" <td>0.384942</td>\n",
" <td>1.000000</td>\n",
" <td>0.025974</td>\n",
" <td>2.711772</td>\n",
" <td>0.992003</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_Random</td>\n",
2020-05-21 16:20:12 +02:00
" <td>1.518964</td>\n",
" <td>1.222159</td>\n",
" <td>0.046554</td>\n",
" <td>0.020603</td>\n",
" <td>0.023679</td>\n",
" <td>0.031216</td>\n",
" <td>0.028970</td>\n",
" <td>0.021179</td>\n",
" <td>0.050489</td>\n",
" <td>0.019185</td>\n",
" <td>0.123856</td>\n",
" <td>0.506812</td>\n",
" <td>0.322375</td>\n",
" <td>0.987805</td>\n",
" <td>0.184704</td>\n",
" <td>5.103172</td>\n",
" <td>0.906873</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_I-KNN</td>\n",
" <td>1.030386</td>\n",
" <td>0.813067</td>\n",
" <td>0.026087</td>\n",
" <td>0.006908</td>\n",
" <td>0.010593</td>\n",
" <td>0.016046</td>\n",
" <td>0.021137</td>\n",
" <td>0.009522</td>\n",
" <td>0.024214</td>\n",
" <td>0.008958</td>\n",
" <td>0.048068</td>\n",
" <td>0.499885</td>\n",
" <td>0.154825</td>\n",
" <td>0.402333</td>\n",
" <td>0.434343</td>\n",
" <td>5.133650</td>\n",
" <td>0.877999</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_I-KNNBaseline</td>\n",
" <td>0.935327</td>\n",
" <td>0.737424</td>\n",
" <td>0.002545</td>\n",
" <td>0.000755</td>\n",
" <td>0.001105</td>\n",
" <td>0.001602</td>\n",
" <td>0.002253</td>\n",
" <td>0.000930</td>\n",
" <td>0.003444</td>\n",
" <td>0.001362</td>\n",
" <td>0.011760</td>\n",
" <td>0.496724</td>\n",
" <td>0.021209</td>\n",
" <td>0.482821</td>\n",
" <td>0.059885</td>\n",
" <td>2.232578</td>\n",
" <td>0.994487</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_U-KNN</td>\n",
" <td>1.023495</td>\n",
" <td>0.807913</td>\n",
" <td>0.000742</td>\n",
" <td>0.000205</td>\n",
" <td>0.000305</td>\n",
" <td>0.000449</td>\n",
" <td>0.000536</td>\n",
" <td>0.000198</td>\n",
" <td>0.000845</td>\n",
" <td>0.000274</td>\n",
" <td>0.002744</td>\n",
" <td>0.496441</td>\n",
" <td>0.007423</td>\n",
" <td>0.602121</td>\n",
" <td>0.010823</td>\n",
" <td>2.089186</td>\n",
" <td>0.995706</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_BaselineUI</td>\n",
" <td>0.967585</td>\n",
" <td>0.762740</td>\n",
" <td>0.000954</td>\n",
" <td>0.000170</td>\n",
" <td>0.000278</td>\n",
" <td>0.000463</td>\n",
" <td>0.000644</td>\n",
" <td>0.000189</td>\n",
" <td>0.000752</td>\n",
" <td>0.000168</td>\n",
" <td>0.001677</td>\n",
" <td>0.496424</td>\n",
" <td>0.009544</td>\n",
" <td>0.600530</td>\n",
" <td>0.005051</td>\n",
" <td>1.803126</td>\n",
" <td>0.996380</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_IKNN</td>\n",
" <td>1.018363</td>\n",
" <td>0.808793</td>\n",
" <td>0.000318</td>\n",
" <td>0.000108</td>\n",
" <td>0.000140</td>\n",
" <td>0.000189</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000214</td>\n",
" <td>0.000037</td>\n",
" <td>0.000368</td>\n",
" <td>0.496391</td>\n",
" <td>0.003181</td>\n",
" <td>0.392153</td>\n",
" <td>0.115440</td>\n",
" <td>4.174741</td>\n",
" <td>0.965327</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Model RMSE MAE precision recall F_1 \\\n",
"0 Self_TopPop 2.508258 2.217909 0.188865 0.116919 0.118732 \n",
2020-05-21 16:20:12 +02:00
"0 Self_SVD 0.914856 0.718384 0.100424 0.040859 0.050523 \n",
2020-05-21 13:42:50 +02:00
"0 Ready_Baseline 0.949459 0.752487 0.091410 0.037652 0.046030 \n",
"0 Self_GlobalAvg 1.125760 0.943534 0.061188 0.025968 0.031383 \n",
2020-05-21 16:20:12 +02:00
"0 Ready_Random 1.518964 1.222159 0.046554 0.020603 0.023679 \n",
2020-05-21 13:42:50 +02:00
"0 Ready_I-KNN 1.030386 0.813067 0.026087 0.006908 0.010593 \n",
"0 Ready_I-KNNBaseline 0.935327 0.737424 0.002545 0.000755 0.001105 \n",
"0 Ready_U-KNN 1.023495 0.807913 0.000742 0.000205 0.000305 \n",
"0 Self_BaselineUI 0.967585 0.762740 0.000954 0.000170 0.000278 \n",
"0 Self_IKNN 1.018363 0.808793 0.000318 0.000108 0.000140 \n",
"\n",
" F_05 precision_super recall_super NDCG mAP MRR \\\n",
"0 0.141584 0.130472 0.137473 0.214651 0.111707 0.400939 \n",
2020-05-21 16:20:12 +02:00
"0 0.067431 0.090665 0.068368 0.101328 0.047917 0.183792 \n",
2020-05-21 13:42:50 +02:00
"0 0.061286 0.079614 0.056463 0.095957 0.043178 0.198193 \n",
"0 0.041343 0.040558 0.032107 0.067695 0.027470 0.171187 \n",
2020-05-21 16:20:12 +02:00
"0 0.031216 0.028970 0.021179 0.050489 0.019185 0.123856 \n",
2020-05-21 13:42:50 +02:00
"0 0.016046 0.021137 0.009522 0.024214 0.008958 0.048068 \n",
"0 0.001602 0.002253 0.000930 0.003444 0.001362 0.011760 \n",
"0 0.000449 0.000536 0.000198 0.000845 0.000274 0.002744 \n",
"0 0.000463 0.000644 0.000189 0.000752 0.000168 0.001677 \n",
"0 0.000189 0.000000 0.000000 0.000214 0.000037 0.000368 \n",
"\n",
" LAUC HR Reco in test Test coverage Shannon Gini \n",
"0 0.555546 0.765642 1.000000 0.038961 3.159079 0.987317 \n",
2020-05-21 16:20:12 +02:00
"0 0.517141 0.459173 0.860551 0.146465 3.853236 0.971798 \n",
2020-05-21 13:42:50 +02:00
"0 0.515501 0.437964 1.000000 0.033911 2.836513 0.991139 \n",
"0 0.509546 0.384942 1.000000 0.025974 2.711772 0.992003 \n",
2020-05-21 16:20:12 +02:00
"0 0.506812 0.322375 0.987805 0.184704 5.103172 0.906873 \n",
2020-05-21 13:42:50 +02:00
"0 0.499885 0.154825 0.402333 0.434343 5.133650 0.877999 \n",
"0 0.496724 0.021209 0.482821 0.059885 2.232578 0.994487 \n",
"0 0.496441 0.007423 0.602121 0.010823 2.089186 0.995706 \n",
"0 0.496424 0.009544 0.600530 0.005051 1.803126 0.996380 \n",
"0 0.496391 0.003181 0.392153 0.115440 4.174741 0.965327 "
]
},
2020-05-21 16:20:12 +02:00
"execution_count": 11,
2020-05-21 13:42:50 +02:00
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import imp\n",
"imp.reload(ev)\n",
"\n",
"import evaluation_measures as ev\n",
"dir_path=\"Recommendations generated/ml-100k/\"\n",
"super_reactions=[4,5]\n",
"test=pd.read_csv('./Datasets/ml-100k/test.csv', sep='\\t', header=None)\n",
"\n",
"ev.evaluate_all(test, dir_path, super_reactions)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Embeddings"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 12,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1, 2],\n",
" [3, 4]])"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"array([[0.4472136 , 0.89442719],\n",
" [0.6 , 0.8 ]])"
]
},
2020-05-21 16:20:12 +02:00
"execution_count": 12,
2020-05-21 13:42:50 +02:00
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x=np.array([[1,2],[3,4]])\n",
"display(x)\n",
"x/np.linalg.norm(x, axis=1)[:,None]"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 13,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"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>code</th>\n",
" <th>score</th>\n",
" <th>item_id</th>\n",
" <th>id</th>\n",
" <th>title</th>\n",
" <th>genres</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
2020-05-21 16:20:12 +02:00
" <td>916</td>\n",
2020-05-21 13:42:50 +02:00
" <td>1.000000</td>\n",
2020-05-21 16:20:12 +02:00
" <td>917</td>\n",
" <td>917</td>\n",
" <td>Mercury Rising (1998)</td>\n",
" <td>Action, Drama, Thriller</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
2020-05-21 16:20:12 +02:00
" <td>914</td>\n",
" <td>0.991506</td>\n",
" <td>915</td>\n",
" <td>915</td>\n",
" <td>Primary Colors (1998)</td>\n",
" <td>Drama</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
2020-05-21 16:20:12 +02:00
" <td>908</td>\n",
" <td>0.990078</td>\n",
" <td>909</td>\n",
" <td>909</td>\n",
" <td>Dangerous Beauty (1998)</td>\n",
2020-05-21 13:42:50 +02:00
" <td>Drama</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
2020-05-21 16:20:12 +02:00
" <td>690</td>\n",
" <td>0.989487</td>\n",
" <td>691</td>\n",
" <td>691</td>\n",
" <td>Dark City (1998)</td>\n",
" <td>Film-Noir, Sci-Fi, Thriller</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
2020-05-21 16:20:12 +02:00
" <td>359</td>\n",
" <td>0.988384</td>\n",
" <td>360</td>\n",
" <td>360</td>\n",
" <td>Wonderland (1997)</td>\n",
" <td>Documentary</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
2020-05-21 16:20:12 +02:00
" <td>810</td>\n",
" <td>0.987781</td>\n",
" <td>811</td>\n",
" <td>811</td>\n",
" <td>Thirty-Two Short Films About Glenn Gould (1993)</td>\n",
" <td>Documentary</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
2020-05-21 16:20:12 +02:00
" <td>917</td>\n",
" <td>0.986770</td>\n",
" <td>918</td>\n",
" <td>918</td>\n",
" <td>City of Angels (1998)</td>\n",
" <td>Romance</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
2020-05-21 16:20:12 +02:00
" <td>869</td>\n",
" <td>0.986746</td>\n",
" <td>870</td>\n",
" <td>870</td>\n",
" <td>Touch (1997)</td>\n",
" <td>Romance</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
2020-05-21 16:20:12 +02:00
" <td>756</td>\n",
" <td>0.986005</td>\n",
" <td>757</td>\n",
" <td>757</td>\n",
" <td>Across the Sea of Time (1995)</td>\n",
" <td>Documentary</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
2020-05-21 16:20:12 +02:00
" <td>732</td>\n",
" <td>0.985919</td>\n",
" <td>733</td>\n",
" <td>733</td>\n",
" <td>Go Fish (1994)</td>\n",
" <td>Drama, Romance</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
2020-05-21 16:20:12 +02:00
" code score item_id id \\\n",
"0 916 1.000000 917 917 \n",
"1 914 0.991506 915 915 \n",
"2 908 0.990078 909 909 \n",
"3 690 0.989487 691 691 \n",
"4 359 0.988384 360 360 \n",
"5 810 0.987781 811 811 \n",
"6 917 0.986770 918 918 \n",
"7 869 0.986746 870 870 \n",
"8 756 0.986005 757 757 \n",
"9 732 0.985919 733 733 \n",
2020-05-21 13:42:50 +02:00
"\n",
2020-05-21 16:20:12 +02:00
" title \\\n",
"0 Mercury Rising (1998) \n",
"1 Primary Colors (1998) \n",
"2 Dangerous Beauty (1998) \n",
"3 Dark City (1998) \n",
"4 Wonderland (1997) \n",
"5 Thirty-Two Short Films About Glenn Gould (1993) \n",
"6 City of Angels (1998) \n",
"7 Touch (1997) \n",
"8 Across the Sea of Time (1995) \n",
"9 Go Fish (1994) \n",
"\n",
" genres \n",
"0 Action, Drama, Thriller \n",
"1 Drama \n",
"2 Drama \n",
"3 Film-Noir, Sci-Fi, Thriller \n",
"4 Documentary \n",
"5 Documentary \n",
"6 Romance \n",
"7 Romance \n",
"8 Documentary \n",
"9 Drama, Romance "
2020-05-21 13:42:50 +02:00
]
},
2020-05-21 16:20:12 +02:00
"execution_count": 13,
2020-05-21 13:42:50 +02:00
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"item=random.choice(list(set(train_ui.indices)))\n",
"\n",
"embeddings_norm=model.Qi/np.linalg.norm(model.Qi, axis=1)[:,None] # we do not mean-center here\n",
"# omitting normalization also makes sense, but items with a greater magnitude will be recommended more often\n",
"\n",
"similarity_scores=np.dot(embeddings_norm,embeddings_norm[item].T)\n",
"top_similar_items=pd.DataFrame(enumerate(similarity_scores), columns=['code', 'score'])\\\n",
".sort_values(by=['score'], ascending=[False])[:10]\n",
"\n",
"top_similar_items['item_id']=top_similar_items['code'].apply(lambda x: item_code_id[x])\n",
"\n",
"items=pd.read_csv('./Datasets/ml-100k/movies.csv')\n",
"\n",
"result=pd.merge(top_similar_items, items, left_on='item_id', right_on='id')\n",
"\n",
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# project task 5: implement SVD on top baseline (as it is in Surprise library)"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [],
"source": [
"# making changes to our implementation by considering additional parameters in the gradient descent procedure \n",
"# seems to be the fastest option\n",
"# please save the output in 'Recommendations generated/ml-100k/Self_SVDBaseline_reco.csv' and\n",
"# 'Recommendations generated/ml-100k/Self_SVDBaseline_estimations.csv'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Ready-made SVD - Surprise implementation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### SVD"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 14,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Generating predictions...\n",
"Generating top N recommendations...\n",
"Generating predictions...\n"
]
}
],
"source": [
"import helpers\n",
"import surprise as sp\n",
"import imp\n",
"imp.reload(helpers)\n",
"\n",
"algo = sp.SVD(biased=False) # to use unbiased version\n",
"\n",
"helpers.ready_made(algo, reco_path='Recommendations generated/ml-100k/Ready_SVD_reco.csv',\n",
" estimations_path='Recommendations generated/ml-100k/Ready_SVD_estimations.csv')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### SVD biased - on top baseline"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 15,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Generating predictions...\n",
"Generating top N recommendations...\n",
"Generating predictions...\n"
]
}
],
"source": [
"import helpers\n",
"import surprise as sp\n",
"import imp\n",
"imp.reload(helpers)\n",
"\n",
"algo = sp.SVD() # default is biased=True\n",
"\n",
"helpers.ready_made(algo, reco_path='Recommendations generated/ml-100k/Ready_SVDBiased_reco.csv',\n",
" estimations_path='Recommendations generated/ml-100k/Ready_SVDBiased_estimations.csv')"
]
},
{
"cell_type": "code",
2020-05-21 16:20:12 +02:00
"execution_count": 16,
2020-05-21 13:42:50 +02:00
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
2020-05-21 16:20:12 +02:00
"943it [00:00, 8010.33it/s]\n",
"943it [00:00, 7939.12it/s]\n",
"943it [00:00, 8331.15it/s]\n",
"943it [00:00, 8696.10it/s]\n",
"943it [00:00, 8172.62it/s]\n",
"943it [00:00, 8807.34it/s]\n",
"943it [00:00, 8646.67it/s]\n",
"943it [00:00, 7192.36it/s]\n",
"943it [00:00, 8888.67it/s]\n",
"943it [00:00, 8736.94it/s]\n",
"943it [00:00, 8047.44it/s]\n",
"943it [00:00, 8326.85it/s]\n"
2020-05-21 13:42:50 +02:00
]
},
{
"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>Model</th>\n",
" <th>RMSE</th>\n",
" <th>MAE</th>\n",
" <th>precision</th>\n",
" <th>recall</th>\n",
" <th>F_1</th>\n",
" <th>F_05</th>\n",
" <th>precision_super</th>\n",
" <th>recall_super</th>\n",
" <th>NDCG</th>\n",
" <th>mAP</th>\n",
" <th>MRR</th>\n",
" <th>LAUC</th>\n",
" <th>HR</th>\n",
" <th>Reco in test</th>\n",
" <th>Test coverage</th>\n",
" <th>Shannon</th>\n",
" <th>Gini</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_TopPop</td>\n",
" <td>2.508258</td>\n",
" <td>2.217909</td>\n",
" <td>0.188865</td>\n",
" <td>0.116919</td>\n",
" <td>0.118732</td>\n",
" <td>0.141584</td>\n",
" <td>0.130472</td>\n",
" <td>0.137473</td>\n",
" <td>0.214651</td>\n",
" <td>0.111707</td>\n",
" <td>0.400939</td>\n",
" <td>0.555546</td>\n",
" <td>0.765642</td>\n",
" <td>1.000000</td>\n",
" <td>0.038961</td>\n",
" <td>3.159079</td>\n",
" <td>0.987317</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_SVD</td>\n",
2020-05-21 16:20:12 +02:00
" <td>0.952889</td>\n",
" <td>0.750674</td>\n",
" <td>0.098834</td>\n",
" <td>0.047899</td>\n",
" <td>0.053663</td>\n",
" <td>0.068581</td>\n",
" <td>0.087876</td>\n",
" <td>0.076831</td>\n",
" <td>0.113446</td>\n",
" <td>0.054127</td>\n",
" <td>0.242918</td>\n",
" <td>0.520677</td>\n",
" <td>0.488865</td>\n",
" <td>0.998091</td>\n",
" <td>0.204906</td>\n",
" <td>4.440336</td>\n",
" <td>0.952374</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_SVD</td>\n",
2020-05-21 16:20:12 +02:00
" <td>0.914856</td>\n",
" <td>0.718384</td>\n",
" <td>0.100424</td>\n",
" <td>0.040859</td>\n",
" <td>0.050523</td>\n",
" <td>0.067431</td>\n",
" <td>0.090665</td>\n",
" <td>0.068368</td>\n",
" <td>0.101328</td>\n",
" <td>0.047917</td>\n",
" <td>0.183792</td>\n",
" <td>0.517141</td>\n",
" <td>0.459173</td>\n",
" <td>0.860551</td>\n",
" <td>0.146465</td>\n",
" <td>3.853236</td>\n",
" <td>0.971798</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_Baseline</td>\n",
" <td>0.949459</td>\n",
" <td>0.752487</td>\n",
" <td>0.091410</td>\n",
" <td>0.037652</td>\n",
" <td>0.046030</td>\n",
" <td>0.061286</td>\n",
" <td>0.079614</td>\n",
" <td>0.056463</td>\n",
" <td>0.095957</td>\n",
" <td>0.043178</td>\n",
" <td>0.198193</td>\n",
" <td>0.515501</td>\n",
" <td>0.437964</td>\n",
" <td>1.000000</td>\n",
" <td>0.033911</td>\n",
" <td>2.836513</td>\n",
" <td>0.991139</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
2020-05-21 16:20:12 +02:00
" <td>Ready_SVDBiased</td>\n",
" <td>0.939807</td>\n",
" <td>0.741610</td>\n",
" <td>0.082078</td>\n",
" <td>0.032691</td>\n",
" <td>0.040611</td>\n",
" <td>0.054503</td>\n",
" <td>0.073391</td>\n",
" <td>0.051400</td>\n",
" <td>0.088531</td>\n",
" <td>0.039739</td>\n",
" <td>0.188187</td>\n",
" <td>0.512998</td>\n",
" <td>0.423118</td>\n",
" <td>0.995864</td>\n",
" <td>0.172439</td>\n",
" <td>4.176612</td>\n",
" <td>0.963967</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
2020-05-21 13:42:50 +02:00
" <td>Self_GlobalAvg</td>\n",
" <td>1.125760</td>\n",
" <td>0.943534</td>\n",
" <td>0.061188</td>\n",
" <td>0.025968</td>\n",
" <td>0.031383</td>\n",
" <td>0.041343</td>\n",
" <td>0.040558</td>\n",
" <td>0.032107</td>\n",
" <td>0.067695</td>\n",
" <td>0.027470</td>\n",
" <td>0.171187</td>\n",
" <td>0.509546</td>\n",
" <td>0.384942</td>\n",
" <td>1.000000</td>\n",
" <td>0.025974</td>\n",
" <td>2.711772</td>\n",
" <td>0.992003</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_Random</td>\n",
2020-05-21 16:20:12 +02:00
" <td>1.518964</td>\n",
" <td>1.222159</td>\n",
" <td>0.046554</td>\n",
" <td>0.020603</td>\n",
" <td>0.023679</td>\n",
" <td>0.031216</td>\n",
" <td>0.028970</td>\n",
" <td>0.021179</td>\n",
" <td>0.050489</td>\n",
" <td>0.019185</td>\n",
" <td>0.123856</td>\n",
" <td>0.506812</td>\n",
" <td>0.322375</td>\n",
" <td>0.987805</td>\n",
" <td>0.184704</td>\n",
" <td>5.103172</td>\n",
" <td>0.906873</td>\n",
2020-05-21 13:42:50 +02:00
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_I-KNN</td>\n",
" <td>1.030386</td>\n",
" <td>0.813067</td>\n",
" <td>0.026087</td>\n",
" <td>0.006908</td>\n",
" <td>0.010593</td>\n",
" <td>0.016046</td>\n",
" <td>0.021137</td>\n",
" <td>0.009522</td>\n",
" <td>0.024214</td>\n",
" <td>0.008958</td>\n",
" <td>0.048068</td>\n",
" <td>0.499885</td>\n",
" <td>0.154825</td>\n",
" <td>0.402333</td>\n",
" <td>0.434343</td>\n",
" <td>5.133650</td>\n",
" <td>0.877999</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_I-KNNBaseline</td>\n",
" <td>0.935327</td>\n",
" <td>0.737424</td>\n",
" <td>0.002545</td>\n",
" <td>0.000755</td>\n",
" <td>0.001105</td>\n",
" <td>0.001602</td>\n",
" <td>0.002253</td>\n",
" <td>0.000930</td>\n",
" <td>0.003444</td>\n",
" <td>0.001362</td>\n",
" <td>0.011760</td>\n",
" <td>0.496724</td>\n",
" <td>0.021209</td>\n",
" <td>0.482821</td>\n",
" <td>0.059885</td>\n",
" <td>2.232578</td>\n",
" <td>0.994487</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Ready_U-KNN</td>\n",
" <td>1.023495</td>\n",
" <td>0.807913</td>\n",
" <td>0.000742</td>\n",
" <td>0.000205</td>\n",
" <td>0.000305</td>\n",
" <td>0.000449</td>\n",
" <td>0.000536</td>\n",
" <td>0.000198</td>\n",
" <td>0.000845</td>\n",
" <td>0.000274</td>\n",
" <td>0.002744</td>\n",
" <td>0.496441</td>\n",
" <td>0.007423</td>\n",
" <td>0.602121</td>\n",
" <td>0.010823</td>\n",
" <td>2.089186</td>\n",
" <td>0.995706</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_BaselineUI</td>\n",
" <td>0.967585</td>\n",
" <td>0.762740</td>\n",
" <td>0.000954</td>\n",
" <td>0.000170</td>\n",
" <td>0.000278</td>\n",
" <td>0.000463</td>\n",
" <td>0.000644</td>\n",
" <td>0.000189</td>\n",
" <td>0.000752</td>\n",
" <td>0.000168</td>\n",
" <td>0.001677</td>\n",
" <td>0.496424</td>\n",
" <td>0.009544</td>\n",
" <td>0.600530</td>\n",
" <td>0.005051</td>\n",
" <td>1.803126</td>\n",
" <td>0.996380</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Self_IKNN</td>\n",
" <td>1.018363</td>\n",
" <td>0.808793</td>\n",
" <td>0.000318</td>\n",
" <td>0.000108</td>\n",
" <td>0.000140</td>\n",
" <td>0.000189</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000214</td>\n",
" <td>0.000037</td>\n",
" <td>0.000368</td>\n",
" <td>0.496391</td>\n",
" <td>0.003181</td>\n",
" <td>0.392153</td>\n",
" <td>0.115440</td>\n",
" <td>4.174741</td>\n",
" <td>0.965327</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Model RMSE MAE precision recall F_1 \\\n",
"0 Self_TopPop 2.508258 2.217909 0.188865 0.116919 0.118732 \n",
2020-05-21 16:20:12 +02:00
"0 Ready_SVD 0.952889 0.750674 0.098834 0.047899 0.053663 \n",
"0 Self_SVD 0.914856 0.718384 0.100424 0.040859 0.050523 \n",
2020-05-21 13:42:50 +02:00
"0 Ready_Baseline 0.949459 0.752487 0.091410 0.037652 0.046030 \n",
2020-05-21 16:20:12 +02:00
"0 Ready_SVDBiased 0.939807 0.741610 0.082078 0.032691 0.040611 \n",
2020-05-21 13:42:50 +02:00
"0 Self_GlobalAvg 1.125760 0.943534 0.061188 0.025968 0.031383 \n",
2020-05-21 16:20:12 +02:00
"0 Ready_Random 1.518964 1.222159 0.046554 0.020603 0.023679 \n",
2020-05-21 13:42:50 +02:00
"0 Ready_I-KNN 1.030386 0.813067 0.026087 0.006908 0.010593 \n",
"0 Ready_I-KNNBaseline 0.935327 0.737424 0.002545 0.000755 0.001105 \n",
"0 Ready_U-KNN 1.023495 0.807913 0.000742 0.000205 0.000305 \n",
"0 Self_BaselineUI 0.967585 0.762740 0.000954 0.000170 0.000278 \n",
"0 Self_IKNN 1.018363 0.808793 0.000318 0.000108 0.000140 \n",
"\n",
" F_05 precision_super recall_super NDCG mAP MRR \\\n",
"0 0.141584 0.130472 0.137473 0.214651 0.111707 0.400939 \n",
2020-05-21 16:20:12 +02:00
"0 0.068581 0.087876 0.076831 0.113446 0.054127 0.242918 \n",
"0 0.067431 0.090665 0.068368 0.101328 0.047917 0.183792 \n",
2020-05-21 13:42:50 +02:00
"0 0.061286 0.079614 0.056463 0.095957 0.043178 0.198193 \n",
2020-05-21 16:20:12 +02:00
"0 0.054503 0.073391 0.051400 0.088531 0.039739 0.188187 \n",
2020-05-21 13:42:50 +02:00
"0 0.041343 0.040558 0.032107 0.067695 0.027470 0.171187 \n",
2020-05-21 16:20:12 +02:00
"0 0.031216 0.028970 0.021179 0.050489 0.019185 0.123856 \n",
2020-05-21 13:42:50 +02:00
"0 0.016046 0.021137 0.009522 0.024214 0.008958 0.048068 \n",
"0 0.001602 0.002253 0.000930 0.003444 0.001362 0.011760 \n",
"0 0.000449 0.000536 0.000198 0.000845 0.000274 0.002744 \n",
"0 0.000463 0.000644 0.000189 0.000752 0.000168 0.001677 \n",
"0 0.000189 0.000000 0.000000 0.000214 0.000037 0.000368 \n",
"\n",
" LAUC HR Reco in test Test coverage Shannon Gini \n",
"0 0.555546 0.765642 1.000000 0.038961 3.159079 0.987317 \n",
2020-05-21 16:20:12 +02:00
"0 0.520677 0.488865 0.998091 0.204906 4.440336 0.952374 \n",
"0 0.517141 0.459173 0.860551 0.146465 3.853236 0.971798 \n",
2020-05-21 13:42:50 +02:00
"0 0.515501 0.437964 1.000000 0.033911 2.836513 0.991139 \n",
2020-05-21 16:20:12 +02:00
"0 0.512998 0.423118 0.995864 0.172439 4.176612 0.963967 \n",
2020-05-21 13:42:50 +02:00
"0 0.509546 0.384942 1.000000 0.025974 2.711772 0.992003 \n",
2020-05-21 16:20:12 +02:00
"0 0.506812 0.322375 0.987805 0.184704 5.103172 0.906873 \n",
2020-05-21 13:42:50 +02:00
"0 0.499885 0.154825 0.402333 0.434343 5.133650 0.877999 \n",
"0 0.496724 0.021209 0.482821 0.059885 2.232578 0.994487 \n",
"0 0.496441 0.007423 0.602121 0.010823 2.089186 0.995706 \n",
"0 0.496424 0.009544 0.600530 0.005051 1.803126 0.996380 \n",
"0 0.496391 0.003181 0.392153 0.115440 4.174741 0.965327 "
]
},
2020-05-21 16:20:12 +02:00
"execution_count": 16,
2020-05-21 13:42:50 +02:00
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import imp\n",
"imp.reload(ev)\n",
"\n",
"import evaluation_measures as ev\n",
"dir_path=\"Recommendations generated/ml-100k/\"\n",
"super_reactions=[4,5]\n",
"test=pd.read_csv('./Datasets/ml-100k/test.csv', sep='\\t', header=None)\n",
"\n",
"ev.evaluate_all(test, dir_path, super_reactions)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.9"
}
},
"nbformat": 4,
"nbformat_minor": 4
}