Как предварительно обработать числовые признаки с разными диапазонами значений
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 также предоставляет более конкретные преобразования, которые объясняются в документации пакета предварительной обработки.
Спасибо за чтение. Пожалуйста, дайте мне знать, если у вас есть какие-либо отзывы.