Scikit-learnχ²(卡方)统计量和相应的列联表

tia*_*iao 11 python statistics numpy machine-learning scikit-learn

在scikit-learn http://cikit-learn.org/stable/modules/generated/sklearn.feature_selection.chi2.html的卡方单面特征选择函数的文档中,它指出

该分数可用于选择具有来自X的χ2(卡方)统计值的最高值的n_features特征,其必须包含相对于类的布尔值或频率(例如,文档分类中的术语计数).

我很难理解相应的列联表是什么样的,特别是在频率特征的情况下.

例如,考虑具有布尔特征和目标的以下数据集:

import numpy as np

>>> X = np.random.randint(2, size=50).reshape(10, 5)
array([[1, 0, 0, 0, 1],
       [1, 1, 0, 1, 1],
       [1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 1],
       [1, 0, 0, 0, 1],
       [1, 0, 1, 1, 1],
       [0, 1, 1, 0, 0],
       [1, 0, 1, 1, 1],
       [1, 1, 1, 1, 0]])

>>> y = np.random.randint(2, size=10)
array([1, 0, 0, 0, 1, 1, 1, 1, 0, 1])
Run Code Online (Sandbox Code Playgroud)

要构建关于第一个特征的列联表,我们可以这样做(原谅我的PEP8违规)

import scipy as sp

>>> contingency_table = sp.sparse.coo_matrix(
...    (np.ones_like(y), (X[:, 0], y)), 
...    shape=(np.unique(X[:, 0]).shape[0], np.unique(y).shape[0])).A
array([[1, 2],
       [3, 4]])
Run Code Online (Sandbox Code Playgroud)

所以现在我可以计算卡方统计量及其p值

>>> sp.stats.chi2_contingency(contingency_table)
(0.17857142857142855,
 0.67260381744151676,
 1,
 array([[ 1.2,  1.8],
       [ 2.8,  4.2]]))
Run Code Online (Sandbox Code Playgroud)

这应该与scikit-learn的一致 chi2

from sklearn.feature_selection import chi2

>>> chi2_, pval = chi2(X, y)
>>> chi2_[0], pval[0]
(0.023809523809523787, 0.87737055606414338)
Run Code Online (Sandbox Code Playgroud)

...不.我误解了什么吗?

此外,在频率情况下,列联表是什么样的?我以为它会是这样的

contingency_table = sp.sparse.coo_matrix(
    (np.ones_like(y), (X[:, 0], y)), 
    shape=(X[:, 0].max()+1, np.unique(y).shape[0])).A
Run Code Online (Sandbox Code Playgroud)

但是相应的预期频率表很可能有几个零元素.

编辑:

为了进一步澄清,考虑第一个特征X[:, 0],即性别和目标y,比如手性.

从这里我们得到交叉表

                Right-handed    Left-handed (!right-handed)
Male            1               2
Female (!male)  3               4
Run Code Online (Sandbox Code Playgroud)

我们可以通过设置预期频率,使用卡方检验来评估两个比例之间差异的显着性

expfreq

sklearn.feature_selection.chi2直接做到这一点,无需借助于显式计算表,并使用相当于更高效的过程获得分数scipy.stats.chisquare.

在明确枚举上面显示的表之后,我想验证它与chi2应用时是否一致,scipy.stats.chi2_contingency令我沮丧的是,它不是.我想问为什么不是.

Fre*_*Foo 6

鉴于您的数据,

>>> X = array([[1, 0, 0, 0, 1],
...        [1, 1, 0, 1, 1],
...        [1, 0, 0, 0, 0],
...        [0, 0, 0, 0, 0],
...        [0, 0, 0, 0, 1],
...        [1, 0, 0, 0, 1],
...        [1, 0, 1, 1, 1],
...        [0, 1, 1, 0, 0],
...        [1, 0, 1, 1, 1],
...        [1, 1, 1, 1, 0]])
>>> y = array([1, 0, 0, 0, 1, 1, 1, 1, 0, 1])
Run Code Online (Sandbox Code Playgroud)

这是feature_selection.chi2计算:

>>> Y = np.vstack([1 - y, y])
>>> observed = np.dot(Y, X)
>>> observed
array([[3, 1, 1, 2, 2],
       [4, 2, 3, 2, 4]])
Run Code Online (Sandbox Code Playgroud)

这些是每类观察到的特征频率,即列联表.那么期望值:

>>> feature_count = X.sum(axis=0)
>>> class_prob = Y.mean(axis=1)
>>> expected = np.dot(feature_count.reshape(-1, 1), class_prob.reshape(1, -1)).T
>>> expected
array([[ 2.8,  1.2,  1.6,  1.6,  2.4],
       [ 4.2,  1.8,  2.4,  2.4,  3.6]])
Run Code Online (Sandbox Code Playgroud)

最后,它运行χ²测试:

>>> from scipy.stats import chisquare
>>> score, pval = chisquare(observed, expected)
>>> score
array([ 0.02380952,  0.05555556,  0.375     ,  0.16666667,  0.11111111])
>>> pval
array([ 0.87737056,  0.81366372,  0.54029137,  0.6830914 ,  0.73888268])
Run Code Online (Sandbox Code Playgroud)

分数是相关的位:它们用于通过判别力对特征进行排序.请注意,每个功能可获得一个分数和一个p值.


War*_*ser 5

考虑列xX. sklearn.feature_selection.chi2测试y值为x1的频率是否y与整个群体的频率一致.(@ larsman的回答显示了如何再现与numpy的和SciPy的计算.)这是不一样的标准2×2列联表分析xy.在2x2列联表分析中,y where x为0 的频率也有助于测试.

假设我们为x和形成了列联表y:

    | y=0  y=1
----+---------
x=0 |  a    b
x=1 |  c    d
Run Code Online (Sandbox Code Playgroud)

设n = a + b + c + d.这是样本数(即与len(x)和len(y)相同).

设nx = c + d.这是1in 的出现次数x.

设py1 =(b + d)/ n.这是y为1的完整人口的一部分.

sklearn.feature_selection.chi2使用期望值[(1-py1)*nx,py1*nx]对[c,d]执行chi2检验.这与2x2表的标准列联表分析不同.

这是一个极端的例子.假设2×2列联表的xy

    |  y=0  y=1
----+----------
x=0 |   8    8
x=1 |  20  188
Run Code Online (Sandbox Code Playgroud)

sklearn计算得出的chi2得分为1.58,p值为0.208.

列联表分析scipy.stats.chi2_contingency得出chi2得分为18.6,p值为1.60e-5.