Как предварительно обработать числовые признаки с разными диапазонами значений

Scikit-learn - широко используемая библиотека машинного обучения для Python. Он приобрел огромную популярность среди практиков в области науки о данных благодаря разнообразию алгоритмов и легкому для понимания синтаксису. Помимо готовых алгоритмов, scikit-learn также предоставляет полезные функции и методы для предварительной обработки данных.

Предварительная обработка данных - чрезвычайно важный шаг в машинном обучении или глубоком обучении. Мы не можем просто выгружать необработанные данные в модель и ожидать, что она будет работать хорошо. Даже если мы построим сложную, хорошо структурированную модель, ее производительность будет такой же хорошей, как и данные, которые мы ей скармливаем. Таким образом, нам необходимо обработать необработанные данные, чтобы повысить производительность моделей.

В этом посте мы рассмотрим способы обработки числовых функций (столбцов), которые имеют очень разные диапазоны значений. Применим стандартизацию и масштабирование. Давайте начнем с мотивации этих преобразований, а затем исследуем различия между ними на примерах.

Мотивация

Наборы данных, которые мы подбираем для моделей машинного обучения, обычно имеют много функций. Значения разных характеристик, скорее всего, будут в разном масштабе. Например, рассмотрим модель, пытающуюся предсказать цены на жилье. Площадь дома составляет около 200 квадратных метров, тогда как возраст обычно меньше 20 лет. Количество спален может быть 1, 2 или 3 в большинстве случаев. Все эти особенности важны при определении цены на дом. Однако, если мы будем использовать их без масштабирования, модели машинного обучения могут придать большее значение функциям с более высокими значениями. Модели, как правило, работают лучше и быстрее сходятся, когда функции находятся в относительно одинаковом масштабе.

Стандартизация и StandardScaler

Одно из решений этой проблемы - стандартизация. Считайте столбцы переменными. Если столбец стандартизирован, среднее значение столбца вычитается из каждого значения, а затем значения делятся на стандартное отклонение столбца. Полученные столбцы имеют стандартное отклонение, равное 1, и среднее значение, которое очень близко к нулю. Таким образом, мы получаем переменные (столбцы), которые имеют почти нормальное распределение. Стандартизация может быть достигнута StandardScaler.

Функции и преобразователи, используемые во время предварительной обработки, находятся в пакете sklearn.preprocessing. Давайте импортируем этот пакет вместе с numpy и pandas.

import numpy as np
import pandas as pd
from sklearn import preprocessing

Мы можем создать образец матрицы, представляющий функции. Затем преобразуйте его с помощью объекта StandardScaler.

a = np.random.randint(10, size=(10,1))
b = np.random.randint(50, 100, size=(10,1))
c = np.random.randint(500, 700, size=(10,1))
X = np.concatenate((a,b,c), axis=1)
X

X представляет значения в кадре данных с 3 столбцами и 10 строками. Столбцы представляют функции. Среднее и стандартное отклонение каждого столбца:

Столбцы сильно различаются по среднему значению и стандартному отклонению.

Теперь мы можем создать объект StandardScaler и подогнать под него X.

sc = preprocessing.StandardScaler().fit(X)

X можно преобразовать, применив метод преобразования к объекту StandardScaler.

X_standardized = sc.transform(X)
X_standardized

Давайте посчитаем среднее значение и стандартное отклонение преобразованных функций.

Среднее значение каждого признака очень близко к 0, и все признаки имеют дисперсию единицы (1). Обратите внимание, что стандартное отклонение - это квадратный корень из дисперсии. Стандартное отклонение 1 означает, что дисперсия равна 1.

Здесь я хотел бы подчеркнуть очень важный момент. Предположим, мы работаем над задачей обучения с учителем, поэтому мы разделили набор данных на обучающие и тестовые подмножества. В этом случае мы используем только fit обучающий набор для стандартного объекта масштабирования, а не для всего набора данных. Нам, конечно, нужно преобразовать тестовый набор, но это делается с помощью метода преобразования.

  • StandardScaler.fit (X_train)
  • StandardScaler.transform (X_train)
  • StandardScaler.transform (X_test)

Подгонка всего набора данных к стандартному объекту масштабирования заставляет модель узнавать о наборе тестов. Однако модели не должны ничего узнавать о тестовом наборе. Это разрушает цель разделения поезд-тест. Обычно эта проблема называется утечкой данных.



