From 0c2d6f12b18da9191ca9a30d8a90ecc79395f59d Mon Sep 17 00:00:00 2001 From: MariaLuk <144106192+MariaLuk@users.noreply.github.com> Date: Mon, 8 Apr 2024 22:25:06 +0700 Subject: [PATCH] Add Notebook with Dota winer prediction --- HW6/Code/HW6_dota_pred_lukina.ipynb | 1 + 1 file changed, 1 insertion(+) create mode 100644 HW6/Code/HW6_dota_pred_lukina.ipynb diff --git a/HW6/Code/HW6_dota_pred_lukina.ipynb b/HW6/Code/HW6_dota_pred_lukina.ipynb new file mode 100644 index 0000000..a0a6325 --- /dev/null +++ b/HW6/Code/HW6_dota_pred_lukina.ipynb @@ -0,0 +1 @@ +{"cells":[{"cell_type":"code","execution_count":null,"metadata":{"id":"uhLqnaui04BG","trusted":true},"outputs":[],"source":["\n","# IMPORTANT: RUN THIS CELL IN ORDER TO IMPORT YOUR KAGGLE DATA SOURCES\n","# TO THE CORRECT LOCATION (/kaggle/input) IN YOUR NOTEBOOK,\n","# THEN FEEL FREE TO DELETE THIS CELL.\n","# NOTE: THIS NOTEBOOK ENVIRONMENT DIFFERS FROM KAGGLE'S PYTHON\n","# ENVIRONMENT SO THERE MAY BE MISSING LIBRARIES USED BY YOUR\n","# NOTEBOOK.\n","\n","import os\n","import sys\n","from tempfile import NamedTemporaryFile\n","from urllib.request import urlopen\n","from urllib.parse import unquote, urlparse\n","from urllib.error import HTTPError\n","from zipfile import ZipFile\n","import tarfile\n","import shutil\n","\n","CHUNK_SIZE = 40960\n","DATA_SOURCE_MAPPING = 'bi-ml-competition-2023:https%3A%2F%2Fstorage.googleapis.com%2Fkaggle-competitions-data%2Fkaggle-v2%2F49431%2F5228520%2Fbundle%2Farchive.zip%3FX-Goog-Algorithm%3DGOOG4-RSA-SHA256%26X-Goog-Credential%3Dgcp-kaggle-com%2540kaggle-161607.iam.gserviceaccount.com%252F20240311%252Fauto%252Fstorage%252Fgoog4_request%26X-Goog-Date%3D20240311T140336Z%26X-Goog-Expires%3D259200%26X-Goog-SignedHeaders%3Dhost%26X-Goog-Signature%3D0439a6647118ef93fac3b8d2f72135cfd433fa2ff3d0992a9bb24360bf7e359ce6346e0acb775939df8562e3d5ce4efb67bf65176232bd7293a8398aa85ebc4751da621a3cacef50ff5146703ffdff98d954899ee2baa8cf917f55500c0917d2f532b56b4417aa1ec82004552736d80fdc551ea663815efdb030039529fb4bbe7f4cfc7a9d859ef8ec998a3d5e8792b96eedf04e359fa2cc87bc5a691514009a2b428db00d65db322390551a6651afabef44689b1d40bfd1670fa5ff224f377ce4821e5f3b4f1a39b14007b4a62c1855d6e2f7348d17370c1dca2a4a17aa19cfeb7286b7427a95c9ca95d1190483075c33f893db9fc8526f59e53fee57f34673'\n","\n","KAGGLE_INPUT_PATH='/kaggle/input'\n","KAGGLE_WORKING_PATH='/kaggle/working'\n","KAGGLE_SYMLINK='kaggle'\n","\n","!umount /kaggle/input/ 2> /dev/null\n","shutil.rmtree('/kaggle/input', ignore_errors=True)\n","os.makedirs(KAGGLE_INPUT_PATH, 0o777, exist_ok=True)\n","os.makedirs(KAGGLE_WORKING_PATH, 0o777, exist_ok=True)\n","\n","try:\n"," os.symlink(KAGGLE_INPUT_PATH, os.path.join(\"..\", 'input'), target_is_directory=True)\n","except FileExistsError:\n"," pass\n","try:\n"," os.symlink(KAGGLE_WORKING_PATH, os.path.join(\"..\", 'working'), target_is_directory=True)\n","except FileExistsError:\n"," pass\n","\n","for data_source_mapping in DATA_SOURCE_MAPPING.split(','):\n"," directory, download_url_encoded = data_source_mapping.split(':')\n"," download_url = unquote(download_url_encoded)\n"," filename = urlparse(download_url).path\n"," destination_path = os.path.join(KAGGLE_INPUT_PATH, directory)\n"," try:\n"," with urlopen(download_url) as fileres, NamedTemporaryFile() as tfile:\n"," total_length = fileres.headers['content-length']\n"," print(f'Downloading {directory}, {total_length} bytes compressed')\n"," dl = 0\n"," data = fileres.read(CHUNK_SIZE)\n"," while len(data) > 0:\n"," dl += len(data)\n"," tfile.write(data)\n"," done = int(50 * dl / int(total_length))\n"," sys.stdout.write(f\"\\r[{'=' * done}{' ' * (50-done)}] {dl} bytes downloaded\")\n"," sys.stdout.flush()\n"," data = fileres.read(CHUNK_SIZE)\n"," if filename.endswith('.zip'):\n"," with ZipFile(tfile) as zfile:\n"," zfile.extractall(destination_path)\n"," else:\n"," with tarfile.open(tfile.name) as tarfile:\n"," tarfile.extractall(destination_path)\n"," print(f'\\nDownloaded and uncompressed: {directory}')\n"," except HTTPError as e:\n"," print(f'Failed to load (likely expired) {download_url} to path {destination_path}')\n"," continue\n"," except OSError as e:\n"," print(f'Failed to load {download_url} to path {destination_path}')\n"," continue\n","\n","print('Data source import complete.')\n"]},{"cell_type":"markdown","metadata":{"id":"HfkYZ3AN04BJ","papermill":{"duration":0.044486,"end_time":"2022-02-13T23:28:22.423626","exception":false,"start_time":"2022-02-13T23:28:22.37914","status":"completed"},"tags":[]},"source":["#
Предсказание победителя в Dota 2\n","
"]},{"cell_type":"markdown","metadata":{"id":"svZh95LZ04BK","papermill":{"duration":0.042953,"end_time":"2022-02-13T23:28:22.51031","exception":false,"start_time":"2022-02-13T23:28:22.467357","status":"completed"},"tags":[]},"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)"]},{"cell_type":"markdown","metadata":{"id":"l9Ks3PrA04BK","papermill":{"duration":0.042954,"end_time":"2022-02-13T23:28:22.59833","exception":false,"start_time":"2022-02-13T23:28:22.555376","status":"completed"},"tags":[]},"source":["#### [Оригинальная статья](https://arxiv.org/pdf/2106.01782.pdf)\n"," \n","### Начало\n","\n","Посмотрим на готовые признаки и сделаем первую посылку.\n","\n","1. [Описание данных](#Описание-данных)\n","2. [Описание признаков](#Описание-признаков)\n","3. [Наша первая модель](#Наша-первая-модель)\n","4. [Посылка](#Посылка)\n","\n","### Первые шаги на пути в датасайенс\n","\n","5. [Кросс-валидация](#Кросс-валидация)\n","6. [Что есть в json файлах?](#Что-есть-в-json-файлах?)\n","7. [Feature engineering](#Feature-engineering)"]},{"cell_type":"markdown","metadata":{"id":"KXWlzyH104BL","papermill":{"duration":0.045141,"end_time":"2022-02-13T23:28:22.688388","exception":false,"start_time":"2022-02-13T23:28:22.643247","status":"completed"},"tags":[]},"source":["### Импорты"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"OAN8tYgU04BL","papermill":{"duration":1.526998,"end_time":"2022-02-13T23:28:24.258607","exception":false,"start_time":"2022-02-13T23:28:22.731609","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["import os\n","import json\n","import pandas as pd\n","import datetime\n","import warnings\n","import seaborn as sns\n","import matplotlib.pyplot as plt\n","import numpy as np\n","import matplotlib.pyplot as plt\n","import seaborn as sns\n","import random\n","import math\n","import xgboost\n","import lightgbm\n","import catboost\n","\n","#from math import comb\n","from sklearn.model_selection import train_test_split, ShuffleSplit, cross_val_score\n","from sklearn.ensemble import RandomForestClassifier\n","from sklearn.metrics import roc_auc_score, accuracy_score\n","from matplotlib.colors import ListedColormap\n","from scipy.stats import pearsonr\n","from itertools import combinations\n","from sklearn.base import BaseEstimator\n","from sklearn import datasets\n","from sklearn.ensemble import (RandomForestClassifier,\n"," ExtraTreesClassifier,\n"," VotingClassifier)\n","from sklearn.tree import (DecisionTreeRegressor,\n"," DecisionTreeClassifier)\n","from sklearn.neighbors import KNeighborsClassifier\n","from sklearn.svm import SVC\n","from sklearn.linear_model import LogisticRegression\n","from sklearn.naive_bayes import GaussianNB\n","from sklearn.model_selection import cross_val_score\n","\n","%matplotlib inline"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"gLjgaTtL04BL","papermill":{"duration":0.051811,"end_time":"2022-02-13T23:28:24.354647","exception":false,"start_time":"2022-02-13T23:28:24.302836","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["SEED = 10801\n","sns.set_style(style=\"whitegrid\")\n","plt.rcParams[\"figure.figsize\"] = 12, 8\n","warnings.filterwarnings(\"ignore\")"]},{"cell_type":"markdown","metadata":{"id":"X4WIvaOF04BL","papermill":{"duration":0.042707,"end_time":"2022-02-13T23:28:24.441767","exception":false,"start_time":"2022-02-13T23:28:24.39906","status":"completed"},"tags":[]},"source":["## Описание данных\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`: результаты тренировочных игр"]},{"cell_type":"markdown","metadata":{"id":"6X7awb9s04BM","papermill":{"duration":0.042685,"end_time":"2022-02-13T23:28:24.527617","exception":false,"start_time":"2022-02-13T23:28:24.484932","status":"completed"},"tags":[]},"source":["## Описание признаков\n"," \n","Набор простых признаков, описывающих игроков и команды в целом"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"X-ENehsH04BM","papermill":{"duration":1.383765,"end_time":"2022-02-13T23:28:25.955912","exception":false,"start_time":"2022-02-13T23:28:24.572147","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["PATH_TO_DATA = \"/kaggle/input/copy-of-23-24-ml/\"\n","\n","df_train_features = pd.read_csv(os.path.join(PATH_TO_DATA,\n"," \"train_data.csv\"),\n"," index_col=\"match_id_hash\")\n","df_train_targets = pd.read_csv(os.path.join(PATH_TO_DATA,\n"," \"train_targets.csv\"),\n"," index_col=\"match_id_hash\")"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"nGy8OmUE04BM","papermill":{"duration":0.055919,"end_time":"2022-02-13T23:28:26.055573","exception":false,"start_time":"2022-02-13T23:28:25.999654","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["df_train_features.shape"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"SD7rpkYg04BM","papermill":{"duration":0.073611,"end_time":"2022-02-13T23:28:26.173793","exception":false,"start_time":"2022-02-13T23:28:26.100182","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["df_train_features.head()"]},{"cell_type":"markdown","metadata":{"id":"UTQCmaAM04BM","papermill":{"duration":0.043707,"end_time":"2022-02-13T23:28:26.26179","exception":false,"start_time":"2022-02-13T23:28:26.218083","status":"completed"},"tags":[]},"source":["Имеем ~32 тысячи наблюдений, каждое из которых характеризуется уникальным `match_id_hash` (захэшированное id матча), и 245 признаков. `game_time` показывает момент времени, в который получены эти данные. То есть по сути это не длительность самого матча, а например, его середина, таким образом, в итоге мы сможем получить модель, которая будет предсказывать вероятность победы каждой из команд в течение матча (хорошо подходит для букмекеров)."]},{"cell_type":"markdown","metadata":{"id":"u8t4RnnV04BM","papermill":{"duration":0.043619,"end_time":"2022-02-13T23:28:26.350788","exception":false,"start_time":"2022-02-13T23:28:26.307169","status":"completed"},"tags":[]},"source":["Нас интересует поле `radiant_win` (так называется одна из команд, вторая - dire). Остальные колоки здесь по сути получены из \"будущего\" и есть только для тренировочных данных, поэтому на них можно просто посмотреть)."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"8NR2kzUI04BN","papermill":{"duration":0.059594,"end_time":"2022-02-13T23:28:26.454584","exception":false,"start_time":"2022-02-13T23:28:26.39499","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["df_train_targets.head()"]},{"cell_type":"markdown","metadata":{"id":"pNypQlel04BN","papermill":{"duration":0.046788,"end_time":"2022-02-13T23:28:26.547845","exception":false,"start_time":"2022-02-13T23:28:26.501057","status":"completed"},"tags":[]},"source":["## Наша первая модель"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"KtNJF78e04BN","papermill":{"duration":0.078234,"end_time":"2022-02-13T23:28:26.672769","exception":false,"start_time":"2022-02-13T23:28:26.594535","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["X = df_train_features.values\n","y = df_train_targets[\"radiant_win\"].values.astype(\"int8\")"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"tuKrE8cu04BN","papermill":{"duration":0.152481,"end_time":"2022-02-13T23:28:26.871414","exception":false,"start_time":"2022-02-13T23:28:26.718933","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["X_train, X_valid, y_train, y_valid = train_test_split(X, y,\n"," test_size=0.3,\n"," random_state=SEED)"]},{"cell_type":"markdown","metadata":{"id":"CMeUr4xR04BO","papermill":{"duration":0.046122,"end_time":"2022-02-13T23:28:37.825794","exception":false,"start_time":"2022-02-13T23:28:37.779672","status":"completed"},"tags":[]},"source":["## Кросс-валидация"]},{"cell_type":"markdown","metadata":{"id":"uabPsoTI04BO","papermill":{"duration":0.047147,"end_time":"2022-02-13T23:28:37.919675","exception":false,"start_time":"2022-02-13T23:28:37.872528","status":"completed"},"tags":[]},"source":["Во многих случаях кросс-валидация оказывается лучше простого разбиения на test и train. Воспользуемся `ShuffleSplit` чтобы создать 5 70%/30% наборов данных."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"xl5vFaaY04BO","papermill":{"duration":0.054303,"end_time":"2022-02-13T23:28:38.021177","exception":false,"start_time":"2022-02-13T23:28:37.966874","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=SEED)"]},{"cell_type":"markdown","metadata":{"id":"Y5qLxRfG04BO","papermill":{"duration":0.04757,"end_time":"2022-02-13T23:29:33.025145","exception":false,"start_time":"2022-02-13T23:29:32.977575","status":"completed"},"tags":[]},"source":["## Что есть в json файлах?"]},{"cell_type":"markdown","metadata":{"id":"3OaNn5wS04BO","papermill":{"duration":0.048776,"end_time":"2022-02-13T23:29:33.122475","exception":false,"start_time":"2022-02-13T23:29:33.073699","status":"completed"},"tags":[]},"source":["Описание сырых данных можно найти в `train_matches.jsonl` и `test_matches.jsonl`. Каждый файл содержит одну запись для каждого матча в [JSON](https://en.wikipedia.org/wiki/JSON) формате. Его легко превратить в питоновский объект при помощи метода `json.loads`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"suiICQsv04BO","papermill":{"duration":0.514659,"end_time":"2022-02-13T23:29:33.685074","exception":false,"start_time":"2022-02-13T23:29:33.170415","status":"completed"},"tags":[],"trusted":true},"outputs":[],"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)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"DPdciVYq04BP","papermill":{"duration":0.057975,"end_time":"2022-02-13T23:29:33.792713","exception":false,"start_time":"2022-02-13T23:29:33.734738","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["player = match[\"players\"][9]\n","player[\"kills\"], player[\"deaths\"], player[\"assists\"]"]},{"cell_type":"markdown","metadata":{"id":"am-oibE204BP","papermill":{"duration":0.047795,"end_time":"2022-02-13T23:29:33.888962","exception":false,"start_time":"2022-02-13T23:29:33.841167","status":"completed"},"tags":[]},"source":["KDA - может быть неплохим признаком, этот показатель считается как:\n"," \n","
$KDA = \\frac{K + A}{D}$"]},{"cell_type":"markdown","metadata":{"id":"iSNh43qe04BW","papermill":{"duration":0.047726,"end_time":"2022-02-13T23:29:33.984909","exception":false,"start_time":"2022-02-13T23:29:33.937183","status":"completed"},"tags":[]},"source":["Информация о количестве использованных способностей:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"YdFfusiX04BW","papermill":{"duration":0.058567,"end_time":"2022-02-13T23:29:34.091868","exception":false,"start_time":"2022-02-13T23:29:34.033301","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["player[\"ability_uses\"]"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"I6zjkRpj04BW","papermill":{"duration":0.497079,"end_time":"2022-02-13T23:29:34.637657","exception":false,"start_time":"2022-02-13T23:29:34.140578","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["for i, player in enumerate(match[\"players\"]):\n"," plt.plot(player[\"times\"], player[\"xp_t\"], label=str(i+1))\n","\n","plt.legend()\n","plt.xlabel(\"Time, s\")\n","plt.ylabel(\"XP\")\n","plt.title(\"XP change for all players\");"]},{"cell_type":"markdown","metadata":{"id":"242fnSSE04BW","papermill":{"duration":0.052753,"end_time":"2022-02-13T23:29:34.742623","exception":false,"start_time":"2022-02-13T23:29:34.68987","status":"completed"},"tags":[]},"source":["#### Сделаем чтение файла с сырыми данными и добавление новых признаков удобным"]},{"cell_type":"markdown","metadata":{"id":"FXhodgk504BW","papermill":{"duration":0.051195,"end_time":"2022-02-13T23:29:34.845611","exception":false,"start_time":"2022-02-13T23:29:34.794416","status":"completed"},"tags":[]},"source":["В этот раз для чтение `json` файлов лучше использовать библиотеку `ujson`, иначе все будет слишком долго :("]},{"cell_type":"code","execution_count":null,"metadata":{"id":"AdMM16A504BW","papermill":{"duration":0.069503,"end_time":"2022-02-13T23:29:34.966941","exception":false,"start_time":"2022-02-13T23:29:34.897438","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["try:\n"," import ujson as json\n","except ModuleNotFoundError:\n"," import json\n"," print (\"Подумайте об установке ujson, чтобы работать с JSON объектами быстрее\")\n","\n","try:\n"," from tqdm.notebook import tqdm\n","except ModuleNotFoundError:\n"," tqdm_notebook = lambda x: x\n"," print (\"Подумайте об установке tqdm, чтобы следить за прогрессом\")\n","\n","\n","def 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)"]},{"cell_type":"markdown","metadata":{"id":"vhF8YjWa04BX","papermill":{"duration":0.052275,"end_time":"2022-02-13T23:29:35.07086","exception":false,"start_time":"2022-02-13T23:29:35.018585","status":"completed"},"tags":[]},"source":["#### Чтение данных в цикле\n","\n","Чтение всех данных занимает 1-2 минуты, поэтому для начала можно попробовать следующее:\n","\n","1. Читать 10-50 игр\n","2. Написать код для работы с этими JSON объектами\n","3. Убедиться, что все работает\n","4. Запустить код на всем датасете\n","5. Сохранить результат в `pickle` файл, чтобы в следующий раз не переделывать все заново"]},{"cell_type":"markdown","metadata":{"id":"tJFzB58604BX","papermill":{"duration":0.051565,"end_time":"2022-02-13T23:29:35.175139","exception":false,"start_time":"2022-02-13T23:29:35.123574","status":"completed"},"tags":[]},"source":["## Feature engineering"]},{"cell_type":"markdown","metadata":{"id":"PvzVyd8p04BX","papermill":{"duration":0.051315,"end_time":"2022-02-13T23:29:35.278664","exception":false,"start_time":"2022-02-13T23:29:35.227349","status":"completed"},"tags":[]},"source":["Напишем функцию, которая поможет нам легче добавлять новые признаки."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"XJiUranL04BX","papermill":{"duration":0.063047,"end_time":"2022-02-13T23:29:35.393977","exception":false,"start_time":"2022-02-13T23:29:35.33093","status":"completed"},"tags":[],"trusted":true},"outputs":[],"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"," # ... (/¯◡ ‿ ◡)/¯☆*:・゚ добавляем новые признаки ..."]},{"cell_type":"markdown","metadata":{},"source":["Если мы создаем новые признаки, нам нужно добавлять их в тренировочные и тестовые данные, делаю новые датафреймы для test_features и train_features"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"B3wPM_v904BX","papermill":{"duration":100.250385,"end_time":"2022-02-13T23:31:15.696073","exception":false,"start_time":"2022-02-13T23:29:35.445688","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["# Скопируем таблицу с признаками\n","df_train_features_extended = df_train_features.copy()\n","\n","# Добавим новые\n","add_new_features(df_train_features_extended,\n"," os.path.join(PATH_TO_DATA,\n"," \"train_raw_data.jsonl\"))\n","\n","# повторим для тестовых\n","df_test_features = pd.read_csv(os.path.join(PATH_TO_DATA,\n"," \"test_data.csv\"),\n"," index_col=\"match_id_hash\")\n","\n","df_test_features_extended = df_test_features.copy()\n","\n","# Добавим новые\n","add_new_features(df_test_features_extended,\n"," os.path.join(PATH_TO_DATA,\n"," \"test_raw_data.jsonl\"))\n"]},{"cell_type":"raw","metadata":{"execution":{"iopub.execute_input":"2024-04-05T04:32:29.682091Z","iopub.status.busy":"2024-04-05T04:32:29.681688Z","iopub.status.idle":"2024-04-05T04:32:29.734770Z","shell.execute_reply":"2024-04-05T04:32:29.733595Z","shell.execute_reply.started":"2024-04-05T04:32:29.682062Z"}},"source":["Проверяем размеры, видим, что все хорошо, длина нужная, количество столбцов увеличилось"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["print(df_test_features_extended.shape)\n","print(df_test_features.shape)"]},{"cell_type":"markdown","metadata":{},"source":["Разделим их тоже на train/valid"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["X_new = df_train_features_extended.values\n","X_train_n, X_valid_n, y_train_n, y_valid_n = train_test_split(X_new, y,\n"," test_size=0.3,\n"," random_state=SEED)\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"FWEFR-1w04BX","papermill":{"duration":0.08167,"end_time":"2022-02-13T23:31:15.83029","exception":false,"start_time":"2022-02-13T23:31:15.74862","status":"completed"},"tags":[],"trusted":true},"outputs":[],"source":["df_train_features_extended.head()"]},{"cell_type":"markdown","metadata":{},"source":["Я решила пойти таким путем. Потестировать разные модели с базовыми настройками и посмотреть, какой получается ROC AUC. И выбрать перспективных кандидатов. Сначала буду работать с базовыми данными без новых признаков.\n"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["dt = DecisionTreeClassifier(random_state=SEED, max_depth=10, min_samples_leaf=10)\n","rf = RandomForestClassifier(n_estimators=50, random_state=SEED)\n","etc = ExtraTreesClassifier(random_state=SEED)\n","knn = KNeighborsClassifier(n_neighbors=5, weights=\"distance\")\n","svc_lin = SVC(kernel='linear', probability=True, random_state=SEED)\n","svc_rbf = SVC(kernel='rbf', probability=True, random_state=SEED)\n","cat = catboost.CatBoostClassifier(verbose=0, random_seed=SEED)\n","lgbm = lightgbm.LGBMClassifier(random_state=SEED)\n","lgbm_rf = lightgbm.LGBMClassifier(boosting_type=\"rf\", bagging_freq=1, bagging_fraction=0.7, random_state=SEED)\n","xgb = xgboost.XGBClassifier(random_state=SEED)\n","xgb_rf = xgboost.XGBRFClassifier(random_state=SEED)\n","lr = LogisticRegression(solver='liblinear', max_iter=10000)\n","nb = GaussianNB()\n","\n","base_models = [(\"DT\", dt), (\"RF\", rf), \n"," (\"ETC\", etc), (\"KNN\", knn), \n"," (\"SVC_LIN\", svc_lin), (\"SVC_RBF\", svc_rbf), \n"," (\"CAT\", cat), (\"LGBM\", lgbm), \n"," (\"LGBM_RF\", lgbm_rf), (\"XGB\", xgb), \n"," (\"XGB_RF\", xgb_rf), (\"LR\", lr), (\"NB\", nb)]"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["#random.seed(SEED)\n","#np.random.seed(SEED)"]},{"cell_type":"markdown","metadata":{},"source":["Посмотрим рядом на все результаты"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["results = []\n","\n","for model in [dt, rf, cat, etc, knn, xgb, lgbm, xgb_rf, lgbm_rf, lr, nb]: \n"," scores = cross_val_score(model, X_train, y_train, cv=5, scoring=\"roc_auc\")\n"," results.append(f\"{model.__class__.__name__}: {scores.mean()}\")\n"," print(f\"{model.__class__.__name__}: {scores.mean()}\")"]},{"cell_type":"markdown","metadata":{},"source":["Еще раз напечатаю без Warnings"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["for r in results:\n"," print(r)"]},{"cell_type":"markdown","metadata":{},"source":["Интересненько, с базовыми параметрами лучше всего проявили себе логистическая регрессия,немного неожиданно, вроде самый базовый вариант классификации. Но круто! \n","Второй кандидат - CatBoost. попробую их отдельно, и еще собрать вместе"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["my_models = [ (\"CAT\", cat), (\"LR\", lr)]\n","voting_soft = VotingClassifier(estimators=my_models, voting = 'soft')"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","scores = cross_val_score(voting_soft, X_train, y_train, cv=3, scoring=\"roc_auc\")\n","print(f\"{voting_soft.__class__.__name__}: {scores.mean()}\")\n"]},{"cell_type":"markdown","metadata":{},"source":["Score 0.80866, это выше, чем то что было для отдельных методов. Попробуем на тестовых данных. "]},{"cell_type":"markdown","metadata":{},"source":["Сделаем предсказание для тестовых данных, используя логистическую регрессию"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","lr.fit(X_train, y_train)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["%%time\n","y_pred = lr.predict_proba(X_valid)[:, 1]\n","valid_score = roc_auc_score(y_valid, y_pred)\n","print(\"ROC-AUC score на отложенной части:\", valid_score)"]},{"cell_type":"markdown","metadata":{},"source":["Это значение выше, чем baseline (сохраняем в CSV файл и отправляем)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","cat.fit(X_train, y_train)\n","y_pred = cat.predict_proba(X_valid)[:, 1]\n","valid_score = roc_auc_score(y_valid, y_pred)\n","print(\"ROC-AUC score на отложенной части:\", valid_score)"]},{"cell_type":"markdown","metadata":{},"source":["0,79898, неплохо, тоже выше, чем baseline. И voiting_soft теперь посмотрим на тестовых"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","voting_soft.fit(X_train, y_train)\n","y_pred = voting_soft.predict_proba(X_valid)[:, 1]\n","valid_score = roc_auc_score(y_valid, y_pred)\n","print(\"ROC-AUC score на отложенной части voting_soft:\", valid_score)"]},{"cell_type":"markdown","metadata":{},"source":["Немного получше, чем просто логистическая регрессия. Отправляю файл с эти результатов в соревнование и продолжаю страдать дальше"]},{"cell_type":"markdown","metadata":{},"source":["Попробуем с новыми признаками lr и cat"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=SEED)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","cv_scores_extended = cross_val_score(lr, df_train_features_extended.values, y,\n"," cv=cv, scoring=\"roc_auc\", n_jobs=-1)\n","print(f\"ROC-AUC на кросс-валидации для новых признаков Logistic regression: {cv_scores_extended.mean()}\")"]},{"cell_type":"markdown","metadata":{},"source":["Стало чуть получше"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","cv_scores_extended = cross_val_score(cat, df_train_features_extended.values, y,\n"," cv=cv, scoring=\"roc_auc\", n_jobs=-1)\n","print(f\"ROC-AUC на кросс-валидации для новых признаков CatBoost: {cv_scores_extended.mean()}\")"]},{"cell_type":"markdown","metadata":{},"source":["Да, тоже получше немного, чем CatBoost на исходных данных"]},{"cell_type":"markdown","metadata":{},"source":["Ну посмотрим теперь на ансамбль из логистической регрессии и catboost"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","cv_scores_extended = cross_val_score(voting_soft, df_train_features_extended.values, y,\n"," cv=cv, scoring=\"roc_auc\", n_jobs=-1)\n","print(f\"ROC-AUC на кросс-валидации для новых признаков LogisticRegression + CatBoost: {cv_scores_extended.mean()}\")"]},{"cell_type":"markdown","metadata":{},"source":["0.8105, пока это лучшее, что я видела. Я обучила модель, рассчитата ROC_AUC для тестовых данных, отправила в соревноание и решила посмотреть на данных с добавленными признаками. Попробуем посчитать на тестовых c новыми признаками\n","P.S. Тут я сохраняла разные csv файлы, оставила последний вариант, регрессия + catboost на расширенных данных"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","voting_soft.fit(X_train_n, y_train_n)\n","y_pred = voting_soft.predict_proba(X_valid_n)[:, 1]\n","valid_score = roc_auc_score(y_valid_n, y_pred)\n","print(\"ROC-AUC score на отложенной части voting_soft:\", valid_score)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["#df_test_features = pd.read_csv(os.path.join(PATH_TO_DATA, \"test_data.csv\"),\n","# index_col=\"match_id_hash\")\n","\n","X_test = df_test_features_extended.values\n","y_test_pred = voting_soft.predict_proba(X_test)[:, 1]"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["df_submission = pd.DataFrame({\"radiant_win_prob\": y_test_pred},\n"," index=df_test_features_extended.index)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["submission_filename = \"submission_lr_cat_ext.csv\"\n","df_submission.to_csv(submission_filename)\n","print(\"Файл посылки сохранен, как: {}\".format(submission_filename))"]},{"cell_type":"markdown","metadata":{},"source":["Попробуем подобрать гиперпараметры для логистической регрессии и Catboost и собрать из них ансамбль.\n","Disclaimer: тут было очень много неудач, долго, больно, не эффективно.\n","\n","// я уже делала это только с 'C' и 'max_iter', получилось, что наилучшие 0.1 и 100,a solver был равен = liblinear оставлю их и запущу только с ними плюс 'solver' варируем"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["%%time\n","from sklearn.model_selection import GridSearchCV\n","lr = LogisticRegression()\n","param_grid = {'C': [1], 'max_iter': [100], 'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga']} \n","grid_search = GridSearchCV(lr, param_grid, scoring='roc_auc', cv=cv)\n","grid_search.fit(X_train, y_train)\n","print(\"Лучшие параметры lr:\", grid_search.best_params_)"]},{"cell_type":"markdown","metadata":{},"source":["Получилось, что 'saga' лучше, пересчитываем с новой lr моделью"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["%%time\n","lr = LogisticRegression(solver='saga', max_iter=100, C=1)\n","lr.fit(X_train, y_train)\n","y_pred = lr.predict_proba(X_valid)[:, 1]\n","valid_score = roc_auc_score(y_valid, y_pred)\n","print(\"ROC-AUC score на отложенной части:\", valid_score)\n","#print(\"ROC AUC на тестовом наборе:\", roc_auc_score(y_valid, grid_search.predict_proba(X_test)[:, 1]))"]},{"cell_type":"markdown","metadata":{},"source":["И на данных с новыми признаками. Пока это лучший результат. Отправляю этот результат в соревнование"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["%%time\n","my_models = [ (\"CAT\", cat), (\"LR\", lr)]\n","vsbest = VotingClassifier(estimators=my_models, voting = 'soft')\n","vsbest.fit(X_train_n, y_train_n)\n","y_pred = vsbest.predict_proba(X_valid_n)[:, 1]\n","valid_score = roc_auc_score(y_valid_n, y_pred)\n","print(\"ROC-AUC score на отложенной части voting_soft c оптимизированной Lr и Cat:\", valid_score)"]},{"cell_type":"markdown","metadata":{},"source":[" я оставлю часть подбора параметров для catboost, но они не привели к улучшению результата. А считалось все очень долго и порой вылетало за 12 часов, поэтому я тут подбирала \"группами\". Поэтому предыдущую модель можно считать финальной, и этот результат стал лучшим из моих."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["X_test = df_test_features_extended.values\n","y_test_pred = vsbest.predict_proba(X_test)[:, 1]"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["df_submission = pd.DataFrame({\"radiant_win_prob\": y_test_pred},\n"," index=df_test_features.index)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["submission_filename = \"submission_lr_opt_cat_ext.csv\"\n","df_submission.to_csv(submission_filename)\n","print(\"Файл посылки сохранен, как: {}\".format(submission_filename))"]},{"cell_type":"markdown","metadata":{},"source":["Вот что получалось с подбором параметров для Catboost"]},{"cell_type":"markdown","metadata":{},"source":["Лучшие параметры catboost: {'bootstrap_type': 'MVS', 'depth': 8, 'iterations': 100, 'l2_leaf_reg': 7, 'learning_rate': 0.05}, но на финальное значение ROC AUC это влияло не особо, получалось даже чуть хуже дефолтных."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["cat = catboost.CatBoostClassifier( verbose = 0)\n","param_grid = {\n"," 'learning_rate': [ 0.01, 0.05],\n"," 'depth': [8, 10],\n"," 'l2_leaf_reg': [7, 9],\n"," 'iterations': [100],\n"," 'bootstrap_type': ['Bayesian', 'MVS'] }\n","\n","grid_search = GridSearchCV(cat, param_grid, scoring='roc_auc', cv=cv)\n","grid_search.fit(X_train, y_train)\n","\n","\n","print(\"Лучшие параметры catboost:\", grid_search.best_params_)"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["# Получить результаты GridSearch\n","results = grid_search.cv_results_\n","\n","# Вывод значений roc_auc для всех параметров\n","means = results['mean_test_score']\n","stds = results['std_test_score']\n","params = results['params']\n","\n","for mean, std, params in zip(means, stds, params):\n"," print(\"Среднее значение ROC AUC: %0.3f (±%0.3f) для параметров %r\" % (mean, std * 2, params))"]},{"cell_type":"code","execution_count":null,"metadata":{"trusted":true},"outputs":[],"source":["cat = catboost.CatBoostClassifier(verbose = 0, iterations = 1000, learning_rate = 0.1, depth = 8, bootstrap_type = 'MVS', l2_leaf_reg = 7)\n","cat.fit(X_train, y_train)\n","y_pred = cat.predict_proba(X_valid)[:, 1]\n","valid_score = roc_auc_score(y_valid, y_pred)\n","print(\"ROC-AUC score на отложенной части cat_optimized:\", valid_score)"]},{"cell_type":"markdown","metadata":{},"source":["Вроде, чуть-чуть повыше, проверяю на тестовых эти данные."]},{"cell_type":"markdown","metadata":{},"source":["После часов и ночей этих подсчетов, у меня не получилось как-то улучшить модель для catboost дефолтные параметры, внезапно оказались лучше, подбираемых мной."]},{"cell_type":"markdown","metadata":{},"source":["В итоге лучшей оказалась модель, обученная на данных с доп признаками, оптимизированной логистичекой регрессией + CatBoost с дефолтными параметрами. "]}],"metadata":{"colab":{"provenance":[{"file_id":"https://storage.googleapis.com/kaggle-colab-exported-notebooks/baseline-9b91a0e3-79c0-41c6-ac3a-cb52246ce672.ipynb?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=gcp-kaggle-com%40kaggle-161607.iam.gserviceaccount.com/20240311/auto/storage/goog4_request&X-Goog-Date=20240311T140337Z&X-Goog-Expires=259200&X-Goog-SignedHeaders=host&X-Goog-Signature=9adfbe2ed572d128d069f327e194f24edf589c05e0471d65dbe890f137537652e98ce8d45363ad09b50780386f7f9ce451a1418af036777740866d889b5a82c00cb2de001da77f3044dcd45776805322668e799ae76d802eff0b02cfc78880732646e5dc7f85b135ef4f32cecd03031d2c3887a526c76d73dcf8c4edc286ea02e2960525ae8ab88d4d01728f36759e8c56e8c9a643a43450c97d4f281676c0377e125cfb7e9b6c0c60dc31f054b4051904181f226948934accb169a985ab794aba4ea32212e06cf24e65184ae3a0a2c97c79036bde593a77ee487b90acb43a659ca29e64389ccb5bea19ec912326920fa6955a391e5012a5054efb9b61ea8e64","timestamp":1710165846930}]},"kaggle":{"accelerator":"none","dataSources":[{"databundleVersionId":7919275,"sourceId":72284,"sourceType":"competition"}],"dockerImageVersionId":30664,"isGpuEnabled":false,"isInternetEnabled":true,"language":"python","sourceType":"notebook"},"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.10.13"}},"nbformat":4,"nbformat_minor":4}