SmartCorrelatedSelection#
在处理包含众多特征的数据集时,通常会有两个以上的特征彼此之间表现出相关性。这种相关性可能存在于数据集中的三个、四个甚至更多的特征之间。因此,确定哪些特征应该保留,哪些应该剔除,成为一个关键的考虑因素。
决定从相关组中保留哪些特征涉及几种策略,例如:
模型性能:某些功能返回的模型性能高于其他功能。
变异性和基数:具有较高变异性或基数的特征通常提供更多关于目标变量的信息。
缺失数据:缺失数据较少的特征通常更可靠且信息量更大。
我们可以使用 SmartCorrelatedSelection
直接应用这种选择策略。
从一组相关的变量中,SmartCorrelatedSelection
将保留具有以下特征的变量:
最高方差
最高基数
最少缺失数据
表现最佳的模型(基于单一特征)
每个相关联的组中剩余的特性将被丢弃。
具有更高值多样性(更高方差或基数)的特征,往往更具预测性,而缺失数据最少的特征,往往更有用。
或者,直接使用组内的每个特征训练模型,并保留训练出最佳表现模型的那个特征,这直接评估了该特征对目标的影响。
程序#
SmartCorrelatedSelection
首先使用 pandas.corr()
支持的任何相关性方法,或返回 -1 到 1 之间值的用户定义函数,来查找相关特征组。
然后,它将根据上述标准,从每个相关特征组中尝试识别最佳候选者。
如果标准基于模型性能,SmartCorrelatedSelection
将训练一个单一特征的机器学习模型,使用相关组中的每一个特征,计算模型的性能,并选择返回最高性能模型的特征。简单来说,它训练单一特征模型,并保留性能最高的模型的特征。
如果标准是基于方差或基数,SmartCorrelatedSelection
将确定组中每个特征的这些属性,并保留最高的那个。但请注意,变异性受变量尺度的影响。因此,尺度较大的变量将主导选择过程,除非您有一个已缩放的数据集。
如果标准是基于缺失数据,SmartCorrelatedSelection
将从相关组中的每个特征中确定NA的数量,并保留NA较少的那个。
方差#
让我们看看如何在玩具示例中使用 SmartCorrelatedSelection
。让我们创建一个包含4个相关特征的玩具数据框:
import pandas as pd
from sklearn.datasets import make_classification
from feature_engine.selection import SmartCorrelatedSelection
# make dataframe with some correlated variables
def make_data():
X, y = make_classification(n_samples=1000,
n_features=12,
n_redundant=4,
n_clusters_per_class=1,
weights=[0.50],
class_sep=2,
random_state=1)
# transform arrays into pandas df and series
colnames = ['var_'+str(i) for i in range(12)]
X = pd.DataFrame(X, columns=colnames)
return X
X = make_data()
现在,我们设置 SmartCorrelatedSelection
来查找特征组,这些特征组的(绝对)相关系数 >0.8。在这些组中,我们希望保留具有最高方差的特征:
# set up the selector
tr = SmartCorrelatedSelection(
variables=None,
method="pearson",
threshold=0.8,
missing_values="raise",
selection_method="variance",
estimator=None,
)
使用 fit()
,转换器找到相关的变量并选择要保留的变量。使用 transform()
,它会从数据集中删除相关组中剩余的特征:
Xt = tr.fit_transform(X)
相关特征组存储在转换器的一个属性中:
tr.correlated_feature_sets_
在第一组中,4个特征至少与其中一个相关。在第二组中,2个特征相关。
[{'var_4', 'var_6', 'var_7', 'var_9'}, {'var_0', 'var_8'}]
SmartCorrelatedSelection
选择一个特征,然后确定数据框中其他特征与该特征的相关性。因此,组中的所有特征都将与此一个特征相关,但它们可能与组内的其他特征相关,也可能不相关,因为相关性不是传递的。
在评估中使用的这个特征,要么是具有较高方差、较高基数或较少缺失数据的特征。或者,如果选择了模型性能,那么它是按字母顺序排在第一位的特征。
我们可以通过检查以下属性来确定每个组中哪些功能将被保留,哪些将被移除:
tr.correlated_feature_dict_
在下面的字典中,我们看到从第一个相关组中,var_7
是一个键,因此它将被保留,而变量 4、6 和 9 是值,这意味着它们与 var_7
相关,因此将被移除。
因为我们基于变异性选择特征,var_7
在这个组中具有更高的变异性。
{'var_7': {'var_4', 'var_6', 'var_9'}, 'var_8': {'var_0'}}
同样,var_8
是一个键,将被保留,而 var_0
是一个值,这意味着它与 var_8
相关联,因此将被移除。
我们可以证实,例如,var_7
具有最高的变异性,如下所示:
X[list(tr.correlated_feature_sets_[0])].std()
该命令返回以下输出,从中我们可以看到 var_7
的变异性最高:
var_4 1.810273
var_7 2.159634
var_9 1.764249
var_6 2.032947
dtype: float64
将从数据集中移除的特征存储在以下属性中:
tr.features_to_drop_
['var_6', 'var_4', 'var_9', 'var_0']
如果我们现在继续打印转换后的数据,我们会看到相关的特征已经被移除。
print(Xt.head())
var_1 var_2 var_3 var_5 var_7 var_8 var_10 \
0 -2.376400 -0.247208 1.210290 0.091527 -2.230170 2.070483 2.070526
1 1.969326 -0.126894 0.034598 -0.186802 -1.447490 2.421477 1.184820
2 1.499174 0.334123 -2.233844 -0.313881 -2.240741 2.263546 -0.066448
3 0.075341 1.627132 0.943132 -0.468041 -3.534861 2.792500 0.713558
4 0.372213 0.338141 0.951526 0.729005 -2.053965 2.186741 0.398790
var_11
0 -1.989335
1 -1.309524
2 -0.852703
3 0.484649
4 -0.186530
性能#
现在让我们从每个组中选择返回性能最高的机器学习模型的特征。我们将使用决策树。
我们首先创建一个玩具数据框:
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.tree import DecisionTreeClassifier
from feature_engine.selection import SmartCorrelatedSelection
# make dataframe with some correlated variables
def make_data():
X, y = make_classification(n_samples=1000,
n_features=12,
n_redundant=4,
n_clusters_per_class=1,
weights=[0.50],
class_sep=2,
random_state=1)
# transform arrays into pandas df and series
colnames = ['var_'+str(i) for i in range(12)]
X = pd.DataFrame(X, columns=colnames)
return X, y
X, y = make_data()
现在让我们设置选择器:
tr = SmartCorrelatedSelection(
variables=None,
method="pearson",
threshold=0.8,
missing_values="raise",
selection_method="model_performance",
estimator=DecisionTreeClassifier(random_state=1),
scoring='roc_auc',
cv=3,
)
接下来,我们将选择器拟合到数据上。这里,由于我们正在训练一个模型,因此还需要传递目标变量:
Xt = tr.fit_transform(X, y)
让我们探索相关的特征组:
tr.correlated_feature_sets_
我们看到相关特征的组略有不同,因为在这种情况下,特征是按字母顺序评估的,而当我们使用方差时,特征是根据评估的标准差排序的。
[{'var_0', 'var_8'}, {'var_4', 'var_6', 'var_7', 'var_9'}]
我们可以在以下属性中找到将被保留为关键的功能:
tr.correlated_feature_dict_
变量 var_0
和 var_7
将被保留,其余的将被丢弃。
{'var_0': {'var_8'}, 'var_7': {'var_4', 'var_6', 'var_9'}}
我们在以下属性中找到将被删除的变量:
tr.features_to_drop_
['var_8', 'var_4', 'var_6', 'var_9']
现在我们可以打印转换后的结果数据框:
print(Xt.head())
var_0 var_1 var_2 var_3 var_5 var_7 var_10 \
0 1.471061 -2.376400 -0.247208 1.210290 0.091527 -2.230170 2.070526
1 1.819196 1.969326 -0.126894 0.034598 -0.186802 -1.447490 1.184820
2 1.625024 1.499174 0.334123 -2.233844 -0.313881 -2.240741 -0.066448
3 1.939212 0.075341 1.627132 0.943132 -0.468041 -3.534861 0.713558
4 1.579307 0.372213 0.338141 0.951526 0.729005 -2.053965 0.398790
var_11
0 -1.989335
1 -1.309524
2 -0.852703
3 0.484649
4 -0.186530
让我们检查其他可能有用的属性。与任何 Scikit-learn 转换器一样,我们可以如下获取结果数据框中的特征名称:
tr.get_feature_names_out()
['var_0', 'var_1', 'var_2', 'var_3', 'var_5', 'var_7', 'var_10', 'var_11']
我们还发现了 get_support
方法,该方法标记了将从数据框中保留的特征:
tr.get_support()
[True, True, True, True, False, True, False, True, False, False, True, True]
就是这样!
其他资源#
在这个笔记本中,我们展示了如何使用 SmartCorrelatedSelection
与不同的关系度量:
所有笔记本都可以在 专用仓库 中找到。
有关此功能选择方法及其他方法的更多详细信息,请查看以下资源:
或者阅读我们的书:
我们的书籍和课程都适合初学者和更高级的数据科学家。通过购买它们,您正在支持 Feature-engine 的主要开发者 Sole。