2 回答

TA貢獻1783條經驗 獲得超4個贊
該計算sklearn.feature_selection.chi2
?與卡方獨立性檢驗的典型教科書示例不同(對于此類經典的卡方檢驗,請參閱下面我提供的手動計算)。
sklearn.feature_selection.chi2
:假設我們有一個目標變量 y(分類,例如 0, 1, 2)和一個非負連續變量 x(例如,0 到 100 之間的任何位置),并且我們想要測試 x 和 y 之間的獨立性(例如,y 獨立于 x 意味著 x 作為預測特征沒有用)。該算法計算給定 y 的 x 的組和(例如,sum_x_y0、sum_x_y1、sum_x_y2 - 稱它們為觀察值),并將這些?觀察值與 x 的概率權重總計(例如,prob_y0*x_tot、prob_y1*x_tot、prob_y2* x_tot——稱它們為預期),使用卡方檢驗,對 y 中的 k 類別具有 (k-1) 個自由度。因為它使用卡方檢驗,所以正如我想象的那樣,它的計算中不能有負和。(我不確定這是否有學術參考,但這種方法似乎是有意義的。)
這是sklearn 用戶指南中的示例代碼,用于使用chi2
.
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
X, y = load_iris(return_X_y=True)
print(X.shape)
X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
X_new.shape
對于兩個分類變量之間獨立性的經典卡方檢驗,這是我的手動計算代碼,它似乎與scipy
卡方計算相匹配。我使用的公式與您上面發布的相同,但dof是(x - 1 中的 var 級別)和(y - 1 中的級別)。
from sklearn.feature_selection import chi2
x = [[1, 2, 0, 0, 1],
? ? ?[0, 0, 1, 0, 0],
? ? ?[0, 0, 0, 2, 1]]
y = [True, False, False]
chi2(x,y)[0]
import numpy as np
def is_val_eq(vec, val): return [i==val for i in vec]
def chi_E(vec1, vec1_val, vec2, vec2_val):?
? ? num1 = sum(is_val_eq(vec1, vec1_val))
? ? num2 = sum(is_val_eq(vec2, vec2_val))
? ? return num1*num2/len(vec1)
def chi_O(vec1, vec1_val, vec2, vec2_val):
? ? idx1 = is_val_eq(vec1, vec1_val)
? ? idx2 = is_val_eq(vec2, vec2_val)
? ? return sum(np.logical_and(idx1, idx2))
def chi_inside(O, E): return (O-E)**2/E
def chi_square(Os, Es): return sum([chi_inside(O,E) for O,E in zip(Os, Es)])
def get_col(x, col): return [row[col] for row in x]
def calc_chi(vec_x, vec_y):
? ? val_xs = set(vec_x)
? ? val_ys = set(vec_y)
? ? Es = [chi_E(vec_x, val_x, vec_y, val_y)?
? ? ? for val_x in val_xs for val_y in val_ys]
? ? Os = [chi_O(vec_x, val_x, vec_y, val_y)?
? ? ? for val_x in val_xs for val_y in val_ys]
? ? return chi_square(Os, Es), Es, Os
from scipy.stats import chi2_contingency?
from scipy import stats
chi_calc = dict(manual=[], scipy_cont=[], scipy_stats=[])
for idx_feature in range(5):
? ? chi_sq, Es, Os = calc_chi(get_col(x, idx_feature), y)
? ? chi_calc['manual'].append(chi_sq)
? ??
? ? data = [Os[0:2], Os[2:4]]
? ? stat, p, dof, expected = chi2_contingency(data, correction=False)
? ? chi_calc['scipy_cont'].append(stat)
? ??
? ? result = stats.chisquare(data, f_exp = expected, ddof = 1, axis=None)
? ? chi_calc['scipy_stats'].append(result.statistic)
直觀上,如果您試圖測試 的分類變量列相x對于 的獨立性y,則 的前兩列x應該給出相同的統計量(因為它們只是彼此的縮放版本,因此在分類級別方面是相同的) 。

TA貢獻1934條經驗 獲得超2個贊
我剛剛研究了 scikit-learn 的來源。計算實際上相當簡單。在我的示例中,我們有兩個類(True 和 False)。對于第二類,我們有兩個樣本 ([0, 0, 1, 0, 0]
和[0, 0, 0, 2, 1]
)。
我們首先列出每個類的一些列,其中給出了觀察到的值:
True: [1, 2, 0, 0, 1] False: [0, 0, 1, 2, 1]
為了計算預期值,我們計算所有列的總和(即在所有類中觀察到的特征的總數),得出[1, 2, 1, 2, 2]
。如果我們假設某個特征與其所在的類別之間沒有相關性,則這些值的分布必須與我們擁有的樣本數量相對應。即,應該在類和類1/3
中找到值,這給出了預期值:True
2/3
False
True: 1/3 * [1, 2, 1, 2, 2] = [1/3 2/3 1/3 2/3 2/3] False: 2/3 * [1, 2, 1, 2, 2] = [2/3 4/3 2/3 4/3 4/3]
現在可以計算每一列的 chi2,作為最有趣的最后一列的示例:
(1-2/3)^2 / (2/3) + (1-4/3)^2 / (4/3) = 1/6 + 1/12 = 1/4 = 0.25
0.25 的誤差相對較小,因此,正如人們所期望的那樣,該特征與類別無關。
添加回答
舉報