Модуль 1. Что значит «работает»¶
Чему вы научитесь в этом модуле
- Разбирать любое утверждение из научной статьи на три составляющие: что именно измерили, на каких данных, и с каким эталоном сравнивали.
- Понимать, почему одно-единственное число без указания разброса — это ещё не результат.
- Вычислять среднее, дисперсию, стандартную ошибку и доверительный интервал, а также объяснять, что стоит за каждой из этих величин.
- Строить бутстрэп-интервал и межквартильное среднее (IQM) вручную, без специальных библиотек.
- Самостоятельно проверять опубликованные заявления и формировать собственное суждение о том, подтверждаются ли они.
Время: примерно одна неделя. Пререквизиты: Python, проверьте себя.
Ноутбук: открыть в Colab · notebooks/01-claim-baseline-noise.ipynb
Почему мы начинаем именно с этого¶
Большинство курсов по машинному обучению начинается примерно так: берём набор данных, обучаем модель, получаем точность 0.93. Выглядит как готовый результат. На самом деле — нет.
Вот типичная фраза из статьи:
Наш метод достигает точности 0.93 на этом наборе данных, превосходя предыдущий результат 0.91.
Прежде чем принять это на веру, нужно задать четыре вопроса.
Точность чего именно. Слово «точность» обозначает целое семейство метрик, а не какую-то одну конкретную величину.
На каких данных. Использовалась ли та же самая выборка, на которой получили 0.91, или другая.
Сколько раз проводился эксперимент и каков был разброс результатов. Если при другом начальном зерне генератора случайных чисел метод показывает 0.90, то результат 0.93 мог оказаться просто везением, а не реальным улучшением.
С чем именно сравнивают. Настраивали ли предыдущий метод с той же тщательностью, что и свой, — или просто взяли старые числа из статьи трёхлетней давности с параметрами по умолчанию.
Ни один из этих четырёх вопросов не требует знания машинного обучения. Но все четыре требуют навыка критического чтения и немного арифметики.
Этот модуль стоит первым не потому, что он самый простой, а потому, что без него все следующие двадцать шесть теряют смысл. Модель, про которую вы не можете сказать, работает она или нет, ничем не отличается от модели, которая не работает.
Три составляющие любого утверждения¶
Каждое утверждение о результате можно разложить на три части. Не на две — именно на три.
Величина. Что конкретно измерялось. Под словом «точность» может скрываться доля правильных ответов, F1-мера, площадь под ROC-кривой (AUC) или точность на редком классе. В задачах обучения с подкреплением под «наградой» может подразумеваться суммарная награда за эпизод, средняя награда за один шаг, дисконтированная или нет. Значительная часть некорректных сравнений в научной литературе возникает именно из-за того, что сравниваются разные величины, названные одним и тем же словом.
Условия. На каких данных проводился эксперимент, в какой постановке задачи, с каким вычислительным бюджетом. Модель, обученная за десять эпох, и модель, обученная за сто эпох, — это разные условия. Метод, у которого подобрали двадцать гиперпараметров, и метод с настройками по умолчанию — тоже.
База сравнения. С чем именно сравнивается результат, когда говорят «лучше». Это самая важная часть — и одновременно та, которую чаще всего портят.
Разберём конкретный пример
На задаче управления запасами с нестационарным спросом обученная политика даёт прибыль 274.0 против 240.7 у лучшей фиксированной политики base-stock. Числа — межквартильное среднее по пяти зёрнам с 95-процентным бутстрэп-интервалом [247.3, 280.4].
Величина: прибыль за один эпизод, агрегированная с помощью межквартильного среднего (IQM). Условия: спрос нестационарный, эксперимент проведён на пяти разных зёрнах генератора. База: лучшая фиксированная политика base-stock — не самая простая, а найденная полным перебором лучшая в своём классе стратегий.
А теперь обратите внимание на то, чего здесь нет: для базовой политики не указан доверительный интервал. Это не попытка обмануть — базовая политика детерминирована (при одних и тех же входных данных она всегда даёт один и тот же результат). Однако из самого текста это не очевидно, и внимательный читатель обязательно на этом остановится. Вы остановились?
База сравнения¶
Утверждение «наш метод даёт 0.93» само по себе ничего не значит. Значение имеет только разница между результатом метода и тем, что получилось бы без него.
Существуют три уровня базы сравнения, от самой слабой к самой честной.
Тривиальная база. Что получится, если давать один и тот же ответ на все примеры. Если 95 % писем в выборке — не спам, то классификатор, который всегда отвечает «не спам», автоматически получает точность 0.95. Метод с точностью 0.93 в этом случае хуже, чем отсутствие всякого метода, хотя в статье может быть написано «достигает точности 0.93». Проверка тривиальной базы занимает одну минуту — и при этом отсеивает удивительно много заявлений.
Простая база. Что покажет самый стандартный, самый «скучный» работающий метод: логистическая регрессия, градиентный бустинг с параметрами по умолчанию, скользящее среднее для временных рядов, формула из учебника для задач управления запасами. В таблицах ML-статей эта строка отсутствует чаще, чем присутствует.
Настроенная база. Тот же самый простой метод, но которому дали столько же попыток на подбор параметров, сколько и основному. Вот это — по-настоящему честное сравнение. Встречается оно редко, потому что регулярно показывает, что никакого улучшения нет.
Ловушка: неравные условия настройки
Самый распространённый способ получить улучшение, которого на самом деле нет, — это не подделка данных. Это разная тщательность настройки. Свой метод настраивают целую неделю, а базовый берут из чужого репозитория с настройками по умолчанию. Формально всё корректно: числа настоящие, код доступен. Но по существу сравниваются не два метода, а разное количество вложенного труда.
Когда читаете статью, ищите информацию о том, как авторы настраивали базовый метод. Если такой информации нет — это тревожный сигнал.
Шум¶
А теперь — самое главное. Запустите обучение модели дважды, изменив только начальное зерно генератора случайных чисел. Результаты окажутся разными. И разными не в шестом знаке после запятой: в задачах обучения с подкреплением разброс результатов между разными зёрнами нередко оказывается больше, чем разница между сравниваемыми методами.
Откуда берётся эта случайность: из начальной инициализации весов, из порядка перемешивания данных, из того, как именно разбились данные на обучающую и тестовую выборки, из механизма dropout, из случайности самой среды.
Из этого следует неприятный, но важный вывод:
Число, полученное из одного запуска, — это не свойство метода. Это одно-единственное наблюдение случайной величины.
Сравнивать два таких числа — всё равно что бросить кубик дважды, получить 5 и 3, и заключить, что первый кубик «лучше» второго.
Что нужно считать вместо одного числа¶
Нужно запустить эксперимент \(n\) раз с разными начальными зёрнами и работать не с отдельными числами, а с распределением результатов.
Пусть \(x_1, \dots, x_n\) — результаты \(n\) запусков.
Среднее арифметическое показывает, где находится центр распределения:
Выборочная дисперсия показывает, насколько сильно отдельные результаты разбросаны вокруг этого центра:
Почему в знаменателе \(n-1\), а не \(n\)?
Дело в том, что среднее \(\bar{x}\) вычислено по тем же самым данным, от которых мы считаем отклонения. Отклонения от собственного среднего получаются систематически меньше, чем отклонения от истинного математического ожидания. Деление на \(n-1\) вместо \(n\) в точности компенсирует эту систематическую занижение — в результате оценка дисперсии оказывается несмещённой. Убедиться в этом можно численно, буквально за восемь строк кода — это первое задание в ноутбуке.
Стандартное отклонение \(s = \sqrt{s^2}\) — это разброс, выраженный в тех же единицах измерения, что и сама величина (а не в квадратах единиц, как дисперсия).
Стандартная ошибка среднего показывает, насколько точно мы знаем положение центра распределения:
Эти две величины — стандартное отклонение и стандартная ошибка — часто путают, хотя они означают совершенно разные вещи. Стандартное отклонение \(s\) говорит о том, насколько разбросаны отдельные запуски. Стандартная ошибка \(\mathrm{SE}\) говорит о том, насколько разбросанным оказалось бы среднее, если бы мы заново повторили весь эксперимент из \(n\) запусков целиком. Обратите внимание на \(\sqrt{n}\) в знаменателе: чтобы уточнить среднее вдвое, нужно провести вчетверо больше запусков. Именно поэтому в статьях так часто стоит \(n = 3\) — больше запусков элементарно дорого.
Доверительный интервал приблизительно 95 %:
Читается он так: если многократно повторять весь эксперимент и каждый раз строить такой интервал, то примерно в 95 % случаев построенный интервал накроет истинное значение. Обратите внимание: он не означает, что «истинное значение лежит внутри интервала с вероятностью 0.95». Истинное значение — фиксированная константа, оно не случайно. Случайным является сам интервал, который меняется от эксперимента к эксперименту.
Практическое правило перекрытия¶
Простое и полезное правило: если доверительные интервалы двух методов перекрываются — разница между ними не продемонстрирована.
Не «методы одинаковы». А именно — «не продемонстрирована». Разница вполне может существовать, но имеющихся данных недостаточно, чтобы её убедительно показать.
Правило грубое и осторожное (консервативное). Оно помогает отсечь большинство случаев, когда улучшение заявлено на основе случайного шума, и служит первым фильтром при чтении статей.
Вот интерактивная иллюстрация. Метод и база с истинной разницей 0.023 — маленькой, но реальной. Подвигайте ползунок числа зёрен и нажимайте «Другое зерно»: при малом \(n\) интервалы перекрываются, и «лучшим» оказывается то метод, то база — в зависимости от случая. Разница существует, но данных слишком мало, чтобы её надёжно увидеть.
Понаблюдайте, при каком значении \(n\) интервалы начинают стабильно расходиться. Это и есть ответ на вопрос «сколько зёрен нужно» — не формулой, а на собственном опыте. Формальный ответ с формулой появится в модуле 2.
Этот приём встретится ещё как минимум трижды. Бутстрэп на фиксированных зёрнах — это не тема одного модуля, а инструмент, который проходит через весь курс. В модуле 14 с его помощью сравнивают алгоритм PPO с базой, в модуле 20 — две ветки A/B-теста, в модуле 26 — собственный результат с опубликованным в статье. Один и тот же код из одиннадцати строк, четыре совершенно разные задачи.
Когда среднее арифметическое обманывает¶
У среднего арифметического есть неприятное свойство: один-единственный выброс способен сдвинуть его очень сильно. В задачах обучения с подкреплением это происходит регулярно — часть запусков расходится (не обучается), а часть попадает в удачный режим.
Пример: пять запусков дали результаты 10, 11, 9, 10, 60. Среднее арифметическое равно 20. Но такого результата не показал ни один из пяти запусков — число 20 не описывает ни типичный, ни реальный результат.
Поэтому используются две более устойчивые альтернативы.
Медиана — значение, стоящее ровно посередине упорядоченного списка результатов. Она устойчива к выбросам, но платит за это потерей информации: при \(n = 5\) она по сути опирается на одно-единственное наблюдение, игнорируя остальные.
Межквартильное среднее (IQM) — это среднее арифметическое, вычисленное после того, как из данных убрали нижнюю и верхнюю четверти. Другими словами: упорядочиваем результаты, отбрасываем 25 % самых плохих и 25 % самых хороших, и считаем среднее по оставшейся середине. IQM устойчивее обычного среднего к выбросам и при этом информативнее медианы. Это стандартная мера в современных работах по обучению с подкреплением, и именно она использовалась в примере выше.
Формула может выглядеть пугающе, но на деле всё просто: отсортировать результаты, отрезать по четверти с каждого края, посчитать среднее того, что осталось. На NumPy это три строки кода.
Перемещайте точку выброса на интерактивном графике и наблюдайте за поведением маркеров. Среднее арифметическое послушно следует за выбросом, а IQM остаётся на месте. Причина в том, что среднее учитывает все точки без исключения, а IQM заранее исключил крайние четверти — и выброс просто не попадает в расчёт.
Бутстрэп¶
Для IQM не существует простой аналитической формулы стандартной ошибки. Но она и не нужна — есть универсальный метод.
Бутстрэп работает так: из имеющихся \(n\) результатов многократно извлекается новая выборка размера \(n\) с возвращением (то есть одно и то же значение может попасть в выборку несколько раз). На каждой такой выборке вычисляется интересующая нас статистика (среднее, IQM или любая другая). Затем из полученного набора значений берутся 2.5-й и 97.5-й процентили — они и образуют 95-процентный доверительный интервал.
Почему это работает: наша выборка — это лучшее имеющееся приближение к тому распределению, из которого пришли данные. Многократно извлекая из неё подвыборки с возвращением, мы фактически имитируем повторение всего эксперимента.
def bootstrap_ci(values, statistic, n_resamples=10_000, seed=0):
"""95% доверительный интервал для любой статистики.
Пересэмплирование с возвращением имитирует повторение эксперимента:
выборка — наше лучшее приближение к тому, откуда пришли данные.
"""
rng = np.random.default_rng(seed)
values = np.asarray(values)
draws = rng.choice(values, size=(n_resamples, len(values)), replace=True)
stats = np.array([statistic(row) for row in draws])
return np.percentile(stats, [2.5, 97.5])
Одиннадцать строк кода. Этот код работает для среднего, медианы, IQM, доли правильных ответов — для любой статистики, которую вы можете задать как функцию. Это самый полезный фрагмент кода во всём курсе.
Важное ограничение
Бутстрэп не создаёт информацию из ниоткуда. Если у вас всего \(n = 3\) запуска, он даст какой-то интервал — но этот интервал будет малоинформативным, потому что три числа слишком мало говорят о форме распределения. Пять зёрен и при этом широкие интервалы в статье — это не слабость, а проявление честности. Настоящая проблема — когда в статье три зерна и никаких интервалов вообще.
Практическая часть¶
Часть 1. Работа с ноутбуком¶
Откройте notebooks/01-claim-baseline-noise.ipynb.
В этом ноутбуке весь описанный путь проходится на симулированном эксперименте, в котором правильный ответ известен заранее. На реальных данных истинное значение скрыто, и понять, где оценка ошибается, невозможно. Здесь же вы видите истину — и можете проверить, насколько хорошо ваши инструменты её обнаруживают.
Что содержится в ноутбуке:
- Численная проверка того, зачем в формуле дисперсии стоит \(n-1\).
- Два «метода» с заранее известной истинной разницей. Задача — определить, сколько зёрен нужно, чтобы эту разницу обнаружить.
- Подсчёт того, как часто при \(n = 3\) худший метод ошибочно объявляется лучшим. Здесь мы считаем, а не гадаем.
- Сравнение поведения среднего арифметического и IQM на распределении с выбросами.
- Построение бутстрэп-интервалов с нуля, без использования готовых библиотек.
Пройдите ноутбук дважды, следуя рекомендациям из раздела как учиться: первый раз — целиком по порядку, второй — экспериментируя и ломая.
Часть 2. Проверка реального заявления¶
Теория без применения на практике быстро забывается. Поэтому берём реальное опубликованное утверждение и проверяем его сами.
В библиотеке decisionrl заявлено: на задаче управления запасами с нестационарным спросом обученная политика даёт прибыль 274.0 против 240.7 у лучшей фиксированной политики base-stock. Эти числа получены с помощью скрипта
examples/verify_applied_claims.py
из того же репозитория. Это редкий и правильный случай: авторы приложили к заявлению готовый инструмент для его проверки.
pip install "decisionrl[gym]"
git clone https://github.com/DrobyshevDev/decisionrl
cd decisionrl
python examples/verify_applied_claims.py
Вычисление занимает некоторое время, но не требует видеокарты. Пока скрипт работает, ответьте письменно на следующие вопросы:
- Какая именно величина сравнивается и на скольких зёрнах проведён эксперимент.
- Что такое «лучшая фиксированная base-stock» и почему это более сильная база сравнения, чем просто произвольная base-stock политика.
- Перекрываются ли доверительные интервалы обученной политики и базы.
- Для базы доверительный интервал не указан. Обоснованно ли это в данном случае? В каком случае было бы необоснованно?
Когда вычисления завершатся — сравните полученные числа с опубликованными. Расхождение — это нормальный результат, а не провал. Другая версия PyTorch, другое оборудование, другие начальные зёрна — всё это влияет. Вопрос не в том, совпали ли числа в точности, а в том, попадает ли ваш результат в опубликованный доверительный интервал, и если нет — насколько далеко он от него.
Именно такую работу вы будете делать в модуле 26 с настоящей научной статьёй. Здесь — тренировка на задаче, где код гарантированно запускается.
Шесть типичных способов ошибиться¶
Речь идёт не о намеренном обмане. Все шесть ошибок регулярно совершаются добросовестными исследователями — в том числе, скорее всего, и вами в ближайшие полгода работы.
1. Выбор удачного зерна. Запустили эксперимент пять раз — показали только лучший результат. Формально число настоящее, эксперимент проведён. Как защититься: набор зёрен генератора фиксируется до начала экспериментов, показываются результаты для всех зёрен без исключения.
2. Неравные условия настройки. Свой метод настраивали целую неделю, а базовый запустили с параметрами по умолчанию. Как защититься: выделять одинаковый бюджет на настройку обоих методов и явно указывать, какой именно.
3. Подглядывание в тестовую выборку. Посмотрели на метрику на тестовых данных, внесли изменения в модель, снова посмотрели на тест. После двадцати таких итераций тестовая выборка фактически перестаёт быть тестовой: вы неявно подстроились под неё, используя себя как передаточное звено. Как защититься: все решения по модели принимаются на основе валидационной выборки, тестовая открывается ровно один раз — в самом конце.
4. Утечка данных. Использование признака, который в момент реального предсказания не был бы доступен. Нормализация, вычисленная по всему набору данных до его разбиения на части. Дублирующиеся записи, попавшие одновременно и в обучающую, и в тестовую выборки. Как защититься: для каждого признака задавать вопрос — существовал бы он в тот момент, когда предсказание действительно потребовалось бы?
5. Остановка по результату. Отслеживали метрику в процессе обучения и остановились в тот момент, когда числа выглядели хорошо. По сути, это тот же выбор удачного зерна, только развёрнутый во времени. Как защититься: критерий остановки обучения определяется и фиксируется до начала эксперимента.
6. Множественные сравнения. Проверили двадцать различных вариантов модели, один из них показал улучшение с \(p < 0.05\). При двадцати независимых проверках как минимум один ложно-положительный результат ожидается просто по теории вероятностей. Как защититься: применять поправку на множественность тестирования или честно указывать в статье: «мы проверили двадцать вариантов».
Как пользоваться этим списком
Это не список для проверки чужих работ — это контрольный список для вашей собственной. Ваш метод показал улучшение — пройдитесь по всем шести пунктам, прежде чем делать выводы. Примерно в половине случаев окажется, что радоваться рано, — и лучше обнаружить это самому, чем узнать от рецензента.
Задание¶
Возьмите любую задачу с числовым результатом: из ноутбука этого модуля, из библиотеки decisionrl, или из собственного проекта.
- Сформулируйте утверждение письменно, разложив его на три составляющие: величина, условия, база сравнения.
- Выберите базу сравнения и обоснуйте, почему она честная. Тривиальную базу посчитайте обязательно.
- Проведите не менее десяти запусков с разными зёрнами. Набор зёрен определите до запуска экспериментов и запишите.
- Вычислите среднее арифметическое, IQM и бутстрэп-интервалы для обоих методов.
- Сформулируйте вывод одним предложением — таким, которое вы готовы защищать перед критиком.
- Отдельным абзацем укажите: какой из шести описанных способов ошибиться наиболее вероятен именно в вашей ситуации и что вы сделали, чтобы его исключить.
Шестой пункт — самый важный. Он же единственный, ответ на который невозможно списать.
Проверка усвоения¶
Попробуйте ответить вслух, не заглядывая в текст. Если не получается — это указатель на то, что стоит перечитать.
- Чем стандартное отклонение отличается от стандартной ошибки среднего? Что произойдёт с каждой из этих величин, если увеличить число запусков в четыре раза?
- Почему в формуле выборочной дисперсии стоит \(n-1\)?
- Что означает 95-процентный доверительный интервал? Сформулируйте ответ так, чтобы не использовать фразу «истинное значение лежит здесь с вероятностью 0.95».
- Доверительные интервалы двух методов перекрываются. Что из этого можно заключить? Чего заключить нельзя?
- Зачем нужен IQM, если уже есть среднее арифметическое и медиана?
- Объясните бутстрэп человеку, который знает только, что такое среднее арифметическое.
- Метод показывает точность 0.95. Какой первый вопрос вы зададите?
- Почему сравнение тщательно настроенного метода с ненастроенной базой — это не обман, но и не настоящий результат?
Что дальше¶
В модуле 2 появится точный математический язык для всего, что мы здесь обсуждали: случайная величина, распределение, оценка параметра. Вопрос «сколько зёрен нужно для надёжного результата» получит строгий ответ в виде формулы, а не подбора вручную.
А привычку формируйте уже сейчас — и сохраняйте её до конца курса:
Увидели число — сразу спросите: с чем сравнивают и сколько раз запускали.
Это две трети критического чтения научных статей. Оставшаяся треть — тема части VII.
Принцип
Зелёный пайплайн на одной машине — это не доказательство. Каждое число, которое вы публикуете, должно быть измерено именно на том прогоне, который вы описываете.