3.4. Кривые валидации: построение оценок для оценки моделей¶
У каждого модели есть свои преимущества и недостатки. Ошибка обобщения может быть разложена на смещение, дисперсию и шум. - Смещение модели - это его средняя ошибка для разных обучающих наборов. - Дисперсия модели показывает, насколько он чувствителен к различным обучающим наборам. - Шум - это свойство данных.
На следующем графике мы видим функцию \(f(x) = \cos (\frac{3}{2} \pi x)\) и несколько зашумленных образцов этой функции. Мы используем три разных средства оценки для подбора функции: линейную регрессию с полиномиальными характеристиками степени 1, 4 и 15. Мы видим, что первая оценка может в лучшем случае обеспечить лишь плохое соответствие выборкам и истинной функции, поскольку она слишком проста ( высокое смещение), вторая оценка аппроксимирует ее почти идеально, а последняя оценка идеально аппроксимирует обучающие данные, но не очень хорошо соответствует истинной функции, т.е. она очень чувствительна к изменяющимся обучающим данным (высокая дисперсия).
Смещение и дисперсия являются неотъемлемыми свойствами модели, и нам обычно приходится выбирать алгоритмы обучения и гиперпараметры так, чтобы как смещение, так и дисперсия были как можно меньшими (см. Дилемма смещения-дисперсии). Другой способ уменьшить дисперсию модели - использовать больше обучающих данных. Однако вам следует собирать больше обучающих данных только в том случае, если истинная функция слишком сложна, чтобы ее можно было аппроксимировать моделью с меньшей дисперсией.
В простой одномерной задаче, которую мы видели в примере, легко увидеть, страдает ли модель от смещения или дисперсии. Однако в многомерных пространствах модели может быть очень трудно визуализировать. По этой причине часто бывает полезно использовать инструменты, описанные ниже.
3.4.1. Кривая проверки¶
Для проверки модели нам нужна функция оценки (см. Метрики и оценка: количественная оценка качества прогнозов), например точность для классификаторов. Правильный способ выбора нескольких гиперпараметров модели - это, конечно, поиск по сетке или аналогичные методы (см. Настройка гиперпараметров модели), которые выбирают гиперпараметр с максимальньной оценкой в наборе проверки или нескольких наборах проверки. Обратите внимание: если мы оптимизируем гиперпараметры на основе оценки валидации, оценка валидации будет смещена и больше не будет хорошей оценкой обобщения. Чтобы получить правильную оценку обобщения, нам нужно вычислить оценку на другом тестовом наборе.
Однако иногда полезно построить график влияния одного гиперпараметра на оценку обучения и оценку проверки, чтобы выяснить, подходит ли модель для некоторых значений гиперпараметра или нет.
В этом случае может помочь функция validation_curve
:
>>> import numpy as np
>>> from sklearn.model_selection import validation_curve
>>> from sklearn.datasets import load_iris
>>> from sklearn.svm import SVC
>>> np.random.seed(0)
>>> X, y = load_iris(return_X_y=True)
>>> indices = np.arange(y.shape[0])
>>> np.random.shuffle(indices)
>>> X, y = X[indices], y[indices]
>>> train_scores, valid_scores = validation_curve(
... SVC(kernel="linear"), X, y, param_name="C", param_range=np.logspace(-7, 3, 3),
... )
>>> train_scores
array([[0.90..., 0.94..., 0.91..., 0.89..., 0.92...],
[0.9... , 0.92..., 0.93..., 0.92..., 0.93...],
[0.97..., 1... , 0.98..., 0.97..., 0.99...]])
>>> valid_scores
array([[0.9..., 0.9... , 0.9... , 0.96..., 0.9... ],
[0.9..., 0.83..., 0.96..., 0.96..., 0.93...],
[1.... , 0.93..., 1.... , 1.... , 0.9... ]])
Если вы собираетесь строить только кривые проверки, класс ValidationCurveDisplay
является более прямым, чем использование matplotlib вручную по результатам вызова validation_curve
.
Вы можете использовать метод from_estimator
аналогично validation_curve
для создания и построения кривой проверки:
from sklearn.datasets import load_iris
from sklearn.model_selection import ValidationCurveDisplay
from sklearn.svm import SVC
from sklearn.utils import shuffle
X, y = load_iris(return_X_y=True)
X, y = shuffle(X, y, random_state=0)
ValidationCurveDisplay.from_estimator(
SVC(kernel="linear"), X, y, param_name="C", param_range=np.logspace(-7, 3, 10)
)
Если оценка обучения и оценка валидации оба низкие, модель будет недообучена.
Если оценка обучения высокая, а оценка проверки низкая, модель переобучена, в противном случае она работает очень хорошо.
Низкий балл обучения и высокий балл валидации обычно невозможны.
Недообученная, переобученная и рабочая модель показаны на графике ниже, где мы изменяем параметр gamma
SVM с ядром RBF в наборе данных цифр.
3.4.2. Кривая обучения¶
Кривая обучения (Learning curve) показывает оценку проверки и обучения модели для различного количества обучающих выборок. Это инструмент, позволяющий выяснить, какую выгоду мы получим от добавления дополнительных обучающих данных и страдает ли модель больше от ошибки дисперсии или ошибки смещения. Рассмотрим следующий пример, где мы строим кривую обучения наивного байесовского классификатора и SVM.
Для наивного байесовского метода и оценка валидации, и оценка обучения сходятся к довольно низкому значению с увеличением размера обучающего набора. Таким образом, мы, вероятно, не получим особой пользы от большего количества обучающих данных.
Напротив, для небольших объемов данных оценка обучения SVM намного выше, чем оценка проверки. Добавление большего количества обучающих выборок, скорее всего, увеличит обобщение.
Мы можем использовать функцию learning_curve
для генерации значений, необходимых для построения такой кривой обучения (количество использованных выборок, средние баллы в обучающих наборах и средние баллы в проверочных наборах):
>>> from sklearn.model_selection import learning_curve
>>> from sklearn.svm import SVC
>>> train_sizes, train_scores, valid_scores = learning_curve(
... SVC(kernel='linear'), X, y, train_sizes=[50, 80, 110], cv=5)
>>> train_sizes
array([ 50, 80, 110])
>>> train_scores
array([[0.98..., 0.98 , 0.98..., 0.98..., 0.98...],
[0.98..., 1. , 0.98..., 0.98..., 0.98...],
[0.98..., 1. , 0.98..., 0.98..., 0.99...]])
>>> valid_scores
array([[1. , 0.93..., 1. , 1. , 0.96...],
[1. , 0.96..., 1. , 1. , 0.96...],
[1. , 0.96..., 1. , 1. , 0.96...]])
Если вы собираетесь строить только кривые обучения, проще использовать класс LearningCurveDisplay
.
Вы можете использовать метод from_estimator
аналогично learning_curve
для создания и построения кривой обучения:
from sklearn.datasets import load_iris
from sklearn.model_selection import LearningCurveDisplay
from sklearn.svm import SVC
from sklearn.utils import shuffle
X, y = load_iris(return_X_y=True)
X, y = shuffle(X, y, random_state=0)
LearningCurveDisplay.from_estimator(
SVC(kernel="linear"), X, y, train_sizes=[50, 80, 110], cv=5)