{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"#### reco (https://github.com/mayukh18/reco) \nWe'll be using my RecSys library **reco**. Give it a ⭐ if it helps you in this competition. Check it out. There are other models implemented which can all be applied in this competition.","metadata":{}},{"cell_type":"code","source":"!pip install git+https://github.com/lishenghui/recsys","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:07:03.782496Z","iopub.execute_input":"2022-05-04T12:07:03.782836Z","iopub.status.idle":"2022-05-04T12:07:17.880578Z","shell.execute_reply.started":"2022-05-04T12:07:03.782804Z","shell.execute_reply":"2022-05-04T12:07:17.879441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# It is available on pypi but I haven't updated the release there. So install from github\n!pip install git+https://github.com/mayukh18/reco","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:07:17.883745Z","iopub.execute_input":"2022-05-04T12:07:17.884054Z","iopub.status.idle":"2022-05-04T12:07:32.563619Z","shell.execute_reply.started":"2022-05-04T12:07:17.884016Z","shell.execute_reply":"2022-05-04T12:07:32.562455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\")\n\nimport numpy as np\nimport pandas as pd\nimport os\nimport glob\nimport reco\nfrom tqdm import tqdm\nimport datetime\nfrom collections import Counter","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:07:32.565813Z","iopub.execute_input":"2022-05-04T12:07:32.566133Z","iopub.status.idle":"2022-05-04T12:07:32.573448Z","shell.execute_reply.started":"2022-05-04T12:07:32.566093Z","shell.execute_reply":"2022-05-04T12:07:32.571686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Forming Train Set 🔹\n\nWe'll keep 2 weeks as train and the last week as validation.","metadata":{}},{"cell_type":"code","source":"data = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/transactions_train.csv\", dtype={'article_id':str})\ndata[\"t_dat\"] = pd.to_datetime(data[\"t_dat\"])\ndata.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:07:32.575930Z","iopub.execute_input":"2022-05-04T12:07:32.576222Z","iopub.status.idle":"2022-05-04T12:08:33.507878Z","shell.execute_reply.started":"2022-05-04T12:07:32.576187Z","shell.execute_reply":"2022-05-04T12:08:33.507029Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"All Transactions Date Range: {} to {}\".format(data['t_dat'].min(), data['t_dat'].max()))\n\ndata[\"t_dat\"] = pd.to_datetime(data[\"t_dat\"])\ntrain1 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,9,8)) & (data['t_dat'] < datetime.datetime(2020,9,16))]\ntrain2 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,9,1)) & (data['t_dat'] < datetime.datetime(2020,9,8))]\ntrain3 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,8,23)) & (data['t_dat'] < datetime.datetime(2020,9,1))]\ntrain4 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,8,15)) & (data['t_dat'] < datetime.datetime(2020,8,23))]\n\nval = data.loc[data[\"t_dat\"] >= datetime.datetime(2020,9,16)]","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:08:33.509235Z","iopub.execute_input":"2022-05-04T12:08:33.509509Z","iopub.status.idle":"2022-05-04T12:08:35.639993Z","shell.execute_reply.started":"2022-05-04T12:08:33.509477Z","shell.execute_reply":"2022-05-04T12:08:35.639064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# List of all purchases per user (has repetitions)\npositive_items_per_user1 = train1.groupby(['customer_id'])['article_id'].apply(list)\npositive_items_per_user2 = train2.groupby(['customer_id'])['article_id'].apply(list)\npositive_items_per_user3 = train3.groupby(['customer_id'])['article_id'].apply(list)\npositive_items_per_user4 = train4.groupby(['customer_id'])['article_id'].apply(list)","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:08:35.641633Z","iopub.execute_input":"2022-05-04T12:08:35.642071Z","iopub.status.idle":"2022-05-04T12:08:43.393106Z","shell.execute_reply.started":"2022-05-04T12:08:35.642024Z","shell.execute_reply":"2022-05-04T12:08:43.392075Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Implicit to Explicit Feedback 🔹\n\nThere can be multiple ways to convert the implicit data to explicit. But all ways have the same fundamental idea. We'll treat the purchase of an unpopular item to be of high explicit feedback and that of a popular item to be of low explicit feedback. Also, if an user buys a lot of items, that can weigh down the importance of one single item.\n\nSome ideas:\n\n1. user-item purchase count weighed down by time decaying popularity of the item as introduced in https://www.kaggle.com/mayukh18/time-decaying-popularity-benchmark-0-0216 (We will use this in this notebook)\n2. user-item purchase count weighed down by the product of total purchase count of the item and total purchase count of the user.\n\nNote: No idea is the absolute perfect. As you will combine different heuristic approaches with the SVD you'll realize different conversion techniques are favourable for different heuristics approaches.","metadata":{}},{"cell_type":"code","source":"train = pd.concat([train1, train2, train3, train4], axis=0)\n\n#time decay popularity of each article\ntrain['pop_factor'] = train['t_dat'].apply(lambda x: 1/(datetime.datetime(2020,9,16) - x).days**2)\npopular_items_group = train.groupby(['article_id'])['pop_factor'].sum()\n\n# purchase count of each article\nitems_total_count = train.groupby(['article_id'])['article_id'].count()\n# purchase count of each user\nusers_total_count = train.groupby(['customer_id'])['customer_id'].count()\n\n\ntrain['feedback'] = 1\ntrain = train.groupby(['customer_id', 'article_id']).sum().reset_index()\ntrain['feedback'] = train.apply(lambda row: row['feedback']/popular_items_group[row['article_id']], axis=1)\n\ntrain['feedback'] = train['feedback'].apply(lambda x: 5.0 if x>5.0 else x)\ntrain.drop(['price', 'sales_channel_id'], axis=1, inplace=True)\n\n# shuffling\ntrain = train.sample(frac=1).reset_index(drop=True)\ntrain['feedback'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:08:43.394773Z","iopub.execute_input":"2022-05-04T12:08:43.395120Z","iopub.status.idle":"2022-05-04T12:09:36.913435Z","shell.execute_reply.started":"2022-05-04T12:08:43.395078Z","shell.execute_reply":"2022-05-04T12:09:36.912440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Basic time decaying popularity to combine it with the SVD.","metadata":{}},{"cell_type":"code","source":"train_pop = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,9,1)) & (data['t_dat'] < datetime.datetime(2020,9,16))]\ntrain_pop['pop_factor'] = train_pop['t_dat'].apply(lambda x: 1/(datetime.datetime(2020,9,16) - x).days)\npopular_items_group = train_pop.groupby(['article_id'])['pop_factor'].sum()\n\n_, popular_items = zip(*sorted(zip(popular_items_group, popular_items_group.keys()))[::-1])\n\ntrain_pop['pop_factor'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:09:36.914905Z","iopub.execute_input":"2022-05-04T12:09:36.915148Z","iopub.status.idle":"2022-05-04T12:09:47.779364Z","shell.execute_reply.started":"2022-05-04T12:09:36.915119Z","shell.execute_reply":"2022-05-04T12:09:47.778420Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Below part is a cool new addition which gives a small bump. Did not add it to the validation part but it has the same effect there too. It predicts the most frequent next item bought by an user after a particular item.","metadata":{}},{"cell_type":"code","source":"def get_most_freq_next_item(user_group):\n    next_items = {}\n    for user in tqdm(user_group.keys()):\n        items = user_group[user]\n        for i,item in enumerate(items[:-1]):\n            if item not in next_items:\n                next_items[item] = []\n            if item != items[i+1]:\n                next_items[item].append(items[i+1])\n\n    pred_next = {}\n    for item in next_items:\n        if len(next_items[item]) >= 5:\n            most_common = Counter(next_items[item]).most_common()\n            ratio = most_common[0][1]/len(next_items[item])\n            if ratio >= 0.1:\n                pred_next[item] = most_common[0][0]\n            \n    return pred_next\n\nuser_group = train.groupby(['customer_id'])['article_id'].apply(list)\npred_next = get_most_freq_next_item(user_group)","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:09:47.781215Z","iopub.execute_input":"2022-05-04T12:09:47.781670Z","iopub.status.idle":"2022-05-04T12:09:57.419391Z","shell.execute_reply.started":"2022-05-04T12:09:47.781625Z","shell.execute_reply":"2022-05-04T12:09:57.418408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# SVD Training 🔹","metadata":{}},{"cell_type":"code","source":"from reco.recommender import FunkSVD\nfrom reco.metrics import rmse\n\n# k = number of dimensions of the latent embedding. formatizer dict takes in names of the columns\n# for user, item and values/feedback/ratings respectively.\n\nsvd = FunkSVD(k=64, learning_rate=0.002, regularizer = 0.05, iterations = 150, method = 'stochastic', bias=True)\nsvd.fit(X=train, formatizer={'user':'customer_id', 'item':'article_id', 'value':'feedback'},verbose=True)","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:09:57.425086Z","iopub.execute_input":"2022-05-04T12:09:57.425588Z","iopub.status.idle":"2022-05-04T12:12:25.820097Z","shell.execute_reply.started":"2022-05-04T12:09:57.425535Z","shell.execute_reply":"2022-05-04T12:12:25.819160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Validation 🔹\n\nThis is mostly based on [this notebook](https://www.kaggle.com/mayukh18/time-decaying-popularity-benchmark-0-0216) where I have used same pipeline. Will use SVD for re-ranking. Will read all the data anew and train a new model on our new train set with new date ranges for submission. This will align us with the aforementioned notebook.","metadata":{}},{"cell_type":"code","source":"def apk(actual, predicted, k=12):\n    if len(predicted)>k:\n        predicted = predicted[:k]\n\n    score = 0.0\n    num_hits = 0.0\n\n    for i,p in enumerate(predicted):\n        if p in actual and p not in predicted[:i]:\n            num_hits += 1.0\n            score += num_hits / (i+1.0)\n\n    if not actual:\n        return 0.0\n\n    return score / min(len(actual), k)\n\ndef mapk(actual, predicted, k=12):\n    return np.mean([apk(a,p,k) for a,p in zip(actual, predicted)])","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:12:25.821532Z","iopub.execute_input":"2022-05-04T12:12:25.821770Z","iopub.status.idle":"2022-05-04T12:12:25.831311Z","shell.execute_reply.started":"2022-05-04T12:12:25.821742Z","shell.execute_reply":"2022-05-04T12:12:25.830163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"positive_items_val = val.groupby(['customer_id'])['article_id'].apply(list)\nval_users = positive_items_val.keys()\nval_items = []\n\nfor i,user in tqdm(enumerate(val_users)):\n    val_items.append(positive_items_val[user])\n    \nprint(\"Total users in validation:\", len(val_users))","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:12:25.832510Z","iopub.execute_input":"2022-05-04T12:12:25.832753Z","iopub.status.idle":"2022-05-04T12:12:27.908065Z","shell.execute_reply.started":"2022-05-04T12:12:25.832725Z","shell.execute_reply":"2022-05-04T12:12:27.907105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Normal way of prediction without the SVD reranking","metadata":{}},{"cell_type":"code","source":"from collections import Counter\noutputs = []\ncnt = 0\n\npopular_items = list(popular_items)\n\nfor user in tqdm(val_users):\n    user_output = []\n    if user in positive_items_per_user1.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user1[user]).most_common()}\n        user_output += list(most_common_items_of_user.keys())[:12]\n    if user in positive_items_per_user2.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user2[user]).most_common()}\n        user_output += list(most_common_items_of_user.keys())[:12]\n    if user in positive_items_per_user3.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user3[user]).most_common()}\n        user_output += list(most_common_items_of_user.keys())[:12]\n    if user in positive_items_per_user4.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user4[user]).most_common()}\n        user_output += list(most_common_items_of_user.keys())[:12]\n    \n    user_output += [pred_next[item] for item in user_output if item in pred_next and pred_next[item] not in user_output]      \n    \n    user_output += list(popular_items[:12 - len(user_output)])\n    outputs.append(user_output)\n    \nprint(\"mAP Score on Validation set:\", mapk(val_items, outputs))","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:12:27.909754Z","iopub.execute_input":"2022-05-04T12:12:27.909983Z","iopub.status.idle":"2022-05-04T12:12:34.511505Z","shell.execute_reply.started":"2022-05-04T12:12:27.909955Z","shell.execute_reply":"2022-05-04T12:12:34.510493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Now, prediction WITH the SVD reranking!","metadata":{}},{"cell_type":"code","source":"from collections import Counter\noutputs = []\ncnt = 0\n\npopular_items = list(popular_items)\nuserindexes = {svd.users[i]:i for i in range(len(svd.users))}\n\nfor user in tqdm(val_users):\n    user_output = []\n    if user in positive_items_per_user1.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user1[user]).most_common()}\n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = svd.items.index(k)\n                pred_value = np.dot(svd.userfeatures[user_index], svd.itemfeatures[itemindex].T) + svd.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    if user in positive_items_per_user2.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user2[user]).most_common()}\n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = svd.items.index(k)\n                pred_value = np.dot(svd.userfeatures[user_index], svd.itemfeatures[itemindex].T) + svd.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    if user in positive_items_per_user3.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user3[user]).most_common()}\n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = svd.items.index(k)\n                pred_value = np.dot(svd.userfeatures[user_index], svd.itemfeatures[itemindex].T) + svd.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    if user in positive_items_per_user4.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user4[user]).most_common()}\n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = svd.items.index(k)\n                pred_value = np.dot(svd.userfeatures[user_index], svd.itemfeatures[itemindex].T) + svd.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    user_output += [pred_next[item] for item in user_output if item in pred_next and pred_next[item] not in user_output]      \n    \n    user_output += list(popular_items[:12 - len(user_output)])\n    outputs.append(user_output)\n    \nprint(\"mAP Score on Validation set:\", mapk(val_items, outputs))","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:12:34.512982Z","iopub.execute_input":"2022-05-04T12:12:34.513237Z","iopub.status.idle":"2022-05-04T12:14:42.387346Z","shell.execute_reply.started":"2022-05-04T12:12:34.513209Z","shell.execute_reply":"2022-05-04T12:14:42.386360Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Decent jump of 0.001 I would say with 4 weeks of training data!","metadata":{}},{"cell_type":"markdown","source":"# Submission\n\nWe will do all the same things all over again just with different time periods.","metadata":{}},{"cell_type":"code","source":"train1 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,9,16)) & (data['t_dat'] < datetime.datetime(2020,9,23))]\ntrain2 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,9,8)) & (data['t_dat'] < datetime.datetime(2020,9,16))]\ntrain3 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,8,31)) & (data['t_dat'] < datetime.datetime(2020,9,8))]\ntrain4 = data.loc[(data[\"t_dat\"] >= datetime.datetime(2020,8,23)) & (data['t_dat'] < datetime.datetime(2020,8,31))]\n\npositive_items_per_user1 = train1.groupby(['customer_id'])['article_id'].apply(list)\npositive_items_per_user2 = train2.groupby(['customer_id'])['article_id'].apply(list)\npositive_items_per_user3 = train3.groupby(['customer_id'])['article_id'].apply(list)\npositive_items_per_user4 = train4.groupby(['customer_id'])['article_id'].apply(list)\n\ntrain = pd.concat([train1, train2], axis=0)\ntrain['pop_factor'] = train['t_dat'].apply(lambda x: 1/(datetime.datetime(2020,9,23) - x).days)\npopular_items_group = train.groupby(['article_id'])['pop_factor'].sum()\n\n_, popular_items = zip(*sorted(zip(popular_items_group, popular_items_group.keys()))[::-1])\n\nuser_group = pd.concat([train1, train2, train3, train4], axis=0).groupby(['customer_id'])['article_id'].apply(list)","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:14:42.390407Z","iopub.execute_input":"2022-05-04T12:14:42.392355Z","iopub.status.idle":"2022-05-04T12:15:11.189053Z","shell.execute_reply.started":"2022-05-04T12:14:42.392283Z","shell.execute_reply":"2022-05-04T12:15:11.188066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SVD\ntrain = pd.concat([train1, train2, train3, train4], axis=0)\ntrain['pop_factor'] = train['t_dat'].apply(lambda x: 1/(datetime.datetime(2020,9,23) - x).days**2)\npopular_items_group = train.groupby(['article_id'])['pop_factor'].sum()\n\ntrain['feedback'] = 1\ntrain = train.groupby(['customer_id', 'article_id']).sum().reset_index()\n\ntrain['feedback'] = train.apply(lambda row: row['feedback']/popular_items_group[row['article_id']], axis=1)\n\ntrain['feedback'] = train['feedback'].apply(lambda x: 5.0 if x>5.0 else x)\ntrain.drop(['price', 'sales_channel_id'], axis=1, inplace=True)\ntrain['feedback'].describe()","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:15:11.190390Z","iopub.execute_input":"2022-05-04T12:15:11.190740Z","iopub.status.idle":"2022-05-04T12:16:05.236604Z","shell.execute_reply.started":"2022-05-04T12:15:11.190691Z","shell.execute_reply":"2022-05-04T12:16:05.235451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = train.sample(frac=1).reset_index(drop=True)\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:16:05.238287Z","iopub.execute_input":"2022-05-04T12:16:05.238558Z","iopub.status.idle":"2022-05-04T12:16:05.743615Z","shell.execute_reply.started":"2022-05-04T12:16:05.238528Z","shell.execute_reply":"2022-05-04T12:16:05.742459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install git+https://github.com/gbolmier/funk-svd","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:16:05.745079Z","iopub.execute_input":"2022-05-04T12:16:05.745479Z","iopub.status.idle":"2022-05-04T12:16:18.831561Z","shell.execute_reply.started":"2022-05-04T12:16:05.745441Z","shell.execute_reply":"2022-05-04T12:16:18.830465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from funk_svd.dataset import fetch_ml_ratings\nfrom funk_svd import SVD\n\nfrom sklearn.metrics import mean_absolute_error\n\n\n#df = fetch_ml_ratings(variant='100k')\n\n#train = df.sample(frac=0.8, random_state=7)\n\n#svd = SVD(lr=0.001, reg=0.005, n_epochs=100, n_factors=15,early_stopping=True, shuffle=False, min_rating=1, max_rating=5)\n\nf = FunkSVD(k=64, learning_rate=0.002, regularizer = 0.05, iterations = 300, method = 'stochastic', bias=True)\nf.fit(X=train, formatizer={'user':'customer_id', 'item':'article_id', 'value':'feedback'},verbose=True)","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:16:18.833706Z","iopub.execute_input":"2022-05-04T12:16:18.834014Z","iopub.status.idle":"2022-05-04T12:20:34.404193Z","shell.execute_reply.started":"2022-05-04T12:16:18.833977Z","shell.execute_reply":"2022-05-04T12:20:34.403151Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:20:34.406052Z","iopub.execute_input":"2022-05-04T12:20:34.407538Z","iopub.status.idle":"2022-05-04T12:20:34.426126Z","shell.execute_reply.started":"2022-05-04T12:20:34.407487Z","shell.execute_reply":"2022-05-04T12:20:34.425238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/sample_submission.csv\")\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:20:34.427954Z","iopub.execute_input":"2022-05-04T12:20:34.428287Z","iopub.status.idle":"2022-05-04T12:20:37.427077Z","shell.execute_reply.started":"2022-05-04T12:20:34.428243Z","shell.execute_reply":"2022-05-04T12:20:37.426205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"outputs = []\ncnt = 0\n\npopular_items = list(popular_items)\nuserindexes = {f.users[i]:i for i in range(len(f.users))}\n\nfor user in tqdm(submission['customer_id']):\n    user_output = []\n    if user in positive_items_per_user1.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user1[user]).most_common()}\n        \n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = f.items.index(k)\n                pred_value = np.dot(f.userfeatures[user_index], f.itemfeatures[itemindex].T) + f.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    if user in positive_items_per_user2.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user2[user]).most_common()}\n        \n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = f.items.index(k)\n                pred_value = np.dot(f.userfeatures[user_index], f.itemfeatures[itemindex].T) + f.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    if user in positive_items_per_user3.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user3[user]).most_common()}\n        \n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = f.items.index(k)\n                pred_value = np.dot(f.userfeatures[user_index], f.itemfeatures[itemindex].T) + f.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    if user in positive_items_per_user4.keys():\n        most_common_items_of_user = {k:v for k, v in Counter(positive_items_per_user4[user]).most_common()}\n        \n        user_index = userindexes[user]\n        new_order = {}\n        for k in list(most_common_items_of_user.keys())[:20]:\n            try:\n                itemindex = f.items.index(k)\n                pred_value = np.dot(f.userfeatures[user_index], f.itemfeatures[itemindex].T) + f.item_bias[0, itemindex]\n            except:\n                pred_value = most_common_items_of_user[k]\n            new_order[k] = pred_value\n        user_output += [k for k, v in sorted(new_order.items(), key=lambda item: item[1])][:12]\n        \n    user_output += [pred_next[item] for item in user_output if item in pred_next and pred_next[item] not in user_output]      \n    \n    user_output += list(popular_items[:12 - len(user_output)])\n    outputs.append(user_output)\n    \nstr_outputs = []\nfor output in outputs:\n    str_outputs.append(\" \".join([str(x) for x in output]))","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:20:37.428368Z","iopub.execute_input":"2022-05-04T12:20:37.428588Z","iopub.status.idle":"2022-05-04T12:32:36.213249Z","shell.execute_reply.started":"2022-05-04T12:20:37.428562Z","shell.execute_reply":"2022-05-04T12:32:36.210275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission['prediction'] = str_outputs\nsubmission.to_csv(\"submissions.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:32:36.217143Z","iopub.execute_input":"2022-05-04T12:32:36.218704Z","iopub.status.idle":"2022-05-04T12:34:40.193464Z","shell.execute_reply.started":"2022-05-04T12:32:36.218635Z","shell.execute_reply":"2022-05-04T12:34:40.192221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-04T12:34:40.195947Z","iopub.execute_input":"2022-05-04T12:34:40.196501Z","iopub.status.idle":"2022-05-04T12:34:40.208784Z","shell.execute_reply.started":"2022-05-04T12:34:40.196451Z","shell.execute_reply":"2022-05-04T12:34:40.207772Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### That's it! Upvote and Enjoy!\nExamples of FunkSVD and FM are over at https://github.com/mayukh18/reco/tree/master/examples. I'll try to add an example of [Wide And Deep Network](https://arxiv.org/pdf/1606.07792.pdf) in the coming days. That is also a pretty cool model to try next.","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}