10.1. Несогласованная предварительная обработка

Цель этой главы — проиллюстрировать некоторые распространенные ловушки и антишаблоны, которые возникают при использовании scikit-learn. В нем приведены примеры того, чего не следует делать, и соответствующий правильный пример.

scikit-learn предоставляет библиотеку преобразований набора данных , которые могут очищать (см. Предварительная обработка данных ), уменьшать (см. Неконтролируемое уменьшение размерности ), расширять (см. Аппроксимация ядра ) или генерировать (см. Извлечение функций ) представления функций. Если эти преобразования данных используются при обучении модели, они также должны использоваться в последующих наборах данных, будь то тестовые данные или данные в производственной системе. В противном случае пространство функций изменится, и модель не сможет работать эффективно.

В следующем примере давайте создадим синтетический набор данных с одной функцией:

>>> from sklearn.datasets import make_regression
>>> from sklearn.model_selection import train_test_split

>>> random_state = 42
>>> X, y = make_regression(random_state=random_state, n_features=1, noise=1)
>>> X_train, X_test, y_train, y_test = train_test_split(
...     X, y, test_size=0.4, random_state=random_state)

Неправильный

Набор данных поезда масштабируется, но не набор тестовых данных, поэтому производительность модели в наборе тестовых данных хуже, чем ожидалось:

>>> from sklearn.metrics import mean_squared_error
>>> from sklearn.linear_model import LinearRegression
>>> from sklearn.preprocessing import StandardScaler

>>> scaler = StandardScaler()
>>> X_train_transformed = scaler.fit_transform(X_train)
>>> model = LinearRegression().fit(X_train_transformed, y_train)
>>> mean_squared_error(y_test, model.predict(X_test))
62.80...

Верно

Вместо того, чтобы передавать непреобразованное X_test в predict, мы должны преобразовать тестовые данные так же, как мы преобразовали данные обучения:

>>> X_test_transformed = scaler.transform(X_test)
>>> mean_squared_error(y_test, model.predict(X_test_transformed))
0.90...

В качестве альтернативы мы рекомендуем использовать Pipeline, что упрощает цепочку преобразований с оценками и снижает возможность забыть преобразование:

>>> from sklearn.pipeline import make_pipeline

>>> model = make_pipeline(StandardScaler(), LinearRegression())
>>> model.fit(X_train, y_train)
Pipeline(steps=[('standardscaler', StandardScaler()),
                ('linearregression', LinearRegression())])
>>> mean_squared_error(y_test, model.predict(X_test))
0.90...

Конвейеры также помогают избежать еще одной распространенной ошибки: утечки тестовых данных в обучающие данные.