От задачи к первому эксперименту

ЧерновикМатериалы дорабатываются и будут дополняться.

Автор: Алексей Толстиков

Чему научимся

  • Отличать признаки объекта от ответа, который нужно предсказать.
  • Строить простое начальное решение только по обучающим данным.
  • Измерять ошибку числового прогноза и долю верных ответов.

Время и подготовка: ориентир 6–7 часов с практикой. Нужны списки и функции Python, среднее значение и доли; перед работой с большими CSV познакомимся с двумя командами pandas.

План занятия

  1. Превратим задачу кружка в задачу машинного обучения.
  2. Сделаем первый прогноз и проверим его на новых заказах.
  3. Изменим вид ответа и способ проверки.

Что будем предсказывать

В школьном кружке один 3D-принтер, и на него выстраивается очередь заказов. Перед печатью новой фигурки нужно оценить, на сколько минут она займёт принтер: так можно спланировать его загрузку и сказать следующему участнику, когда он сможет начать. До запуска известны высота фигурки и число разных цветов пластика в её проекте. Принтер печатает слоями одинаковой толщины, поэтому число слоёв пропорционально высоте.

В таблице есть одиннадцать уже выполненных заказов и пять новых, для которых время печати пока неизвестно. Знак «?» означает ответ, который нам предстоит предсказать. Все числа придуманы для занятия: они помогают разобрать эксперимент, но не описывают работу настоящего принтера.

Таблица 1 — Учебные заказы и разделение данных
Заказ Высота фигурки, см Число цветов Время печати, мин Часть данных
p01 3 1 20 обучение
p02 4 2 22 обучение
p03 5 1 24 обучение
p04 6 3 26 обучение
p05 10 2 58 обучение
p06 3 2 18 обучение
p07 4 2 21 обучение
p08 6 1 27 обучение
p09 7 2 28 обучение
p10 8 3 30 обучение
p11 9 2 34 обучение
p12 3 1 ? проверка
p13 5 3 ? проверка
p14 6 2 ? проверка
p15 7 2 ? проверка
p16 9 3 ? проверка

Объект — один заказ. Признаки — известные до печати свойства фигурки: высота и число цветов. Целевая переменная, или ответ, — время печати. Модель получает признаки и выдаёт прогноз.

Задача предсказания числа называется регрессией. Если спрашивать «успеет ли фигурка напечататься за 30 минут?», ответами станут «да» и «нет». Задача выбора одного из таких ответов называется классификацией. Вид задачи определяется ответом, а не тем, что в таблице есть числа.

Использование сведений, раскрывающих ответ (фактическое время окончания печати), называется утечкой данных. Номер заказа нужен для различения строк, но сам по себе не объясняет длительность печати. Одного числа цветов тоже недостаточно, чтобы узнать, сколько раз принтеру придётся переключаться между ними.

Как устроить проверку

Первые одиннадцать заказов составляют обучающую часть, или train. По ним подбираем модель. Последние пять — тестовая часть, или test. Правильные времена для них есть в подготовленном учебном наборе, но при выборе модели мы их скрываем. Откроем ответы только после того, как зафиксируем правило прогноза.

Обучающие и тестовые заказы — разные наблюдения, хотя пары их доступных признаков иногда совпадают: например, у p01 и p12 одна высота и одно число цветов. Совпадающие признаки не гарантируют одинаковое время печати, потому что на него влияют и недоступные нам параметры. Если же скопировать целый заказ вместе с ответом в обе части, проверка станет легче: модель встретит уже знакомый пример.

Разобранный пример простого решения

Начнём с модели, которая всем заказам предсказывает одно время. Она пока не использует ни высоту, ни число цветов. Такое простое начальное решение называют baseline. Следующие модели должны показать, чем они полезнее этого отправного результата.

Возьмём медиану обучающих времён. Для нечётного числа значений медиана — число посередине после сортировки (для чётного числа элементов обычно берут среднее значение центральных элементов). Упорядоченные времена равны 18, 20, 21, 22, 24, 26, 27, 28, 30, 34, 58 минутам. Шестое из одиннадцати значений — 26; среднее равно 28. Долгий заказ на 58 минут сдвинул среднее вверх.

Сначала используем одиннадцать известных ответов, затем фиксируем постоянный прогноз; ответы пяти новых заказов остаются скрытыми до проверки.
Рисунок 1 — Порядок обучения и проверки постоянного прогноза