Когда мы преобразуем тестовый набор, функции не будут иметь точно нулевое среднее значение и единичное стандартное отклонение, потому что средство масштабирования, используемое при преобразовании, основано на обучающем наборе. Величина изменения в тестовой выборке такая же, как и в обучающей. Создадим образец набора тестов и преобразуем его.

X_test = np.array([[8, 90, 650], [5, 70, 590], [7, 80, 580]])
X_test

X_test_transformed = sc.transform(X_test)
X_test_transformed

Среднее и стандартное отклонение столбцов тестового набора:

MinMaxScaler и RobustScaler

Другой способ привести диапазоны значений к аналогичному уровню - масштабировать их в определенном диапазоне. Например, мы можем сжать каждый столбец между 0 и 1 таким образом, чтобы минимальное и максимальное значения перед масштабированием стали 0 и 1 после масштабирования. Такое масштабирование может быть достигнуто с помощью MinMaxScaler scikit learn. Диапазон по умолчанию - [0,1], но мы можем изменить его с помощью параметра feature_range.

from sklearn.preprocessing import MinMaxScaler
mm_scaler = MinMaxScaler()
X_scaled = mm_scaler.fit_transform(X)
X_scaled

mm_scaler2 = MinMaxScaler(feature_range=(0,10))
X_scaled2 = mm_scaler2.fit_transform(X)
X_scaled2

StandardScaler и MinMaxScaler не устойчивы к выбросам. Предположим, у нас есть функция, значения которой находятся в диапазоне от 100 до 500 с исключительным значением 15000. Если мы масштабируем эту функцию с MinMaxScaler(feature_range=(0,1)), 15000 масштабируется как 1, а все остальные значения становятся очень близкими к нижней границе, которая равна нулю. Таким образом, мы получаем непропорциональный масштаб, который отрицательно сказывается на производительности модели. Одно из решений - удалить выбросы, а затем применить масштабирование. Однако удаление выбросов не всегда является хорошей практикой. В таких случаях мы можем использовать RobustScaler scikit-learn.

RobustScaler, как следует из названия, устойчив к выбросам. Он удаляет медианное значение и масштабирует данные в соответствии с квантильным диапазоном (по умолчанию IQR: межквартильный диапазон). IQR - это диапазон между 1-м квартилем (25-й квантиль) и 3-м квартилем (75-й квантиль). RobustScaler не ограничивает масштабируемый диапазон заранее определенным интервалом. Таким образом, нам не нужно указывать диапазон, как мы это делаем для MinMaxScaler.

Мы можем увидеть разницу между MinMaxScaler и RobustScaler, добавив ряд выбросов к нашему предыдущему набору данных.

X_new = np.append(X, np.array([[50,420,1400]]), axis=0)
X_new

Давайте сначала применим MinMaxScaler с диапазоном [0,1].

X_new_mm = mm_scaler.fit_transform(X_new)
X_new_mm

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

Как насчет RobustScaler?

from sklearn.preprocessing import RobustScaler
r_scaler = RobustScaler()
X_new_rs = r_scaler.fit_transform(X_new)
X_new_rs

Когда какой использовать?

Мы рассмотрели StandardScaler, MinMaxScaler и RobustScaler. Многие модели машинного обучения выигрывают от наличия функций в аналогичных масштабах. Однако не существует строгого правила, определяющего, какой вид преобразования оптимален для конкретного алгоритма.

И MinMaxScaler, и StandardScaler чувствительны к выбросам. Таким образом, в случае выбросов, которые мы не можем удалить, RobustScaler - лучший выбор, чем два других.

Без наличия выбросов MinMaxScaler в большинстве случаев работает хорошо. Однако алгоритмы глубокого обучения (например, нейронные сети) и алгоритмы регрессии выступают за наличие функций с нормальным распределением. StandardScaler - лучший выбор для таких случаев.

Это наиболее часто используемые методы трансформации, которые в целом удовлетворяют наши потребности. Scikit-learn также предоставляет более конкретные преобразования, которые объясняются в документации пакета предварительной обработки.

Спасибо за чтение. Пожалуйста, дайте мне знать, если у вас есть какие-либо отзывы.