Вступление

Как лучше спроектировать данные - одна из основных задач при разработке функций. За исключением обработки данных, такой как вменение пропущенного значения, слияние и т. Д., Создание новых столбцов и преобразование существующих столбцов в контролируемом обучении важно для различения меток с полными изображениями данных и уменьшения несущественного шума. Если данные беспорядочные и совершенно не могут сказать вам, в чем заключаются основные различия между метками с несколькими необработанными столбцами, какие бы впечатляющие методы ни использовались, или насколько хороша модель, результат в большинстве случаев будет очень разочаровывающим. По этой причине я хочу поделиться некоторыми общими и общими способами мозгового штурма более полезных функций в большинстве случаев. Более того, я надеюсь, что читатели захотят поделиться со мной дополнительными знаниями!

Темы будут рассмотрены в следующем:

  1. Числовые переменные
  2. Переменные временного ряда
  3. Категориальные переменные

Машинное обучение пожирает то, что вы даете

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

Числовые особенности # 1

  • Преобразовать в логарифм

Логарифмы могут естественным образом уменьшить динамический диапазон переменной, поэтому различия сохранятся, а масштаб не будет сильно искажен. Например, в одной переменной некоторые люди получили ссуды на 100000000 долларов, некоторые - на 10000 долларов, а некоторые - на 0 долларов. Если мы собираемся масштабировать эту переменную без логарифма, шкала примет 0 и 10 000 долларов очень похоже друг на друга и повлияет на границу.

import numpy as np
## For columns with a small input value, using np.log1p to get more accurate result than np.log
data['log_col'] = data[col].apply(np.log1p)
## For columns with a small input value
data['log_col'] = data['col'].apply(np.log)
  • Группирование числовых переменных

Числовые столбцы иногда сталкиваются с проблемой асимметрии, которая влияет на модель машинного обучения, изучающую данные (например, выброс с чрезвычайно высоким или низким значением). Несомненно, ввод необработанных числовых данных без преобразования иногда оказывает обратное влияние на результат. Биннинг значений включает 1) фиксированный диапазон и 2) адаптивный диапазон.

1) Разбиение значений - фиксированный диапазон

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

import pandas as pd
bins = [20,40,60,80,100]
bins_labels = [1,2,3,4]
## If want to take range as labels
data['bin_range_col'] = pd.cut(data['col'], bins=bins)
## If pre-defined labels
data['bin_label_col'] = pd.cut(data['col'], bins=bins,   labels=bins_labels)

2) Разбиение значений - Адаптивный диапазон

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

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

import pandas as pd
## Pre-defined the bins by training dataset only
cat_series, bins = pd.qcut(train_data['col'], bins, retbins=True, labels=False)
## Transform the pre-defined the bins to both datasets.
train_data['col_group'] = pd.cut(train_data['col'], bins=bins, labels=False, include_lowest=True)            
test_data['col_group'] = pd.cut(test_data['col'], bins=bins, labels=False, include_lowest=True)
  • Преобразовать результат GROUPBY в каждую строку

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

## General case
data['new_col'] = data.groupby('parent_col')['child_col'].transform(func)

Вычислить относительное значение в соответствии с результатом GROUPBY

data[relative_value] = data['child_col'] / data.groupby(['parent_col'])['child_col'].transform('mean')

Особенности временных рядов # 2

  • Изменение в процентах для функций на основе временных рядов

Для столбцов, основанных на временных рядах, им иногда необходимо понять, что происходит между текущей строкой и предыдущими (t-1, t-2… t-n) строками. Изменение в процентах - хороший показатель для сравнения. Следующий пример будет использоваться numba и numpy для увеличения скорости вычислений:

from numba import jit
import numpy as np
import pandas as pd
## Traditional Way
@jit(nopython=True, parallel=True)
def change(col):  
    len = col.shape[0]  
    vc = np.zeros(len)
    for i in range(1,len):
        vc[i] = (col[i]-col[i-1])/col[i-1]
    return vc
data['pct_ch_col'] = change(data['col'])
## Convenient Way (With Pandas Function)
df['pct_ch_col'] = df['col'].pct_change(1)
  • Сдвиг (отставание) функций

Кроме того, в функциях временных рядов пользователи могут сдвигать значения (t-1, t-2… t-n) в текущую строку как полунезависимые переменные. Вот пример смещения:

## x: the desired fallback period
x = 1
data[f'col_shift_{x}'] = data['col'].shift(x
  • Обработка даты

Аналитики считают, что для столбца даты шаблон даты каким-то образом повлияет на результат, а сезонный шаблон будет повторяться в указанном диапазоне дат, например Год, Месяц, День недели и т. Д.

data['Year'] = data['date'].dt.year
data['Quarter'] = data['date'].dt.quarter
data['Month'] = data['date'].dt.month
data['Week_of_year'] = data['date'].dt.week
data['Day_of_week'] = data['date'].dt.dayofweek
date['Weekend'] = data['Day_of_week'].apply(lambda x: 'Weekend' if x >= 5 else 'Weekday')
  • Скользящее окно

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

data['rolling_mean'] = data['Close'].rolling(window=7).mean()
date[['Date', 'Close', 'rolling_mean']].head(15)

  • Расширяющееся окно

Expanding Window - это другая версия Rolling Window. Поскольку скользящее окно учитывает только недавнюю статистику данных и игнорирует прошлое значение, возникает риск потери статистической информации прошлого значения, которой нет в окне.

Expanding Window продолжает расширять диапазон вычислений по прошествии времени и вычислять статистику всех прошлых значений.

qt['expanding_mean'] = data['Close'].expanding(min_periods=7).mean()
qt[['Date', 'Close', 'expanding_mean']].iloc[:15]

Категориальные особенности # 3

Категориальные переменные, также известные как номинальные переменные, которые содержат как минимум две категории. Например, цвета (желтый, синий, красный), пол (мужской, женский), страна и т. Д. Их нельзя упорядочить по разным категориям. В машинном обучении в большинстве моделей используется математика, поэтому их трудно выучить необработанные обозначения категориальных переменных. Эти переменные необходимо преобразовать в обучаемую структуру для обучения этим моделям. Кроме того, вы можете переносить числовые переменные в категориальные переменные в некоторых случаях, например, при использовании метода биннинга (см. Часть 1).

  • Кодировщик этикеток

Label Encoder включен в Scikit-Learn, он преобразует категориальную переменную в числовую переменную. Вот пример преобразования цвета в значение.

In[]:
from sklearn.preprocessing import LabelEncoder
colors = ["red", "blue", "red", "yellow"]
transformer = LabelEncoder()
transformer.fit(colors)
transformer.transform(["red", "red", "yellow"])
Out[]:
array([1, 1, 2], dtype=int64)
  • One-Hot Encoder

В отличие от Label Encoder, One-Hot Encoder преобразует данные как фиктивные переменные и установит их как метку [0,1] для каждой категории.

Поскольку Label Encoder преобразует категории в ряд чисел, иногда модель ошибочно думает, что существует корреляция между преобразованными категориальными переменными с другими числовыми переменными, в конечном итоге модель также ошибочно узнает корреляцию, которая, как предполагается, изначально не существовала. .

In[]:
import pandas as pd
colors = ["red", "blue", "red", "yellow"]
colors = pd.Series(colors)
pd.get_dummies(colors)
Out[]:
    blue  red  yellow
0      0    1       0
1      1    0       0
2      0    1       0
3      0    0       1
  • Категориальное объединение (Очистка)

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

In[]:
import pandas as pd
phone = ["samsung-note-10", "Samsung-note-7", "iPhone8", "iphone10", "LG-G8", "Lg-V40"]
phone_series = pd.Series(phone)phone_type = np.where(phone_series.str.contains('samsung',case=False),'Samsung', 
np.where(phone_series.str.contains('iphone',case=False),'iPhone', 
np.where(phone_series.str.contains('LG',case=False), 'LG','Other')))phone_type
Out[]:
array(['Samsung', 'Samsung', 'iPhone', 'iPhone', 'LG', 'LG'])
  • Взаимодействие с категориальными переменными (создание)

Комбинирование категориальных переменных может создать новую переменную или объединить набор переменных, а затем привести нас к новому пониманию или помочь нам детализировать полезные детали. Мы просто сделаем простую работу, тогда мы, вероятно, получим сюрприз !!

import pandas as pd
df['interaction_col'] = df['cat_variable_A'] + df['cat_variable_B']

Заключение

Разработка функций занимает ~ 80% рабочей нагрузки в процессе машинного обучения, что очень сложно. Я надеюсь, что прочитав эту статью, вы получите вдохновение для создания новых функций. Эта статья посвящена применению создания новых функций, способам обогащения данных и обмену моими знаниями. Если у вас есть идеи или вопросы, вы можете связаться со мной через LinkedIn или по электронной почте: [email protected], а затем поздороваться!