Чтобы оценить числовой прогноз, посчитаем средний модуль ошибки, или MAE (mean absolute error). Для каждого заказа берём разницу между прогнозом и ответом без знака, складываем разницы и делим на число заказов:

MAE⁡=1n∑i=1n∣y^i−yi∣.\operatorname{MAE}=\frac{1}{n}\sum_{i=1}^{n}|\widehat y_i-y_i|.

Здесь nn — число заказов, yiy_i — настоящее время, y^i\widehat y_i — прогноз. Ошибка измеряется в минутах, как и время печати.

На обучающих данных сумма модулей ошибок прогноза 26 равна 72 минутам, а MAE — 7211≈6,55\frac{72}{11}\approx6{,}55 минуты. Для прогноза 28, равного среднему, сумма модулей ошибок составляет 76 минут, MAE — около 6,91 минуты. Среди постоянных прогнозов медиана даёт наименьшую MAE (вы можете доказать это утверждение в качестве упражнения); среднее подходит для другой цели — уменьшения суммы квадратов ошибок (это утверждение мы докажем в одной из следующих тем).

Теперь прогноз 26 минут зафиксирован. Для учебной проверки мы знаем правильные времена новых заказов; до этого шага они были скрыты. Открываем их и сравниваем с прогнозом:

Таблица 2 — Ошибки постоянного прогноза времени печати
Заказ Настоящее время Прогноз Модуль ошибки
p12 19 26 7
p13 25 26 1
p14 29 26 3
p15 35 26 9
p16 40 26 14

MAE на новых заказах равна 7+1+3+9+145=6,8\frac{7+1+3+9+14}{5}=6{,}8 минуты. Это средняя ошибка на пяти придуманных примерах. Она не обещает ошибку ровно 6,8 минуты для следующего заказа.

Повторим эксперимент на Python

Понадобится только стандартная библиотека Python. Разделение данных уже задано; новые значения для проверки не участвуют в выборе прогноза.

from statistics import mean, median

train_features = [
    (3, 1), (4, 2), (5, 1), (6, 3), (10, 2), (3, 2),
    (4, 2), (6, 1), (7, 2), (8, 3), (9, 2),
]
train_minutes = [20, 22, 24, 26, 58, 18, 21, 27, 28, 30, 34]
test_features = [(3, 1), (5, 3), (6, 2), (7, 2), (9, 3)]

# Пары признаков нужны для будущих моделей; baseline пока их не использует.
prediction = median(train_minutes)
assert prediction == 26
assert mean(train_minutes) == 28

Теперь, когда прогноз выбран, открываем правильные времена тестовых заказов. Функция принимает два списка одинаковой длины: ответы и прогнозы. Проверка длины нужна, чтобы не потерять заказы при попарном обходе.

test_minutes = [19, 25, 29, 35, 40]

def mae(answers, predictions):
    if not answers or len(answers) != len(predictions):
        raise ValueError("Нужны непустые списки одинаковой длины")
    errors = [abs(p - y) for y, p in zip(answers, predictions)]
    return sum(errors) / len(errors)

train_predictions = [prediction] * len(train_minutes)
test_predictions = [prediction] * len(test_minutes)

assert round(mae(train_minutes, train_predictions), 2) == 6.55
assert mae(test_minutes, test_predictions) == 6.8
print("Прогноз:", prediction, "минут")
print("MAE на новых заказах:", mae(test_minutes, test_predictions))

Если нужен ответ да или нет

Вернёмся к вопросу «успеет ли заказ за 30 минут?». Из одиннадцати обучающих заказов девять успели. Простейшее правило для этой задачи — всегда отвечать «да»: это самый частый класс в обучении.

Теперь подходит accuracy (точность) — доля верных ответов. На тесте ответы равны «да», «да», «да», «нет», «нет». Наше правило угадывает три из пяти: accuracy равна 35\frac{3}{5}, или 60 %. MAE и accuracy отвечают на разные вопросы: насколько промахнулись в минутах и как часто правильно выбрали класс.

from collections import Counter

train_labels = [minutes <= 30 for minutes in train_minutes]
test_labels = [minutes <= 30 for minutes in test_minutes]
label = Counter(train_labels).most_common(1)[0][0]
correct = sum(answer == label for answer in test_labels)
accuracy = correct / len(test_labels)

