{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Финальное задание" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Предметная область: Игра Dota 2\n", "\n", "[Dota 2](https://ru.wikipedia.org/wiki/Dota_2) — многопользовательская компьютерная игра жанра [MOBA](https://ru.wikipedia.org/wiki/MOBA). Игроки играют между собой матчи. В каждом матче участвует две команды, 5 человек в каждой. Одна команда играет за светлую сторону (The Radiant), другая — за тёмную (The Dire). Цель каждой команды — уничтожить главное здание базы противника (трон).\n", "\n", "Существуют [разные режимы игры](http://dota2.gamepedia.com/Game_modes/ru), мы будем рассматривать режим [Captain's Mode](http://dota2.gamepedia.com/Game_modes/ru#Captain.27s_Mode), в формате которого происходит большая часть киберспортивных мероприятий по Dota 2.\n", "\n", "### Как проходит матч\n", "\n", "#### 1. Игроки выбирают героев\n", "\n", "Всего в игре чуть более 100 различных героев (персонажей). В начале игры, команды в определенном порядке выбирают героев себе и запрещают выбирать определенных героев противнику (баны). Каждый игрок будет управлять одним героем, в рамках одного матча не может быть несколько одинаковых героев. Герои различаются между собой своими характеристиками и способностями. От комбинации выбранных героев во многом зависит успех команды.\n", "\n", "![](http://imgur.com/XFr4HYE.jpg)\n", "\n", "#### 2. Основная часть\n", "\n", "Игроки могут получать золото и опыт за убийство чужих героев или прочих юнитов. Накопленный опыт влияет на уровень героя, который в свою очередь позволяет улучшать способности. За накопленное золото игроки покупают предметы, которые улучшают характеристики героев или дают им новые способности.\n", "\n", "После смерти герой отправляется в \"таверну\" и возрождается только по прошествии некоторого времени, таким образом команда на некоторое время теряет игрока, однако игрок может досрочно выкупить героя из таверны за определенную сумму золота.\n", "\n", "В течение игры команды развивают своих героев, обороняют свою часть поля и нападают на вражескую.\n", "\n", "![](http://imgur.com/5b0SlQb.jpg)\n", "\n", "#### 3. Конец игры\n", "\n", "Игра заканчивается, когда одна из команд разрушет определенное число \"башен\" противника и уничтожает трон.\n", "\n", "![](http://imgur.com/Du79Kzf.jpg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Задача: предсказание победы по данным о первых 5 минутах игры\n", "\n", "По первым 5 минутам игры предсказать, какая из команд победит: Radiant или Dire?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Набор данных\n", "\n", "Набор данных с матчами записан в файле `matches.jsonlines.bz2`.\n", "В каталоге `dictionaries` приведены расшифровки идентификаторов, которые присутствуют в записях матчей." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Чтение информации о матчах\n", "\n", "Информация о матчах записана в сжатом текстовом файле `matches.jsonlines.bz2`, каждая строчка которого содержит объект в формате [JSON](https://ru.wikipedia.org/wiki/JSON). Запись в формате JSON преобразуется в python-объект при помощи стандартного модуля `json`. Пример чтения матчей:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import json\n", "import bz2\n", "\n", "with bz2.BZ2File('./matches.jsonlines.bz2') as matches_file:\n", " for line in matches_file:\n", " match = json.loads(line)\n", " \n", " # Обработка матча\n", " break" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Описание полей в записи матча\n", "\n", "```python\n", "{\n", " \"match_id\": 247, # идентификатор матча\n", " \"start_time\": 1430514316, # дата/время начала матча, unixtime\n", " \"lobby_type\": 0, # тип комнаты, в которой собираются игроки \n", " # (расшифровка в dictionaries/lobbies.csv)\n", " \n", " # стадия выбора героев\n", " \"picks_bans\": [\n", " {\n", " \"order\": 0, # порядковый номер действия\n", " \"is_pick\": false, # true если команда выбирает героя, false — если банит\n", " \"team\": 1, # команда, совершающая действие (0 — Radiant, 1 — Dire)\n", " \"hero_id\": 95 # герой, связанный с действием \n", " # (расшифровка в dictionaries/heroes.csv)\n", " }, \n", " ...\n", " ],\n", "\n", " # информация про каждого игрока, список ровно из 10 элементов\n", " # игроки с индексами от 0 до 4 — из команды Radiant, от 5 до 9 — Dire\n", " \"players\": [ \n", " { \n", " \n", " # герой игрока (расшифровка в dictionaries/heroes.csv)\n", " \"hero_id\": 67, \n", "\n", " # временные ряды (отсчеты указаны в поле \"times\")\n", " \"xp_t\": [0, 13, 115, 177, 335, ...], # опыт\n", " \"gold_t\": [0, 99, 243, 343, 499, ...], # золото + стоимость всех купленных вещей (net worth)\n", " \"lh_t\": [0, 0, 2, 2, 2, ...], # количество убитых юнитов (не героев) противника\n", "\n", " # список событий: улучшение способностей героя\n", " \"ability_upgrades\": [\n", " {\n", " \"time\": 51, # игровое время\n", " \"level\": 1, # уровень игрока, на котором произошло улучшение\n", " \"ability\": 5334 # способность, которая была улучшена \n", " # (расшифровка в dictionaries/abilities.csv)\n", " }, \n", " ...\n", " ],\n", "\n", " # список событий: убийства\n", " \"kills_log\": [\n", " {\n", " \"time\": 831, # игровое время\n", " \"player\": 7, # индекс игрока, чей герой был убит \n", " # (не заполнено, если был убит не герой)\n", " \"unit\": \"npc_dota_hero_viper\" # тип убитого юнита\n", " }, \n", " ...\n", " ],\n", "\n", " # список событий: покупка предметов\n", " \"purchase_log\": [\n", " {\n", " \"time\": -73, # игровое время\n", " # точка отсчета игрового времени (ноль) начинается через\n", " # несколько минут после фактического начала матча, поэтому\n", " # время некоторых событий может быть отрицательным\n", " \"item_id\": 44 # купленный предмер (расшифровка в dictionaries/items.csv)\n", " }, \n", " ...\n", " ]\n", "\n", " # список событий: выкуп героя из таверны\n", " \"buyback_log\": [\n", " {\"time\": 2507},\n", " ...\n", " ],\n", "\n", " # список событий: установка героем \"наблюдателей\", позволяющих команде \n", " # следить за чатью игрового поля на некотором расстоянии от точки установки\n", " \"obs_log\": [\n", " {\n", " \"time\": 1711, # игровое время установки\n", " \"xy\": [111, 130] # координаты игрового поля\n", " }, \n", " ...\n", " ],\n", " \"sen_log\": [], # аналогично полю obs_log, другой тип \"наблюдателя\"\n", "\n", " },\n", " ...\n", " ],\n", " \n", " # отсчеты игрового времени, в которые вычисляются значения временных рядов\n", " \"times\": [0, 60, 120, 180, ...],\n", "\n", " # ключевые события игры\n", " \"objectives\": [\n", " {\n", " \"time\": 198, # время события\n", " \"type\": \"firstblood\", # тип события\n", " \"player1\": 6, # параметры события, могут содержать\n", " \"player2\": 1 # индексы игроков (player), \n", " # номер команды (team, 0 — Radiant, 1 — Dire)\n", " }, \n", " {\n", " \"time\": 765, \n", " \"type\": \"tower_kill\", \n", " \"player\": 7, \n", " \"team\": 1\n", " }, \n", " ...\n", " ]\n", " \n", " # итог матча (отсутствует в тестовых матчах)\n", " \"finish\": {\n", " \"duration\": 2980, # длительность в секундах\n", " \"radiant_win\": false, # true, если победила команда Radiant\n", " \"tower_status_radiant\": 0, # состояние башен у команд к концу игры\n", " \"tower_status_dire\": 1972, # (см. описание битовой маски)\n", " \"barracks_status_dire\": 63, # состояние бараков у команд к концу игры\n", " \"barracks_status_radiant\": 0 # (см. описание битовой маски)\n", " }\n", "}\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Описание полей состояния башен и бараков\n", "\n", "Состояние башен к концу игры задается целым числом, закодировано в битах:\n", "\n", "```\n", "┌─┬─┬─┬─┬─────────────────────── Not used.\n", "│ │ │ │ │ ┌───────────────────── Ancient Bottom\n", "│ │ │ │ │ │ ┌─────────────────── Ancient Top\n", "│ │ │ │ │ │ │ ┌───────────────── Bottom Tier 3\n", "│ │ │ │ │ │ │ │ ┌─────────────── Bottom Tier 2\n", "│ │ │ │ │ │ │ │ │ ┌───────────── Bottom Tier 1\n", "│ │ │ │ │ │ │ │ │ │ ┌─────────── Middle Tier 3\n", "│ │ │ │ │ │ │ │ │ │ │ ┌───────── Middle Tier 2\n", "│ │ │ │ │ │ │ │ │ │ │ │ ┌─────── Middle Tier 1\n", "│ │ │ │ │ │ │ │ │ │ │ │ │ ┌───── Top Tier 3\n", "│ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌─── Top Tier 2\n", "│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌─ Top Tier 1\n", "│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │\n", "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n", "```\n", "\n", "Состояние бараков к концу игры закодировано в битах целого числа:\n", "\n", "```\n", "┌─┬───────────── Not used.\n", "│ │ ┌─────────── Bottom Ranged\n", "│ │ │ ┌───────── Bottom Melee\n", "│ │ │ │ ┌─────── Middle Ranged\n", "│ │ │ │ │ ┌───── Middle Melee\n", "│ │ │ │ │ │ ┌─── Top Ranged\n", "│ │ │ │ │ │ │ ┌─ Top Melee\n", "│ │ │ │ │ │ │ │\n", "0 0 0 0 0 0 0 0\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Извлечение признаков\n", "\n", "Скрипт extract_features.py производит извлечение признаков из известной информации о матче за первые 5 игровых минут, составляет из них таблицу. Таблица поможет вам быстрее сформировать матрицу объект-признак, вектор ответов и начать применять методы машинного обучения для решения поставленной задачи.\n", "\n", "Признаки, представленные в таблице `features.csv`, по мнению экспертов в предметной области являются наиболее важными для решения задачи предсказания победы команды. Тем не менее, не обязательно использовать эти признаки в исходном виде для применения методов машинного обучения — вы можете сделать новые признаки из имеющихся. Более того, признаки в файле `features.csv` содержат не всю информацию, известную про матч за первые 5 игровых минут. Вы можете использовать скрипт `extract_features.py` как пример и добавлять свои признаки для улучшения качества предсказания." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Пример чтения файла с признаками" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
start_timelobby_typer1_heror1_levelr1_xpr1_goldr1_lhr1_killsr1_deathsr1_items...dire_boots_countdire_ward_observer_countdire_ward_sentry_countdire_first_ward_timedurationradiant_wintower_status_radianttower_status_direbarracks_status_radiantbarracks_status_dire
match_id
0143019877071152098148920007...422-522874117960510
1143022034504241188103390112...431-52463119740631
21430227081733413191270220012...431132130001830063
3143026353112941779105614005...4202714590192020475063
414302822907134143110908108...330-162449041974363
\n", "

5 rows × 108 columns

\n", "
" ], "text/plain": [ " start_time lobby_type r1_hero r1_level r1_xp r1_gold r1_lh \\\n", "match_id \n", "0 1430198770 7 11 5 2098 1489 20 \n", "1 1430220345 0 42 4 1188 1033 9 \n", "2 1430227081 7 33 4 1319 1270 22 \n", "3 1430263531 1 29 4 1779 1056 14 \n", "4 1430282290 7 13 4 1431 1090 8 \n", "\n", " r1_kills r1_deaths r1_items ... \\\n", "match_id ... \n", "0 0 0 7 ... \n", "1 0 1 12 ... \n", "2 0 0 12 ... \n", "3 0 0 5 ... \n", "4 1 0 8 ... \n", "\n", " dire_boots_count dire_ward_observer_count dire_ward_sentry_count \\\n", "match_id \n", "0 4 2 2 \n", "1 4 3 1 \n", "2 4 3 1 \n", "3 4 2 0 \n", "4 3 3 0 \n", "\n", " dire_first_ward_time duration radiant_win tower_status_radiant \\\n", "match_id \n", "0 -52 2874 1 1796 \n", "1 -5 2463 1 1974 \n", "2 13 2130 0 0 \n", "3 27 1459 0 1920 \n", "4 -16 2449 0 4 \n", "\n", " tower_status_dire barracks_status_radiant barracks_status_dire \n", "match_id \n", "0 0 51 0 \n", "1 0 63 1 \n", "2 1830 0 63 \n", "3 2047 50 63 \n", "4 1974 3 63 \n", "\n", "[5 rows x 108 columns]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas\n", "features = pandas.read_csv('./features.csv', index_col='match_id')\n", "\n", "features.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Описание признаков в таблице\n", "\n", "- `match_id`: идентификатор матча в наборе данных\n", "- `start_time`: время начала матча (unixtime)\n", "- `lobby_type`: тип комнаты, в которой собираются игроки (расшифровка в `dictionaries/lobbies.csv`)\n", "- Наборы признаков для каждого игрока (игроки команды Radiant — префикс `rN`, Dire — `dN`):\n", " - `r1_hero`: герой игрока (расшифровка в dictionaries/heroes.csv)\n", " - `r1_level`: максимальный достигнутый уровень героя (за первые 5 игровых минут)\n", " - `r1_xp`: максимальный полученный опыт\n", " - `r1_gold`: достигнутая ценность героя\n", " - `r1_lh`: число убитых юнитов\n", " - `r1_kills`: число убитых игроков\n", " - `r1_deaths`: число смертей героя\n", " - `r1_items`: число купленных предметов\n", "- Признаки события \"первая кровь\" (first blood). Если событие \"первая кровь\" не успело произойти за первые 5 минут, то признаки принимают пропущенное значение\n", " - `first_blood_time`: игровое время первой крови\n", " - `first_blood_team`: команда, совершившая первую кровь (0 — Radiant, 1 — Dire)\n", " - `first_blood_player1`: игрок, причастный к событию\n", " - `first_blood_player2`: второй игрок, причастный к событию\n", "- Признаки для каждой команды (префиксы `radiant_` и `dire_`)\n", " - `radiant_bottle_time`: время первого приобретения командой предмета \"bottle\"\n", " - `radiant_courier_time`: время приобретения предмета \"courier\" \n", " - `radiant_flying_courier_time`: время приобретения предмета \"flying_courier\" \n", " - `radiant_tpscroll_count`: число предметов \"tpscroll\" за первые 5 минут\n", " - `radiant_boots_count`: число предметов \"boots\"\n", " - `radiant_ward_observer_count`: число предметов \"ward_observer\"\n", " - `radiant_ward_sentry_count`: число предметов \"ward_sentry\"\n", " - `radiant_first_ward_time`: время установки командой первого \"наблюдателя\", т.е. предмета, который позволяет видеть часть игрового поля\n", "- Итог матча (данные поля отсутствуют в тестовой выборке, поскольку содержат информацию, выходящую за пределы первых 5 минут матча)\n", " - `duration`: длительность\n", " - `radiant_win`: 1, если победила команда Radiant, 0 — иначе\n", " - Состояние башен и барраков к концу матча (см. описание полей набора данных)\n", " - `tower_status_radiant`\n", " - `tower_status_dire`\n", " - `barracks_status_radiant`\n", " - `barracks_status_dire`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Метрика качества\n", "\n", "В качестве метрики качества мы будем использовать площадь под ROC-кривой (AUC-ROC). Обратите внимание, что AUC-ROC — это метрика качества для алгоритма, выдающего оценки принадлежности первому классу. Оба алгоритма, которые будут использоваться в проекте — градиентный бустинг, и логистическая регрессия — умеют выдавать такие оценки. Для этого нужно получать предсказания с помощью функции predict_proba. Она возвращает два столбца: первый содержит оценки принадлежности нулевому классу, второй — первому классу. Вам нужны значения из второго столбца:\n", "```python\n", "pred = clf.predict_proba(X_test)[:, 1]\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Что попробовать?\n", "\n", "Вам необходимо провести описанные ниже четыре этапа исследования, написать по результатам каждого этапа небольшой отчет (ниже указаны вопросы, ответы на которые должны содержаться в отчете), и предоставить для ревью данный отчет и код, с помощью которого вы выполнили задание.\n", "\n", "**Обратите внимание:** высокое качество работы на кросс-валидации (близкое к 100%) — это в первую очередь повод задуматься о том, правильно ли вы обучаете модель. Возможно, вы заглядываете в будущее или настраиваетесь на неправильном наборе признаков." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Подход 1: градиентный бустинг\n", "\n", "1. Считайте таблицу с признаками из файла features.csv с помощью кода, приведенного выше. Удалите признаки, связанные с итогами матча (они помечены в описании данных как отсутствующие в тестовой выборке).\n", "2. Проверьте выборку на наличие пропусков. Замените их на нули с помощью функции fillna(), или воспользуйтесь более грамотным подходом.\n", "3. Забудьте, что в выборке есть категориальные признаки, и попробуйте обучить градиентный бустинг над деревьями из scikit-learn на имеющейся матрице \"объекты-признаки\".\n", "4. Попробуйте сделать one-hot-кодирование категориальных признаков. Возможно, пригодятся и другие способы их преобразования — например, счетчики.\n", "5. Попробуйте XGBoost. Позволяет ли он добиться более высокого качества?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Подход 2: логистическая регрессия\n", "\n", "\n", "**Важно:** не забывайте, что линейные алгоритмы чувствительны к масштабу признаков! Может пригодиться sklearn.preprocessing.StandartScaler.\n", "\n", "1. Попробуйте логистическую регрессию (sklearn.linear_model.LogisticRegression). Как вариант — обучите модель с помощью Vowpal Wabbit.\n", "2. Среди признаков в выборке есть 11 категориальных: lobby_type и r1_hero, r2_hero, ..., r5_hero, d1_hero, d2_hero, ..., d5_hero. Попробуйте удалить их из выборки, или сделать one-hot-кодирование, или воспользоваться для них счетчиками.\n", "3. Признаки rM_hero и dM_hero показывают, какие именно герои играли за каждую команду. Это важные признаки — герои имеют разные характеристики, и некоторые из них выигрывают чаще, чем другие. Воспользуйтесь подходом \"мешок слов\" для кодирования информации о героях. Пусть всего в игре имеет N различных героев. Сформируем N признаков, при этом i-й будет равен нулю, если i-й герой не участвовал в матче; единице, если i-й герой играл за команду Radiant; минус единице, если i-й герой играл за команду Dire. Ниже вы можете найти код, который выполняет данное преобразование. Добавьте полученные признаки к числовым, проверьте качество логистической регрессии.\n", "4. Ничто не мешает попробовать на этих признаках и градиентный бустинг.\n", "\n", "##### Код для формирования \"мешка слов\" по героям\n", "```python\n", "# N — количество различных героев в выборке\n", "X_pick = np.zeros((data.shape[0], N))\n", "\n", "for i, match_id in enumerate(data.index):\n", " for p in xrange(5):\n", " X_pick[i, data.ix[match_id, 'r%d_hero' % (p+1)]-1] = 1\n", " X_pick[i, data.ix[match_id, 'd%d_hero' % (p+1)]-1] = -1\n", "for i, match_id in enumerate(data.index):\n", " for p in xrange(5):\n", " X_pick[i, data.ix[match_id, 'r%d_hero' % (p+1)]-1] = 1\n", " X_pick[i, data.ix[match_id, 'd%d_hero' % (p+1)]-1] = -1\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Проверка финальной модели\n", "\n", "\n", "Для всех матчей из тестового набора предскажите вероятность победы Radiant, запишите предсказания в CSV файл с колонками `match_id` (идентификатор матча) и `radiant_win` — предсказанная вероятность. Файл с предсказаниями должен выглядеть примерно следующим образом:\n", "\n", "```\n", "match_id,radiant_win\n", "1,0.51997370502\n", "4,0.51997370502\n", "15,0.51997370502\n", "...\n", "```\n", "\n", "Отправьте решение на Kaggle." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Что еще попробовать?\n", "\n", "Разумеется, можно попробовать еще очень много разных идей, которые помогут вам получить еще более высокий результат на kaggle. Вот лишь несколько возможных вариантов:\n", "1. Про каждого из игроков есть достаточно много показателей: максимальный опыт, число смертей и т.д. (см. список выше). Можно попробовать просуммировать или усредних их, получив агрегированные показатели для всей команды.\n", "2. В сырых данных (файл matches.jsonlines.bz2) содержится очень много информации, которую мы пока не использовали. Вы можете, например, составить \"мешки слов\" для покупок различных предметов (то есть кодировать информацию о том, сколько раз каждая команда покупала тот или иной предмет). Обратите внимание, что при этом вы можете получить слишком большое количество признаков, для которых может иметь смысл сделать понижение размерности с помощью метода главных компонент.\n", "3. Можно сформировать признаки про изменения способностей героев в течение матча (ability_upgrades)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Про задачу и финальное задание\n", "\n", "\n", "\n", "#### Где взяли данные?\n", "\n", "Набор данных был сделан на основе выгрузки [YASP 3.5 Million Data Dump](http://academictorrents.com/details/5c5deeb6cfe1c944044367d2e7465fd8bd2f4acf) реплеев матчей Dota 2 с сайта [yasp.co](http://yasp.co/). За выгрузку огромное спасибо Albert Cui and Howard Chung and Nicholas Hanson-Holtry. Лицензия на выгрузку: CC BY-SA 4.0.\n", "\n", "#### Как сформировали выборку?\n", "\n", "Оригинальная выгрузка матчей была очищена, в предложенном наборе присутствуют матчи:\n", " - сыгранные с 2015-05-01 до 2015-12-17\n", " - длительностью не менее 15 минут\n", " - убраны матчи с неполной информацией (например: отсутвует информация про игроков)\n", "\n", "Из всего датасета 15% случайных записей были выделены в тестовое множество.\n", "\n", "Для того чтобы размотивировать участников соревнования на Kaggle занимать высокие места читерскими методами (например, скачав оригинальный набор данных и подсмотрев ответы на тестовом множестве матчей), мы произвели минимальную обфускацию данных, т.е. немного запутали датасет:\n", " - поменяли идентификаторы матчей\n", " - время начала каждого матча сдвинули на значение случайной величины, нормально распределенной со стандартным отклонением в 1 сутки" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }