2014-03-12 911 views
5

我已經在sklearn中使用RandomForestClassifier來確定我的數據集中的重要特徵。我如何能夠返回實際的功能名稱(我的變量被標記爲x1,x2,x3等)而不是它們的相對名稱(它告訴我重要的功能是'12','22'等)。以下是我目前用來返回重要功能的代碼。如何sklearn隨機森林指數feature_importances_

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 


然後進行分割數據集和目標類數據集進入測試和t下雨的部分。

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] 


這似乎是其並沒有看出任何變化longer.Additionally,當我移動相同的變量到第5列的原始數據集的輸出是這樣的:

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


這看起來像它再次承認它。最後一件事,在我通過你的建議返回變量名後,它給了我一個7個變量的列表。當我使用最初的代碼返回重要變量時,它給了我一個更長的重要變量列表。爲什麼是這樣?再次感謝您的幫助。對此,我真的非常感激!

回答

9

功能重要性返回一個數組,其中每個索引對應於該特徵在訓練集中的估計特徵重要性。內部沒有進行排序,它與訓練期間給予它的功能是一一對應的。

如果您將要素名稱存儲爲numpy數組並確保其與傳遞給模型的要素保持一致,則可以利用numpy索引來執行此操作。

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

感謝您的快速響應。我已經將feature_names存儲在一個numpy數組中,並且將編輯我的註釋以包含代碼,如果在方便時可以看一看。 –

2

獲取變量解釋:

regressor.score(X, y) 

獲取變量的重要性:

importances = regressor.feature_importances_ 
print(importances) 
+0

也是一個很好的建議。謝謝! –

2

這是我用來打印和打印功能的重要性,包括姓名,而不僅僅是值

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()