过滤方法提供了一种计算成本较低的方式,在将特征输入机器学习模型之前对其进行修剪。它们评估特征的固有属性,通常使用统计度量,而不考虑最终将使用的预测模型。最简单的过滤技术之一是基于特征方差的。方差阈值处理的原理方差阈值处理的核心思想直观明了:在数据集中变化很小的特征不太可能提供有效信息。如果一个特征对于几乎所有样本都具有相同的值,那么它提供的用于区分样本的信息将非常少。在极端情况下,方差为零的特征在所有样本中都是恒定的,显然无法帮助模型进行预测。移除低方差特征是一个基本的数据清理步骤。通过消除恒定或接近恒定的特征,我们可以降低数据集的维度,可能加快模型训练并降低复杂性,而不会显著影响性能。计算方差回想一下,特征 $X$ 的方差衡量其值相对于均值 ($\mu$) 的离散程度。其计算方式如下:$$ \text{方差}(X) = \frac{1}{N} \sum_{i=1}^{N} (x_i - \mu)^2 $$这里 $N$ 是样本数量,而 $x_i$ 是第 $i$ 个样本的特征值。方差接近零表明数据点紧密地聚集在均值附近。对于二元特征(取值 0 或 1),方差计算为 $p(1-p)$,这里 $p$ 是取值为 1 的样本比例。如果 $p$ 接近 0 或 1(这意味着特征几乎总是 0 或几乎总是 1),方差将接近 0。在 Scikit-learn 中实现方差阈值Scikit-learn 在其 feature_selection 模块中提供了 VarianceThreshold 转换器以实现此目的。import pandas as pd from sklearn.feature_selection import VarianceThreshold # 包含低方差特征的样本数据 data = { 'feat1': [0.1, 0.12, 0.09, 0.11, 0.1], # 低方差数值特征 'feat2': [10, 12, 9, 110, 50], # 高方差数值特征 'feat3': [0, 0, 0, 0, 0], # 零方差(常数) 'feat4': [1, 1, 1, 1, 0], # 低方差二元特征(大多为1) 'feat5': [0, 1, 0, 1, 0] # 较高方差二元特征 } df = pd.DataFrame(data) print("原始 DataFrame:") print(df) print("\n方差:") print(df.var()) # 1. 移除零方差特征(默认阈值=0) selector_zero = VarianceThreshold(threshold=0.0) df_zero_removed = selector_zero.fit_transform(df) # 获取选定列的名称 cols_zero_removed = selector_zero.get_feature_names_out(input_features=df.columns) df_zero_removed = pd.DataFrame(df_zero_removed, columns=cols_zero_removed) print("\n移除零方差特征后的 DataFrame:") print(df_zero_removed) # 2. 移除方差低于特定阈值(例如,0.1)的特征 # 注意:对于非布尔特征,如果它们处于不同的尺度上,请先考虑进行缩放。 # 这里,我们直接应用它作为演示。 selector_low = VarianceThreshold(threshold=0.1) # 示例阈值 df_low_removed = selector_low.fit_transform(df) cols_low_removed = selector_low.get_feature_names_out(input_features=df.columns) df_low_removed = pd.DataFrame(df_low_removed, columns=cols_low_removed) print("\n移除方差 < 0.1 的特征后的 DataFrame:") print(df_low_removed) 输出:Original DataFrame: feat1 feat2 feat3 feat4 feat5 0 0.10 10 0 1 0 1 0.12 12 0 1 1 2 0.09 9 0 1 0 3 0.11 110 0 1 1 4 0.10 50 0 0 0 Variances: feat1 0.000130 feat2 1813.200000 feat3 0.000000 feat4 0.160000 feat5 0.240000 dtype: float64 DataFrame after removing zero-variance features: feat1 feat2 feat4 feat5 0 0.10 10.0 1.0 0.0 1 0.12 12.0 1.0 1.0 2 0.09 9.0 1.0 0.0 3 0.11 110.0 1.0 1.0 4 0.10 50.0 0.0 0.0 DataFrame after removing features with variance < 0.1: feat2 feat4 feat5 0 10.0 1.0 0.0 1 12.0 1.0 1.0 2 9.0 1.0 0.0 3 110.0 1.0 1.0 4 50.0 0.0 0.0在第一步中,使用默认 threshold=0.0,VarianceThreshold 找到并移除了 feat3,因为它是一个常数特征。在第二步中,将 threshold 设置为 0.1,它移除了 feat1(方差约 0.00013)和 feat3(方差 0),保留了 feat2、feat4 和 feat5,因为它们的方差高于 0.1。注意事项与局限性尺度依赖性: 方差高度依赖于特征的尺度。一个取值范围在 0 到 1 之间的特征,其方差自然会比取值范围在 0 到 1,000,000 之间的特征小得多,即使两者相对于各自的尺度而言具有同等的“信息量”。通常建议在应用非零阈值的 VarianceThreshold 之前,先对特征进行缩放(例如,使用 StandardScaler 或 MinMaxScaler)。 否则,你可能会因为特征单位导致数值较小而错误地舍弃它们。默认的阈值 0(移除常数特征)不需要事先缩放。阈值选择: 设置非零阈值需要仔细考虑。没有普适的“正确”阈值。你可以检查特征的方差,并根据它们的分布来决定。对于布尔特征,像 $p(1-p)$ 这样的阈值,其中 $p$ 是一个小的比例(例如,阈值 = $0.01 \times (1 - 0.01) = 0.0099$),可以移除对于不到 1% 或超过 99% 样本为真的特征。然而,这是一种启发式方法。忽略目标变量: 这是过滤方法的一个基本特点。VarianceThreshold 只查看特征 ($X$) 本身的方差;它不考虑特征与目标变量 ($y$) 之间的任何关系。在少数情况下,低方差特征仍可能具有预测性。反之,高方差特征可能与目标完全无关。方差阈值处理作为一种基本的合理性检查和预处理步骤,对于快速移除明显无信息量的特征(尤其是常数特征)很有用。它通常用作在应用更复杂的特征选择技术之前的初步筛选。