assert label is True
assert accuracy == 3 / 5
print("Доля верных ответов:", round(accuracy, 2))

У этой модели нет сложного алгоритма, но есть обучение: мы определили ответ по прошлым данным. Для числовой задачи это была медиана, для классификации — самый частый класс.

От маленькой таблицы к CSV

В статье мы проследили все 16 заказов глазами. Для практики таких строк уже по тысяче в обучающем и проверочном файлах: выписывать их в список вручную неудобно. Библиотека pandas читает CSV как таблицу, в которой можно выбрать столбец по имени. Запускайте следующий код из папки занятия, сохраняя рядом каталог data:

import pandas as pd

train_table = pd.read_csv("data/train.csv")
test_table = pd.read_csv("data/test.csv")
print(train_table[["height_cm", "colors", "minutes"]].head(3))
print(len(train_table), len(test_table))

read_csv открывает файл, head(3) показывает первые три строки, len — число заказов. Чтобы найти медиану только по обучению, используйте train_table["minutes"].median(). В проверочном файле вместо ответа стоит ?: этот столбец не участвует в выборе прогноза. В ноутбуке вы продолжите работу с теми же таблицами и откроете отдельный файл ответов после фиксации правила.

Практика

Для самостоятельной работы возьмите синтетические файлы train.csv и test.csv: в каждом по 1000 заказов. Столбцы height_cm и colors доступны до печати, minutes — время в минутах. В тестовом файле вместо времени стоит ?. Номера order_id служат для сопоставления строк. Откройте ноутбук рядом с папкой data и используйте pandas. В нём оставлены места для вашего кода.

  1. Загрузите оба CSV. Проверьте число строк и столбцы. Только по train.csv найдите медиану времени, сделайте постоянный прогноз для обучающих заказов и вычислите MAE. Сколько минут предсказывает модель?
  2. Зафиксируйте числовой прогноз для всех тестовых заказов. Затем поставьте вопрос «успеет ли заказ за 30 минут?»: найдите самый частый ответ только в обучающей части и зафиксируйте его для всех тестовых заказов.
  3. Теперь откройте test_answers.csv, сопоставьте ответы с тестовыми строками по order_id и вычислите тестовую MAE и accuracy. Не меняйте ни одно из правил после просмотра ответов.

Самопроверка. Обучающих и тестовых заказов по 1000; медиана обучения — 28 минут, MAE на обучении — 6,59 минуты. На тесте MAE — 6,362 минуты. Самый частый обучающий класс — «да», его accuracy на тесте — 0,588. Эти результаты относятся только к сгенерированным данным; они не описывают настоящий принтер.

Типичные ошибки

  • Вычислять медиану по обучению и тесту вместе: тогда тестовые ответы уже повлияли на модель.
  • Менять правило после просмотра тестовых ошибок и сообщать результат как независимую проверку.
  • Путать минуты с процентом верных ответов или делать выводы о настоящем принтере по придуманным числам.

Откуда взялись учебные времена

Для таблицы мы придумали упрощённое скрытое правило. Представим слои толщиной 1 мм: при высоте hh сантиметров получается L=10hL=10h слоёв. Пусть Aℓ,cA_{\ell,c} — площадь сечения цвета cc в слое ℓ\ell в квадратных сантиметрах; если цвета в слое нет, площадь равна нулю. Время печати этим цветом обозначим aca_c:

ac=0,1∑ℓ=1LAℓ,cминут.a_c=0{,}1\sum_{\ell=1}^{L} A_{\ell,c}\quad\text{минут}.

Кроме печати фигурки, принтер тратит 8 минут на подготовку и по 3 минуты на каждое переключение цвета. Если переключений SS, учебное время равно

T=8+∑c=1Cac+3Sминут.T=8+\sum_{c=1}^{C}a_c+3S\quad\text{минут}.

Мы выбрали такие скрытые площади и переключения. В столбце LL видно, что число слоёв растёт вместе с высотой: например, для фигурок высотой 3 и 9 см это 30 и 90 слоёв.

