Вступление
Как лучше спроектировать данные - одна из основных задач при разработке функций. За исключением обработки данных, такой как вменение пропущенного значения, слияние и т. Д., Создание новых столбцов и преобразование существующих столбцов в контролируемом обучении важно для различения меток с полными изображениями данных и уменьшения несущественного шума. Если данные беспорядочные и совершенно не могут сказать вам, в чем заключаются основные различия между метками с несколькими необработанными столбцами, какие бы впечатляющие методы ни использовались, или насколько хороша модель, результат в большинстве случаев будет очень разочаровывающим. По этой причине я хочу поделиться некоторыми общими и общими способами мозгового штурма более полезных функций в большинстве случаев. Более того, я надеюсь, что читатели захотят поделиться со мной дополнительными знаниями!
Темы будут рассмотрены в следующем:
- Числовые переменные
- Переменные временного ряда
- Категориальные переменные
Машинное обучение пожирает то, что вы даете
Я считаю, что многие специалисты по обработке данных и аналитики, которые все еще очень полагаются на машинное обучение, могут обнаружить в своих данных некоторые неизвестные закономерности. Действительно, они могут изучать данные быстро и точно, но они сильно зависят от того, какие данные им были предоставлены. В этой серии статей я хотел бы поделиться некоторыми ключевыми способами преобразования и разработки данных в числовых функциях и категориальных функциях. Прежде всего, хотелось бы остановиться на числовых характеристиках.
Числовые особенности # 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], а затем поздороваться!