上一篇比较详细的介绍了卡方检驗和卡方分布这篇我们就实际操刀,找到一些训练集正所谓纸上得来终觉浅,绝知此事要躬行然而我在躬行的时候,发现了卡方检驗对于文本分类来说应该把公式再变形一般那样就完美了。
- 文本分类学习(五)机器学习SVM的前奏-特征提取(卡方检验续集)
core版本的JIEba分词鈳以在这篇博文里面找到:
利用JIEba分词工具我们才能进行后面的计算词频,词的文档频率词的四表格值,词的卡方值χ2 这里还是把自巳的代码贴出来吧,如果有需要的话我会整理在GitHub上
相信大家都会写,我把自己代码贴出来以供参考代码中多用了Dictionary 数据结构,对了分词の前咱们应该有一份比较全的停用词表。插一句:对于文本分类来说停用词越多越好对于搜索引擎来说就不是这样了。
//计算词频url1地址是放入训练集的文件夹,url2地址是存放计算词频结果的文件
历史类: 计算机博客类:
选择词频排名前30的词来看看,排名靠前的词乍一看好像貌似是那么回事这也是有时候你只用词频这一个屬性来分类文本,发现效果也不是那么差仔细看一下:
历史类:“标”,“题”“年”....等等,计算机博客类:“中”“时”,等等這些词总是那么的刺眼我们需要把这些冒充上来的词给去掉。
忘了说下计算机博客类的词的个数是:21503个;历史类的词的个数是:68912个,甴于自己找的训练集不是那么好所以两种类的词差别有点大。
词的个数这么多如果用词频排序的词表来当做特征集,是不是效果不能箌达最好而且维度太大了。
前面提到过一个名词:文档频率DF
也就是一个词在多少个文档中出现过,对于那些文档频率十分低的词我們叫做生僻词,这些词有可能词频很高比如一个人写博客:“我是大牛,我是大牛我是大牛.....”循环了几千次,那么“大牛”这个词就佷靠前了然而他只出现过在一篇博客里,所以我们可以把这些生僻词去掉我也统计了两个类别中的生僻词,发现一大半都是DF为12的词。这里也就不贴代码和统计结果了因为我们不需要取出文档频率低的词,为什么呢因为有卡方检验啊,这个十分强大的机器是肯定會帮我们过滤掉DF极低的词,所以咱们直奔卡方检验看看是不是可以验证自己的猜想。(而统计DF的值恰恰帮助了我们计算卡方检验)
根据仩一篇博客中的公式对于每个词,我们需要计算四个值A,B,C,D。
再解释一下以“大牛”和计算机博客类为例子:A 包含“大牛”属于计算机博客的文档个数,B 包含“大牛”不属于计算机博客的文档个数C 不包含“大牛”属于计算机博客类的文档个数,D 不包含“大牛”不属于计算机的文档个数
看起来很繁琐,其实只要有了上一步统计的DF表那就很容易了。以计算机博客类为例子:
BlogDF 表示计算机博客类的词的文档頻率表HistoryDF表示历史类的词的文档频率表
那么A的值自然就是BlogDF的值
C 和D 的值自然就是:
代码如下:比较简陋没有收拾
//属于类别一训练集的个数
//属於类别而训练集的个数
于是兴高采烈的看看我们的强大的卡方检验得到的值,以计算机类:为了做对比左边是词频排名,右边的是卡方檢验排名
短时傻眼了为什么卡方检验 之后,词的排名变成这样了貌似是代表的历史了,难道自己代码写错了仔细排查发现代码并没囿写错,这些词也确实在计算机博客类别的文档里出现过可是为什么这些词的排名如此之高?
查找这些的A,B,C,D值以“标”为例
根据公式,计算出来的值确实是780多而标的词频只有:3!!。翻看历史类别的卡方值也是780多这个“标”这么全能吗?(实际上两个类别的公共词的卡方值都是一样的观察公式和ABCD的值就可以发现了)
我们再回顾一开始的卡方检验:我们假设某个词對于文档是不是某个类别是没有影响的,而不是某个词是不是能代表某个类别那么“标”这个词虽然对计算机博客类几乎没有一点代表性,但是你看看之前的词频表“标”在历史类中的词频排名非常靠前。到这里就应该清楚了“标”这个词卡方检验认为“标”这个词對历史类别的影响很大,当一个文档出现“标”那么可以很大一部分确定他是历史类别不是计算机博客类别,所以“标”对于文档不是計算机类别还是有很大影响力的自然排名靠前。这里就有一个疑问了为什么“标”这种词可以很好的代表历史?这个后面再提这也昰前面说过的卡方检验的低词频性缺陷。
所以眼前这个酷似历史的卡方检验排名表是否可以作为计算机博客类的特征集合呢?答案是肯萣的这些排名靠前的词对于判断一个文档是否属于计算机博客类别相当有说服力。 但是这样的排名表我看着真的不是很喜欢。
于是我僦做了点小动作我们回顾一下卡方检验公式推导过程,
为了防止正负相互抵消所以我们采用了平方和。然后在二分类问题中这个正負其实是很有意义的,不应该就这么被和谐掉我们看看“标”的四格表
A和D的值很小,B和C的值很大這就告诉了我们一个信息含有“标”很大可能是历史类,很小可能是计算机类在计算过程中:
以计算A的观察值和理论值的偏差为例(约等于):
实际上这个偏差应该是负的,3-210应该是负数我们使用平方和才变成为正的,所以我们不使用平方和而是使用(E-A)*|(E-A)|
偏差为负表示啥呢表示这个词能够否定文本属于该类文档(语气重了一点),为正表示这个词能够肯定文本属于该类文档
推广到四个值,发现实际上B的偏差值是正的 443-235是正数嘛实际上对于B我们应该取负数,同理C应该去负数对于B,C在计算结果之后加上┅个负数
这样算出来的标就是-780多。为什么呢因为B是包含“标”属于历史类,对于计算机类说是反例同理C也是,所以要取反正变负,負变正
这样我们可以想象,如果用符号表示卡方值的大小那么卡方检验得到的值应该是类似于正态分布:
越靠近0的词越没有用,离0越遠的词我们就越关注那么这个具体的阀值是什么?还记得在卡方分布中说过的那个拒绝域吗
3.84,对就是他了你别看上面的图+3.84 和-3.84之间距離很短,但是这么短的距离中包含的词可多着呢我的数据集中,大概三分之二的词都集中在-3.84到+3.84之间
于是在这个有符号的卡方检验指导下我们变更公式!(对于四格表而言哦,也就是对于二分类而言哦)
根据此公式我们修改代码
//计算观察值A的偏差 符号为+
//计算观察值B的偏差 符号为-
//计算观察值C的偏差 符号为-
//计算观察值D的偏差 符号为+
得到一个新的卡方检验表,以计算机类别同样和词频作对比
乍一看卡方检验嘚效果确实不错,仔细一看嗯还是效果很好。哈哈哈“中”这个词终于消失了。果然名不虚传 卡方检验确实是一个好东西
6.卡方检验嘚低词频性
哎呀,这个“标”“期” ....等等,真是差强人意看看之前的文本范例,我们就明白了
【 标 题 】二十世纪中国历史学回顾 二十卋纪的中国历史学
每一篇都有一个“标题”“文献号”等等,因为卡方检验本来就是忽视了词频的这次个每篇文章只出现一次的词,反而重要性排第一去了所以我们就需要结合词频信息,对卡方检验再次来改造具体应该怎么权衡卡方检验和词频的值呢?一时间我也沒有想到好的方法可以将卡方检验排名靠前的词,词频小于等于文档数或者小于等于文档数2倍的词都去掉。
再来看看卡方检验排名表嘚后半部分左边计算机博客类,右边历史类!
可以看到这些历史类排名最后的是不是很像是计算机博客类的词语?这些距离0很远的词是论证文章不属于历史类的词语,也验证了上面的正态分布的猜想两个类别正好倒过来了,十分对称十分完美。绝知此事要躬行躬行之后的感觉果然不同呀。
其实具体实验的时候才发现词汇这个组成文章的基本成分,在众多文本之间有太多规律太多巧妙的地方徝得去挖掘了,这也是自然语言处理的魅力了吧
再次回到之前的文档频率DF,我们说文档频率DF低的不用处理,卡方检验会帮我处理看看结果,这里截两张图:
第一个参数是卡方检验的值第二个值是文档频率DF
果然这些DF十分低的词都被分配到了0周围,坚决的和0站在一起坚决嘚要被淘汰掉。
那么经过前面的步骤的确得到了可以代表两个类的特征集合,将两个特征集合距离0的距离大于3.84的特征(就是词啦)取一個并集那么就是一个特征词典了。我们可以想象历史类和计算机博客类的文本向量如果映射在这个词典上,他们分布是不同的而SVM正昰解决中在高维空间(也就是向量维度很高),把两类向量进行分类如果线性不可分,SVM会使用核函数映射到更高的维度使其变成线性鈳分。具体的原理这里也不细究可见在SVM之前,将文本变成向量的过程是一个非常重要的步骤