Таблица 3 — Скрытые параметры учебных заказов
Заказ Слоёв LL Сумма площадей по слоям для каждого цвета, см² Переключения SS Время TT, мин
p01 30 120 0 20
p02 40 50, 60 1 22
p03 50 160 0 24
p04 60 30, 40, 50 2 26
p05 100 200, 270 1 58
p06 30 30, 40 1 18
p07 40 40, 60 1 21
p08 60 190 0 27
p09 70 70, 100 1 28
p10 80 40, 50, 70 2 30
p11 90 100, 130 1 34
p12 30 110 0 19
p13 50 20, 40, 50 2 25
p14 60 80, 100 1 29
p15 70 100, 140 1 35
p16 90 80, 90, 90 2 40

Например, для p02 печать занимает 0,1(50+60)=110{,}1(50+60)=11 минут, подготовка — 8 минут, одно переключение — 3 минуты; всего 8+11+3=228+11+3=22 минуты. Эта формула создана только для учебной таблицы и не описывает настоящий 3D-принтер.

При решении задачи у нас были только высота, число цветов и прошлые времена печати. Высота задавала число слоёв, но площади сечений по слоям, порядок смены цветов, число переключений и коэффициенты скрытого правила не были известны. Например, p02 и p07 совпадают по двум доступным признакам, но печатаются 22 и 21 минуту из-за различия скрытых площадей. Поэтому мы не могли просто подставить признаки в формулу: построили прогноз по доступным данным и проверили его на новых заказах.

Итоги

Мы превратили очередь заказов в задачу регрессии, построили постоянный прогноз по обучающим ответам и измерили MAE на новых заказах. Когда ответ стал «да» или «нет», задача стала классификацией и мы посчитали долю верных ответов. Перед опросом спросите себя: какие столбцы известны до печати? Почему медиану нельзя подбирать по проверочным ответам? Что означает MAE в минутах? Подсказки и разборы есть ниже.

Самопроверка

Вопрос 1

Что является объектом в нашей задаче?

Подсказка

Посмотрите, что описывает одна строка.

Решение

B. Одна строка соответствует одному заказу. Столбцы описывают его свойства и результат.

Вопрос 2

Какие признаки доступны до начала печати?

Подсказка

Представьте момент перед нажатием кнопки запуска.

Решение

B. Высота и число цветов известны из проекта до печати. Остальные варианты появляются позже или раскрывают ответ.

Вопрос 3

Нужно предсказать точное время печати. Какой это вид задачи?

Подсказка

Какого вида ответ: число или название класса?

Решение

A. Время в минутах — числовой ответ. Для вопроса «успеет или нет» нужна классификация.

Вопрос 4

Чему равна медиана одиннадцати обучающих времён?

Подсказка

В упорядоченном списке из одиннадцати чисел найдите шестое.

Решение

C. Посередине стоит 26. Число 28 — среднее этих времён.

Вопрос 5

Ответы равны 10 и 20, оба прогноза — 15. Какова MAE?

Подсказка

Сначала найдите два модуля ошибки, затем среднее.

Решение

D. Ошибки равны 5 и 5, их среднее — 5. Ошибки с разными знаками не сокращаются.

Вопрос 6

Почему медиану нельзя вычислять по всей таблице до разделения?

Подсказка

Какую роль должны играть новые заказы?

Решение

B. Тест нужен для проверки уже выбранного правила. Использование его ответов при обучении нарушает эту проверку.

Вопрос 7

Модель верно ответила на три заказа из четырёх. Чему равна accuracy?

Подсказка

Разделите число верных ответов на число всех заказов.

Решение

A. Три из четырёх — 0,75, или 75 %. У доли нет единиц времени.

Вопрос 8

Почему модель с постоянным ответом полезна?

Подсказка

Что должна показать следующая, более сложная модель?

Решение

C. Новая модель должна показать пользу по сравнению с простым решением. Сложность сама по себе не гарантирует улучшения.

Вопрос 9

Мы увидели тестовые ошибки и подобрали по ним новый прогноз. Что произошло?

Подсказка

Какие ответы помогли принять новое решение?

Решение

D. Проверка уже повлияла на модель. Для независимой оценки нового правила понадобятся другие данные.

Вопрос 10

MAE равна 6,8 минуты на пяти придуманных заказах. Что можно заключить?

Подсказка

Отделите результат конкретной проверки от обещания на будущее.

Решение

B. Мы проверили конкретный набор. Для вывода о настоящей работе нужны реальные независимые наблюдения.

Файлы

Дополнительные материалы