Функциональный трансформер, как создавать и когда использовать
Функциональная трансформация поможет быстро создать преобразование колонок для пайплайна без сохранения состояния (создание других описывал здесь). Эта возможность реализована в классе FunctionTransformer из модуля sklearn.preprocessing. Например, это могут быть преобразования для создания цикличных признаков (из месяца, часа как здесь) или для извлечения слов из текста, его длины или других характеристик. Создадим демонстрационный набор из температур по месяцам и сделаем из месяца цикличный признак с помощью функционального трансформера:
import pandas as pd import numpy as np np.random.seed(5) temp_avg_d = {1:0, 2:-2, 3:15, 4:20, 5:25, 6:28, 7:30, 8:27, 9:20, 10:12, 11:7, 12: 2} mon_ar = np.tile(np.arange(1, 13), 3) ts = pd.DataFrame({'mon':mon_ar}) ts['t'] = ts['mon'].map(lambda x:temp_avg_d[x] + np.random.normal(loc=0, scale=2)) ts.head()
func
Основным аргументом необходимым классу FunctionTransformer является пользовательская функция:
from sklearn.preprocessing import FunctionTransformer def sin_transformer(period): return FunctionTransformer(lambda x: np.sin(2 * np.pi* x / period )) def cos_transformer(period): return FunctionTransformer(lambda x: np.cos(2 * np.pi * x / period ))
Теперь с помощью ColumnTransformer проверим работу трансформеров:
from sklearn.compose import ColumnTransformer ct = ColumnTransformer(transformers=[('sin', sin_transformer(12), ['mon']), ('cos', cos_transformer(12), ['mon'])], remainder='passthrough') ct.fit_transform(ts)[:5]
inverse_func
В FunctionTransformer можно передавать функцию обратного преобразования. В нашем случае оно неоднозначно (arcsin), но в демонстрационных целях приведем пример:
sin_tr = FunctionTransformer(lambda x: np.sin(2 * np.pi* x / 12), inverse_func=lambda x: np.arcsin(x)*12/(2*np.pi)) sin_tr.fit_transform(np.array([[1, 3, 6]])), sin_tr.inverse_transform(np.array([[0.5, 1, 0]]))
check_inverse
Даже вылетает предупреждение о том, что переданные функции не являются строго обратными. Сообщение можно приглушить с параметром check_inverse=False:
sin_tr = FunctionTransformer(lambda x: np.sin(2 * np.pi* x / 12), check_inverse=False, inverse_func=lambda x: np.arcsin(x)*12/(2*np.pi)) sin_tr.fit_transform(np.array([[1, 3, 6]])), sin_tr.inverse_transform(np.array([[0.5, 1, 0]]))
feature_names_out
Данный аргумент определяет то, как будут называться колонки после преобразования, например, если попытаться извлечь без использования параметра, получим ошибку:
sin_tr.fit(ts[['mon']]).get_feature_names_out()
feature_names_out='one-to-one' позволит сохранить имена после преобразований:
sin_tr = FunctionTransformer(lambda x: np.sin(2 * np.pi* x / 12), feature_names_out='one-to-one') sin_tr.fit(ts[['mon']]).get_feature_names_out()
Можно изменить именование, если передать в параметр feature_names_out функцию, которая получает в качестве параметров ссылку на объект FunctionTransformer и старые имена, а возвращает новые имена:
sin_tr = FunctionTransformer(lambda x: np.sin(2 * np.pi* x / 12), feature_names_out=lambda x, names: [f'tr_{it}' for it in names]) sin_tr.fit(ts[['mon']]).get_feature_names_out()
kw_args, inv_kw_args
Эти параметры позволяют передать словарь аргументов в функции func и inverse_func. Переделаем cos_transformer, определенный выше:
ct = ColumnTransformer(transformers=[('cos', FunctionTransformer(lambda x, period: np.cos(2 * np.pi* x / period ), kw_args={'period':12}), ['mon'])] , remainder='passthrough') ct.fit_transform(ts)[:5]