#python #scikit-learn #random-forest
Вопрос:
Я хотел бы получить ненормализованную оценку важности от RandomForestRegressor.
После установки регрессора я могу получить доступ к feature_importances_
тому, что содержит нормализованную оценку важности.
Чтобы получить ненормализованный балл, я попробовал это, но это не сработало. Я не могу получить правильные значения:
arr = []
for i in range(0,len(clf.feature_importances_)):
arr.append(np.array(clf.feature_importances_)[0:i].sum())
non_normalized = clf.feature_importances_*arr
Есть ли возможность отключить нормализацию?
Ответ №1:
Важность всегда нормализуется до 1, даже если вы переходите к каждому регрессору дерева решений, например:
import numpy as np
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.ensemble import RandomForestRegressor
boston = load_boston()
X = pd.DataFrame(boston.data, columns=boston.feature_names)
y = boston.target
X_train, X_test,y_train, y_test = train_test_split(X,y,test_size=0.3)
rf = RandomForestRegressor(n_estimators=100)
rf.fit(X_train, y_train)
Вы можете видеть, что в каждом дереве значения важности уже нормализованы:
[x.feature_importances_.sum() for x in rf.estimators_]
[1.0,
0.9999999999999999,
1.0,
1.0,
0.9999999999999999,
1.0,
0.9999999999999998,...
Не так уж тривиально вытащить уменьшение mse для дерева и пересчитать. Одним из альтернативных решений было бы использовать permutation_importance
r в квадрате или rmse в качестве меры, чтобы получить оценку того, насколько важной будет каждая функция, эти значения не нормализуются:
from sklearn.inspection import permutation_importance
importance_r2 = permutation_importance(rf, X_test, y_test,scoring="r2")
importance_rmse = permutation_importance(rf, X_test,
y_test,scoring="neg_root_mean_squared_error")
И составление графика результатов:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
ax1.boxplot(importance_r2.importances.T, vert=False,labels=X_test.columns)
ax1.set_xlabel('Decrease in R2')
ax2.boxplot(importance_rmse.importances.T, vert=False,labels=X_test.columns)
ax2.set_xlabel('Decrease in RMSE')
fig.tight_layout()
Ответ №2:
Поскольку случайный лес-это метод ансамбля, основанный на дереве решений, вы можете получить доступ к базовым деревьям решений с атрибутом clf.estimators_
RandomForestRegressor. С помощью списка деревьев вы можете получить доступ к важности функций каждого дерева решений :
feat_imp = [tree.feature_importances_ for tree in clf.estimators_]
Комментарии:
1. Спасибо вам, но мне также нужен OOB, когда начальная загрузка в TRUE и, похоже, OOB для каждого дерева недоступна ?
Ответ №3:
По умолчанию значения нормализуются до 1. Однако это можно изменить, обратившись к деревьям случайного леса или модели дерева решений и вызвав функцию для вычисления значений normalize=False
.
Во-первых, вот пример регрессии с одним деревом решений:
from sklearn.datasets import load_diabetes
from sklearn import tree
X, y = load_diabetes(return_X_y=True)
model = tree.DecisionTreeRegressor(random_state=0)
model.fit(X,y)
model.tree_.compute_feature_importances(normalize=False)
array([ 273.29445957, 55.8130721 , 1383.95383906, 447.64458872,
414.2412427 , 412.20392795, 423.76003212, 77.75521807,
2063.37527614, 377.84324049])
Для случайного леса есть дополнительный шаг. Сначала нам нужно получить доступ к каждому дереву, вычислить значения функций для каждого дерева, а затем выполнить среднее значение по деревьям:
import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.ensemble import RandomForestRegressor
X, y = load_diabetes(return_X_y=True)
model = RandomForestRegressor(random_state=0)
model.fit(X,y)
importances = np.zeros((model.n_estimators, model.n_features_))
for i,tree in enumerate(model.estimators_):
importances[i] = tree.tree_.compute_feature_importances(normalize=False)
np.mean(importances, axis=0)
array([ 363.40653952, 78.42318883, 1767.47349563, 564.32760593,
275.84188613, 318.61079764, 310.57670354, 160.56454205,
1655.62870107, 424.28382897])