Всем привет. В последнее время я часто проверяю гипотезы на наличие зависимости в признаках. Идеи возникают самые разнообразные, которые нужно быстро оценить.
Поэтому представляю Вашему вниманию небольшой шаблон Jupyter для быстрой оценки гипотезы алгоритмом случайного леса, так как он универсален, не требует масштабируемости, отбора признаков, не чувствителен к выбросам, неплохо справляется с пропущенными данными, и не требует тщательной подборки гиперпараметров. Более того можно посмотреть после построения модели на признаки, которые внесли наибольший вклад в результат модели. И вообще как сам алгоритм он очень эффективен и красив, а идея вычисления прироста информации просто шикарна.
Итак, поехали
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
Загрузка данных
from sklearn.model_selection import train_test_split
# загрузка данных для классификации
path_file = 'example_data.xlsx'
sheet_name = 'example_load'
data = pd.read_excel(path_file, sheet_name=sheet_name)
print(data.shape)
# просмотр столбцов
data.columns
# проверка на необходимые столбцы
if not set(['idx','label']).issubset(data.columns):
raise Exception('не хватает необходимых столбцов')
# проверка на уникальность индекса
if not data['idx'].is_unique:
raise Exception('индексы должны быть уникальными')
Тут мы загружаем excel-файл. Два необходимых столбца это "idx" и "label".
# присвоение индекса
if 'idx' in data:
if not data['idx'].is_unique:
raise Exception('входные индексы имеют дубликаты')
data.set_index(['idx'], inplace=True)
# смотрим на данные
print('размерность:', data.shape)
data.head(4)
from sklearn.preprocessing import MinMaxScaler, StandardScaler
# # масштабирование данных - нормализация (минимакс)
# scaler = MinMaxScaler(feature_range=(0.1, 0.9))
# scaled_features = scaler.fit_transform(data[data.columns.difference(['label'])].astype('float64'))
# scaled_data = pd.DataFrame(data=scaled_features, index=data.index, columns=data.drop(['label'], axis=1).columns)
# scaled_data['label'] = data['label']
# scaled_data.head(4)
# # масштабирование данных - стандартизация
# scaler = StandardScaler()
# scaled_features = scaler.fit_transform(data[data.columns.difference(['label'])].astype('float64'))
# scaled_data = pd.DataFrame(data=scaled_features, index=data.index, columns=data.drop(['label'], axis=1).columns)
# scaled_data['label'] = data['label']
# scaled_data.head(4)
# оставить без масштабирования
scaled_data = data.copy()
scaled_data.head(4)
При необходимости задайте масштабирование признаков, хотя случайный лес один из немногих алгоритмов, который не требует обязательного масштабирования признаков.
# замена пустых значений
scaled_data.fillna(value=0, inplace=True)
Тут можно описать свои собственные методы заполнения пропущенных значений (в зависимости от конкретной задачи)
from sklearn.model_selection import train_test_split
X_data = scaled_data.drop('label', axis=1).select_dtypes(include=[np.number])
y_data = scaled_data['label'].astype('int32')
print('size train data:', X_data.shape)
print('size train labels:', y_data.shape)
# разбивка на тестовые и тренировочные данные
X_train, X_test, y_train, y_test = train_test_split(X_data, y_data, test_size=0.2)
Модель - Random forest
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.metrics import accuracy_score
# модель случайный лес
from sklearn.ensemble import RandomForestClassifier
# случайный лес
rf = RandomForestClassifier(max_features='auto', random_state=1, n_jobs=-1, n_estimators=10)
# посмотрим на примерный результат, без поиска лучших гиперпараметров
print(np.mean(cross_val_score(rf, X_data, y_data, cv=5)))
# оптимизируемые параметры (по каким будет идти перебор)
# для каждой задачи нужно проставлять индивидуально
rf_params = {'criterion' : ['entropy'],
'min_samples_leaf' : [1,2,3],
'min_samples_split' : [5,15,50,100],
'n_estimators': [10,25,50,75,100]}
rf_params - словарь подбираемых гиперпараметров
# объект для поиска наилучших параметров
rf_grid = GridSearchCV(rf,
rf_params,
cv=5,
n_jobs=-1,
verbose=True)
Поиск лучших гиперпараметров
# поиск наилучших параметров для модели
rf_grid.fit(X_train, y_train);
# просмотр лучших параметров
rf_grid.best_params_
# просмотр лучшего результата
rf_grid.best_score_
# просмотр комбинаций гиперпараметров с оценками
means = rf_grid.cv_results_['mean_test_score']
stds = rf_grid.cv_results_['std_test_score']
for mean, std, params in zip(means, stds, rf_grid.cv_results_['params']):
print("%0.3f (+/-%0.03f) for %r" % (mean, std * 2, params))
plt.subplots(figsize=(9,5))
plt.plot(np.sort(rf_grid.cv_results_['mean_test_score']));
plt.grid(alpha=0.4)
plt.ylabel('точность модели');
plt.xlabel('модели с разными параметрами');
plt.title('Точность модели от оптимизируемых гиперпараметров');
развернуть комбинации гиперпараметров
# (обычно я выбираю те гиперпараметры, где проходит зеленая линия, см. выше)
# отбираем лучшую модель
best_model = rf_grid.best_estimator_
# обучаем модель на всех данных
best_model.fit(X_train, y_train)
# смотрим на результативность на тестовых данных
best_model.score(X_test, y_test)
# сформируем важности признаков
imp_df = pd.DataFrame(best_model.feature_importances_,
columns=['Feature_Imp'],
index=X_train.columns)
imp_df.sort_values(by=['Feature_Imp'], ascending=False, inplace=True)
print(imp_df)
Комментариев нет