基于卡方检验的特征选择,更多也可参考http://nlp.stanford.edu/IR-book/html/htmledition/feature-selectionchi2-feature-selection-1.html
卡方检验(\(\chi ^2\) test),是一种常用的特征选择方法,尤其是在生物和金融领域。\(\chi ^2\) 用来描述两个事件的独立性或者说描述实际观察值与期望值的偏离程度。\(\chi ^2\)值越大,则表明实际观察值与期望值偏离越大,也说明两个事件的相互独立性越弱。
以下表我们简单说明一下,\(\chi ^2\) test的意思:
比如我们现在有一个生物学问题,我们需要从采样的5个基因 \(gene1,…,gene5\) 中找到某种疾病的1个致病基因。下表我们分别统计了患病和不患病人群5种基因的出现频率。当我们把一种基因看做一种特征的时候,找到致病基因就可以看做是选择一种特征使得患病-不患病的二分类问题准确率最高。
gene1 | gene2 | gene3 | gene4 | gene5 |
---|---|---|---|---|
患病 | 0.73 | 0.24 | 0.21 | 0.54 |
不患病 | 0.71 | 0.26 | 0.87 | 0.55 |
首先,我们做出假设 “患病与gene_x无关”。
以gene1为例,分布比较稳定, \(\chi ^2\) 值应该比较小,即两事件相互独立性比较强,即假设成立。
再以gene3为例,分布偏差很大, \(\chi ^2\) 值应该很大,即两事件相互独立性很弱,即假设不成立,因此最后我们选择gene3作为致病基因。
上述的例子比较简单,也存在一些不合常理的地方,仅仅用于帮助大家理解。
接下来我们讲怎样具体地计算 \(\chi ^2\) 值。
先直接上公式:
\(X^2(t,c) =
\sum_{e_t \in { 0,1 } }
\sum_{e_c \in { 0,1 } }
\frac{(N_{e_t e_c}-E_{e_t e_c})^2}{E_{e_t e_c}}\)
其中\(t:term\),即某个特征有或无,\(c: class\) ,即类别1或0(这里只支持2分类)。\(N\) 是观察值, \(E\) 是期望值。则 \(E_{11}\) 表示出现特征 \(t\) 且 类别 \(c=1\)。
现在,我们以第一节中的 gene3 为例,来计算 \(\chi ^2\) 值,当然按照公式我们首先应该计算各种期望和观测值。首先,我们来虚构一个完整的患病-基因数据集。假如我们记录了10个人的gene3出现情况,得到类似于下面的表格:
样本编号 | gene3是否出现 | 是否患病 |
---|---|---|
1 | 1 | 0 |
2 | 1 | 0 |
3 | 1 | 1 |
4 | 1 | 0 |
5 | 1 | 0 |
6 | 0 | 1 |
7 | 1 | 0 |
8 | 0 | 1 |
9 | 1 | 0 |
10 | 0 | 1 |
据此我们可以很容易的计算所有的观测值以及期望值。
首先是观测值
\(N_{11} = 患病且出现gene3的人数=1\)
\(N_{01} = 患病且不出现gene3的人数=3\)
\(N_{10} = 不患病出现gene3的人数=6\)
\(N_{00} = 不患病不出现gene3的人数=0\)
然后是期望值:(因为我们的假设是t和c独立,因此可以直接按照下式计算)
\(E_{11} = 10\times P(t=1)\times P(c=1)=2.8\)
\(N_{01} = 10\times P(t=0)\times P(c=1)=1.2\)
\(N_{10} = 10\times P(t=1)\times P(c=0)=4.2\)
\(N_{00} = 10\times P(t=0)\times P(c=0)=1.8\)
代入公式有:
\(X^2(t,c) = \frac{(1-2.8)^2}{2.8} + \frac{(3-1.2)^2}{1.2} + \frac{(6-4.2)^2}{4.2} + \frac{(0-1.8)^2}{1.8} = 6.4286 \)
我们已经得到了 \(\chi ^2\) 值,但是这并不够直接明了的说明问题。因此,我们还需要将 \(\chi ^2\) 值转化为 p-value。p-value是一种给定原假设为真时样本结果出现的概率,我们可以通过简单查表来进行转化。如下表:自由度=1时的转化表格。(自由度=分类数-1,因此这里自由度=1.)
p-value | \(\chi ^2\) |
---|---|
0.1 | 2.71 |
0.05 | 3.84 |
0.01 | 6.63 |
0.005 | 7.88 |
0.001 | 10.83 |
我们的\(\chi^2\) 值为6.4286,转化为p-value约为0.01,意思是假设患病和gene3无关的情况下,只有约0.01的概率会出现这样的样本结果。因此,我们就有约0.99的概率认为原假设错误,则gene3与患病有关。
下面给出Matlab下针对二分类问题的 \(\chi^2\) 特征选择代码:
function [chi, df] = chi2feature(feature, label)
% chi squared feature measure for binary class
% feature: m*n,m个样本,每个样本有n个特征
% label: m*1,m个样本的label,二分类只能有两种label
% find class name
class = unique(label);
rows = size(feature, 1);
dim = size(feature, 2);
ct = cell(dim, 1);
for j = 1:dim
member = unique(feature(:, j));
% find number of each member
for k = 1:size(member, 1)
n_member(k, 1) = length(find(feature(:, j) == member(k, 1)));
end
% find partioned class of each member
for p = 1:size(member, 1)
% find index
[xInd, yInd] = find(feature(:, j) == member(p, 1));
% partioned class
p1_member = length(find(label(xInd) == class(1, 1)));
p2_member = length(find(label(xInd) == class(2, 1)));
% negative class is 1st column, positive is 2nd
ct{j, 1}(p, 1) = p1_member;
ct{j, 1}(p, 2) = p2_member;
end
clear n_member;
end
% compute chi squared
for i = 1:dim
member = unique(feature(:, i));
for j = 1:size(member, 1)
n_fstar = ct{i, 1}(j, 1) + ct{i, 1}(j, 2);
n = rows;
% negative class
n_in = ct{i, 1}(j, 1);
n_starn = sum(ct{i, 1}(:, 1));
mu_in = (n_starn*n_fstar)/n;
negPart = (n_in-mu_in)^2/mu_in;
% positive class
n_ip = ct{i, 1}(j, 2);
n_starp = sum(ct{i, 1}(:, 2));
mu_ip = (n_starp*n_fstar)/n;
posPart = (n_ip-mu_ip)^2/mu_ip;
negPos(j, 1) = negPart + posPart;
end
% degree of freedom
df(i, 1) = size(member, 1) - 1;
% chi squared value, needed to compare with the threshold of
% corresponding significance value
chi(i, 1) = sum(negPos(:, 1));
clear negPos
end
Matlab下将 \(\chi^2\) 值转化为自由度的函数是:
p = chi2pdf(X,v) %X是卡方值,v是自由度
同样,p-value转化为 \(\chi^2\) 值的函数为:
X = chi2inv(P,v) %P是p-value,v是自由度