Въведение

Как да проектирате вашите данни по-добре —е една от основните грижи в инженерството на функциите. Освен обработката на данни като вписване на липсващата стойност, сливане и т.н., генерирането на нови колони и трансформирането на съществуващи колони в контролираното обучение е важно за разграничаване на етикетите с пълни картини на данните и намаляване на несъществения шум. Ако данните са объркани и напълно не могат да ви кажат какви са основните разлики между етикетите само с няколко необработени колони, каквито и впечатляващи техники да се използват или колко добър е моделът, резултатът най-вече ще бъде много разочароващ. Поради тази причина искам да споделя някои често срещани и общи начини за обмисляне на по-полезни функции в повечето случаи. Още повече, надявам се, че читателите са готови да споделят повече знания с мен!

Темите ще бъдат разгледани в следното:

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

Машинното обучение изяжда това, което давате

Вярвам, че много учени и анализатори на данни, които все още разчитат много на машинното обучение, могат да открият някои неизвестни модели в своите данни. Наистина те могат да научат данните бързо и точно, но са силно зависими от това какви данни са им дадени. В тази серия бих искал да споделя някои ключови начини за трансформация на данни и инженеринг в числови характеристикиикатегориални характеристикии. Първо, бих искал да се съсредоточа върху числените характеристики.

Числени характеристики #1

  • Преобразуване в логаритъм

Логаритмите могат естествено да намалят динамичния обхват на променлива, така че разликите да се запазят, докато мащабът не е толкова драматично изкривен. Например, в една променлива някои хора са получили $100 000 000 заеми, някои са получили $10 000, а други са получили $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. Тъй като 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

За разлика от 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], след което кажете здравей!