作者:陈颖祥、杨子晗
编译:AI有道
数据预处理后,我们生成了大量的新变量(比如独热编码生成了大量仅包含0或1的变量)。但实际上,部分新生成的变量可能是多余:一方面它们本身不一定包含有用的信息,故无法提高模型性能;另一方面过这些多余变量在构建模型时会消耗大量内存和计算能力。因此,我们应该进行特征选择并选择特征子集进行建模。
项目地址:
https://github.com/YC-Coder-Chen/feature-engineering-handbook
本文将介绍特征工程中的 Multivariate Filter Methods 多元特征过滤。
目录:
1.1.2 Multivariate Filter Methods 多元特征过滤
单变量特征过滤仅考虑了每一变量与目标变量之间的关系,而忽视了变量间的相关性。多元变量过滤则解决了这一问题,其考虑了变量之间的相互关系,基于整个特征空间选择最佳特征。因此多元特征过滤在删除冗余变量方面表现更好。这里利用亚利桑那州立大学开发的skfeature模块来进行多元特征过滤。
1.1.2.1 Max-Relevance Min-Redundancy (mRMR) 最大相关最小冗余
最大相关最小冗余试图寻找一个与目标变量有较高相关性(例如:MI)的变量子集,同时这个子集中的变量还应具有较低的相互关联性。通过解析源代码,我们发现,skfeature中最大相关最小冗余方法仅适用于分类问题中的离散特征,因为它计算过程中使用的是计算离散情形下的互信息 (MI)的公式。
公式:
假设数据集共包含m个特征,则基于mRMR公式,其中第n个特征的重要性可被表示为:
????(????,????????) 为变量????????与目标变量Y的互信息。1/|????|∑????????∈????????(????????,????????)为变量????????与现有变量子集中所有变量的互信息的平均值。
mRMR其实是一个逐步(step-wise)的方法,在mRMR特征选择过程的每一步中,具有最高特征重要性????????????????????(????????)的变量????????,(????????∉????)将会被加入子集中,直至子集中的变量数达到用户要求。
代码语言:javascript复制import numpy as np
from skfeature.function.information_theoretical_based import MRMR
from sklearn.datasets import load_iris # 利用iris数据作为演示数据集
# 载入数据集
iris = load_iris()
X, y = iris.data, iris.target
# 选择前100个观测点作为训练集
# 剩下的50个观测点作为测试集
# 由于skfeature中的mRMR仅适用于离散变量
# 因此我们通过将float转换为int而把所有连续变量转换为离散变量
# 此转换仅用于演示目的
train_set = X[0:100,:].astype(int)
test_set = X[100:,].astype(int)
train_y = y[0:100].astype(int)
feature_index,_,_ = MRMR.mrmr(train_set, train_y, n_selected_features=2) # 在训练集上训练
transformed_train = train_set[:,feature_index] # 转换训练集
assert np.array_equal(transformed_train, train_set[:,[2,3]]) # 其选择了第三个及第四个变量
transformed_test = test_set[:,feature_index] # 转换测试集
assert np.array_equal(transformed_test, test_set[:,[2,3]]) # 其选择了第三个及第四个变量
1.1.2.2 Correlation-based Feature Selection (CFS) 基于相关性的特征选择
与mRMR类似,基于相关性的特征选择(CFS)也基于一个类似的假设:一个好的特征子集应包含与目标高度相关且彼此不相关的特征。通过解析源代码,我们发现,skfeature中CFS的实现也仅适用于分类问题中的离散特征。因为其使用的是离散情形下的对称不确定性(symmetrical uncertainty)作为变量间相关性的衡量标准。
公式:
???? 为特征子集. 我们需要寻找最大化????????????????????????的最优子集????∗。
????????(????????,????)为离散变量????????与目标变量????间的对称不确定性(SU)。
????????(????????,????????)为离散变量????????与离散变量????????间的对称不确定性(SU)。
代码语言:javascript复制import numpy as np
from skfeature.function.statistical_based import CFS
from sklearn.datasets import load_iris # 利用iris数据作为演示数据集
# 载入数据集
iris = load_iris()
X, y = iris.data, iris.target
# 选择前100个观测点作为训练集
# 剩下的50个观测点作为测试集
# 由于skfeature中的CFS仅适用于离散变量
# 因此我们通过将float转换为int而把所有连续变量转换为离散变量
# 此转换仅用于演示目的
train_set = X[0:100,:].astype(int)
test_set = X[100:,].astype(int)
train_y = y[0:100].astype(int)
num_feature = 2 # 从原数据集中选择两个变量
feature_index = CFS.cfs(train_set, train_y) # 在训练集上训练
transformed_train = train_set[:,feature_index[0:num_feature]] # 转换训练集
assert np.array_equal(transformed_train, train_set[:,[3,2]]) # 其选择了第三个及第四个变量
transformed_test = test_set[:,feature_index[0:num_feature]] # 转换测试集
assert np.array_equal(transformed_test, test_set[:,[3,2]]) # 其选择了第三个及第四个变量
1.1.2.3 Fast Correlation-based Filter (FCBF) 基于相关性的快速特征选择
相比于CFS,FCBS能够更加高效的筛选变量。其同样为逐步(step-wise)的方法,具体步骤与mRMR非常类似,但FCBS使用对称不确定性(SU)衡量变量间的关联性。FCBF首先剔除与目标变量具有较低SU值的变量,并对剩下的变量按与目标变量的SU值从最高到最低排序,然后逐一删除冗余特征。与mRMR,CFS相似,在skfeature中实现的FCBF仅适用于具有离散变量的分类问题。
公式:
步骤:
1)计算每个特征变量 ???????? 与目标变量 ???? 之间的相关性 ????????(????????,????)
2)仅保留 ????????(????????,????) 大于一定阈值 ???? 的特征变量,组成候选列表 ????????????????????
3)按照 ????????(????????,????) 值的大小对 ???????????????????? 中的变量从大到小排序
4)按顺序依次计算每一个特征 ???????? 与候选列表 ???????????????????? 中顺序靠后的每一个特征 ???????? 的相关SU值 ????????(????????,????????)
5)若 ????????(????????,????????) 大于 ????????(????????,????) ,则从候选列表 ???????????????????? 中删除 ????????
代码语言:javascript复制import numpy as np
from skfeature.function.information_theoretical_based import FCBF
from sklearn.datasets import load_iris # 利用iris数据作为演示数据集
# 载入数据集
iris = load_iris()
X, y = iris.data, iris.target
# 选择前100个观测点作为训练集
# 剩下的50个观测点作为测试集
# 由于skfeature中的FCFS仅适用于离散变量
# 因此我们通过将float转换为int而把所有连续变量转换为离散变量
# 此转换仅用于演示目的
train_set = X[0:100,:].astype(int)
test_set = X[100:,].astype(int)
train_y = y[0:100].astype(int)
num_feature = 2 # 从原数据集中选择两个变量
feature_index = FCBF.fcbf(train_set, train_y, n_selected_features = num_feature)[0] # 在训练集上训练
transformed_train = train_set[:,feature_index[0:num_feature]] # 转换训练集
assert np.array_equal(transformed_train, train_set[:,[3]]) # 其仅选择了第四个变量
# 这是由于其他变量目标变量????之间的相关性过低造成的
transformed_test = test_set[:,feature_index[0:num_feature]] # 转换测试集
assert np.array_equal(transformed_test, test_set[:,[3]]) # 其仅选择了第四个变量
1.1.2.4 ReliefF
ReliefF方法是一种基于Relief方法的特征加权算法。在Relief方法中,其根据特征与目标变量的相关性强弱(二分类)给变量分配权重,并删除权重低于特定阈值的特征。其将相关性定义为变量区分邻近观测点的能力。
具体来说,在每一步中,Relief方法都会从训练集中随机选择一个观测点S,然后找到具有相同目标标签的S的最近邻观测点,称为NearHit。它还将找到具有不同目标标签的S的最近邻观测点,称为NearMiss。然后根据以下规则更新每个功能的权重:
1)若观测点S在某变量上与NearHit的距离大于与NearMiss的距离,则该变量的权重将增加,因为变量有助于区分最邻近情形下的目标标签。2)相反,若观测点S在某变量上与NearHit的距离小于与NearMiss的距离,则该变量的权重会降低。
将上述过程重复m次,最后我们会获得每个特征变量的平均权重。特征变量的权重越大,则特征的分类能力越强,越应该被留在最终的特征子集中。
在ReliefF中,其修改了权重更新的方式,因此ReliefF方法可以被应用于多类分类问题。另外,它随机采样K个最近的观测点而不是一个。
在skfeature中实现的ReliefF可用于分类问题中的连续特征或二元类别特征,因其使用的是L1范数来衡量差异。针对非二元特征,我们可以先将其独热编码,再使用ReliefF方法。
公式:
????1 and ????2 为任意两个观测点。????????为某一特征变量. S为我们选择的观测点. ????????为第j个NearHit,????????为第j个NearMiss. C为与我们所选的观测点不同的其他目标类别标签。
代码语言:javascript复制import numpy as np
from skfeature.function.similarity_based import reliefF
from sklearn.datasets import load_iris # 利用iris数据作为演示数据集
# 载入数据集
iris = load_iris()
X, y = iris.data, iris.target
# 选择前100个观测点作为训练集
# 剩下的50个观测点作为测试集
# skfeature中的reliefF直接适用于连续变量
train_set = X[0:100,:]
test_set = X[100:,]
train_y = y[0:100]
num_feature = 2 # 从原数据集中选择两个变量
score = reliefF.reliefF(train_set, train_y) # 计算每一个变量的权重
feature_index = reliefF.feature_ranking(score) # 依据权重选择变量
transformed_train = train_set[:,feature_index[0:num_feature]] # 转换训练集
assert np.array_equal(transformed_train, train_set[:,[2, 3]]) # 其选择了第三个及第四个变量
transformed_test = test_set[:,feature_index[0:num_feature]] # 转换测试集
assert np.array_equal(transformed_test, test_set[:,[2, 3]]) # 其选择了第三个及第四个变量
1.1.2.5 Spectral Feature Selection (SPEC) 基于谱图的特征选择
基于谱图的特征选择(SPEC)方法是基于谱图理论的无监督方法。其首先建立变量相似度集合S,并建立其图表示。然后,其根据构造图的频谱评估特征。由于在skfeature中实现的SPEC方基于RBF(高斯)内核建立相似集,因此其可用于分类问题中的连续特征或二元类别特征。针对非二元特征,我们可以先将其独热编码,再使用ReliefF方法。
代码语言:javascript复制import numpy as np
from skfeature.function.similarity_based import SPEC
from sklearn.datasets import load_iris # 利用iris数据作为演示数据集
# 载入数据集
iris = load_iris()
X, y = iris.data, iris.target
# 选择前100个观测点作为训练集
# 剩下的50个观测点作为测试集
# skfeature中的SEPC方法直接适用于连续变量
train_set = X[0:100,:]
test_set = X[100:,]
train_y = y[0:100]
num_feature = 2 # 从原数据集中选择两个变量
score = SPEC.spec(train_set) # 计算每一个变量的得分
feature_index = SPEC.feature_ranking(score) #依据变量得分选择变量
transformed_train = train_set[:,feature_index[0:num_feature]] # 转换训练集
assert np.array_equal(transformed_train, train_set[:,[1, 0]]) # 其选择了第一个及第二个变量
transformed_test = test_set[:,feature_index[0:num_feature]] # 转换测试集
assert np.array_equal(transformed_test, test_set[:,[1, 0]]) # 其选择了第一个及第二个变量
专栏系列:
专栏 | 基于 Jupyter 的特征工程手册:数据预处理(一)
专栏 | 基于 Jupyter 的特征工程手册:数据预处理(二)
专栏 | 基于 Jupyter 的特征工程手册:数据预处理(三)
专栏 | 基于 Jupyter 的特征工程手册:数据预处理(四)
专栏 | 基于 Jupyter 的特征工程手册:特征选择(一)
专栏 | 基于Jupyter 的特征工程手册:特征选择(二)