引入
机器学习中,一个重要的步骤就是特征工程。在特征降维中,对于一数据集,其中某些特征值与目标值的相关性并不大,因此对于这些特征值,往往需要进行处理(这里指的是去除),有一种常用的方法是--低方差特征过滤法。
该方法的原理是:计算逐个计算所有特征值的方差,如果得到的方差值小于给定的超参数,则认为该特征大多样本的值比较接近,进而选择性的去除该特征。
api为:sklearn.feature_selection.VarianceThreshold(X),参数X为方差阈值,若计算得出的特征方差小于该值,则去除该特征。
举例说明
在最近的使用过程中,发现一个巨大的缺陷--低方差特征过滤法对特征值的大小极为敏感。
下面用一个例子来说明这个问题:
import numpy as np
import pandas as pd
from sklearn.feature_selection import VarianceThreshold
data = [
[0.124, 1, 124],
[0.576, 3, 576],
[0.036, 4, 36],
[0.796, 6, 796],
[0.326, 5, 326],
[0.148, 1, 148]
]
line_name = ['l1', 'l2', 'l3', 'l4', 'l5', 'l6']
col_name = ['feature1', 'feature2', 'target']
data = pd.DataFrame(data, line_name, col_name)
# print(data)
# print(np.var(data['feature1']), np.var(data['feature2']))
transfer = VarianceThreshold(threshold=1)
transfer_data = transfer.fit_transform(data.iloc[:, 0:2])
# print(data.iloc[:, 0:2])
# print(transfer_data)
代码如上,data为数据集,其中data的前两列为特征值feature1和feature2,最后一列为特征值target。单从肉眼看,feature1明显与target有极大的线性相关性,而feature2基本没有。下面计算feature1与feature2的方差:
D1 = np.var(data['feature1']) D2 = np.var(data['feature2'])
计算结果为:
D1 = 0.07326188888888889
D2 = 3.555555555555556
那么根据低方差特征过滤法,代码中超参数的值为1(方差阈值),明显D1<1<D2,那么该算法将删除feature1特征,然而feature1的与特征值的线性相关度明显比feature2大。那么从这里不难看出,这种算法确实很容易受到特征值大小的影响。
改进方法
预判数据相关性
所谓预判数据相关性,就是在进行低方差特征过滤法之前,先对所有特征值,计算其与目标值之间的线性相关程度,记为K(可以拿损失函数的最小值作为K)。对于K的值,确定时应该尽量偏大(即我们有很大的把握对于某特征值,该特征是与目标值线性相关的)。而筛选后的那些,很可能相关、几乎不相关...的数据,则作为低方差特征过滤法的输入进一步筛选。
在上面的例子中该过程可以理解为,先计算feature1和feature2与target之间的线性相关程度,得到结果为:feature1明显与特征值线性相关,feature2几乎不相关(feature2的值为其他也可以,只要feature2的值计算后,被认为不是有很大把握feature2与target线性相关,那么就应该与feature1区分开来)。之后,feature2作为低方差特征过滤法的输入(显然当超参数X设置为1时,feature2会被过滤掉),而feature1则被保护,不参与低方差特征过滤法。
经过这种操作,某些特征值大小较小,却与目标值有很大相关的特征会被“保护起来”,低方差特征过滤法的准确率会大大提升,具体的代码实践不会特别难,这里就不展示。