{"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":"# 3rd Place - Team G & B & D & T Final Solution - LB 0.604!\nThis notebook is the 3rd place final submission for Team G&B&D&T for Kaggle's OTTO RecSys competition. Team members are Giba ( @titericz ), Benny ( @benediktschifferer ), Chris Deotte ( @cdeotte ), and Theo ( @theoviel ). This solution is an ensemble of 3 single XGB reranker models. Discussion explaining this solution is [here][1], [here][2], and [here][3].\n\n[1]: https://www.kaggle.com/competitions/otto-recommender-system/discussion/386497\n[2]: https://www.kaggle.com/competitions/otto-recommender-system/discussion/383013\n[3]: https://www.kaggle.com/competitions/otto-recommender-system/discussion/382975","metadata":{}},{"cell_type":"code","source":"import gc\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nfrom collections import Counter\n\npd.options.display.max_colwidth = 500","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.execute_input":"2023-01-31T17:15:22.383134Z","iopub.status.busy":"2023-01-31T17:15:22.382173Z","iopub.status.idle":"2023-01-31T17:15:22.395318Z","shell.execute_reply":"2023-01-31T17:15:22.39441Z"},"papermill":{"duration":0.021588,"end_time":"2023-01-31T17:15:22.397756","exception":false,"start_time":"2023-01-31T17:15:22.376168","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FILES = [\n    \"/kaggle/input/otto-comp-single-models/submission_chris_v186v406v412.csv\", # Chris 0.601\n    \"/kaggle/input/otto-comp-single-models/submission_benny_601.csv\",      # Benny 0.601\n    \"/kaggle/input/otto-comp-single-models/submission_theo_6029.csv\"       # Theo 0.603\n]\n\nWEIGHTS = [1, 1, 3]","metadata":{"execution":{"iopub.execute_input":"2023-01-31T17:15:22.406185Z","iopub.status.busy":"2023-01-31T17:15:22.40542Z","iopub.status.idle":"2023-01-31T17:15:22.410915Z","shell.execute_reply":"2023-01-31T17:15:22.410169Z"},"papermill":{"duration":0.012207,"end_time":"2023-01-31T17:15:22.413271","exception":false,"start_time":"2023-01-31T17:15:22.401064","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subs = [\n    pd.read_csv(f).sort_values(['session_type']).reset_index(drop=True) for f in FILES\n]\n\nfor s in subs:\n    assert len(s) == len(subs[0])","metadata":{"execution":{"iopub.execute_input":"2023-01-31T17:15:22.421025Z","iopub.status.busy":"2023-01-31T17:15:22.420664Z","iopub.status.idle":"2023-01-31T17:17:32.57267Z","shell.execute_reply":"2023-01-31T17:17:32.571724Z"},"papermill":{"duration":130.159027,"end_time":"2023-01-31T17:17:32.575337","exception":false,"start_time":"2023-01-31T17:15:22.41631","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for s, f in zip(subs, FILES):\n    print(f.split('/')[-1])\n    assert len(s) == len(subs[0])\n    display(s.head(3))\n    print()","metadata":{"execution":{"iopub.execute_input":"2023-01-31T17:17:32.58369Z","iopub.status.busy":"2023-01-31T17:17:32.58276Z","iopub.status.idle":"2023-01-31T17:17:32.627446Z","shell.execute_reply":"2023-01-31T17:17:32.626285Z"},"papermill":{"duration":0.051056,"end_time":"2023-01-31T17:17:32.62971","exception":false,"start_time":"2023-01-31T17:17:32.578654","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for idx in range(9):\n    for j in range(len(subs)):\n        for k in range(j):\n            p1 = np.array(sorted(subs[j]['labels'][idx].split(' '))).astype(int)\n            p2 = np.array(sorted(subs[k]['labels'][idx].split(' '))).astype(int)\n            sim = len((set(p1).intersection(set(p2)))) / 20\n            print(f'Similarity of row {subs[0][\"session_type\"][idx]} between subs {j} & {k} : {sim :.3f}')\n    print()","metadata":{"execution":{"iopub.execute_input":"2023-01-31T17:17:32.639483Z","iopub.status.busy":"2023-01-31T17:17:32.639079Z","iopub.status.idle":"2023-01-31T17:17:32.651727Z","shell.execute_reply":"2023-01-31T17:17:32.650844Z"},"papermill":{"duration":0.020269,"end_time":"2023-01-31T17:17:32.654143","exception":false,"start_time":"2023-01-31T17:17:32.633874","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"blend = []\nfor idx in tqdm(range(len(subs[0]))):    \n    amap = Counter()\n    for sub, sub_w in zip(subs, WEIGHTS):\n        for w, i in enumerate(sub[\"labels\"][idx].split(' ')):\n            amap[i] += (sub_w * (20 - w))\n\n    aid = ' '.join([aid_ for aid_, _ in amap.most_common(20)])\n    blend.append(aid)","metadata":{"execution":{"iopub.execute_input":"2023-01-31T17:17:32.664208Z","iopub.status.busy":"2023-01-31T17:17:32.663821Z","iopub.status.idle":"2023-01-31T17:26:33.083747Z","shell.execute_reply":"2023-01-31T17:26:33.082578Z"},"papermill":{"duration":540.427811,"end_time":"2023-01-31T17:26:33.086154","exception":false,"start_time":"2023-01-31T17:17:32.658343","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub = subs[0].copy()\nsub['labels'] = blend\nsub.to_csv('submission.csv', index=False)\n\nsub.head(12)","metadata":{"execution":{"iopub.execute_input":"2023-01-31T17:26:33.784221Z","iopub.status.busy":"2023-01-31T17:26:33.78382Z","iopub.status.idle":"2023-01-31T17:26:54.945836Z","shell.execute_reply":"2023-01-31T17:26:54.9445Z"},"papermill":{"duration":21.482596,"end_time":"2023-01-31T17:26:54.948903","exception":false,"start_time":"2023-01-31T17:26:33.466307","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for idx in range(3):\n    for j in range(len(subs)):\n        p1 = np.array(sorted(subs[j]['labels'][idx].split(' '))).astype(int)\n        p2 = np.array(sorted(sub['labels'][idx].split(' '))).astype(int)\n        sim = len((set(p1).intersection(set(p2)))) / 20\n        print(f'Similarity of row {subs[0][\"session_type\"][idx]} between sub {j} & blend : {sim :.3f}')\n    print()","metadata":{"execution":{"iopub.execute_input":"2023-01-31T17:26:55.588268Z","iopub.status.busy":"2023-01-31T17:26:55.587859Z","iopub.status.idle":"2023-01-31T17:26:55.597186Z","shell.execute_reply":"2023-01-31T17:26:55.595762Z"},"papermill":{"duration":0.333482,"end_time":"2023-01-31T17:26:55.599998","exception":false,"start_time":"2023-01-31T17:26:55.266516","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Done ! ","metadata":{"papermill":{"duration":0.316415,"end_time":"2023-01-31T17:26:56.297275","exception":false,"start_time":"2023-01-31T17:26:55.98086","status":"completed"},"tags":[]}}]}