На этом шаге мы рассмотрим механизм такого преобразования.
Теперь, когда мы увидели, что делают различные виды преобразований, давайте применим их, воспользовавшись scikit-learn. Мы будем использовать уже известный нам набор данных cancer. Методы предварительной обработки обычно применяются перед использованием алгоритма машинного обучения с учителем. Допустим, в качестве примера нам нужно применить ядерный SVM (SVC) к набору данных cancer и использовать MinMaxScaler для предварительной обработки данных. Мы начнем с того, что загрузим наш набор данных и разобьем его на тренировочный и тестовый наборы (обучающий и тестовый наборы нам нужны для оценки качества модели, которую мы построим с помощью алгоритма контролируемого обучения после предварительной обработки):
[In 3]: from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split cancer = load_breast_cancer() X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, random_state=1) print(X_train.shape) print(X_test.shape) (426, 30) (143, 30)
Напомним, что набор содержит 569 точек данных, каждая из которых представлена 30 признаками. Мы разбиваем набор данных на 426 примеров в обучающей выборке и 143 примера в тестовой выборке.
Как и в случае с моделями контролируемого обучения, построенными ранее, мы сначала импортируем класс, который осуществляет предварительную обработку, а затем создаем его экземпляр:
[In 4]: from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler()
Затем с помощью метода fit() мы подгоняем scaler на обучающих данных. Для MinMaxScaler метод fit() вычисляет минимальное и максимальное значения каждого признака на обучающем наборе. В отличие от классификаторов и регрессоров, при вызове метода fit() scaler работает с данными (X_train), а ответы (y_train) не используются:
[In 5]:
scaler.fit(X_train)
MinMaxScaler()
Чтобы применить преобразование, которое мы только что подогнали, то есть фактически отмасштабировать (scale) обучающие данные, мы воспользуемся методом transform(). Метод transform() используется в scikit-learn, когда модель возвращает новое представление данных:
[In 6]: # преобразовываем данные X_train_scaled = scaler.transform(X_train) # печатаем значения признаков в обучающем наборе до и после масштабирования print("форма преобразованного массива: {}".format(X_train_scaled.shape)) print("min значение признака до масштабирования:\n {}".format(X_train.min(axis=0))) print("max значение признака до масштабирования:\n {}".format(X_train.max(axis=0))) print("min значение признака после масштабирования:\n {}".format(X_train_scaled.min(axis=0))) print("max значение признака после масштабирования:\n {}".format(X_train_scaled.max(axis=0))) форма преобразованного массива: (426, 30) min значение признака до масштабирования: [6.981e+00 9.710e+00 4.379e+01 1.435e+02 5.263e-02 1.938e-02 0.000e+00 0.000e+00 1.060e-01 5.024e-02 1.153e-01 3.602e-01 7.570e-01 6.802e+00 1.713e-03 2.252e-03 0.000e+00 0.000e+00 9.539e-03 8.948e-04 7.930e+00 1.202e+01 5.041e+01 1.852e+02 7.117e-02 2.729e-02 0.000e+00 0.000e+00 1.566e-01 5.521e-02] max значение признака до масштабирования: [2.811e+01 3.928e+01 1.885e+02 2.501e+03 1.634e-01 2.867e-01 4.268e-01 2.012e-01 3.040e-01 9.575e-02 2.873e+00 4.885e+00 2.198e+01 5.422e+02 3.113e-02 1.354e-01 3.960e-01 5.279e-02 6.146e-02 2.984e-02 3.604e+01 4.954e+01 2.512e+02 4.254e+03 2.226e-01 9.379e-01 1.170e+00 2.910e-01 5.774e-01 1.486e-01] min значение признака после масштабирования: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] max значение признака после масштабирования: [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
Преобразованные данные имеют такую же форму, что и исходные данные - признаки просто смещены и масштабированы. Видно, что теперь все признаки принимают значения в диапазоне от 0 до 1, как нам и требовалось.
Чтобы применить SVM к масштабированным данным, мы должны преобразовать еще тестовый набор. Это снова делается с помощью вызова метода transform(), на этот раз для X_test:
[In 7]: # преобразовываем тестовые данные X_test_scaled = scaler.transform(X_test) # печатаем значения признаков в тестовом наборе после масштабирования print("min значение признака после масштабирования:\n{}".format(X_test_scaled.min(axis=0))) print("max значение признака после масштабирования:\n{}".format(X_test_scaled.max(axis=0))) min значение признака после масштабирования: [ 0.0336031 0.0226581 0.03144219 0.01141039 0.14128374 0.04406704 0. 0. 0.1540404 -0.00615249 -0.00137796 0.00594501 0.00430665 0.00079567 0.03919502 0.0112206 0. 0. -0.03191387 0.00664013 0.02660975 0.05810235 0.02031974 0.00943767 0.1094235 0.02637792 0. 0. -0.00023764 -0.00182032] max значение признака после масштабирования: [0.9578778 0.81501522 0.95577362 0.89353128 0.81132075 1.21958701 0.87956888 0.9333996 0.93232323 1.0371347 0.42669616 0.49765736 0.44117231 0.28371044 0.48703131 0.73863671 0.76717172 0.62928585 1.33685792 0.39057253 0.89612238 0.79317697 0.84859804 0.74488793 0.9154725 1.13188961 1.07008547 0.92371134 1.20532319 1.63068851]
Возможно, полученные результаты несколько удивят вас: после масштабирования минимальные и максимальные значения признаков в тестовом наборе не равны 0 и 1. Некоторые признаки даже выходят за пределами диапазона 0-1! Объяснить это можно тем, что MinMaxScaler (и все остальные типы масштабирования) всегда применяют одинаковое преобразование к обучающему и тестовому наборам. Это означает, что метод transform() всегда вычитает минимальное значение, вычисленное для обучающего набора, и делит на ширину диапазона, вычисленную также для обучающего набора. Минимальное значение и ширина диапазона для обучающего набора могут отличаться от минимального значения и ширины диапазона для тестового набора.
На следующем шаге мы рассмотрим масштабирование обучаюшего и тестового наборов одинаковым образом.