{"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":"# <center> Предсказание победителя в Dota 2\n<center> <img src=\"https://meduza.io/impro/YnJZAHUW6WHz_JQm1uRPkTql_qAhbfxt3oFJLGH7CJg/fill/980/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNy8x/NTcvNjk1L29yaWdp/bmFsL0tMVThLbUti/ZG5pSzlibDA0Wmlw/WXcuanBn.webp\" width=\"700\" height=\"700\">","metadata":{"papermill":{"duration":0.036237,"end_time":"2022-02-13T23:12:16.653396","exception":false,"start_time":"2022-02-13T23:12:16.617159","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"[Почитать подбробнее](https://meduza.io/feature/2021/10/19/rossiyskaya-komanda-vyigrala-chempionat-mira-po-dota-2-i-poluchila-18-millionov-dollarov-postoyte-otkuda-takie-dengi-neuzheli-igrat-v-dotu-tak-slozhno)","metadata":{"papermill":{"duration":0.034411,"end_time":"2022-02-13T23:12:16.723175","exception":false,"start_time":"2022-02-13T23:12:16.688764","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"#### [Оригинальная статья](https://arxiv.org/pdf/2106.01782.pdf)\n    \n### Начало\n\nПосмотрим на готовые признаки и сделаем первую посылку. \n\n1. [Описание данных](#Описание-данных)\n2. [Описание признаков](#Описание-признаков)\n3. [Наша первая модель](#Наша-первая-модель)\n4. [Посылка](#Посылка)\n\n### Первые шаги на пути в датасайенс\n\n5. [Кросс-валидация](#Кросс-валидация)\n6. [Что есть в json файлах?](#Что-есть-в-json-файлах?)\n7. [Feature engineering](#Feature-engineering)","metadata":{"papermill":{"duration":0.043877,"end_time":"2022-02-13T23:12:16.809506","exception":false,"start_time":"2022-02-13T23:12:16.765629","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"### Импорты","metadata":{"papermill":{"duration":0.034281,"end_time":"2022-02-13T23:12:16.883754","exception":false,"start_time":"2022-02-13T23:12:16.849473","status":"completed"},"tags":[]}},{"cell_type":"code","source":"import os\nimport json\nimport pandas as pd\nimport datetime\nimport warnings\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split, ShuffleSplit, cross_val_score\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.metrics import roc_auc_score, accuracy_score\n\n%matplotlib inline","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:16.957141Z","iopub.status.busy":"2022-02-13T23:12:16.956004Z","iopub.status.idle":"2022-02-13T23:12:18.348152Z","shell.execute_reply":"2022-02-13T23:12:18.347483Z","shell.execute_reply.started":"2022-02-13T22:54:24.504400Z"},"papermill":{"duration":1.430171,"end_time":"2022-02-13T23:12:18.348353","exception":false,"start_time":"2022-02-13T23:12:16.918182","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SEED = 10801\nsns.set_style(style=\"whitegrid\")\nplt.rcParams[\"figure.figsize\"] = 12, 8\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:18.425717Z","iopub.status.busy":"2022-02-13T23:12:18.424682Z","iopub.status.idle":"2022-02-13T23:12:18.426840Z","shell.execute_reply":"2022-02-13T23:12:18.427336Z","shell.execute_reply.started":"2022-02-13T22:54:27.968328Z"},"papermill":{"duration":0.042869,"end_time":"2022-02-13T23:12:18.427502","exception":false,"start_time":"2022-02-13T23:12:18.384633","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <left>Описание данных\n\nФайлы:\n\n- `sample_submission.csv`: пример файла-посылки\n- `train_raw_data.jsonl`, `test_raw_data.jsonl`: \"сырые\" данные \n- `train_data.csv`, `test_data.csv`: признаки, созданные авторами\n- `train_targets.csv`: результаты тренировочных игр","metadata":{"papermill":{"duration":0.034932,"end_time":"2022-02-13T23:12:18.496885","exception":false,"start_time":"2022-02-13T23:12:18.461953","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"## <left>Описание признаков\n    \nНабор простых признаков, описывающих игроков и команды в целом","metadata":{"papermill":{"duration":0.034346,"end_time":"2022-02-13T23:12:18.565919","exception":false,"start_time":"2022-02-13T23:12:18.531573","status":"completed"},"tags":[]}},{"cell_type":"code","source":"PATH_TO_DATA = \"../input/bi-2021-ml-competitions-dota2\"\n\ndf_train_features = pd.read_csv(os.path.join(PATH_TO_DATA, \n                                             \"train_data.csv\"), \n                                    index_col=\"match_id_hash\")\ndf_train_targets = pd.read_csv(os.path.join(PATH_TO_DATA, \n                                            \"train_targets.csv\"), \n                                   index_col=\"match_id_hash\")","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:18.639904Z","iopub.status.busy":"2022-02-13T23:12:18.638908Z","iopub.status.idle":"2022-02-13T23:12:19.909730Z","shell.execute_reply":"2022-02-13T23:12:19.910247Z","shell.execute_reply.started":"2022-02-13T22:54:30.336618Z"},"papermill":{"duration":1.309296,"end_time":"2022-02-13T23:12:19.910434","exception":false,"start_time":"2022-02-13T23:12:18.601138","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_features.shape","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:19.983605Z","iopub.status.busy":"2022-02-13T23:12:19.982960Z","iopub.status.idle":"2022-02-13T23:12:19.990391Z","shell.execute_reply":"2022-02-13T23:12:19.990938Z","shell.execute_reply.started":"2022-02-13T22:54:33.105218Z"},"papermill":{"duration":0.045278,"end_time":"2022-02-13T23:12:19.991115","exception":false,"start_time":"2022-02-13T23:12:19.945837","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_features.head()","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:20.067908Z","iopub.status.busy":"2022-02-13T23:12:20.067237Z","iopub.status.idle":"2022-02-13T23:12:20.092038Z","shell.execute_reply":"2022-02-13T23:12:20.092529Z","shell.execute_reply.started":"2022-02-13T22:54:34.150651Z"},"papermill":{"duration":0.065603,"end_time":"2022-02-13T23:12:20.092716","exception":false,"start_time":"2022-02-13T23:12:20.027113","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Имеем ~32 тысячи наблюдений, каждое из которых характеризуется уникальным `match_id_hash` (захэшированное id матча), и 245 признаков. `game_time` показывает момент времени, в который получены эти данные. То есть по сути это не длительность самого матча, а например, его середина, таким образом, в итоге мы сможем получить модель, которая будет предсказывать вероятность победы каждой из команд в течение матча (хорошо подходит для букмекеров).","metadata":{"papermill":{"duration":0.037227,"end_time":"2022-02-13T23:12:20.167000","exception":false,"start_time":"2022-02-13T23:12:20.129773","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"Нас интересует поле `radiant_win` (так называется одна из команд, вторая - dire). Остальные колоки здесь по сути получены из \"будущего\" и есть только для тренировочных данных, поэтому на них можно просто посмотреть).","metadata":{"papermill":{"duration":0.037139,"end_time":"2022-02-13T23:12:20.240639","exception":false,"start_time":"2022-02-13T23:12:20.203500","status":"completed"},"tags":[]}},{"cell_type":"code","source":"df_train_targets.head()","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:20.316784Z","iopub.status.busy":"2022-02-13T23:12:20.316092Z","iopub.status.idle":"2022-02-13T23:12:20.326908Z","shell.execute_reply":"2022-02-13T23:12:20.326377Z","shell.execute_reply.started":"2022-02-13T22:54:36.171466Z"},"papermill":{"duration":0.049678,"end_time":"2022-02-13T23:12:20.327042","exception":false,"start_time":"2022-02-13T23:12:20.277364","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <left>Наша первая модель","metadata":{"papermill":{"duration":0.036013,"end_time":"2022-02-13T23:12:20.399533","exception":false,"start_time":"2022-02-13T23:12:20.363520","status":"completed"},"tags":[]}},{"cell_type":"code","source":"X = df_train_features.values\ny = df_train_targets[\"radiant_win\"].values.astype(\"int8\")","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:20.476156Z","iopub.status.busy":"2022-02-13T23:12:20.475498Z","iopub.status.idle":"2022-02-13T23:12:20.504532Z","shell.execute_reply":"2022-02-13T23:12:20.505141Z","shell.execute_reply.started":"2022-02-13T22:54:39.221703Z"},"papermill":{"duration":0.069566,"end_time":"2022-02-13T23:12:20.505342","exception":false,"start_time":"2022-02-13T23:12:20.435776","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_valid, y_train, y_valid = train_test_split(X, y, \n                                                      test_size=0.3, \n                                                      random_state=SEED)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:20.581534Z","iopub.status.busy":"2022-02-13T23:12:20.580886Z","iopub.status.idle":"2022-02-13T23:12:20.676297Z","shell.execute_reply":"2022-02-13T23:12:20.676920Z","shell.execute_reply.started":"2022-02-13T22:54:39.486872Z"},"papermill":{"duration":0.135291,"end_time":"2022-02-13T23:12:20.677101","exception":false,"start_time":"2022-02-13T23:12:20.541810","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Обучим случайный лес","metadata":{"papermill":{"duration":0.035934,"end_time":"2022-02-13T23:12:20.749995","exception":false,"start_time":"2022-02-13T23:12:20.714061","status":"completed"},"tags":[]}},{"cell_type":"code","source":"%%time\nrf_model = RandomForestClassifier(n_estimators=300, max_depth=7, n_jobs=-1, random_state=SEED)\nrf_model.fit(X_train, y_train)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:20.826125Z","iopub.status.busy":"2022-02-13T23:12:20.825488Z","iopub.status.idle":"2022-02-13T23:12:30.132769Z","shell.execute_reply":"2022-02-13T23:12:30.133531Z","shell.execute_reply.started":"2022-02-13T22:55:21.167897Z"},"papermill":{"duration":9.347015,"end_time":"2022-02-13T23:12:30.133763","exception":false,"start_time":"2022-02-13T23:12:20.786748","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Сделаем предсказания и оценим качество на отложенной части данных","metadata":{"papermill":{"duration":0.041856,"end_time":"2022-02-13T23:12:30.212928","exception":false,"start_time":"2022-02-13T23:12:30.171072","status":"completed"},"tags":[]}},{"cell_type":"code","source":"y_pred = rf_model.predict_proba(X_valid)[:, 1]","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:30.293275Z","iopub.status.busy":"2022-02-13T23:12:30.292562Z","iopub.status.idle":"2022-02-13T23:12:30.604347Z","shell.execute_reply":"2022-02-13T23:12:30.603730Z","shell.execute_reply.started":"2022-02-13T22:55:33.749369Z"},"papermill":{"duration":0.353253,"end_time":"2022-02-13T23:12:30.604516","exception":false,"start_time":"2022-02-13T23:12:30.251263","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_score = roc_auc_score(y_valid, y_pred)\nprint(\"ROC-AUC score на отложенной части:\", valid_score)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:30.685551Z","iopub.status.busy":"2022-02-13T23:12:30.684486Z","iopub.status.idle":"2022-02-13T23:12:30.694865Z","shell.execute_reply":"2022-02-13T23:12:30.694172Z","shell.execute_reply.started":"2022-02-13T22:55:34.515933Z"},"papermill":{"duration":0.053288,"end_time":"2022-02-13T23:12:30.695003","exception":false,"start_time":"2022-02-13T23:12:30.641715","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Посмотрим на accuracy:","metadata":{"papermill":{"duration":0.037253,"end_time":"2022-02-13T23:12:30.770017","exception":false,"start_time":"2022-02-13T23:12:30.732764","status":"completed"},"tags":[]}},{"cell_type":"code","source":"valid_accuracy = accuracy_score(y_valid, y_pred > 0.5)\nprint(\"Accuracy score (p > 0.5) на отложенной части:\", valid_accuracy)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:30.851561Z","iopub.status.busy":"2022-02-13T23:12:30.850510Z","iopub.status.idle":"2022-02-13T23:12:30.857343Z","shell.execute_reply":"2022-02-13T23:12:30.856784Z","shell.execute_reply.started":"2022-02-13T22:55:46.570239Z"},"papermill":{"duration":0.049802,"end_time":"2022-02-13T23:12:30.857480","exception":false,"start_time":"2022-02-13T23:12:30.807678","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <left>Посылка","metadata":{"papermill":{"duration":0.037715,"end_time":"2022-02-13T23:12:30.932941","exception":false,"start_time":"2022-02-13T23:12:30.895226","status":"completed"},"tags":[]}},{"cell_type":"code","source":"df_test_features = pd.read_csv(os.path.join(PATH_TO_DATA, \"test_data.csv\"), \n                                   index_col=\"match_id_hash\")\n\nX_test = df_test_features.values\ny_test_pred = rf_model.predict_proba(X_test)[:, 1]\n\ndf_submission = pd.DataFrame({\"radiant_win_prob\": y_test_pred}, \n                                 index=df_test_features.index)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:31.016356Z","iopub.status.busy":"2022-02-13T23:12:31.015669Z","iopub.status.idle":"2022-02-13T23:12:31.531306Z","shell.execute_reply":"2022-02-13T23:12:31.531863Z","shell.execute_reply.started":"2022-02-13T22:55:54.636469Z"},"papermill":{"duration":0.561329,"end_time":"2022-02-13T23:12:31.532046","exception":false,"start_time":"2022-02-13T23:12:30.970717","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_filename = \"submission_{}.csv\".format(\n    datetime.datetime.now().strftime(\"%Y-%m-%d_%H-%M-%S\"))\ndf_submission.to_csv(submission_filename)\nprint(\"Файл посылки сохранен, как: {}\".format(submission_filename))","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:31.614098Z","iopub.status.busy":"2022-02-13T23:12:31.613358Z","iopub.status.idle":"2022-02-13T23:12:31.651586Z","shell.execute_reply":"2022-02-13T23:12:31.650986Z","shell.execute_reply.started":"2022-02-13T22:55:58.549750Z"},"papermill":{"duration":0.081747,"end_time":"2022-02-13T23:12:31.651724","exception":false,"start_time":"2022-02-13T23:12:31.569977","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <left>Кросс-валидация","metadata":{"papermill":{"duration":0.038042,"end_time":"2022-02-13T23:12:31.728003","exception":false,"start_time":"2022-02-13T23:12:31.689961","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"Во многих случаях кросс-валидация оказывается лучше простого разбиения на test и train. Воспользуемся `ShuffleSplit` чтобы создать 5 70%/30% наборов данных.","metadata":{"papermill":{"duration":0.037622,"end_time":"2022-02-13T23:12:31.804031","exception":false,"start_time":"2022-02-13T23:12:31.766409","status":"completed"},"tags":[]}},{"cell_type":"code","source":"cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=SEED)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:31.888954Z","iopub.status.busy":"2022-02-13T23:12:31.887914Z","iopub.status.idle":"2022-02-13T23:12:31.890534Z","shell.execute_reply":"2022-02-13T23:12:31.889871Z","shell.execute_reply.started":"2022-02-13T22:56:24.879618Z"},"papermill":{"duration":0.047215,"end_time":"2022-02-13T23:12:31.890672","exception":false,"start_time":"2022-02-13T23:12:31.843457","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nrf_model = RandomForestClassifier(n_estimators=300, max_depth=7, n_jobs=-1, random_state=SEED)\ncv_scores_rf = cross_val_score(rf_model, X, y, cv=cv, scoring=\"roc_auc\")","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:12:31.976597Z","iopub.status.busy":"2022-02-13T23:12:31.975254Z","iopub.status.idle":"2022-02-13T23:13:25.411148Z","shell.execute_reply":"2022-02-13T23:13:25.411674Z","shell.execute_reply.started":"2022-02-13T22:56:42.398744Z"},"papermill":{"duration":53.482844,"end_time":"2022-02-13T23:13:25.411896","exception":false,"start_time":"2022-02-13T23:12:31.929052","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cv_scores_rf","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:25.493196Z","iopub.status.busy":"2022-02-13T23:13:25.492573Z","iopub.status.idle":"2022-02-13T23:13:25.498122Z","shell.execute_reply":"2022-02-13T23:13:25.498732Z","shell.execute_reply.started":"2022-02-13T22:57:33.757348Z"},"papermill":{"duration":0.048131,"end_time":"2022-02-13T23:13:25.498903","exception":false,"start_time":"2022-02-13T23:13:25.450772","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Среднее значение ROC-AUC на кросс-валидации: {cv_scores_rf.mean()}\")","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:25.581644Z","iopub.status.busy":"2022-02-13T23:13:25.581004Z","iopub.status.idle":"2022-02-13T23:13:25.586312Z","shell.execute_reply":"2022-02-13T23:13:25.586817Z","shell.execute_reply.started":"2022-02-13T22:57:38.647385Z"},"papermill":{"duration":0.047354,"end_time":"2022-02-13T23:13:25.586984","exception":false,"start_time":"2022-02-13T23:13:25.539630","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## <left>Что есть в json файлах?","metadata":{"papermill":{"duration":0.038799,"end_time":"2022-02-13T23:13:25.664983","exception":false,"start_time":"2022-02-13T23:13:25.626184","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"Описание сырых данных можно найти в `train_matches.jsonl` и `test_matches.jsonl`. Каждый файл содержит одну запись для каждого матча в [JSON](https://en.wikipedia.org/wiki/JSON) формате. Его легко превратить в питоновский объект при помощи метода `json.loads`.","metadata":{"papermill":{"duration":0.038673,"end_time":"2022-02-13T23:13:25.742566","exception":false,"start_time":"2022-02-13T23:13:25.703893","status":"completed"},"tags":[]}},{"cell_type":"code","source":"with open(os.path.join(PATH_TO_DATA, \"train_raw_data.jsonl\")) as fin:\n    # прочтем 419 строку\n    for i in range(419):\n        line = fin.readline()\n    \n    # переведем JSON в питоновский словарь \n    match = json.loads(line)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:25.824572Z","iopub.status.busy":"2022-02-13T23:13:25.823929Z","iopub.status.idle":"2022-02-13T23:13:26.265063Z","shell.execute_reply":"2022-02-13T23:13:26.264479Z","shell.execute_reply.started":"2022-02-13T22:57:44.043572Z"},"papermill":{"duration":0.483742,"end_time":"2022-02-13T23:13:26.265242","exception":false,"start_time":"2022-02-13T23:13:25.781500","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"player = match[\"players\"][9]\nplayer[\"kills\"], player[\"deaths\"], player[\"assists\"]","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:26.348137Z","iopub.status.busy":"2022-02-13T23:13:26.347521Z","iopub.status.idle":"2022-02-13T23:13:26.352594Z","shell.execute_reply":"2022-02-13T23:13:26.353086Z","shell.execute_reply.started":"2022-02-13T22:57:45.161882Z"},"papermill":{"duration":0.047215,"end_time":"2022-02-13T23:13:26.353291","exception":false,"start_time":"2022-02-13T23:13:26.306076","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"KDA - может быть неплохим признаком, этот показатель считается как:\n    \n<center>$KDA = \\frac{K + A}{D}$","metadata":{"papermill":{"duration":0.038891,"end_time":"2022-02-13T23:13:26.431457","exception":false,"start_time":"2022-02-13T23:13:26.392566","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"Информация о количестве использованных способностей:","metadata":{"papermill":{"duration":0.039281,"end_time":"2022-02-13T23:13:26.509955","exception":false,"start_time":"2022-02-13T23:13:26.470674","status":"completed"},"tags":[]}},{"cell_type":"code","source":"player[\"ability_uses\"]","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:26.592332Z","iopub.status.busy":"2022-02-13T23:13:26.591649Z","iopub.status.idle":"2022-02-13T23:13:26.595957Z","shell.execute_reply":"2022-02-13T23:13:26.596503Z","shell.execute_reply.started":"2022-02-13T22:57:47.094707Z"},"papermill":{"duration":0.047359,"end_time":"2022-02-13T23:13:26.596669","exception":false,"start_time":"2022-02-13T23:13:26.549310","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i, player in enumerate(match[\"players\"]):\n    plt.plot(player[\"times\"], player[\"xp_t\"], label=str(i+1))\n\nplt.legend()\nplt.xlabel(\"Time, s\")\nplt.ylabel(\"XP\")\nplt.title(\"XP change for all players\");","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:26.687321Z","iopub.status.busy":"2022-02-13T23:13:26.686645Z","iopub.status.idle":"2022-02-13T23:13:27.133480Z","shell.execute_reply":"2022-02-13T23:13:27.132512Z","shell.execute_reply.started":"2022-02-13T22:57:52.249048Z"},"papermill":{"duration":0.497026,"end_time":"2022-02-13T23:13:27.133643","exception":false,"start_time":"2022-02-13T23:13:26.636617","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Сделаем чтение файла с сырыми данными и добавление новых признаков удобным","metadata":{"papermill":{"duration":0.042348,"end_time":"2022-02-13T23:13:27.219933","exception":false,"start_time":"2022-02-13T23:13:27.177585","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"В этот раз для чтение `json` файлов лучше использовать библиотеку `ujson`, иначе все будет слишком долго :(","metadata":{"papermill":{"duration":0.04339,"end_time":"2022-02-13T23:13:27.305740","exception":false,"start_time":"2022-02-13T23:13:27.262350","status":"completed"},"tags":[]}},{"cell_type":"code","source":"try:\n    import ujson as json\nexcept ModuleNotFoundError:\n    import json\n    print (\"Подумайте об установке ujson, чтобы работать с JSON объектами быстрее\")\n    \ntry:\n    from tqdm.notebook import tqdm\nexcept ModuleNotFoundError:\n    tqdm_notebook = lambda x: x\n    print (\"Подумайте об установке tqdm, чтобы следить за прогрессом\")\n\n    \ndef read_matches(matches_file, total_matches=31698, n_matches_to_read=None):\n    \"\"\"\n    Аргуент\n    -------\n    matches_file: JSON файл с сырыми данными\n    \n    Результат\n    ---------\n    Возвращает записи о каждом матче\n    \"\"\"\n    \n    if n_matches_to_read is None:\n        n_matches_to_read = total_matches\n        \n    c = 0\n    with open(matches_file) as fin:\n        for line in tqdm(fin, total=total_matches):\n            if c >= n_matches_to_read:\n                break\n            else:\n                c += 1\n                yield json.loads(line)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:27.399422Z","iopub.status.busy":"2022-02-13T23:13:27.393830Z","iopub.status.idle":"2022-02-13T23:13:27.407569Z","shell.execute_reply":"2022-02-13T23:13:27.406864Z","shell.execute_reply.started":"2022-02-13T22:57:54.823795Z"},"papermill":{"duration":0.059265,"end_time":"2022-02-13T23:13:27.407711","exception":false,"start_time":"2022-02-13T23:13:27.348446","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Чтение данных в цикле\n\nЧтение всех данных занимает 1-2 минуты, поэтому для начала можно попробовать следующее:\n\n1. Читать 10-50 игр\n2. Написать код для работы с этими JSON объектами\n3. Убедиться, что все работает\n4. Запустить код на всем датасете\n5. Сохранить результат в `pickle` файл, чтобы в следующий раз не переделывать все заново","metadata":{"papermill":{"duration":0.042266,"end_time":"2022-02-13T23:13:27.492942","exception":false,"start_time":"2022-02-13T23:13:27.450676","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"## <left>Feature engineering","metadata":{"papermill":{"duration":0.042432,"end_time":"2022-02-13T23:13:27.578084","exception":false,"start_time":"2022-02-13T23:13:27.535652","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"Напишем функцию, которая поможет нам легче добавлять новые признаки.","metadata":{"papermill":{"duration":0.043572,"end_time":"2022-02-13T23:13:27.664358","exception":false,"start_time":"2022-02-13T23:13:27.620786","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def add_new_features(df_features, matches_file):\n    \"\"\"\n    Аргуенты\n    -------\n    df_features: таблица с данными\n    matches_file: JSON файл с сырыми данными\n    \n    Результат\n    ---------\n    Добавляет новые признаки в таблицу\n    \"\"\"\n    \n    for match in read_matches(matches_file):\n        match_id_hash = match['match_id_hash']\n\n        # Посчитаем количество разрушенных вышек обеими командами\n        radiant_tower_kills = 0\n        dire_tower_kills = 0\n        for objective in match[\"objectives\"]:\n            if objective[\"type\"] == \"CHAT_MESSAGE_TOWER_KILL\":\n                if objective[\"team\"] == 2:\n                    radiant_tower_kills += 1\n                if objective[\"team\"] == 3:\n                    dire_tower_kills += 1\n\n        df_features.loc[match_id_hash, \"radiant_tower_kills\"] = radiant_tower_kills\n        df_features.loc[match_id_hash, \"dire_tower_kills\"] = dire_tower_kills\n        df_features.loc[match_id_hash, \"diff_tower_kills\"] = radiant_tower_kills - dire_tower_kills\n        \n        # ... (/¯◡ ‿ ◡)/¯☆*:・ﾟ добавляем новые признаки ...","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:27.756046Z","iopub.status.busy":"2022-02-13T23:13:27.755297Z","iopub.status.idle":"2022-02-13T23:13:27.762856Z","shell.execute_reply":"2022-02-13T23:13:27.762320Z","shell.execute_reply.started":"2022-02-13T22:57:58.423089Z"},"papermill":{"duration":0.054892,"end_time":"2022-02-13T23:13:27.763000","exception":false,"start_time":"2022-02-13T23:13:27.708108","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Скопируем таблицу с признаками\ndf_train_features_extended = df_train_features.copy()\n\n# Добавим новые\nadd_new_features(df_train_features_extended, \n                 os.path.join(PATH_TO_DATA, \n                              \"train_raw_data.jsonl\"))","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:13:27.854323Z","iopub.status.busy":"2022-02-13T23:13:27.853612Z","iopub.status.idle":"2022-02-13T23:15:05.115381Z","shell.execute_reply":"2022-02-13T23:15:05.114784Z","shell.execute_reply.started":"2022-02-13T22:58:02.081870Z"},"papermill":{"duration":97.309868,"end_time":"2022-02-13T23:15:05.115547","exception":false,"start_time":"2022-02-13T23:13:27.805679","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_features_extended.head()","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:15:05.205523Z","iopub.status.busy":"2022-02-13T23:15:05.204874Z","iopub.status.idle":"2022-02-13T23:15:05.227751Z","shell.execute_reply":"2022-02-13T23:15:05.227157Z","shell.execute_reply.started":"2022-02-13T23:00:24.658661Z"},"papermill":{"duration":0.06882,"end_time":"2022-02-13T23:15:05.227889","exception":false,"start_time":"2022-02-13T23:15:05.159069","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ncv_scores_base = cross_val_score(rf_model, X, y, cv=cv, scoring=\"roc_auc\", n_jobs=-1)\ncv_scores_extended = cross_val_score(rf_model, df_train_features_extended.values, y, \n                                     cv=cv, scoring=\"roc_auc\", n_jobs=-1)","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:15:05.320382Z","iopub.status.busy":"2022-02-13T23:15:05.319662Z","iopub.status.idle":"2022-02-13T23:16:41.094374Z","shell.execute_reply":"2022-02-13T23:16:41.095109Z","shell.execute_reply.started":"2022-02-13T23:00:39.716567Z"},"papermill":{"duration":95.822707,"end_time":"2022-02-13T23:16:41.095367","exception":false,"start_time":"2022-02-13T23:15:05.272660","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"ROC-AUC на кросс-валидации для базовых признаков: {cv_scores_base.mean()}\")\nprint(f\"ROC-AUC на кросс-валидации для новых признаков: {cv_scores_extended.mean()}\")","metadata":{"execution":{"iopub.execute_input":"2022-02-13T23:16:41.190890Z","iopub.status.busy":"2022-02-13T23:16:41.189960Z","iopub.status.idle":"2022-02-13T23:16:41.193041Z","shell.execute_reply":"2022-02-13T23:16:41.193577Z","shell.execute_reply.started":"2022-02-13T23:02:14.824997Z"},"papermill":{"duration":0.053312,"end_time":"2022-02-13T23:16:41.193746","exception":false,"start_time":"2022-02-13T23:16:41.140434","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Видно, что случайный лес стал работать немного лучше при добавлении новых признаков. A еще нужно, наверное, как-то по-умному закодировать категориальные признаки.","metadata":{"papermill":{"duration":0.044129,"end_time":"2022-02-13T23:16:41.282132","exception":false,"start_time":"2022-02-13T23:16:41.238003","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"Дальше дело за малым. Добавляйте новые признаки, пробуйте другие методы, которые мы изучили, а также что-то интересное, что мы не прошли. Удачи!","metadata":{"papermill":{"duration":0.043839,"end_time":"2022-02-13T23:16:41.370079","exception":false,"start_time":"2022-02-13T23:16:41.326240","status":"completed"},"tags":[]}}]}