Преобразование данных - важная часть набора инструментов специалиста по данным. Поскольку мы изменяем данные, мы должны быть осторожны с методами и причинами, которые мы используем для этих манипуляций. В этой статье мы рассмотрим использование модуля силового трансформатора sklearn, который содержит как преобразование Бокса-Кокса, так и преобразование Йео-Джонсона.

Наиболее распространенное статистическое предположение, которое делают ученые, состоит в том, что их данные получены в результате распределения Гаусса, и, кроме того, многие из наиболее распространенных моделей машинного обучения построены на этом предположении. Поскольку многие инструменты машинного обучения требуют данных, подобных гауссу, первая проверка перед реализацией модели заключается в том, чтобы определить, являются ли данные подобными Гауссу. Существуют различные подходы к проверке нормальности. Тестирование на нормальность делится на две большие категории: визуальные проверки (гистограммы, QQ-графики) и статистические методы (тест Шапиро-Уилка, тест Д’Агостино K ^ 2).

Проверка на нормальность

Для этого кода я собираюсь работать с частью набора данных Ames Housing. Если у вас есть доступ, вы можете использовать свою копию. Если нет, то я дал ссылку здесь. Если вы изучите данные, мы можем использовать любое количество различных функций, но я решил использовать Garage Area. Быстрый EDA покажет, что существует одно нулевое значение, для простоты я заменил это нулевое значение на ноль. Кроме того, в данных есть множество нулей, давайте просто предположим, что нули представляют дома, в которых нет гаража.

#Load the Data
df = pd.read_csv(‘./train.csv’)
#Checking for Nulls / EDA 
nulls = df[‘Garage Area’].isnull().sum()
print (f’The numbers of nulls: {nulls}’)
#Replace the Null with 0 
df[‘Garage Area’] = df[‘Garage Area’].replace(np.nan, 0)
nulls = df[‘Garage Area’].isnull().sum()
print (f’The numbers of nulls: {nulls}’)
#Drop Zeros from the pd.series (if zero we can assume that a garage is not around) 
garage_area = df[‘Garage Area’]
garage_area = garage_area[garage_area != 0]

Допустим, вы думаете об использовании метода силового трансформатора. Мы не только хотим проверить нормальность перед применением преобразования, но также можем собрать дополнительную информацию о текущем распределении данных, например, эксцесс и перекос. Самый простой способ сделать это - построить простую гистограмму.

#Plot a Histogram of the data 
ax = sns.distplot(garage_area, kde=True)
ax.set(xlabel= ‘Garage Area (ft²)’, ylabel=’Counts’, title=’Frequency of Garage Sizes (ft²)’)
plt.show()

Как упоминалось выше, эксцесс и перекос - два общих термина, с которыми вы можете столкнуться при описании нормальности. На гистограмме переменной площади гаража ясно видно, что распределение неравномерное (нормальное). Мы можем формально рассчитать перекос распределения, используя статистическую модель SciPy, в данном случае 0,80.

Хорошая эвристика, которую вы можете использовать для оценки этого значения, находится в таблице ниже, и в этом случае распределение площади гаража умеренно искажено. Менее распространенная описательная статистика, с которой вы можете столкнуться, - это эксцесс. Как и перекос, эксцесс описывает распределение. Одна из причин, по которой мы меньше говорим о эксцессе, заключается в том, что его терминология может сбивать с толку. Чтобы упростить ситуацию, давайте просто поговорим о положительном и отрицательном эксцессе. Положительный эксцесс (больше 1) означает, что плечи распределения слишком узкие, а отрицательный эксцесс (меньше 0) означает, что плечи распределения слишком широкие. В этом случае у нас есть эксцесс, равный 0,81, и, следовательно, распределение показывает положительный избыточный эксцесс.

Теперь, когда мы визуально проверили и описали текущее распределение переменной площади гаража, мы можем использовать статистический подход, называемый тестом Д’Агостино K2. Проще говоря, этот статистический тест вычисляет эксцесс и перекос распределения и сравнивает его с нормальным распределением. В нашем случае возвращенное значение p было равно 3,07 x 10–45, и поэтому образец не выглядит гауссовым, и мы можем отклонить нулевую гипотезу.

Что касается статистических тестов на нормальность, как Шапиро-Уилка, так и Д’Агостино, я хочу включить это важное предостережение. С небольшими выборками, скажем, менее 50, тесты на нормальность малоэффективны. В этих случаях очень важны визуальный осмотр, перекос и эксцесс данных. Вы также можете рассмотреть возможность использования тестов на выбросы, таких как Grubs, а затем повторно протестировать перекос и эксцесс.

Использование модуля силового трансформатора Sklearn

Теперь, когда мы оценили нормальность наших данных, давайте перейдем к использованию модуля силового трансформатора в sklearn. Как следует из названия, мы собираемся изменить (или преобразовать) данные в нашей входной переменной, в области гаража. Это может показаться тревожным, но помните, что мы постоянно меняем данные. Некоторые распространенные примеры - преобразование единиц измерения, сантиметр в метр или преобразование между градусами Цельсия и Фаренгейта. Ключевое отличие состоит в том, что преобразования, которые я только что описал, не изменяют распределение данных, но преобразование мощности изменит распределение данных. Модуль предварительной обработки силового трансформатора sklearn содержит два различных преобразования:

  • Преобразование Бокса-Кокса: можно использовать только для положительных значений.
  • Преобразование Йео-Джонсона: можно использовать как для положительных, так и для отрицательных значений.

Зачем использовать модуль силовых трансформаторов?

При создании модели линейной регрессии мы делаем некоторые предположения о данных, которые мы используем в модели. Эти предположения резюмированы журналом L.I.N.E. аббревиатура.

  • В СТРОКЕ N = нормальность (ошибки соответствуют нормальному распределению).
  • В СТРОКЕ E = Равенство дисперсий, гомоскедастичность.

Преобразование Бокса-Кокса

Прежде чем мы начнем использовать модуль sklearn, давайте рассмотрим пример кода с использованием math. В этом примере я выбрал два произвольных значения лямбда, 0,1 и 1,0, чтобы продемонстрировать силу преобразования box-cox.

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

Визуализация изменений

Если вам интересно посмотреть, как параметр лямбда влияет на размер преобразования, я предлагаю использовать метод нормализации, такой как Z-оценка или Min-Max Scaler. В этом примере я пошел дальше и использовал Z-оценку, которая дает нулевое среднее значение, и поэтому мы должны переключиться с Бокс-Кокса на Йео-Джонсон.

На гистограммах ниже показаны нормализованные характеристики площади гаража, а затем нанесены на график использованные морские гребни kdeplot.

Если мы визуально проверим эти гистограммы, мы увидим, что большее значение лямбда (1,5) не уменьшает правое плечо. Меньшие значения лямбда (0,1 и 0,58) заметно уменьшают то же плечо.

Реализация Sklearn

Теперь мы эффективно прошли через методы преобразования мощности SciPy, используя одну особенность - площадь гаража. Однако, если мы хотим преобразовать несколько функций одновременно, методы SciPy не будут работать, потому что они принимают один массив. В этом заключается сила реализации sklearn, вы можете передать в модуль несколько функций. Возвращаясь к набору данных Эймса, давайте теперь посмотрим на площадь гаража и площадь участка. Проделывая тот же процесс, нам нужно немного очистить данные. Чтобы сделать это с несколькими функциями, реализация логической маски удалит строки, в которых площадь гаража была равна нулю, и соответствующая строка на участке одновременно.

Подгонка и преобразование данных

Если вы знакомы с другими модулями sklearn, то рабочий процесс для силовых трансформаторов будет иметь полный смысл. Первый шаг - ненасытить модель. Когда вы ненасытите модель, обратите внимание на несколько значений по умолчанию в параметрах:

  • методы = ‘yeo-johnson’
  • standardize = True (применяет к выходным данным нормализацию с нулевым средним и единичной дисперсией)

Затем метод .fit вычислит оптимальные лямбды для включенных вами функций. Доступ к этим значениям можно получить с помощью .lambdas_. Затем, используя метод .tranform, мы применяем вычисленные лямбда-выражения к функциям и передаем преобразованные данные в новый фрейм данных. Хорошая проверка работоспособности - убедиться, что рабочий процесс работает так, как вы предполагали, сделайте это, повторно запустив stats.normaltest и сравните результаты. Исходное значение p было равно 3,07 x 10 ^ -45, а после преобразования оно равно 0,130. Следовательно, мы не можем отвергнуть нулевую гипотезу.

Выводы

Как видно из этого кода, SciPy и Sklearn предоставляют методы для преобразования мощности. Одним из ключевых преимуществ реализации sklearn является то, что вы можете передавать в преобразователь сразу несколько функций. У меня есть и другие записные книжки в репозитории github, которые могут вам пригодиться.

Хорошие лакомые кусочки

Использованная литература:

[1] http://www.kmdatascience.com/2017/07/box-cox-transformations-in-python.html