Почему вы должны указывать доверительные интервалы в своем наборе тестов
В экспериментальных науках мы привыкли сообщать оценки с планками погрешностей и значащими цифрами. Например, когда вы взвешиваете образец в лаборатории, вы можете считать его массу с точностью, скажем, до трех цифр. В машинном обучении все иначе. Когда вы оцениваете точность вашей модели, вы получаете значение с числовой ошибкой до машинной точности. Это похоже на то, как если бы оценка точности, выдаваемая вашей моделью, надежна до семи знаков после запятой. К сожалению, внешность может быть обманчивой. В вашем тестовом балле есть скрытая ошибка. Непреодолимая вариация, присущая стохастической природе данных. Ошибка потенциально настолько велика, что полностью определяет надежность оценки производительности вашей модели.
Я говорю о статистических колебаниях.
Случай
Представьте, что вас только что пригласили в новую биотехнологическую компанию в качестве специалиста по данным. Твое задание? Чтобы предсказать, нужна ли пациенту спасительная операция, используя их передовое измерительное устройство. Генеральный директор выразил вам большое доверие и выделил на ваш проект 100 000 евро. Поскольку технология все еще находится в зачаточном состоянии, каждое измерение по-прежнему довольно дорого — 2500 евро за образец. Вы решаете потратить весь свой бюджет на сбор данных и задаетесь целью собрать 20 обучающих и 20 тестовых выборок.
(Вы можете следить за повествованием, выполняя блоки кода Python.)
from sklearn.datasets import make_blobs centers = [[0, 0], [1, 1]] X_train, y_train = make_blobs( centers=centers, cluster_std=1, n_samples=20, random_state=5 ) X_test, y_test = make_blobs( centers=centers, cluster_std=1, n_samples=20, random_state=1005 )
После завершения измерений вы визуализируете обучающий набор данных (рис. 2). При таком небольшом количестве данных все еще довольно сложно выделить четкие закономерности. Поэтому вы начинаете с установления базовой производительности с помощью простой линейной модели: логистической регрессии.
from sklearn.linear_model import LogisticRegression baseline_model = LogisticRegression(random_state=5).fit(X_train, y_train) baseline_model.score(X_test, y_test) # Output: 0.85.
На самом деле это неплохо: точность на тестовом наборе 85 %. Установив прочную основу, вы приступили к созданию более сложной модели. После недолгих размышлений вы решаете попробовать деревья с градиентным усилением, учитывая их успех на Kaggle.
from sklearn.ensemble import GradientBoostingClassifier tree_model = GradientBoostingClassifier(random_state=5).fit(X_train, y_train) tree_model.score(X_test, y_test) # Output: 0.90.
Ух ты! Точность 90 %. Полный волнения, вы сообщаете о своих выводах генеральному директору. Кажется, она в восторге от вашего большого успеха. Вместе вы решаете внедрить в производство более сложный классификатор.
Вскоре после запуска модели в производство вы начинаете получать жалобы от клиентов. Кажется, что ваша модель может работать не так, как предложенная вами точность тестового набора.
Что происходит? И что делать? Откатиться к более простой, но менее производительной базовой модели?
Статистические колебания
Чтобы понять статистические колебания, мы должны взглянуть на процесс выборки. Когда мы собираем данные, мы берем образцы из неизвестного распределения. Мы говорим неизвестно, потому что если бы мы знали распределение, генерирующее данные, то наша задача была бы выполнена: мы можем идеально классифицировать выборки (с точностью до неустранимой ошибки).
Теперь раскрасьте простые случаи, которые ваша модель может правильно предсказать, синим цветом, а сложные случаи (которые классифицируются неправильно) — красным (рис. 3, слева). Создавая набор данных, вы, по сути, рисуете набор красных и синих шаров (рис. 3, в центре). Точность в данном случае — это количество синих среди всех шаров (рис. 3, справа). Каждый раз, когда вы создаете набор данных, количество синих шариков — точность вашей модели — колеблется вокруг своего «истинного» значения.
Как видите, вытащив горсть шаров, у вас есть все шансы получить преимущественно красные или преимущественно синие шары: статистические колебания велики! По мере того, как вы собираете больше данных, размер колебаний уменьшается, так что средний цвет приближается к своему «истинному» значению.
Другой способ думать об этом состоит в том, что статистические колебания — это ошибки в ваших оценках. В экспериментальных науках мы обычно сообщаем среднее значение µ и стандартное отклонение σ. Под этим мы подразумеваем, что если µ и σ были правильными, мы ожидаем гауссовы колебания между [µ-2σ, µ +2σ]примерно в 95 % случаев. В машинном обучении и статистике мы часто имеем дело с более экзотическими распределениями, чем гауссовы. Поэтому чаще используется 95 % доверительный интервал (ДИ): диапазон колебаний в 95 % случаев, независимо от распределения.
Применим эту теорию на практике.
Разрешение: оценки с планками погрешностей
Возвращаясь к вашей задаче в биотехнологическом стартапе, чтобы предсказать, нужна ли пациенту спасительная операция. Узнав о статистических колебаниях, вы начинаете подозревать, что эти колебания могут лежать в основе вашей проблемы. Если моя тестовая выборка мала, то статистические флуктуации должны быть большими, рассуждаете вы. Поэтому вы намереваетесь количественно оценить диапазон точности, который вы могли бы разумно ожидать.
Одним из способов количественной оценки статистических колебаний оценки вашей модели является использование статистического метода, называемого самозагрузкой. Начальная загрузка означает, что вы берете случайные наборы данных и используете их для оценки неопределенности. Полезным пакетом Python является statkit (pip3 install statkit
), который мы специально разработали для интеграции с sci-kit learning.
Вы начинаете с вычисления доверительного интервала базовой модели.
from sklearn.metrics import accuracy_score from statkit.non_parametric import bootstrap_score y_pred_simple = baseline_model.predict(X_test) baseline_accuracy = bootstrap_score( y_test, y_pred_simple, metric=accuracy_score, random_state=5 ) print(baseline_accuracy) # Output: 0.85 (95 % CI: 0.65-1.0)
Таким образом, хотя точность вашей базовой модели на тестовом наборе составляла 85 %, мы можем ожидать, что точность будет в диапазоне от 65 % до 100 % в большинстве случаев. Оценивая диапазон точности более сложной модели,
y_pred_tree = tree_model.predict(X_test) tree_accuracy = bootstrap_score(y_test, y_pred_tree, metric=accuracy_score, random_state=5) print(tree_accuracy) # Output: 0.90 (95 % CI: 0.75–1.0)
Мы находим, что это примерно то же самое (между 75 % и 100 %). Таким образом, вопреки тому, во что вы и генеральный директор изначально верили, чем сложнее, тем лучше.
Научившись на своей ошибке, вы решаете вернуться к своей более простой базовой модели. Не желая еще больше разозлить клиентов, вы четко сообщаете о производительности вашей модели и остаетесь в тесном контакте, чтобы получить обратную связь как можно раньше. После некоторого времени тщательного мониторинга вам удалось собрать дополнительные данные.
X_large, y_large = make_blobs(centers=centers, cluster_std=1, n_samples=10000, random_state=0)
Эти дополнительные измерения позволяют более точно оценить производительность.
baseline_accuracy_large = bootstrap_score( y_large, baseline_model.predict(X_large), metric=accuracy_score, random_state=5 ) print('Logistic regression:', baseline_accuracy_large) # Output: 0.762 (95 % CI: 0.753-0.771) tree_accuracy_large = bootstrap_score( y_large, tree_model.predict(X_large), metric=accuracy_score, random_state=5 ) print('Gradient boosted trees:', tree_accuracy_large) # Output: 0.704 (95 % CI: 0.694-0.713)
Большой набор данных подтверждает: ваша более простая базовая модель действительно была лучше.
Заключение
Не обманывайтесь своими результатами тестов: они могут быть статистической случайностью. Особенно для небольших наборов данных ошибка из-за статистических флуктуаций может быть большой. Наш совет: примите во внимание неизвестность и оцените неопределенность ваших оценок, используя доверительные интервалы 95 %. Это не позволит вам быть застигнутым врасплох, когда реальная производительность ниже, чем предполагалось в точечной оценке набора тестов.
Благодарности
Я хотел бы поблагодарить Rik Huijzer за корректуру.