Giter Site home page Giter Site logo

shadmltasks's Introduction

{
 "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": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>start_time</th>\n",
       "      <th>lobby_type</th>\n",
       "      <th>r1_hero</th>\n",
       "      <th>r1_level</th>\n",
       "      <th>r1_xp</th>\n",
       "      <th>r1_gold</th>\n",
       "      <th>r1_lh</th>\n",
       "      <th>r1_kills</th>\n",
       "      <th>r1_deaths</th>\n",
       "      <th>r1_items</th>\n",
       "      <th>...</th>\n",
       "      <th>dire_boots_count</th>\n",
       "      <th>dire_ward_observer_count</th>\n",
       "      <th>dire_ward_sentry_count</th>\n",
       "      <th>dire_first_ward_time</th>\n",
       "      <th>duration</th>\n",
       "      <th>radiant_win</th>\n",
       "      <th>tower_status_radiant</th>\n",
       "      <th>tower_status_dire</th>\n",
       "      <th>barracks_status_radiant</th>\n",
       "      <th>barracks_status_dire</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>match_id</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1430198770</td>\n",
       "      <td>7</td>\n",
       "      <td>11</td>\n",
       "      <td>5</td>\n",
       "      <td>2098</td>\n",
       "      <td>1489</td>\n",
       "      <td>20</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "      <td>...</td>\n",
       "      <td>4</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>-52</td>\n",
       "      <td>2874</td>\n",
       "      <td>1</td>\n",
       "      <td>1796</td>\n",
       "      <td>0</td>\n",
       "      <td>51</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1430220345</td>\n",
       "      <td>0</td>\n",
       "      <td>42</td>\n",
       "      <td>4</td>\n",
       "      <td>1188</td>\n",
       "      <td>1033</td>\n",
       "      <td>9</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>...</td>\n",
       "      <td>4</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>-5</td>\n",
       "      <td>2463</td>\n",
       "      <td>1</td>\n",
       "      <td>1974</td>\n",
       "      <td>0</td>\n",
       "      <td>63</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1430227081</td>\n",
       "      <td>7</td>\n",
       "      <td>33</td>\n",
       "      <td>4</td>\n",
       "      <td>1319</td>\n",
       "      <td>1270</td>\n",
       "      <td>22</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>12</td>\n",
       "      <td>...</td>\n",
       "      <td>4</td>\n",
       "      <td>3</td>\n",
       "      <td>1</td>\n",
       "      <td>13</td>\n",
       "      <td>2130</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1830</td>\n",
       "      <td>0</td>\n",
       "      <td>63</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1430263531</td>\n",
       "      <td>1</td>\n",
       "      <td>29</td>\n",
       "      <td>4</td>\n",
       "      <td>1779</td>\n",
       "      <td>1056</td>\n",
       "      <td>14</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "      <td>...</td>\n",
       "      <td>4</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>27</td>\n",
       "      <td>1459</td>\n",
       "      <td>0</td>\n",
       "      <td>1920</td>\n",
       "      <td>2047</td>\n",
       "      <td>50</td>\n",
       "      <td>63</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1430282290</td>\n",
       "      <td>7</td>\n",
       "      <td>13</td>\n",
       "      <td>4</td>\n",
       "      <td>1431</td>\n",
       "      <td>1090</td>\n",
       "      <td>8</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>8</td>\n",
       "      <td>...</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>-16</td>\n",
       "      <td>2449</td>\n",
       "      <td>0</td>\n",
       "      <td>4</td>\n",
       "      <td>1974</td>\n",
       "      <td>3</td>\n",
       "      <td>63</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 108 columns</p>\n",
       "</div>"
      ],
      "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",
    "\n",
    "1. Считайте таблицу с признаками из файла features.csv с помощью кода, приведенного выше. Удалите признаки, связанные с итогами матча (они помечены в описании данных как отсутствующие в тестовой выборке).\n",
    "2. Проверьте выборку на наличие пропусков с помощью функции count(), которая для каждого столбца показывает число заполненных значений. Много ли пропусков в данных? Запишите названия признаков, имеющих пропуски, и попробуйте для любых двух из них дать обоснование, почему их значения могут быть пропущены.\n",
    "3. Замените пропуски на нули с помощью функции fillna(). На самом деле этот способ является предпочтительным для логистической регрессии, поскольку он позволит пропущенному значению не вносить никакого вклада в предсказание. Для деревьев часто лучшим вариантом оказывается замена пропуска на очень большое или очень маленькое значение — в этом случае при построении разбиения вершины можно будет отправить объекты с пропусками в отдельную ветвь дерева. Также есть и другие подходы — например, замена пропуска на среднее значение признака. Мы не требуем этого в задании, но при желании попробуйте разные подходы к обработке пропусков и сравните их между собой.\n",
    "3. Какой столбец содержит целевую переменную? Запишите его название.\n",
    "4. Забудем, что в выборке есть категориальные признаки, и попробуем обучить градиентный бустинг над деревьями на имеющейся матрице \"объекты-признаки\". Зафиксируйте генератор разбиений для кросс-валидации по 5 блокам (KFold), не забудьте перемешать при этом выборку (shuffle=True), поскольку данные в таблице отсортированы по времени, и без перемешивания можно столкнуться с нежелательными эффектами при оценивании качества. Оцените качество градиентного бустинга (GradientBoostingClassifier) с помощью данной кросс-валидации, попробуйте при этом разное количество деревьев (как минимум протестируйте следующие значения для количества деревьев: 10, 20, 30). Долго ли настраивались классификаторы? Достигнут ли оптимум на испытанных значениях параметра n_estimators, или же качество, скорее всего, продолжит расти при дальнейшем его увеличении?\n",
    "\n",
    "##### Что указать в отчете\n",
    "В отчете по данному этапу вы должны ответить на следующие вопросы:\n",
    "1. Какие признаки имеют пропуски среди своих значений? Что могут означать пропуски в этих признаках (ответьте на этот вопрос для двух любых признаков)?\n",
    "2. Как называется столбец, содержащий целевую переменную?\n",
    "3. Как долго проводилась кросс-валидация для градиентного бустинга с 30 деревьями? Инструкцию по измерению времени можно найти ниже по тексту. Какое качество при этом получилось? Напомним, что в данном задании мы используем метрику качества AUC-ROC.\n",
    "4. Имеет ли смысл использовать больше 30 деревьев в градиентном бустинге? Что бы вы предложили делать, чтобы ускорить его обучение при увеличении количества деревьев?\n",
    "\n",
    "\n",
    "##### Рекомендации и советы\n",
    "\n",
    "- Если все работает очень медлено:\n",
    "   - Используйте для обучения и кросс-валидации не всю выборку, а некоторое ее подмножество — например, половину объектов. Подмножество лучше всего брать случайным, а не формировать его из первых m объектов.\n",
    "   - Попробуйте упростить модель — например, уменьшить глубину деревьев в градиентом бустинге (max_depth).\n",
    "   \n",
    "##### Измерение времени работы кода\n",
    "```python\n",
    "import time\n",
    "import datetime\n",
    "\n",
    "start_time = datetime.datetime.now()\n",
    "\n",
    "time.sleep(3) # вместо этой строчки разместить замеряемый код\n",
    "\n",
    "print 'Time elapsed:', datetime.datetime.now() - start_time\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Подход 2: логистическая регрессия\n",
    "\n",
    "Линейные методы работают гораздо быстрее композиций деревьев, поэтому кажется разумным воспользоваться именно ими для ускорения анализа данных. Одним из наиболее распространенных методов для классификации является логистическая регрессия.\n",
    "\n",
    "**Важно:** не забывайте, что линейные алгоритмы чувствительны к масштабу признаков! Может пригодиться sklearn.preprocessing.StandartScaler.\n",
    "\n",
    "1. Оцените качество логистической регрессии (sklearn.linear_model.LogisticRegression с L2-регуляризацией) с помощью кросс-валидации по той же схеме, которая использовалась для градиентного бустинга. Подберите при этом лучший параметр регуляризации (C). Какое наилучшее качество у вас получилось? Как оно соотносится с качеством градиентного бустинга? Чем вы можете объяснить эту разницу? Быстрее ли работает логистическая регрессия по сравнению с градиентным бустингом?\n",
    "2. Среди признаков в выборке есть категориальные, которые мы использовали как числовые, что вряд ли является хорошей идеей. Категориальных признаков в этой задаче одиннадцать: lobby_type и r1_hero, r2_hero, ..., r5_hero, d1_hero, d2_hero, ..., d5_hero. Уберите их из выборки, и проведите кросс-валидацию для логистической регрессии на новой выборке с подбором лучшего параметра регуляризации. Изменилось ли качество? Чем вы можете это объяснить?\n",
    "3. На предыдущем шаге мы исключили из выборки признаки rM_hero и dM_hero, которые показывают, какие именно герои играли за каждую команду. Это важные признаки — герои имеют разные характеристики, и некоторые из них выигрывают чаще, чем другие. Выясните из данных, сколько различных идентификаторов героев существует в данной игре (вам может пригодиться фукнция unique или value_counts).\n",
    "4. Воспользуемся подходом \"мешок слов\" для кодирования информации о героях. Пусть всего в игре имеет N различных героев. Сформируем N признаков, при этом i-й будет равен нулю, если i-й герой не участвовал в матче; единице, если i-й герой играл за команду Radiant; минус единице, если i-й герой играл за команду Dire. Ниже вы можете найти код, который выполняет данной преобразование. Добавьте полученные признаки к числовым, которые вы использовали во втором пункте данного этапа.\n",
    "5. Проведите кросс-валидацию для логистической регрессии на новой выборке с подбором лучшего параметра регуляризации. Какое получилось качество? Улучшилось ли оно? Чем вы можете это объяснить?\n",
    "6. Постройте предсказания вероятностей победы команды Radiant для тестовой выборки с помощью лучшей из изученных моделей (лучшей с точки зрения AUC-ROC на кросс-валидации). Убедитесь, что предсказанные вероятности адекватные — находятся на отрезке [0, 1], не совпадают между собой (т.е. что модель не получилась константной).\n",
    "\n",
    "##### Что указать в отчете\n",
    "В отчете по данному этапу вы должны ответить на следующие вопросы:\n",
    "1. Какое качество получилось у логистической регрессии над всеми исходными признаками? Как оно соотносится с качеством градиентного бустинга? Чем вы можете объяснить эту разницу? Быстрее ли работает логистическая регрессия по сравнению с градиентным бустингом?\n",
    "2. Как влияет на качество логистической регрессии удаление категориальных признаков (укажите новое значение метрики качества)? Чем вы можете объяснить это изменение?\n",
    "3. Сколько различных идентификаторов героев существует в данной игре?\n",
    "4. Какое получилось качество при добавлении \"мешка слов\" по героям? Улучшилось ли оно по сравнению с предыдущим вариантом? Чем вы можете это объяснить?\n",
    "5. Какое минимальное и максимальное значение прогноза на тестовой выборке получилось у лучшего из алгоритмов?\n",
    "\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",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Проверка финальной модели\n",
    "\n",
    "После того как вы провели все эксперименты и выбрали лучшую модель, можете проверить ее качество на тестовых матчах. Выборка тестовых матчей собрана в файле `matches_test.jsonlines.bz2`. В отличие от основного набора матчей, в тестовых матчах есть только та информация, которая известна на момент первых 5 игровых минут, результат матча — неизвестен. Таблица признаков для тестовых матчей — `features_test.csv`.\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 в соревнование: Dota 2: Win Probability Prediction.\n",
    "\n",
    "Ссылка на соревнование: [Dota 2: Win Probability Prediction](https://kaggle.com/join/coursera_ml_dota2_contest)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Что еще попробовать?\n",
    "\n",
    "Разумеется, можно попробовать еще очень много разных идей, которые помогут вам получить еще более высокий результат на kaggle. Вот лишь несколько возможных вариантов:\n",
    "1. Про каждого из игроков есть достаточно много показателей: максимальный опыт, число смертей и т.д. (см. список выше). Можно попробовать просуммировать или усредних их, получив агрегированные показатели для всей команды.\n",
    "2. В сырых данных (файл matches.jsonlines.bz2) содержится очень много информации, которую мы пока не использовали. Вы можете, например, составить \"мешки слов\" для покупок различных предметов (то есть кодировать информацию о том, сколько раз каждая команда покупала тот или иной предмет). Обратите внимание, что при этом вы можете получить слишком большое количество признаков, для которых может иметь смысл сделать понижение размерности с помощью метода главных компонент.\n",
    "3. Можно сформировать признаки про изменения способностей героев в течение матча (ability_upgrades).\n",
    "4. В этом задании используются только градиентный бустинг и логистическая регрессия — но ведь мы изучали и другие модели! Можно попробовать метод k ближайших соседей, SVM, случайный лес и так далее."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Про задачу и финальное задание\n",
    "\n",
    "#### Почему именно такая задача?\n",
    "\n",
    "- Публикация реальных данных из индустриальных задач — очень смелый шаг для компании. Мало кто (даже Яндекс) может на такое пойти. Гораздо проще (а порой и интереснее) воспользоваться данными из открытых источников.\n",
    "- Публичные датасеты из интернета для решения реальных бизнес-задач мало пригодны, собственно поэтому они и лежат в открытом доступе.\n",
    "- Мы предпочли сделать игрушечную задачу на реальных данных, вместо реальной задачи на игрушечных данных.\n",
    "- Задача прогнозирования победы — игрушечная, но вот лишь небольшой перечень реальных задач, на которые она похожа:\n",
    "    - предсказания вероятности покупки услуги клиентом банка\n",
    "    - предсказание вероятности оттока клиента к другому поставщику услуг\n",
    "    - ... (подумайте над другими примерами)\n",
    "\n",
    "#### Задание слишком простое. Что еще можно сделать?\n",
    "\n",
    "Ответить на вопрос: какое минимальное число минут матча необходимо знать, для того чтобы в 80% матчей верно угадывать победившую сторону? А с точностью 90%? Дайте свой ответ на этот вопрос и докажите что такой точности действительно можно достичь, построив модель и качественно провалидировав ее. Насколько матчи в игре Dota 2 предсказуемы?\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
}

shadmltasks's People

Contributors

magzhan-abdibay avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.