特征提取(feature extraction):在尽可能不丢失特征原始信息的情况下,通过创建新特征来降低特征矩阵的维度。
另一种降维方法,特征选择会保留信息量较高的特征而丢弃信息量较低的特征。
- 特征选择的方法:
- 过滤器:过滤器方法根据特征的统计信息来选择最优特征。
- 包装器:包装器通过不断试错,找出一个可以产生高质量预测值得模型的特征子集。
- 嵌入式方法:此方法则将选择最优特征子集作为机器学习算法训练过程的一部分。
1. 数值型特征方差的阈值化
问题描述:从一组数值型特征中移除方差较小(即可能包含的信息较少)的特征。
解决方案:挑出方差大于给定阈值的特征
from sklearn import datasets
from sklearn.feature_selection import VarianceThreshold
#加载数据
iris = datasets.load_iris()
#创建features和target
features = iris.data
target = iris.target
#创建VarianceThreshold
threshold = VarianceThreshold(threshold = 0.5)
#创建大方差特征矩阵
features_high_variance = threshold.fit_transform(features)
#显示大方差特征矩阵
features_high_variance[0:3]
outputs:
array([[5.1, 1.4, 0.2],
[4.9, 1.4, 0.2],
[4.7, 1.3, 0.2]])
方差阈值化(Variance Thresholding,VT)是最基本的特征选择方法之一。此方法依据是小方差的特征可能比大方差的特征的重要性低一些。
- 注意点:
- 方差不是中心化的,因此如果特征数据集中特征的单位不同,那么VT就无法起作用。
- 方差的阈值是手动选择的,所以必须依靠人工来选择一个合适的阈值。可以通过参数variance_来查看每个特征的方差:VarianceThreshold().fit(features).variances_
- 如果特征已经标准化,方差阈值将起不到筛选的作用。
2. 二值特征的方差阈值化
问题描述:有一组而知特征数据,要移除其中方差较小的特征。
解决方案:挑出方差给定阈值的二值特征。
from sklearn.feature_selection import VarianceThreshold
#创建特征矩阵
features = [[0,1,0],
[0,1,1],
[0,1,0],
[0,1,1],
[1,0,0]]
#创建VarianceThreshold对象并运行
thresholder = VarianceThreshold(threshold = (0.75 * (1-0.75)))
thresholder.fit_transform(features)
output:
array([[0],
[1],
[0],
[1],
[0]])
和数值型特征一样,挑选高信息量的分类特征的方法之一就是查看它们的方差。在二值特征(即伯努利随机变量)中,方差的计算方式如下:
V
a
r
(
x
)
=
p
(
1
−
p
)
Var(x) = p(1-p)
Var(x)=p(1−p)
其中p是观察值属于1个分类的概率。通过设置p的值,可以删除大部分观察值都属于同一个类别的特征。
3. 处理高度相关性的特征
问题描述:特征矩阵中的某些特征具有较高的相关性
解决方案:使用相关矩阵检查是否存在较高相关性的特征,如果存在,则删除其中的一个。
import pandas as pd
import numpy as np
#创建一个特征矩阵,其中包含两个高度相关的特征
features = np.array([[1,1,1],
[2,2,0],
[3,3,1],
[4,4,0],
[5,5,1],
[6,6,0],
[7,7,1],
[8,7,0],
[9,7,1]])
#将特征矩阵转换成DataFrame
dataframe = pd.DataFrame(features)
print(dataframe)
#创建相关矩阵
corr_matrix = dataframe.corr().abs()
#选择相关矩阵的上三角阵
upper = corr_matrix.where(np.triu(np.ones(corr_matrix.shape),k =1).astype(np.bool))
#找到相关性大于0.95的特征列的索引
to_drop = [column for column in upper.columns if any(upper[column] > 0.95)]
#删除特征
dataframe.drop(dataframe.columns[to_drop],axis = 1).head(5)
#output:
0 2
0 1 1
1 2 0
2 3 1
3 4 0
4 5 1
4. 删除与分类任务不相关的特征
问题描述:根据分类的目标向量,删除信息量较低的特征
解决方案:
对于分类型特征,计算每个特征和目标向量的卡方统计量
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2,f_classif
#加载数据
iris = load_iris()
features = iris.data
target = iris.target
#将分类数据转换成整数型数据
features = features.astype(int)
#选择卡方统计量最大的两个特征
chi2_selector = SelectKBest(chi2,k = 2)
features_kbest = chi2_selector.fit_transform(features,target)
#显示结果
print("original number of features:",features.shape[1])
print("Reduced number of features:",features_kbest.shape[1])
output:
original number of features: 4
Reduced number of features: 2
对于数值型特征数据,则计算每个特征与目标向量之间的方差分析F值:
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2,f_classif
#加载数据
iris = load_iris()
features = iris.data
target = iris.target
#将分类数据转换成整数型数据
features = features.astype(int)
#选择F值最大的两个特征
fvalue_selector = SelectKBest(f_classif,k = 2)
features_kbest = fvalue_selector.fit_transform(features,target)
#显示结果
print("original number of features:",features.shape[1])
print("Reduced number of features:",features_kbest.shape[1])
除了选择固定特征,可以通过SelectPercentile方法来选择前n%的特征:
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2,f_classif
from sklearn.feature_selection import SelectPercentile
#加载数据
iris = load_iris()
features = iris.data
target = iris.target
#将分类数据转换成整数型数据
features = features.astype(int)
#选择F值位于75%的两个特征
fvalue_selector = SelectPercentile(f_classif, percentile = 75)
features_kbest = fvalue_selector.fit_transform(features,target)
#显示结果
print("original number of features:",features.shape[1])
print("Reduced number of features:",features_kbest.shape[1])
output:
original number of features: 4
Reduced number of features: 3
卡方统计可以检查两个分类向量的相互独立性。也就是说,卡方统计量代表了观察到的样本数量和期望的样本数量(假设特征与目标向量无关)之间的差异。
通过计算特征和目标向量的卡方统计量,可以得到对两者之间独立性的度量值。如果两者相互独立,就代表特征与目标向量无关,特征中不包含分类所需要的信息。相反,如果特征和目标向量高度相关,则代表特征中包含训练分类模型所需的很多信息。
5. 递归式特征消除
问题描述:自动选择需要保留的最优特征。
解决方案:使用sklearn的RFECV类通过交叉验证(crossing validation,CV)进行递归式特征消除(Recursive Feature Elimination,REF)。该方法会重复训练模型,每一次训练移除一个特征,直到模型性能(例如精度)变差。剩余的特征就是最优特征:
import warnings
from sklearn.datasets import make_regression
from sklearn.feature_selection import RFECV
from sklearn import datasets,linear_model
#忽略警告信息
#warnings.filterwarnings(action="ingore",module="scipy",message="^internal gelsd")
#生成特征矩阵、目标向量以及系数
features,target = make_regression(n_samples = 10000,
n_features = 100,
n_informative = 2,
random_state = 1)
#创建线性回归对象
ols = linear_model.LinearRegression()
#递归消除特征
rfecv = RFECV(estimator = ols,step = 1,scoring = "neg_mean_squared_error")
rfecv.fit(features,target)
rfecv.transform(features)
#最优特征数量
rfecv.n_features_
#最优特征
rfecv.support_
#将特征从最好到最差排序
rfecv.ranking_