sklearn随机森林如何索引feature_importances_

7 投票
3 回答
13055 浏览
提问于 2025-04-17 22:00

我在使用sklearn中的RandomForestClassifier来找出我数据集中重要的特征。现在我想知道,怎么才能返回实际的特征名称(我的变量被标记为x1、x2、x3等等),而不是它们的相对名称(比如它告诉我重要特征是'12'、'22'等)。下面是我目前用来返回重要特征的代码。

important_features = []
for x,i in enumerate(rf.feature_importances_):
    if i>np.average(rf.feature_importances_):
        important_features.append(str(x))
print important_features

另外,为了理解索引,我发现了重要特征'12'实际上是什么(它是变量x14)。当我把变量x14移动到训练数据集的第0个位置,并再次运行代码时,它应该告诉我特征'0'是重要的,但它并没有这样做,感觉它看不到这个特征了,列表中的第一个特征实际上是我第一次运行代码时列出的第二个特征(特征'22')。

我在想,也许feature_importances_实际上是把第一列(我放了x14的地方)当作训练数据集其余部分的一个ID,因此在选择重要特征时忽略了它。有没有人能帮我解答这两个问题?非常感谢任何帮助。

编辑
这是我存储特征名称的方式:

tgmc_reader = csv.reader(csvfile)
row = tgmc_reader.next()    #Header contains feature names
feature_names = np.array(row)


然后我加载了数据集和目标类别

tgmc_x, tgmc_y = [], []
for row in tgmc_reader:
    tgmc_x.append(row[3:])    #This says predictors start at the 4th column, columns 2 and 3 are just considered ID variables.
    tgmc_y.append(row[0])     #Target column is the first in the dataset


接着把数据集分成测试和训练部分。

from sklearn.cross_validation import train_test_split

x_train, x_test, y_train, y_test = train_test_split(tgmc_x, tgmc_y, test_size=.10, random_state=33)


然后拟合模型

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=1, criterion='entropy', max_features=2, max_depth=5, bootstrap=True, oob_score=True, n_jobs=2, random_state=33)
rf = rf.fit(x_train, y_train)


然后返回重要特征

important_features = []
for x,i in enumerate(rf.feature_importances_):
    if i>np.average(rf.feature_importances_):
        important_features.append((x))


接着我采纳了你的建议,效果很好(非常感谢!)

important_names = feature_names[important_features > np.mean(important_features)]
print important_names


确实返回了变量名称。

['x9' 'x10' 'x11' 'x12' 'x13' 'x15' 'x16']


所以你确实解决了我问题的一部分,这太棒了。但当我回去打印我重要特征的结果时

print important_features


它返回了以下输出:

[12, 22, 51, 67, 73, 75, 87, 91, 92, 106, 125, 150, 199, 206, 255, 256, 275, 309, 314, 317]


我理解这意味着它认为第12、22、51个等变量是重要的。所以这将是我在代码开头告诉它开始索引观察值时的第12个变量:

tgmc_x.append(row[3:])


我的理解正确吗? 如果正确的话,当我把第12个变量移动到原始数据集的第4列(我在代码中告诉它从这里开始读取预测值)并再次运行代码时,输出如下:

[22, 51, 66, 73, 75, 76, 106, 112, 125, 142, 150, 187, 191, 199, 250, 259, 309, 317]


这似乎不再识别那个变量了。此外,当我把同一个变量移动到原始数据集的第5列时,输出看起来是这样的:

[1,22, 51, 66, 73, 75, 76, 106, 112, 125, 142, 150, 187, 191, 199, 250, 259, 309, 317]


这看起来又识别它了。最后一点,在我通过你的建议让它返回变量名称后,它给了我7个变量的列表。当我用我最初的代码只返回重要变量时,它给了我更长的一个重要变量列表。这是为什么呢?再次感谢你的帮助,我真的很感激!

3 个回答

3

获取变量的解释:

regressor.score(X, y)

获取变量的重要性:

importances = regressor.feature_importances_
print(importances)
4

这是我用来打印和绘制特征重要性的方法,包括特征的名称,而不仅仅是数值

importances = pd.DataFrame({'feature':X_train.columns,'importance':np.round(clf.feature_importances_,3)})
importances = importances.sort_values('importance',ascending=False).set_index('feature')
print importances
importances.plot.bar()

完整示例

from sklearn.ensemble import RandomForestClassifier
from sklearn.cross_validation import train_test_split
import numpy as np
import pandas as pd

# set vars
predictors = ['x1','x2']
response = 'y'

X = df[predictors]
y = df[response]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)

# run model
clf = RandomForestClassifier(max_features=5)
clf.fit(X_train.values, y_train.values)

#show to plot importances
importances = pd.DataFrame({'feature':X_train.columns,'importance':np.round(clf.feature_importances_,3)})
importances = importances.sort_values('importance',ascending=False).set_index('feature')
print importances
importances.plot.bar()
12

特征重要性会返回一个数组,这个数组中的每个位置对应于训练集中每个特征的重要性估计。内部并没有进行排序,这个数组和训练时提供的特征是一一对应的。

如果你把特征名称存储为一个numpy数组,并确保它和传给模型的特征一致,你就可以利用numpy的索引功能来处理它。

importances = rf.feature_importances_
important_names = feature_names[importances > np.mean(importances)]
print important_names

撰写回答