Python 2.7 从递归特征消除(RFE)中提取最佳特征
我有一个由124个特征的分类和数字数据组成的数据集。为了降低它的维数,我想删除不相关的特征。然而,为了针对特征选择算法运行数据集,我使用get_dummies对其进行了热编码,这将特征数量增加到391个Python 2.7 从递归特征消除(RFE)中提取最佳特征,python-2.7,machine-learning,scikit-learn,feature-selection,rfe,Python 2.7,Machine Learning,Scikit Learn,Feature Selection,Rfe,我有一个由124个特征的分类和数字数据组成的数据集。为了降低它的维数,我想删除不相关的特征。然而,为了针对特征选择算法运行数据集,我使用get_dummies对其进行了热编码,这将特征数量增加到391个 In[16]: X_train.columns Out[16]: Index([u'port_7', u'port_9', u'port_13', u'port_17', u'port_19', u'port_21', ... u'os_cpes.1_2', u'os_cpes.1_
In[16]:
X_train.columns
Out[16]:
Index([u'port_7', u'port_9', u'port_13', u'port_17', u'port_19', u'port_21',
...
u'os_cpes.1_2', u'os_cpes.1_1'], dtype='object', length=391)
对于生成的数据,我可以使用交叉验证运行递归特征消除,如下所示:
产生:
Features Selected: 8
Features Indexes:
['5', '6', '20', '26', '27', '28', '67', '98']
Feature Names:
['port_21', 'port_22', 'port_199', 'port_512', 'port_513', 'port_514', 'port_3306', 'port_32768']
考虑到识别的最佳特征数量为8,如何识别特征名称?我假设我可以将它们提取到一个新的数据帧中,用于分类算法
[编辑] 在以下人员的帮助下,我实现了以下目标: 产生:
Features Selected: 8
Features Indexes:
['5', '6', '20', '26', '27', '28', '67', '98']
Feature Names:
['port_21', 'port_22', 'port_199', 'port_512', 'port_513', 'port_514', 'port_3306', 'port_32768']
考虑到一个热编码引入了多重共线性,我认为目标列选择并不理想,因为它选择的特征是非编码的连续数据特征。我已尝试重新添加未编码的目标列,但RFE会抛出以下错误,因为数据是分类的:
ValueError: could not convert string to float: Wireless Access Point
我是否需要将多个“一个热编码”功能列分组作为目标
[编辑2] 如果我简单地将目标列标记为代码,我可以将此目标用作“y”,请参见。但是,输出仅确定单个特征(目标列)为最佳。我想这可能是因为一个热编码,我应该考虑生成一个密集数组吗?如果是的话,它可以针对RFE运行吗 谢谢
亚当在回答我自己的问题时,我发现这个问题与我对数据进行热编码的方式有关。最初,我对所有分类列运行了一个热编码,如下所示:
ohe_df = pd.get_dummies(df[df.columns]) # One-hot encode all columns
这引入了大量附加功能。采用不同的方法,在来自的帮助下,我修改了编码,以按每列/功能对多个列进行编码,如下所示:
cf_df = df.select_dtypes(include=[object]) # Get categorical features
nf_df = df.select_dtypes(exclude=[object]) # Get numerical features
ohe_df = nf_df.copy()
for feature in cf_df:
ohe_df[feature] = ohe_df.loc[:,(feature)].str.get_dummies().values.tolist()
制作:
ohe_df.head(2) # Only showing a subset of the data
+---+---------------------------------------------------+-----------------+-----------------+-----------------------------------+---------------------------------------------------+
| | os_name | os_family | os_type | os_vendor | os_cpes.0 |
+---+---------------------------------------------------+-----------------+-----------------+-----------------------------------+---------------------------------------------------+
| 0 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... | [0, 1, 0, 0, 0] | [1, 0, 0, 0, 0] | [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0] | [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ... |
| 1 | [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... | [0, 0, 0, 1, 0] | [0, 0, 0, 1, 0] | [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0] | [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... |
+---+---------------------------------------------------+-----------------+-----------------+-----------------------------------+---------------------------------------------------+
不幸的是,虽然这是我正在搜索的,但它并没有针对RFECV执行。接下来,我想也许我可以从所有新特性中抽取一部分,并将它们作为目标传递进来,但这导致了一个错误。最后,我意识到我必须迭代所有目标值,并从每个目标值中获取最重要的输出。代码最终看起来像这样:
for num, feature in enumerate(features, start=0):
X = X_dev_train
y = X_dev_train[feature]
# Create the RFE object and compute a cross-validated score.
svc = SVC(kernel="linear")
# The "accuracy" scoring is proportional to the number of correct classifications
# step is the number of features to remove at each iteration
rfecv = RFECV(estimator=svc, step=1, cv=StratifiedKFold(kfold), scoring='accuracy')
try:
rfecv.fit(X, y)
print("Number of observations in each fold: {}".format(len(X)/kfold))
print("Optimal number of features : {}".format(rfecv.n_features_))
g_scores = rfecv.grid_scores_
indices = np.argsort(g_scores)[::-1]
print('Printing RFECV results:')
for num2, f in enumerate(range(X.shape[1]), start=0):
if g_scores[indices[f]] > 0.80:
if num2 < 10:
print("{}. Number of features: {} Grid_Score: {:0.3f}".format(f + 1, indices[f]+1, g_scores[indices[f]]))
print "\nTop features sorted by rank:"
results = sorted(zip(map(lambda x: round(x, 4), rfecv.ranking_), X.columns.values))
for num3, i in enumerate(results, start=0):
if num3 < 10:
print i
# Plot number of features VS. cross-validation scores
plt.rc("figure", figsize=(8, 5))
plt.figure()
plt.xlabel("Number of features selected")
plt.ylabel("CV score (of correct classifications)")
plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_)
plt.show()
except ValueError:
pass
对于num,枚举中的功能(功能,开始=0):
X=X_开发列车
y=X_开发列车[功能]
#创建RFE对象并计算交叉验证分数。
svc=svc(kernel=“linear”)
#“准确度”评分与正确分类的数量成正比
#步骤是每次迭代中要删除的特征数
rfecv=rfecv(估计器=svc,步长=1,cv=StratifiedKFold(kfold),评分=‘准确度’)
尝试:
rfecv.配合(X,y)
打印(“每次折叠的观察次数:{}”。格式(len(X)/kfold))
打印(“最佳特征数:{}”。格式(rfecv.n_特征))
g_分数=rfecv.grid_分数_
指数=np.argsort(g_分数)[:-1]
打印('打印RFECV结果:')
对于num2,枚举中的f(范围(X.shape[1]),起始值为0:
如果g_分数[指数[f]]>0.80:
如果num2<10:
打印(“{}。功能数:{}网格分数:{:0.3f}”。格式(f+1,索引[f]+1,g_分数[索引[f]]))
打印“\n按等级排序的地图要素:”
结果=排序(zip(map(lambda x:round(x,4),rfecv.ranking_ux),x.columns.values))
对于num3,枚举中的i(结果,开始=0):
如果num3<10:
打印i
#绘制特征数量与交叉验证分数
plt.rc(“图”,figsize=(8,5))
plt.图()
plt.xlabel(“选择的特征数量”)
plt.ylabel(“CV分数(正确分类)”)
plt.plot(范围(1,len(rfecv.grid\u分数)+1),rfecv.grid\u分数)
plt.show()
除值错误外:
通过
我相信这可能会更干净,甚至可以绘制在一个图表中,但它对我很有用
干杯,您可以这样做:
`
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
rfe = RFE(model, 5)
rfe = rfe.fit(X, y)
print(rfe.support_)
print(rfe.ranking_)
f = rfe.get_support(1) #the most important features
X = df[df.columns[f]] # final features`
然后,您可以使用X作为神经网络或任何算法的输入