【问题标题】:Using chi2 test for feature selection with continuous features (Scikit Learn)使用 chi2 测试进行具有连续特征的特征选择(Scikit Learn)
【发布时间】:2018-09-25 14:43:42
【问题描述】:

我正在尝试从许多连续特征中预测二元(分类)目标,并希望在进行模型拟合之前缩小您的特征空间。我注意到 SKLearn 的 Feature Selection 包中的 SelectKBest 类在 Iris 数据集上有以下示例(它也从连续特征中预测二进制目标):

from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
iris = load_iris()
X, y = iris.data, iris.target
X.shape
(150, 4)
X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
X_new.shape
(150,2)

该示例使用 chi2 检验来确定模型中应使用哪些特征。然而,据我了解,chi2 测试严格用于我们具有预测分类性能的分类特征的情况。我不认为 chi2 测试可以用于这样的场景。我的理解错了吗? chi2检验可以用来检验分类变量是否依赖于连续变量吗?

【问题讨论】:

    标签: python scikit-learn feature-selection chi-squared


    【解决方案1】:

    带有 chi2 测试的 SelectKBest 函数仅适用于分类数据。事实上,只有当特征只有 1 和 0 时,测试的结果才会真正有意义。

    如果您稍微检查一下chi2 的实现,您会发现代码只对每个功能应用求和,这意味着该函数只需要二进制值。另外,接收 chi2 函数的参数表示如下:

    def chi2(X, y):
    ...
    
    X : {array-like, sparse matrix}, shape = (n_samples, n_features_in)
        Sample vectors.
    y : array-like, shape = (n_samples,)
        Target vector (class labels).
    

    这意味着该函数期望接收包含所有样本的特征向量。但是稍后在计算期望值时,您会看到:

    feature_count = X.sum(axis=0).reshape(1, -1)
    class_prob = Y.mean(axis=0).reshape(1, -1)
    expected = np.dot(class_prob.T, feature_count)
    

    只有当 X 和 Y 向量只有 1 和 0 时,这些代码行才有意义。

    【讨论】:

    【解决方案2】:

    我同意@lalfab 但是,我不清楚为什么 sklearn 提供了在具有所有连续变量的 iris 数据集上使用 chi2 的示例。 https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html

    >>> from sklearn.datasets import load_digits
    >>> from sklearn.feature_selection import SelectKBest, chi2
    >>> X, y = load_digits(return_X_y=True)
    >>> X.shape
    (1797, 64)
    >>> X_new = SelectKBest(chi2, k=20).fit_transform(X, y)
    >>> X_new.shape
    (1797, 20)

    【讨论】:

    • 同样的问题,你找到解释了吗?
    【解决方案3】:

    我的理解是,使用Chi2进行特征选择时,因变量必须是分类类型,但自变量可以是分类变量或连续变量,只要它是非负的。该算法试图做的是首先建立一个矩阵格式的列联表,揭示变量的多元频率分布。然后尝试使用此列联表找到变量背后的依赖结构。 Chi2 是衡量依赖性的一种方法。

    来自维基百科的列联表(https://en.wikipedia.org/wiki/Contingency_table,2020-07-04):

    列联表的标准内容

    • 多列(从历史上看,它们旨在用完打印页面的所有空白)。每行代表人口中的特定子组(在这种情况下为男性或女性),列有时被称为横幅点或切口(而行有时被称为存根)。
    • 显着性检验。通常,列比较(测试列之间的差异并使用字母显示这些结果)或单元格比较(使用颜色或箭头来识别表格中以某种方式突出的单元格)。
    • 作为小计的网或网。
    • 以下一项或多项:百分比、行百分比、列百分比、索引或平均值。
    • 未加权样本量(计数)。

    基于此,纯二元特征可以很容易地总结为计数,这就是人们通常进行 Chi2 测试的方式。但只要特征是非负的,就总能以一种“有意义”的方式将其累积在列联表中。在 sklearn 实现中,它总结为 feature_count = X.sum(axis=0),然后在 class_prob 上取平均值。

    【讨论】:

    • 听起来您是在说连续变量被分箱以创建一个类别,然后该类别具有频率计数,就像您为直方图计算的一样。如果是这种情况,难道不能通过合并两个连续变量来计算 Chi^2 检验统计量和 p 值吗?当然,分箱会丢失信息,最好使用 Pearson 的相关性,但有没有办法量化分箱过程丢失的信息?
    【解决方案4】:

    据我了解,您不能将卡方 (chi2) 用于连续变量。chi2 计算需要构建列联表,您可以在其中计算每个感兴趣变量类别的出现次数。由于该 RC 表中的单元格对应于特定类别,因此我无法看到如何在不进行大量预处理的情况下从连续变量构建此类表。

    因此,在我看来,您引用的 iris 示例是不正确使用的示例。

    但是 Scikit-learn 中 chi2 特征缩减的现有实现存在更多问题。首先,正如@lalfab 所写,实现需要二进制特性,但文档并不清楚这一点。这导致社区普遍认为 SelectKBest 可以用于分类特征,而实际上它不能。其次,Scikit-learn 实现未能实现 chi2 条件(RC 表的 80% 单元格需要具有预期计数 >=5),如果某些分类特征具有许多可能值,则会导致错误结果。总而言之,在我看来,这种方法既不能用于连续特征,也不能用于分类特征(二进制除外)。我在下面写了更多关于此的内容:

    这里是Scikit-learn bug request #21455: 这里是article and the alternative implementation:

    【讨论】:

      猜你喜欢
      • 2014-11-05
      • 2021-03-26
      • 2018-02-24
      • 2018-06-01
      • 1970-01-01
      • 2019-07-25
      • 2015-09-08
      • 2019-01-12
      相关资源
      最近更新 更多