📊 Построение и отбор признаков. Часть 2: feature selection
Мы уже знаем, что такое признаки и почему они важны в моделях машинного обучения. Попробуем разобраться со следующей после построения “фич” техникой – их отбором.
Что такое отбор признаков?
«Прогонка» всех признаков в модели, чтобы посмотреть, какие из них работают – плохая идея. На самом деле алгоритмы работают плохо, когда в них попадает слишком много “фич”. Как решить эту проблему? При помощи отбора признаков.
Существует масса алгоритмов, которые преобразуют набор со слишком большим количеством признаков в управляемое подмножество. Как и в случае с построением признаков, для разных типов данных оптимальны разные способы. Более того, при выборе алгоритма необходимо учитывать наши цели, что мы хотим сделать с обрабатываемым датасетом.
Выбор наиболее оптимальных признаков из множества существующих – непростая задача. Большое их количество значительно увеличивает время вычислений, к тому же, появляется угроза переобучения.
1. Методы фильтрации (filter methods)
Выбирают внутренние свойства признаков – они быстрее и менее затратны с точки зрения вычислений, чем методы-оболочки. При работе с данными большой размерности в вычислительном отношении дешевле использовать методы фильтрации.
Сбор информации (Information Gain, IG)
Вычисляет уменьшение энтропии в результате преобразования набора данных. Его можно использовать для отбора признаков путем оценки информационного прироста каждой переменной в контексте целевой переменной.
import pandas as pd import numpy as np from sklearn.feature_selection import mutual_info_classif import matplotlib.pyplot as plt importances = mutual_info_classif(X, y) # Где data - ваш датасет; X, y – входные и выходные данные соответственно feature_importances = pd.Series(importances, data.columns[0:len(data.columns)-1]) feature_importances.plot(kind='barh', color='teal') plt.show()
Критерий хи-квадрат (Chi-square Test)
Используется для категориальных признаков в датасете. Мы вычисляем хи-квадрат между каждым признаком и целью, после выбираем желаемое количество “фич” с лучшими показателями. Чтобы правильно применить критерий для проверки связи между различными функциями в наборе данных и целевой переменной, должны быть выполнены следующие условия: категориальные переменные, которые выбираются независимо, и частота значений > 5.
import pandas as pd import numpy as np from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 # Преобразование в категориальные данные путем преобразования в целые числа. # Где X, y - входные и выходные данные соответственно. X_categorical = X.astype(int) # Выбираем 3 признака с наивысшим "хи-квадрат". chi2_features = SelectKBest(chi2, k = 3) X_kbest_features = chi2_features.fit_transform(X_categorical, y) # Вывод "до и после" print("Количество признаков до преобразования:", X_categorical.shape[1]) print("Количество признаков после преобразования:", X_kbest_features.shape[1])
Критерий Фишера (F-тест)
Критерий Фишера – один из наиболее широко используемых методов контролируемого выбора признаков. Алгоритм, который мы будем использовать, возвращает ранги переменных на основе оценки критерия в порядке убывания, после чего уже следует их отбор.
import pandas as pd import numpy as np from skfeature.function.similarity_based import fisher_score import matplotlib.pyplot as plt # Вычисляем критерий # Где X, y - входные и выходные данные соответственно. ranks = fisher_score.fisher_score(X, y) # Делаем график наших "фич" # Где data - ваш датасет feature_importances = pd.Series(ranks, data.columns[0:len(data.columns)-1]) feature_importances.plot(kind='barh', color='teal') plt.show()
Коэффициент корреляции
Стоит отметить, что переменные должны коррелировать с целевым показателем, но не должны между собой. В примере ниже мы будем использовать корреляцию Пирсона.
import seaborn as sns import matplotlib.pyplot as plt # Матрица корреляции # Где data - ваш датасет correlation_matrix = data.corr() # Выводим признаки на тепловую карту plt.figure(figsize= (10, 6)) sns.heatmap(correlation_matrix, annot = True)
Абсолютное отклонение (Mean Absolute Difference, MAD)
Эта техника позволяет нам вычислить абсолютное отклонение от среднего.
import pandas as pd import numpy as np import matplotlib as plt # Вычисляем MAD # Где X - входные данные mean_absolute_difference = np.sum(np.abs(X - np.mean(X, axis = 0)), axis = 0) / X.shape[0] # Наш график признаков plt.bar(np.arange(X.shape[1]), mean_absolute_difference, color = 'teal')
2. Методы обертки (wrapper methods)
Процесс выбора функции основан на конкретном алгоритме машинного обучения, который мы используем. Он следует подходу жадного поиска, оценивая все возможные комбинации функций по определенному критерию. Методы оболочки обычно обеспечивают лучшую точность прогнозирования чем методы фильтрации.
Прямой отбор признаков
Это крайне прямолинейный метод, в котором мы начинаем с наиболее эффективной переменной по отношению к цели. Затем мы выбираем другую переменную, которая дает лучшую производительность в сочетании с первой. Этот процесс продолжается до тех пор, пока не будет достигнут заданный критерий.
from sklearn.linear_model import LogisticRegression from mlxtend.feature_selection import SequentialFeatureSelector lr = LogisticRegression(class_weight = 'balanced', solver = 'lbfgs', random_state=42, n_jobs=-1, max_iter=50e) ffs = SequentialFeatureSelector(lr, k_features='best', forward = True, n_jobs=-1) ffs.fit(X, Y) # X, y – входные и выходные данные соответственно. # X_train – входные данные с обучающейся выборки, # y_pred – выходные данные предиктора features = list(ffs.k_feature_names_) features = list(map(int, features)) y_pred = lr.predict(X_train[features])
Последовательный отбор признаков
Этот метод работает прямо противоположно методу прямого выбора характеристик. Здесь мы начинаем со всех доступных функций и строим модель. Затем мы используем переменную из модели, которая дает наилучшее значение меры оценки. Этот процесс продолжается до тех пор, пока не будет достигнут заданный критерий.
from sklearn.linear_model import LogisticRegression from mlxtend.feature_selection import SequentialFeatureSelector lr = LogisticRegression(class_weight = 'balanced', solver = 'lbfgs', random_state=42, n_jobs=-1, max_iter=50e) lr.fit(X, y) bfs = SequentialFeatureSelector(lr, k_features='best', forward = False, n_jobs=-1) bfs.fit(X, y) features = list(bfs.k_feature_names_) features = list(map(int, features)) lr.fit(X_train[features], y_train) y_pred = lr.predict(x_train[features])
Исчерпывающий выбор признаков
Это самый надежный метод выбора функций из всех существующих. Его суть – оценка каждого подмножества функций методом перебора. Это означает, что метод пропускает все возможные комбинации переменных через алгоритм и возвращает наиболее эффективное подмножество.
from mlxtend.feature_selection import ExhaustiveFeatureSelector from sklearn.ensemble import RandomForestClassifier # создаем ExhaustiveFeatureSeLlector объект. efs = ExhaustiveFeatureSelector(RandomForestClassifier(), min_features=4, max_features=8, scoring='roc_auc', cv=2) efs = efs.fit(X, Y) # выводим выбранные признаки selected_features = X_train.columns[list(efs.best_idx_)] print(selected_features) # выводим финальную оценку прогнозирования. print(efs.best_score_)
Рекурсивное исключение признаков
Сначала модель обучается на начальной выборке признаков, и важность каждой функции определяется либо с помощью атрибута coef_
или feature_importances_
. Затем наименее важные “фичи” удаляются из текущего набора. Процедура рекурсивно повторяется для сокращенного набора до тех пор, пока в конечном итоге не будет достигнуто желаемое количество признаков для выбора.
from sklearn.linear_model import LogisticRegression from sklearn.feature_selection import RFE lr = LogisticRegression(class_weight = 'balanced', solver = 'lbfgs', random_state=42, n_jobs=-1, max_iter=50e) rfe = RFE(lr, n_features_to_select=7) rfe.fit(X_train, y_train) # X_train, y_train - входные и выходные данные с обучающей выборки соответственно. y_pred = rfe.predict(X_train)
3. Встроенные методы (embedded methods)
Регуляризация LASSO (L1)
Регуляризация состоит в добавлении штрафа (penalty) к различным параметрам модели во избежание чрезмерной подгонки. При регуляризации линейной модели штраф применяется к коэффициентам, умножающим каждый из предикторов. Lasso-регуляризация обладает свойством, позволяющим уменьшить некоторые коэффициенты до нуля. Следовательно, такие “фичи” можно будет просто удалить из модели.
from sklearn.linear_model import LogisticRegression from sklearn.feature_selection import SelectFromModel # Устанавливаем наш параметр регуляризации C=1 logistic = LogisticRegression(C=1, penalty="l1", solver='liblinear', random_state=7).fit(X, y) # Где X, y - входные и выходные данные соответственно. model = SelectFromModel(logistic, prefit=True) X_new = model.transform(X) # Выбираем нужные нам столбцы из датасета без нулевых данных # Где “selected_features” - предварительно выбранные нами признаки (см. по предыдущим методам) selected_columns = selected_features.columns[selected_features.var() != 0] print(selected_columns)
Метод с использованием Случайного Леса (Random Forest Importance)
Стратегии на основе дерева, используемые случайными лесами, естественным образом ранжируются по тому, насколько хорошо они улучшают чистоту модели в плане данных. Таким образом, “обрезая” деревья ниже определенного коэффициента, мы можем подобрать наиболее важные признаки.
import numpy as np import pandas as pd from sklearn.ensemble import RandomForestClassifier # создаем случайное дерево с вашими гипер параметрами model = RandomForestClassifier(n_estimators=340) # Обучаем модель на вашей выборке; Где X, y - входные и выходные данные соответственно. model.fit(X, y) # Подбираем самые важные признаки importances = model.feature_importances_ # Создаем отдельный датасет для визуализации final_df = pd.DataFrame({"Features" : pd.DataFrame(X).columns, "Importances" : importances}) final_df.set_index('Importances') # Сортируем их по возрастанию для лучшей визуализации final_df = final_df.sort_values('Importances') # Выводим на график final_df.plot.bar(color = 'teal')
Заключение
Правильные преобразования зависят от многих факторов: типа и структуры данных, их объема. Не стоит также забывать о доступных ресурсах нашего компьютера или облака. Взяв на вооружение обе техники из этого цикла статей, вы будете чувствовать себя гораздо увереннее в мире науки о данных.