如何使用最常见的特性选择技术来解决分类问题
原标题:如何使用最常见的特性选择技术来解决分类问题
来源:AI 研习社 链接:https://www.yanxishe.com/TextTranslation/2004
选择要使用哪些特征是任何机器学习项目中的关键步骤,也是数据科学家日常工作中的一项经常性任务。 在本文中,我将回顾实践中用于分类问题的最常见的特征选择技术,并将它们分为6个主要类别。 我提供了如何在机器学习项目中使用它们的技巧,并尽可能提供Python代码示例。 你准备好了吗?
TL; DR-汇总表
下表总结了主要方法,并在以下各节中进行了讨论。
什么是特征选择,为什么有用?
机器学习中的两个最大问题是过拟合(拟合数据集之外无法进行泛化的数据)和维度诅咒(高维度数据的不直观和稀疏特性)。
特征选择通过减少模型中的特征数量,尝试优化模型性能,从而帮助避免这两个问题。 在此过程中,特征选择还提供了额外的好处:模型解释。 由于使用较少的特征,输出模型将变得更简单,更易于解释,并且人们更有可能相信该模型做出的未来预测。
非监督方法
减少特征数量的一种简单方法是对数据应用降维技术。 这通常以无监督的方式完成,即无需使用标签本身。
降维实际上并没有选择特征的子集,而是在低维空间中生成了一组新的特征。 这个新的集合可以在分类过程中使用。
下面的示例使用缩减维度上的特征进行分类。 更准确地说,它使用主成分分析(PCA)的前两个成分作为新特征集。
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.svm import SVC
import matplotlib.pyplot as plt
from matplotlib.colors
import ListedColormapimport numpy as np
h = .01
x_min, x_max = -4,4
y_min, y_max = -1.5,1.5
# loading dataset
data = load_iris()
X, y = data.data, data.target
# selecting first 2 components of PCA
X_pca = PCA().fit_transform(X)
X_selected = X_pca[:,:2]
# training classifier and evaluating on the whole plane
clf = SVC(kernel='linear')
clf.fit(X_selected,y)
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# Plotting
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])
plt.figure(figsize=(10,5))
plt.pcolormesh(xx, yy, Z, alpha=.6,cmap=cmap_light)
plt.title('PCA - Iris dataset')
plt.xlabel('Dimension 1')
plt.ylabel('Dimension 2')
plt.scatter(X_pca[:,0],X_pca[:,1],c=data.target,cmap=cmap_bold)
plt.show()
在评估特征时,降维的另一种用途是可视化:在低维空间中,更容易从视觉上验证数据是否具有潜在可分离性,这有助于对分类精度设置期望。 在实践中,我们对一组特征执行降维(例如PCA),并检查标签在降维空间中的分布情况。 如果它们看起来是独立的,则这清楚地表明使用这组特征时,期望具有较高的分类性能。
在下面的示例中,在2维简化空间中,不同的标签显示为相当可分离的。 这表明,在训练和测试分类器时可以期望获得高性能。
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import matplotlib.pyplot as pltfrom mlxtend.plotting import plot_pca_correlation_graphdata = load_iris()
X, y = data.data, data.targetplt.figure(figsize=(10,5))
X_pca = PCA().fit_transform(X)
plt.title('PCA - Iris dataset')
plt.xlabel('Dimension 1')
plt.ylabel('Dimension 2')
plt.scatter(X_pca[:,0],X_pca[:,1],c=data.target)
_ = plot_pca_correlation_graph(X,data.feature_names)
除此之外,我还绘制了相关圆,它表示每个原始维度和新的PCA维度之间的相关性。 直观地,它显示了每个原始特征对新新创建的PCA成分的贡献。 在上面的示例中,花瓣的长度和宽度显示与第一PCA维度高度相关,而萼片宽度则对第二个维度高度相关。
单变量过滤方法
过滤方法旨在不使用任何类型的分类算法的情况下就对特征的重要性进行排序。
单变量过滤器方法分别评估每个特征,并且不考虑特征间的相互作用。这些方法通常是根据统计测试为每个特征提供分数。
得分通常衡量因变量与特征之间的相关性(例如Chi2,对于回归而言,则为Pearls相关系数),或者给出给定类别标签的特征分布之间的差异(F检验和T检验)。
得分经常对基础数据的统计特性作出假设。理解这些假设对于决定使用哪种测试是很重要的,即使其中一些测试对于这些假设是相反的。
基于统计测试的得分提供p值,该值可用于排除某些特征。如果p值高于某个阈值(通常为0.01或0.05),则会执行此操作。
常见的测试包括:
软件包sklearn实现了一些过滤方法。但是,由于它们大多数基于统计测试,因此也可以使用统计数据包(例如statsmodels)。
下面是一个示例:
from sklearn.feature_selection import f_classif, chi2, mutual_info_classif
from statsmodels.stats.multicomp import pairwise_tukeyhsd
from sklearn.datasets import load_iris
data = load_iris()
X,y = data.data, data.target
chi2_score, chi_2_p_value = chi2(X,y)
f_score, f_p_value = f_classif(X,y)
mut_info_score = mutual_info_classif(X,y)
pairwise_tukeyhsd = [list(pairwise_tukeyhsd(X[:,i],y).reject) for i in range(4)]
print('chi2 score ', chi2_score)
print('chi2 p-value ', chi_2_p_value)
print('F - score score ', f_score)
print('F - score p-value ', f_p_value)
print('mutual info ', mut_info_score)
print('pairwise_tukeyhsd',pairwise_tukeyhsd)
Out:
chi2 score [ 10.82 3.71 116.31 67.05]
chi2 p-value [0. 0.16 0. 0. ]
F - score score [ 119.26 49.16 1180.16 960.01]
F - score p-value [0. 0. 0. 0.]
mutual info [0.51 0.27 0.98 0.98]
pairwise_tukeyhsd [[True, True, True], [True, True, True], [True, True, True], [True, True, True]]
特征分级的可视化方法
箱形图和小提琴图
箱线图/小提琴图可以帮助可视化给定类的特征分布。 对于 Iris数据集,如下所示。
这很有用,因为统计检验通常只评估这种分布的平均值之间的差异。 因此,这些图提供了有关特征质量的更多信息。
import pandas as pd
import seaborn as sns
sns.set()
df = pd.DataFrame(data.data,columns=data.feature_names)
df['target'] = data.target
df_temp = pd.melt(df,id_vars='target',value_vars=list(df.columns)[:-1],
var_name="Feature", value_name="Value")
g = sns.FacetGrid(data = df_temp, col="Feature", col_wrap=4, size=4.5,sharey = False)
g.map(sns.boxplot,"target", "Value");
g = sns.FacetGrid(data = df_temp, col="Feature", col_wrap=4, size=4.5,sharey = False)
g.map(sns.violinplot,"target", "Value");
ROC曲线对特征进行排序
ROC曲线可用于对特征重要性进行排序,这提供了一种可视化方法来对特征性能进行排名。
此技术最适合于二分类任务。 为了解决多分类问题,可以使用微观或宏观平均值或基于多个比较的标准(类似于成对的Tukey测距法)。
下面的示例绘制了各种特征的ROC曲线。
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
from sklearn.metrics import auc
import numpy as np
# loading dataset
data = load_iris()
X, y = data.data, data.target
y_ = y == 2
plt.figure(figsize=(13,7))
for col in range(X.shape[1]):
tpr,fpr = [],[]
for threshold in np.linspace(min(X[:,col]),max(X[:,col]),100):
detP = X[:,col] < threshold
tpr.append(sum(detP & y_)/sum(y_))# TP/P, aka recall
fpr.append(sum(detP & (~y_))/sum((~y_)))# FP/N
if auc(fpr,tpr) < .5:
aux = tpr
tpr = fpr
fpr = aux
plt.plot(fpr,tpr,label=data.feature_names[col] + ', auc = '
+ str(np.round(auc(fpr,tpr),decimals=3)))
plt.title('ROC curve - Iris features')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.show()
多元过滤方法
这些方法考虑了变量之间的相关性,并且没有考虑分类算法的类型。
mRMR
mRMR(最小冗余最大相关性)是一种既考虑特征的重要性,又考虑特征之间相关性来寻找最优特征子集的启发式算法。
其思想是,即使两个特征高度相关,将它们都添加到特征集中可能不是一个好主意。 在那种情况下,同时添加这两个特征会增加模型的复杂度(增加过度拟合的可能性),但由于特征之间的相关性而不会添加大量信息。
在N个特征集合S中,特征相关性(D)的计算如下:
I 是互信息算子。
特征的冗余度可以表示为:
集合S 的mRMR得分定义为(D-R),目标是找到最大值为(D-R)的特征子集。 但是实际上,我们执行增量搜索(也称为前向选择)时在每一步,都会添加产生最大mRMR的特征。
该算法由作者自己用C语言实现。 您可以在此处找到该软件包的源代码以及原始论文。
在名为pymrmr上创建一个(未维护的)python包装器。 如果pymrmr出现问题,我建议直接调用C语言的函数。
下面的代码给出了pymrmr的用法实例。 请注意,pandas数据格式的列应按照C语言(此处)中的说明进行格式化。
import pandas as pd
import pymrmr
df = pd.read_csv('some_df.csv')
# Pass a dataframe with a predetermined configuration.
# Check http://home.penglab.com/proj/mRMR/ for the dataset requirements
pymrmr.mRMR(df, 'MIQ', 10)
输出:
*** This program and the respective minimum Redundancy Maximum Relevance (mRMR)
algorithm were developed by Hanchuan Peng <hanchuan.peng@gmail.com>for
the paper
"Feature selection based on mutual information: criteria of
max-dependency, max-relevance, and min-redundancy,"
Hanchuan Peng, Fuhui Long, and Chris Ding,
IEEE Transactions on Pattern Analysis and Machine Intelligence,
Vol. 27, No. 8, pp.1226-1238, 2005.
*** MaxRel features ***
Order Fea Name Score
1 765 v765 0.375
2 1423 v1423 0.337
3 513 v513 0.321
4 249 v249 0.309
5 267 v267 0.304
6 245 v245 0.304
7 1582 v1582 0.280
8 897 v897 0.269
9 1771 v1771 0.269
10 1772 v1772 0.269
*** mRMR features ***
Order Fea Name Score
1 765 v765 0.375
2 1123 v1123 24.913
3 1772 v1772 3.984
4 286 v286 2.280
5 467 v467 1.979
6 377 v377 1.768
7 513 v513 1.803
8 1325 v1325 1.634
9 1972 v1972 1.741
10 1412 v1412 1.689
Out[1]:
['v765',
'v1123',
'v1772',
'v286',
'v467',
'v377',
'v513',
'v1325',
'v1972',
'v1412']
包装器方法
包装器方法主要思想是搜索哪组特征最适合特定分类器。根据所使用的搜索算法的不同,这些方法可以总结如下。
1.选择一个性能指标(例如,AIC,BIC,F1得分,准确性,MSE,MAE…),记为M。
2.选择分类器/回归器/…,在此标记为C。
3.使用给定的搜索方法搜索不同的特征子集。 对于每个子集S,执行以下操作:
①使用S作为分类器的特征,以交叉验证模式训练和测试C;
②从交叉验证过程中获得平均得分(针对度量M),并将该得分分配给子集S;
③选择一个新的子集并重做步骤a。
步骤3的详细说明
第三步未指定使用哪种搜索方法。几乎在任何情况下,测试所有可能的特征子集都是禁止的(蛮力选择),因为步骤3计算次数将指数增加(是特征次数的2的幂)。除了时间复杂性外,由于有如此多的可能性,某些特征组合很可能仅凭随机机会表现最佳,这使得蛮力解决方案更容易过拟合。
搜索算法在实践中往往可以很好地解决此问题。它们倾向于获得接近于暴力解决方案的性能,但时间复杂度要低得多,并且过拟合的概率也更少。
实际上,前向选择和后向选择(也称为剪枝)及其搜索过程的一些小变化都被大量使用。
后向选择包括从具有全部特征的模型开始,然后在每个步骤中删除特征得分最高的特征。前向选择则相反:它从一组空白特征开始,然后添加最能提高当前得分的特征。
前向/后向选择仍然有过度拟合的倾向,因为通常通过添加更多特征来提高分数。避免这种情况的一种方法是使用分数来惩罚模型的复杂性,例如AIC或BIC。
包装器方法结构的说明如下所示。重要的是要注意,特征集是(1)通过搜索方法找到的;(2)并且在打算使用的同一分类器上进行交叉验证。
第三步还保留了交叉验证参数。 通常,使用k倍。 但是,使用大k会给整体包装方法带来额外的复杂性。
包装方法的Python包
mlxtend(http://rasbt.github.io/mlxtend/)是一个有用的软件包,用于处理与数据科学相关的各种任务。 可以在SequentialFeatureSelector上找到此程序包。 它提供了具有一些变化的前向和后向的特征选择。
该软件包还提供了一种通过函数plot_sequential_feature_selection将得分可视化为特征数量的函数。
下面的示例摘自软件包的主页。
from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from mlxtend.plotting import plot_sequential_feature_selection as plot_sfs
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
boston = load_boston()
X, y = boston.data, boston.target
lr = LinearRegression()
sfs = SFS(lr,
k_features=13,
forward=True,
floating=False,
scoring='neg_mean_squared_error',
cv=10)
sfs = sfs.fit(X, y)
fig = plot_sfs(sfs.get_metric_dict(), kind='std_err')
plt.title('Sequential Forward Selection (w. StdErr)')
plt.grid()
plt.show()
嵌入式方法
训练分类器可以归结为一个优化问题,我们尝试最小化其参数的函数(此处记为)
一THE END一
免责声明:本文来自互联网新闻客户端自媒体,不代表本网的观点和立场。
合作及投稿邮箱:E-mail:editor@tusaishared.com
热门资源
应用笔画宽度变换...
应用背景:是盲人辅助系统,城市环境中的机器导航...
自然语言处理起源...
选自towardsdatascience作者:Raimi Karim机器之心...
神经架构搜索在视...
视频理解一直是项颇具挑战性的难题。视频中包含时...
时至今日,NLP怎么...
在微博和知乎上关注自然语言处理(NLP)技术的朋友...
构建贝叶斯深度学...
这篇文章将讲述如何使用 Keras 和 Tensorflow 训练...
智能在线
400-630-6780
聆听.建议反馈
E-mail: support@tusaishared.com