如何理解 ANOVA-F 在 Python 中进行特征选择。Sklearn SelectKBest 与 f_classif

数据挖掘 分类 特征选择
2021-10-12 10:05:55

我试图理解为二进制分类问题的特征选择计算 ANOVA F 值的真正含义。

正如我从基本统计数据计算 ANOVA 所了解的那样,我们应该至少有 2 个样本可以计算 ANOVA 值。那么这是否意味着在 Sklearn 实现中这些样本取自每个特征?在针对这个问题进行特征选择的情况下,这些样本究竟代表了什么?

我试图设置一个我在下面列出的非常简单的示例,但我仍然很难理解 ANOVA 值在这里的真正含义是什么?我也很难理解如何手动计算,这通常可以帮助我了解内部发生的情况。

在此示例中,还款状态 0 表示贷款已偿还,1 表示违约。为了简单起见,我只提供了 5 行数据。

在此处输入图像描述

代码和结果如下:

在此处输入图像描述

2个回答

直觉

我们有两个类别,我们想为每个特征找到一个分数,说明“这个特征在两个类别之间的区分程度”。现在看下图。有红色和蓝色两个类和两个特征xy 轴。

在此处输入图像描述

x 特征是一个更好的分隔符 y 因为如果我们将数据投影在 x 轴我们得到两个完全分离的类,但如果我们将数据投影到 y,两个类在轴的中间有重叠(如果我们需要更多说明,请评论)。

是什么使得 x 好于 y? 如上图所示:

  • 根据x,两个班相距甚远
    • 数学翻译:类分布均值之间的距离x超过y.
  • 根据x, 类的散布点不是相互重叠而是根据y他们是这样。这意味着根据x,类更紧凑,因此更有可能与另一个类不重叠。
    • 数学翻译:每个单类的方差根据x小于那些y.

现在我们可以很容易地说distance_between_classescompactness_of_classes是个好成绩!这个分数越高,特征区分类别的能力就越好。

现在我们知道,根据这个定义,什么goodbad特征的意思。让我们找到一个数学公式来量化它。

数学(在纸上做)

让我们制定我们的两个标准:

  • 类分布均值之间的距离是分子。考虑到人口,我假设具有统计意义(需要统计学家的参考!)。 在此处输入图像描述
  • 一个类似于类样本方差的概念是分母。这里不是将平方和除以(sample_population1), 我们总结所有(sample_population1)s 并将最终值除以它们。 在此处输入图像描述

现在回到您的数据

要计算上述内容,您可以根据不同的类计算每个特征的类间距离总和和类内变化总和。我只为一个功能做这件事。让我们选择贷款

Class 1: [5000, 18000]
Class 2: [47500, 45600, 49500]

Mean of all points: (47500 + 45600 + 49500 + 5000 + 18000) / 5 = 33120
Mean 1: (5000 + 18000) / 2 = 11500
Mean 2: (47500 + 45600 + 49500) / 3 = 47533
Numerator: 2 x (11500 - 33120)^2 + 3 x (47533 - 33120)^2 = 1,558,052,507

对于分母,我们使用类内的平方和(它只是样本方差公式中的分子):

SSW 1: (5000 - 11500)^2 + (18000 - 11500)^2 = 84,500,000 
SSW 2: (47500 - 47533)^2 + (45600 - 47533)^2 + (49500 - 47533)^2 = 7,606,667
Na = 2, Nb = 3 --> (Na - 1) + (Nb - 1) = 1 + 2 = 3
Denominator: (84,500,000 + 7,606,667)/3 = 30,702,222 

现在特征贷款的 F 分数是:

F-Score: 1,558,052,507 / 30,702,222 = 50.74

正如您在 Python 中的计算所见。

笔记

  • 我试图用一种简单的方式来解释。例如,样本方差的分母称为自由度,但为简单起见,我跳过了这些术语。
  • 只要理解主要思想。进一步的均值和较小的内方差,更好的特征。您也可以自己制定它(但是您将不再有 p 值;))
  • 找到 P 值并理解它的含义是我跳过的另一个故事。

希望它有所帮助。祝你好运!

f_classif 计算的 F-score 可以使用图像中显示的以下公式手动计算:参考视频 视频截图

直观地说,它是(输入特征(X)解释的输出特征(y)的方差与输入特征(X)未解释的输出特征(y)的方差)的比率。

例子 :

使用 f_classif 的 sklearn 代码

from sklearn.feature_selection import f_classif
import numpy as np
X = np.array([5000, 18000, 47500, 45600, 49500]).reshape(-1,1)
y = np.array([1,1,0,0,0])
F,pval = f_classif(X,y)
print(F,pval)

[50.74816155] [0.00569324]

使用上述公式验证

X = np.array([5000, 18000, 47500, 45600, 49500])
X1 = np.array([5000, 18000])
X2 = np.array([47500, 45600, 49500])
mu = np.mean(X)                                   # overall mean
mu1 = np.mean(X1)                                 # mean of X1
mu2 = np.mean(X2).                                # mean of X2
SSm = np.sum(((X-mu)**2))                         # SS(mean)
SSf = np.sum((X1-mu1)**2) + np.sum((X2-mu2)**2)   # SS(fit)
p_fit = 2
p_mean = 1
F = ((SSm - SSf)*(X.shape[0]-p_fit))/((p_fit - p_mean)*SSf)
print(F)

50.74