﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-Jasper's Java Jacal</title><link>http://www.blogjava.net/zhenandaci/</link><description>嘉士伯的Java小屋</description><language>zh-cn</language><lastBuildDate>Sat, 14 Mar 2026 23:15:18 GMT</lastBuildDate><pubDate>Sat, 14 Mar 2026 23:15:18 GMT</pubDate><ttl>60</ttl><item><title>又晒自己的设计</title><link>http://www.blogjava.net/zhenandaci/archive/2009/05/08/269507.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Thu, 07 May 2009 16:32:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/05/08/269507.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/269507.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/05/08/269507.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/269507.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/269507.html</trackback:ping><description><![CDATA[这回是帮自己家小妞的网店做的店标,宣传什么的,所以风格相似恰恰是我想要的。
<p>&nbsp;</p>
<p><img src="http://logo.taobao.com/shop-logo/65/44/T19lpgXeVW6dL1upjX.jpg"  alt="" /></p>
<p>网店的Logo。那大腿不是别人的，正是韩国歌星宝儿&#8230;&#8230;<br />
<br />
</p>
<p><img src="http://p2.images22.51img1.com/6000/yuki0035/2c93ab451dfdeb44ce75d436e31e9540.jpg"  alt="" /></p>
<p>她跟我说上面这张图最大的问题就在于太有夜店风格，与她的店不符。不过用着用着，她自己倒也喜欢上了。<br />
</p>
<p><img src="http://p1.images22.51img1.com/6000/yuki0035/140297fdbc3dc9c6c7ee96d9e02d89ac.jpg"  alt="" /> </p>
<p>这个是刚出炉的5月新款的预告，照片里的人可全是她&#8230;&#8230;</p>
  <img src ="http://www.blogjava.net/zhenandaci/aggbug/269507.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-05-08 00:32 <a href="http://www.blogjava.net/zhenandaci/archive/2009/05/08/269507.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文本分类入门（番外篇）特征选择与特征权重计算的区别</title><link>http://www.blogjava.net/zhenandaci/archive/2009/04/19/266388.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Sun, 19 Apr 2009 03:40:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/04/19/266388.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/266388.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/04/19/266388.html#Feedback</comments><slash:comments>48</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/266388.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/266388.html</trackback:ping><description><![CDATA[<span style="font-family: '微软雅黑', 'sans-serif'"><span style="font-family: '微软雅黑', 'sans-serif'">在文本分类的过程中，特征（也可以简单的理解为&#8220;词&#8221;）从人类能够理解的形式转换为计算机能够理解的形式时，实际上经过了两步骤的量化——特征选择阶段的重要程度量化和将具体文本转化为向量时的特征权重量化。初次接触文本分类的人很容易混淆这两个步骤使用的方法和各自的目的，因而我经常听到读者有类似&#8220;如何使用</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">做特征选择&#8221;或者&#8220;卡方检验量化权重后每篇文章都一样&#8221;等等困惑。</span>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">文本分类本质上也是一个模式识别的问题，因此我想借用一个更直观的例子来说说特征选择和权重量化到底各自是什么东西，当然，一旦解释清楚，你马上就会觉得文本分类这东西实在白痴，实在没什么技术含量，你也就不会再继续看我的技术博客，不过我不担心，因为你已经踏上了更光明的道路（笑），我高兴还来不及。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">想想通过指纹来识别一个人的身份，只看一个人的指纹，当然说不出他姓甚名谁，识别的过程实际上是比对的过程，要与已有的指纹库比较，找出相同的，或者说相似到一定程度的那一个。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">首要的问题是，人的指纹太复杂，包含太多的位置和几何形状，要完全重现一个人的指纹，存储和计算都是大麻烦。因此第一步总是一个特征选择的问题，我们把全人类的指纹都统计一下，看看哪几个位置能够最好的区分不同的人。显然不同的位置效果很不一样，在有的位置上，我的指纹是是什么形状，其他人也大都是这个形状，这个位置就不具有区分度，或者说不具有表征性，或者说，对分类问题来说，它的重要程度低。这样的位置我们就倾向于在识别的时候根本不看它，不考虑它。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">那怎么看谁重要谁不重要呢？这就依赖于具体的选择方法如何来量化重要程度，对卡方检验和信息增益这类方法来说，量化以后的得分越大的特征就越重要（也就是说，有可能有些方法，是得分越小的越重要）。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">比如说你看</span>10<span style="font-family: '微软雅黑', 'sans-serif'">个位置，他们的重要程度分别是：</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal">&nbsp;&nbsp; 1&nbsp;2&nbsp;&nbsp; 3&nbsp;&nbsp; 4&nbsp;&nbsp; 5&nbsp;6&nbsp;&nbsp; 7&nbsp;8&nbsp;9 &nbsp;10</p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>5<span style="font-family: '微软雅黑', 'sans-serif'">，</span>10<span style="font-family: '微软雅黑', 'sans-serif'">，</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>30<span style="font-family: '微软雅黑', 'sans-serif'">，</span>15<span style="font-family: '微软雅黑', 'sans-serif'">，</span>4<span style="font-family: '微软雅黑', 'sans-serif'">，</span>3<span style="font-family: '微软雅黑', 'sans-serif'">，</span>7<span style="font-family: '微软雅黑', 'sans-serif'">，</span> 3<span style="font-family: '微软雅黑', 'sans-serif'">）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">显然第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">，第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">，</span>4<span style="font-family: '微软雅黑', 'sans-serif'">，</span>5<span style="font-family: '微软雅黑', 'sans-serif'">，</span>6<span style="font-family: '微软雅黑', 'sans-serif'">个位置比其他位置更重要，而相对的，第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">个位置又比第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">个位置更重要。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">识别时，我们只在那些重要的位置上采样。当今的指纹识别系统，大都只用到人指纹的</span>5<span style="font-family: '微软雅黑', 'sans-serif'">个位置（惊讶么？只要</span>5<span style="font-family: '微软雅黑', 'sans-serif'">个位置的信息就可以区分</span>60<span style="font-family: '微软雅黑', 'sans-serif'">亿人），这</span>5<span style="font-family: '微软雅黑', 'sans-serif'">个位置就是经过特征选择过程而得以保留的系统特征集合。假设这个就是刚才的例子，那么该集合应该是：</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">个位置，第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">个位置，第</span>4<span style="font-family: '微软雅黑', 'sans-serif'">个位置，第</span>5<span style="font-family: '微软雅黑', 'sans-serif'">个位置，第</span>6<span style="font-family: '微软雅黑', 'sans-serif'">个位置）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">当然，具体的第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">个位置是指纹中的哪个位置你自己总得清楚。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">确定了这</span>5<span style="font-family: '微软雅黑', 'sans-serif'">个位置之后，就可以把一个人的指纹映射到这个只有</span>5<span style="font-family: '微软雅黑', 'sans-serif'">个维度的空间中，我们就把他在</span>5<span style="font-family: '微软雅黑', 'sans-serif'">个位置上的几何形状分别转换成一个具体的值，这就是特征权重的计算。依据什么来转换，就是你选择的特征权重量化方法，在文本分类中，最常用的就是</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">我想一定是&#8220;权重&#8220;这个词误导了所有人，让大家以为</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">计算出的值代表的是特征的重要程度，其实完全不是。例如我们有一位男同学，他的指纹向量是：</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（</span>10<span style="font-family: '微软雅黑', 'sans-serif'">，</span>3<span style="font-family: '微软雅黑', 'sans-serif'">，</span>4<span style="font-family: '微软雅黑', 'sans-serif'">，</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>5<span style="font-family: '微软雅黑', 'sans-serif'">）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">你注意到他第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">个位置的得分（</span>10<span style="font-family: '微软雅黑', 'sans-serif'">）比第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">个位置的得分（</span>3<span style="font-family: '微软雅黑', 'sans-serif'">）高，那么能说第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">个位置比第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">个位置重要么？如果再有一位女同学，她的指纹向量是：</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（</span>10<span style="font-family: '微软雅黑', 'sans-serif'">，</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>4<span style="font-family: '微软雅黑', 'sans-serif'">，</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>5<span style="font-family: '微软雅黑', 'sans-serif'">）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">看看，第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">个位置得分（</span>10<span style="font-family: '微软雅黑', 'sans-serif'">）又比第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">个位置（</span>20<span style="font-family: '微软雅黑', 'sans-serif'">）低了，那这两个位置到底哪个更重要呢？答案是第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">个位置更重要，但这不是在特征权重计算这一步体现出来的，而是在我们特征选择的时候就确定了，第</span>1<span style="font-family: '微软雅黑', 'sans-serif'">个位置比第</span>3<span style="font-family: '微软雅黑', 'sans-serif'">个位置更重要。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">因此要记住，通过</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">计算一个特征的权重时，该权重体现出的根本不是特征的重要程度！</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">那它代表什么？再看看两位同学的指纹，放到一起：</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（</span>10<span style="font-family: '微软雅黑', 'sans-serif'">，</span> 3<span style="font-family: '微软雅黑', 'sans-serif'">，</span>4<span style="font-family: '微软雅黑', 'sans-serif'">，</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>5<span style="font-family: '微软雅黑', 'sans-serif'">）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（</span>10<span style="font-family: '微软雅黑', 'sans-serif'">，</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>4<span style="font-family: '微软雅黑', 'sans-serif'">，</span>20<span style="font-family: '微软雅黑', 'sans-serif'">，</span>5<span style="font-family: '微软雅黑', 'sans-serif'">）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">在第三个位置上女同学的权重高于男同学，这不代表该女同学在指纹的这个位置上更&#8220;优秀&#8220;（毕竟，指纹还有什么优秀不优秀的分别么，笑），也不代表她的这个位置比男同学的这个位置更重要，</span>3<span style="font-family: '微软雅黑', 'sans-serif'">和</span>20<span style="font-family: '微软雅黑', 'sans-serif'">这两个得分，仅仅代表他们的&#8221;不同&#8220;。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">在文本分类中也是如此，比如我们的系统特征集合只有两个词：</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（经济，发展）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">这两个词是使用卡方检验（特征选择）选出来的，有一篇文章的向量形式是</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（</span>2<span style="font-family: '微软雅黑', 'sans-serif'">，</span>5<span style="font-family: '微软雅黑', 'sans-serif'">）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">另一篇</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">（</span>3<span style="font-family: '微软雅黑', 'sans-serif'">，</span>4<span style="font-family: '微软雅黑', 'sans-serif'">）</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">这两个向量形式就是用</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">算出来的，很容易看出两篇文章不是同一篇，为什么？因为他们的特征权重根本不一样，所以说权重代表的是差别，而不是优劣。想想你说&#8220;经济这个词在第二篇文章中得分高，因此它在第二篇文章中比在第一篇文章中更重要&#8220;，这句话代表什么意义呢？你自己都不知道吧（笑）。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">所以，当再说起使用</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">来计算特征权重时，最好把&#8220;权重&#8220;这个字眼忘掉，我们就把它说成计算得分好了（甚至&#8221;得分&#8220;也不太好，因为人总会不自觉的认为，得分高的就更重要），或者就仅仅说成是量化。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">如此，你就再也不会拿</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">去做特征选择了。</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">小</span>Tips<span style="font-family: '微软雅黑', 'sans-serif'">：为什么有的论文里确实使用了</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">作特征选择呢？</span></p>
<p style="margin: 12pt 0cm" class="MsoNormal"><span style="font-family: '微软雅黑', 'sans-serif'">严格说来并不是不可以，而且严格说来只要有一种方法能够从一堆特征中挑出少数的一些，它就可以叫做一种特征选择方法，就连&#8220;随机选取一部分&#8220;都算是一种，而且效果并没有差到惊人的地步哦！还是可以分对一大半的哦！所以有的人就用</span>TFIDF<span style="font-family: '微软雅黑', 'sans-serif'">的得分来把特征排排序，取得分最大的几个进入系统特征集合，效果也还行（毕竟，连随机选取效果也都还行），怎么说呢，他们愿意这么干就这么干吧。就像咱国家非得实行户口制度，这个制度说不出任何道理，也不见他带来任何好处，但不也没影响二十一世纪成为中国的世纪么，呵呵。</span></p>
</span>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/266388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-04-19 11:40 <a href="http://www.blogjava.net/zhenandaci/archive/2009/04/19/266388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>又怠慢了</title><link>http://www.blogjava.net/zhenandaci/archive/2009/04/18/266294.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Sat, 18 Apr 2009 07:02:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/04/18/266294.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/266294.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/04/18/266294.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/266294.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/266294.html</trackback:ping><description><![CDATA[又小忙了几天。打算写一篇澄清特征选择和特征权重计算中许多容易误解的问题的文章，不知大家有没有兴趣。
<img src ="http://www.blogjava.net/zhenandaci/aggbug/266294.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-04-18 15:02 <a href="http://www.blogjava.net/zhenandaci/archive/2009/04/18/266294.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVM入门（十）将SVM用于多类分类</title><link>http://www.blogjava.net/zhenandaci/archive/2009/03/26/262113.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Thu, 26 Mar 2009 06:30:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/03/26/262113.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/262113.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/03/26/262113.html#Feedback</comments><slash:comments>62</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/262113.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/262113.html</trackback:ping><description><![CDATA[<p>从 SVM的那几张图可以看出来，SVM是一种典型的两类分类器，即它只回答属于正类还是负类的问题。而现实中要解决的问题，往往是多类的问题（少部分例外，例如垃圾邮件过滤，就只需要确定&#8220;是&#8221;还是&#8220;不是&#8221;垃圾邮件），比如文本分类，比如数字识别。如何由两类分类器得到多类分类器，就是一个值得研究的问题。
<p>还以文本分类为例，现成的方法有很多，其中一种一劳永逸的方法，就是真的一次性考虑所有样本，并求解一个多目标函数的优化问题，一次性得到多个分类面，就像下图这样：
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMSVM_CBFA/clip_image001_2.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image001" border="0" hspace="12" alt="clip_image001" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMSVM_CBFA/clip_image001_thumb.jpg" width="542" height="407" /></a>
<p>多个超平面把空间划分为多个区域，每个区域对应一个类别，给一篇文章，看它落在哪个区域就知道了它的分类。
<p>看起来很美对不对？只可惜这种算法还基本停留在纸面上，因为一次性求解的方法计算量实在太大，大到无法实用的地步。
<p>稍稍退一步，我们就会想到所谓&#8220;一类对其余&#8221;的方法，就是每次仍然解一个两类分类的问题。比如我们有5个类别，第一次就把类别1的样本定为正样本，其余2，3，4，5的样本合起来定为负样本，这样得到一个两类分类器，它能够指出一篇文章是还是不是第1类的；第二次我们把类别2 的样本定为正样本，把1，3，4，5的样本合起来定为负样本，得到一个分类器，如此下去，我们可以得到5个这样的两类分类器（总是和类别的数目一致）。到了有文章需要分类的时候，我们就拿着这篇文章挨个分类器的问：是属于你的么？是属于你的么？哪个分类器点头说是了，文章的类别就确定了。这种方法的好处是每个优化问题的规模比较小，而且分类的时候速度很快（只需要调用5个分类器就知道了结果）。但有时也会出现两种很尴尬的情况，例如拿一篇文章问了一圈，每一个分类器都说它是属于它那一类的，或者每一个分类器都说它不是它那一类的，前者叫分类重叠现象，后者叫不可分类现象。分类重叠倒还好办，随便选一个结果都不至于太离谱，或者看看这篇文章到各个超平面的距离，哪个远就判给哪个。不可分类现象就着实难办了，只能把它分给第6个类别了&#8230;&#8230;更要命的是，本来各个类别的样本数目是差不多的，但&#8220;其余&#8221;的那一类样本数总是要数倍于正类（因为它是除正类以外其他类别的样本之和嘛），这就人为的造成了上一节所说的&#8220;数据集偏斜&#8221;问题。
<p>因此我们还得再退一步，还是解两类分类问题，还是每次选一个类的样本作正类样本，而负类样本则变成只选一个类（称为&#8220;一对一单挑&#8221;的方法，哦，不对，没有单挑，就是&#8220;一对一&#8221;的方法，呵呵），这就避免了偏斜。因此过程就是算出这样一些分类器，第一个只回答&#8220;是第1类还是第2类&#8221;，第二个只回答&#8220;是第1类还是第3类&#8221;，第三个只回答&#8220;是第1类还是第4类&#8221;，如此下去，你也可以马上得出，这样的分类器应该有5 X 4/2=10个（通式是，如果有k个类别，则总的两类分类器数目为k(k-1)/2）。虽然分类器的数目多了，但是在训练阶段（也就是算出这些分类器的分类平面时）所用的总时间却比&#8220;一类对其余&#8221;方法少很多，在真正用来分类的时候，把一篇文章扔给所有分类器，第一个分类器会投票说它是&#8220;1&#8221;或者&#8220;2&#8221;，第二个会说它是&#8220;1&#8221;或者&#8220;3&#8221;，让每一个都投上自己的一票，最后统计票数，如果类别&#8220;1&#8221;得票最多，就判这篇文章属于第1类。这种方法显然也会有分类重叠的现象，但不会有不可分类现象，因为总不可能所有类别的票数都是0。看起来够好么？其实不然，想想分类一篇文章，我们调用了多少个分类器？10个，这还是类别数为5的时候，类别数如果是1000，要调用的分类器数目会上升至约500,000个（类别数的平方量级）。这如何是好？
<p>看来我们必须再退一步，在分类的时候下功夫，我们还是像一对一方法那样来训练，只是在对一篇文章进行分类之前，我们先按照下面图的样子来组织分类器（如你所见，这是一个有向无环图，因此这种方法也叫做DAG SVM）
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMSVM_CBFA/clip_image002_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002" border="0" hspace="12" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMSVM_CBFA/clip_image002_thumb.gif" width="387" height="308" /></a>
<p>这样在分类时,我们就可以先问分类器&#8220;1对5&#8221;（意思是它能够回答&#8220;是第1类还是第5类&#8221;），如果它回答5，我们就往左走，再问&#8220;2对5&#8221;这个分类器，如果它还说是&#8220;5&#8221;，我们就继续往左走，这样一直问下去，就可以得到分类结果。好处在哪？我们其实只调用了4个分类器（如果类别数是k，则只调用k-1个），分类速度飞快，且没有分类重叠和不可分类现象！缺点在哪？假如最一开始的分类器回答错误（明明是类别1的文章，它说成了5），那么后面的分类器是无论如何也无法纠正它的错误的（因为后面的分类器压根没有出现&#8220;1&#8221;这个类别标签），其实对下面每一层的分类器都存在这种错误向下累积的现象。。
<p>不过不要被DAG方法的错误累积吓倒，错误累积在一对其余和一对一方法中也都存在，DAG方法好于它们的地方就在于，累积的上限，不管是大是小，总是有定论的，有理论证明。而一对其余和一对一方法中，尽管每一个两类分类器的泛化误差限是知道的，但是合起来做多类分类的时候，误差上界是多少，没人知道，这意味着准确率低到0也是有可能的，这多让人郁闷。
<p>而且现在DAG方法根节点的选取（也就是如何选第一个参与分类的分类器），也有一些方法可以改善整体效果，我们总希望根节点少犯错误为好，因此参与第一次分类的两个类别，最好是差别特别特别大，大到以至于不太可能把他们分错；或者我们就总取在两类分类中正确率最高的那个分类器作根节点，或者我们让两类分类器在分类的时候，不光输出类别的标签，还输出一个类似&#8220;置信度&#8221;的东东，当它对自己的结果不太自信的时候，我们就不光按照它的输出走，把它旁边的那条路也走一走，等等。
<p><strong>大Tips</strong><strong>：SVM</strong><strong>的计算复杂度</strong>
<p>使用SVM进行分类的时候，实际上是训练和分类两个完全不同的过程，因而讨论复杂度就不能一概而论，我们这里所说的主要是训练阶段的复杂度，即解那个二次规划问题的复杂度。对这个问题的解，基本上要划分为两大块，解析解和数值解。
<p>解析解就是理论上的解，它的形式是表达式，因此它是精确的，一个问题只要有解（无解的问题还跟着掺和什么呀，哈哈），那它的解析解是一定存在的。当然存在是一回事，能够解出来，或者可以在可以承受的时间范围内解出来，就是另一回事了。对SVM来说，求得解析解的时间复杂度最坏可以达到O(N<sub>sv</sub><sup>3</sup>)，其中N<sub>sv</sub>是支持向量的个数，而虽然没有固定的比例，但支持向量的个数多少也和训练集的大小有关。
<p>数值解就是可以使用的解，是一个一个的数，往往都是近似解。求数值解的过程非常像穷举法，从一个数开始，试一试它当解效果怎样，不满足一定条件（叫做停机条件，就是满足这个以后就认为解足够精确了，不需要继续算下去了）就试下一个，当然下一个数不是乱选的，也有一定章法可循。有的算法，每次只尝试一个数，有的就尝试多个，而且找下一个数字（或下一组数）的方法也各不相同，停机条件也各不相同，最终得到的解精度也各不相同，可见对求数值解的复杂度的讨论不能脱开具体的算法。
<p>一个具体的算法，Bunch-Kaufman训练算法，典型的时间复杂度在O(N<sub>sv</sub><sup>3</sup>+LN<sub>sv</sub><sup>2</sup>+dLN<sub>sv</sub>)和O(dL<sup>2</sup>)之间，其中N<sub>sv</sub>是支持向量的个数，L是训练集样本的个数，d是每个样本的维数（原始的维数，没有经过向高维空间映射之前的维数）。复杂度会有变化，是因为它不光跟输入问题的规模有关（不光和样本的数量，维数有关），也和问题最终的解有关（即支持向量有关），如果支持向量比较少，过程会快很多，如果支持向量很多，接近于样本的数量，就会产生O(dL<sup>2</sup>)这个十分糟糕的结果（给10，000个样本，每个样本1000维，基本就不用算了，算不出来，呵呵，而这种输入规模对文本分类来说太正常了）。
<p>这样再回头看就会明白为什么一对一方法尽管要训练的两类分类器数量多，但总时间实际上比一对其余方法要少了，因为一对其余方法每次训练都考虑了所有样本（只是每次把不同的部分划分为正类或者负类而已<span style="font-family: 宋体">）<span style="font-family: ; font-size: 10.5pt; mso-bidi-font-family: 'Times New Roman'; mso-bidi-font-size: 11.0pt; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">，自然慢上很多。</span></span></p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/262113.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-03-26 14:30 <a href="http://www.blogjava.net/zhenandaci/archive/2009/03/26/262113.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文本分类入门（十一）特征选择方法之信息增益</title><link>http://www.blogjava.net/zhenandaci/archive/2009/03/24/261701.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Tue, 24 Mar 2009 06:54:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/03/24/261701.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/261701.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/03/24/261701.html#Feedback</comments><slash:comments>65</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/261701.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/261701.html</trackback:ping><description><![CDATA[<p>前文提到过，除了开方检验（CHI）以外，信息增益（IG，Information Gain）也是很有效的特征选择方法。但凡是特征选择，总是在将特征的重要程度量化之后再进行选择，而如何量化特征的重要性，就成了各种方法间最大的不同。开方检验中使用特征与类别间的关联性来进行这个量化，关联性越强，特征得分越高，该特征越应该被保留。
<p>在信息增益中，重要性的衡量标准就是看特征能够为分类系统带来多少信息，带来的信息越多，该特征越重要。
<p>因此先回忆一下信息论中有关信息量（就是&#8220;熵&#8221;）的定义。说有这么一个变量X，它可能的取值有n多种，分别是x<sub>1</sub>，x<sub>2</sub>，&#8230;&#8230;，x<sub>n</sub>，每一种取到的概率分别是P<sub>1</sub>，P<sub>2</sub>，&#8230;&#8230;，P<sub>n</sub>，那么X的熵就定义为：
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002" border="0" hspace="12" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002_thumb.gif" width="231" height="69" /></a></p>
<p>意思就是一个变量可能的变化越多（反而跟变量具体的取值没有任何关系，只和值的种类多少以及发生概率有关），它携带的信息量就越大（因此我一直觉得我们的政策法规信息量非常大，因为它变化很多，基本朝令夕改，笑）。
<p>对分类系统来说，类别C是变量，它可能的取值是C<sub>1</sub>，C<sub>2</sub>，&#8230;&#8230;，C<sub>n</sub>，而每一个类别出现的概率是P(C<sub>1</sub>)，P(C<sub>2</sub>)，&#8230;&#8230;，P(C<sub>n</sub>)，因此n就是类别的总数。此时分类系统的熵就可以表示为：</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002%5B4%5D.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002[4]" border="0" hspace="12" alt="clip_image002[4]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002%5B4%5D_thumb.gif" width="240" height="54" /></a></p>
<p>有同学说不好理解呀，这样想就好了，文本分类系统的作用就是输出一个表示文本属于哪个类别的值，而这个值可能是C<sub>1</sub>，C<sub>2</sub>，&#8230;&#8230;，C<sub>n</sub>，因此这个值所携带的信息量就是上式中的这么多。
<p>信息增益是针对一个一个的特征而言的，就是看一个特征t，系统有它和没它的时候信息量各是多少，两者的差值就是这个特征给系统带来的信息量，即增益。系统含有特征t的时候信息量很好计算，就是刚才的式子，它表示的是包含所有特征时系统的信息量。
<p>问题是当系统不包含t时，信息量如何计算？我们换个角度想问题，把系统要做的事情想象成这样：说教室里有很多座位，学生们每次上课进来的时候可以随便坐，因而变化是很大的（无数种可能的座次情况）；但是现在有一个座位，看黑板很清楚，听老师讲也很清楚，于是校长的小舅子的姐姐的女儿托关系（真辗转啊），把这个座位定下来了，每次只能给她坐，别人不行，此时情况怎样？对于座次的可能情况来说，我们很容易看出以下两种情况是等价的：（1）教室里没有这个座位；（2）教室里虽然有这个座位，但其他人不能坐（因为反正它也不能参与到变化中来，它是不变的）。
<p>对应到我们的系统中，就是下面的等价：（1）系统不包含特征t；（2）系统虽然包含特征t，但是t已经固定了，不能变化。
<p>我们计算分类系统不包含特征t的时候，就使用情况（2）来代替，就是计算当一个特征t不能变化时，系统的信息量是多少。这个信息量其实也有专门的名称，就叫做&#8220;条件熵&#8221;，条件嘛，自然就是指&#8220;t已经固定&#8220;这个条件。
<p>但是问题接踵而至，例如一个特征X，它可能的取值有n多种（x<sub>1</sub>，x<sub>2</sub>，&#8230;&#8230;，x<sub>n</sub>），当计算条件熵而需要把它固定的时候，要把它固定在哪一个值上呢？答案是每一种可能都要固定一下，计算n个值，然后取均值才是条件熵。而取均值也不是简单的加一加然后除以n，而是要用每个值出现的概率来算平均（简单理解，就是一个值出现的可能性比较大，固定在它上面时算出来的信息量占的比重就要多一些）。
<p>因此有这样两个条件熵的表达式：
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002%5B6%5D.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002[6]" border="0" hspace="12" alt="clip_image002[6]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002%5B6%5D_thumb.gif" width="170" height="46" /></a></p>
<p>这是指特征X被固定为值x<sub>i</sub>时的条件熵，</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002%5B8%5D.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002[8]" border="0" hspace="12" alt="clip_image002[8]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image002%5B8%5D_thumb.gif" width="132" height="44" /></a></p>
<p>这是指特征X被固定时的条件熵，注意与上式在意义上的区别。从刚才计算均值的讨论可以看出来，第二个式子与第一个式子的关系就是：</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image004_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image004" border="0" hspace="12" alt="clip_image004" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image004_thumb.gif" width="656" height="123" /></a></p>
<p>具体到我们文本分类系统中的特征t，t有几个可能的值呢？注意t是指一个固定的特征，比如他就是指关键词&#8220;经济&#8221;或者&#8220;体育&#8221;，当我们说特征&#8220;经济&#8221;可能的取值时，实际上只有两个，&#8220;经济&#8221;要么出现，要么不出现。一般的，t的取值只有t（代表t出现）和<a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image006_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image006_thumb.gif" width="11" height="29" /></a>（代表t不出现），注意系统包含t但t 不出现与系统根本不包含t可是两回事。
<p>因此固定t时系统的条件熵就有了，为了区别t出现时的符号与特征t本身的符号，我们用T代表特征，而用t代表T出现，那么：
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image008_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image008" border="0" hspace="12" alt="clip_image008" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image008_thumb.gif" width="376" height="58" /></a></p>
<p>与刚才的式子对照一下，含义很清楚对吧，P(t)就是T出现的概率，<a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image010_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image010_thumb.gif" width="35" height="32" /></a>就是T不出现的概率。这个式子可以进一步展开，其中的</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image012_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image012" border="0" hspace="12" alt="clip_image012" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image012_thumb.gif" width="264" height="57" /></a></p>
<p>另一半就可以展开为：</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image014_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image014" border="0" hspace="12" alt="clip_image014" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image014_thumb.gif" width="301" height="63" /></a></p>
<p>因此特征T给系统带来的信息增益就可以写成系统原本的熵与固定特征T后的条件熵之差：
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image016_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image016" border="0" hspace="12" alt="clip_image016" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/7fce385fe28b_D158/clip_image016_thumb.gif" width="583" height="173" /></a>
<p>公式中的东西看上去很多，其实也都很好计算。比如P(C<sub>i</sub>)，表示类别C<sub>i</sub>出现的概率，其实只要用1除以类别总数就得到了（这是说你平等的看待每个类别而忽略它们的大小时这样算，如果考虑了大小就要把大小的影响加进去）。再比如P(t)，就是特征T出现的概率，只要用出现过T的文档数除以总文档数就可以了，再比如P(C<sub>i</sub>|t)表示出现T的时候，类别C<sub>i</sub>出现的概率，只要用出现了T并且属于类别C<sub>i</sub>的文档数除以出现了T的文档数就可以了。
<p>从以上讨论中可以看出，信息增益也是考虑了特征出现和不出现两种情况，与开方检验一样，是比较全面的，因而效果不错。但信息增益最大的问题还在于它只能考察特征对整个系统的贡献，而不能具体到某个类别上，这就使得它只适合用来做所谓&#8220;全局&#8221;的特征选择（指所有的类都使用相同的特征集合），而无法做&#8220;本地&#8221;的特征选择（每个类别有自己的特征集合，因为有的词，对这个类别很有区分度，对另一个类别则无足轻重）。
<p>看看，导出的过程其实很简单，没有什么神秘的对不对。可有的学术论文里就喜欢把这种本来很直白的东西写得很晦涩，仿佛只有读者看不懂才是作者的真正成功。
<p>咱们是新一代的学者，咱们没有知识不怕被别人看出来，咱们有知识也不怕教给别人。所以咱都把事情说简单点，说明白点，大家好，才是真的好。 </p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/261701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-03-24 14:54 <a href="http://www.blogjava.net/zhenandaci/archive/2009/03/24/261701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVM入门（九）松弛变量（续）</title><link>http://www.blogjava.net/zhenandaci/archive/2009/03/17/260315.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Tue, 17 Mar 2009 12:04:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/03/17/260315.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/260315.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/03/17/260315.html#Feedback</comments><slash:comments>29</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/260315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/260315.html</trackback:ping><description><![CDATA[<p>接下来要说的东西其实不是松弛变量本身，但由于是为了使用松弛变量才引入的，因此放在这里也算合适，那就是惩罚因子C。回头看一眼引入了松弛变量以后的优化问题：</p> <p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_11A27/clip_image002_2.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002" border="0" hspace="12" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_11A27/clip_image002_thumb.gif" width="523" height="116"></a></p> <p>注意其中C的位置，也可以回想一下C所起的作用（表征你有多么重视离群点，C越大越重视，越不想丢掉它们）。这个式子是以前做SVM的人写的，大家也就这么用，但没有任何规定说必须对所有的松弛变量都使用同一个惩罚因子，我们完全可以给每一个离群点都使用不同的C，这时就意味着你对每个样本的重视程度都不一样，有些样本丢了也就丢了，错了也就错了，这些就给一个比较小的C；而有些样本很重要，决不能分类错误（比如中央下达的文件啥的，笑），就给一个很大的C。 <p>当然实际使用的时候并没有这么极端，但一种很常用的变形可以用来解决分类问题中样本的&#8220;偏斜&#8221;问题。 <p>先来说说样本的偏斜问题，也叫数据集偏斜（unbalanced），它指的是参与分类的两个类别（也可以指多个类别）样本数量差异很大。比如说正类有10，000个样本，而负类只给了100个，这会引起的问题显而易见，可以看看下面的图：</p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_11A27/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_11A27/image_thumb.png" width="546" height="411"></a>  <p></p> <p>方形的点是负类。H，H<sub>1</sub>，H<sub>2</sub>是根据给的样本算出来的分类面，由于负类的样本很少很少，所以有一些本来是负类的样本点没有提供，比如图中两个灰色的方形点，如果这两个点有提供的话，那算出来的分类面应该是H&#8217;，H<sub>2</sub>&#8217;和H<sub>1</sub>，他们显然和之前的结果有出入，实际上负类给的样本点越多，就越容易出现在灰色点附近的点，我们算出的结果也就越接近于真实的分类面。但现在由于偏斜的现象存在，使得数量多的正类可以把分类面向负类的方向&#8220;推&#8221;，因而影响了结果的准确性。 <p>对付数据集偏斜问题的方法之一就是在惩罚因子上作文章，想必大家也猜到了，那就是给样本数量少的负类更大的惩罚因子，表示我们重视这部分样本（本来数量就少，再抛弃一些，那人家负类还活不活了），因此我们的目标函数中因松弛变量而损失的部分就变成了： <p>&nbsp;</p> <p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_11A27/clip_image002%5B5%5D.gif"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002[5]" border="0" hspace="12" alt="clip_image002[5]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_11A27/clip_image002%5B5%5D_thumb.gif" width="262" height="126"></a></p> <p>其中i=1&#8230;p都是正样本，j=p+1&#8230;p+q都是负样本。libSVM这个算法包在解决偏斜问题的时候用的就是这种方法。 <p>那C<sub>+</sub>和C<sub>-</sub>怎么确定呢？它们的大小是试出来的（参数调优），但是他们的比例可以有些方法来确定。咱们先假定说C<sub>+</sub>是5这么大，那确定C<sub>-</sub>的一个很直观的方法就是使用两类样本数的比来算，对应到刚才举的例子，C<sub>-</sub>就可以定为500这么大（因为10，000：100=100：1嘛）。 <p>但是这样并不够好，回看刚才的图，你会发现正类之所以可以&#8220;欺负&#8221;负类，其实并不是因为负类样本少，真实的原因是负类的样本分布的不够广（没扩充到负类本应该有的区域）。说一个具体点的例子，现在想给政治类和体育类的文章做分类，政治类文章很多，而体育类只提供了几篇关于篮球的文章，这时分类会明显偏向于政治类，如果要给体育类文章增加样本，但增加的样本仍然全都是关于篮球的（也就是说，没有足球，排球，赛车，游泳等等），那结果会怎样呢？虽然体育类文章在数量上可以达到与政治类一样多，但过于集中了，结果仍会偏向于政治类！所以给C<sub>+</sub>和C<sub>-</sub>确定比例更好的方法应该是衡量他们分布的程度。比如可以算算他们在空间中占据了多大的体积，例如给负类找一个超球——就是高维空间里的球啦——它可以包含所有负类的样本，再给正类找一个，比比两个球的半径，就可以大致确定分布的情况。显然半径大的分布就比较广，就给小一点的惩罚因子。 <p>但是这样还不够好，因为有的类别样本确实很集中，这不是提供的样本数量多少的问题，这是类别本身的特征（就是某些话题涉及的面很窄，例如计算机类的文章就明显不如文化类的文章那么&#8220;天马行空&#8221;），这个时候即便超球的半径差异很大，也不应该赋予两个类别不同的惩罚因子。 <p>看到这里读者一定疯了，因为说来说去，这岂不成了一个解决不了的问题？然而事实如此，完全的方法是没有的，根据需要，选择实现简单又合用的就好（例如libSVM就直接使用样本数量的比）。   <img src ="http://www.blogjava.net/zhenandaci/aggbug/260315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-03-17 20:04 <a href="http://www.blogjava.net/zhenandaci/archive/2009/03/17/260315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVM入门（八）松弛变量</title><link>http://www.blogjava.net/zhenandaci/archive/2009/03/15/259786.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Sat, 14 Mar 2009 16:57:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/03/15/259786.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/259786.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/03/15/259786.html#Feedback</comments><slash:comments>52</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/259786.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/259786.html</trackback:ping><description><![CDATA[<p>现在我们已经把一个本来线性不可分的文本分类问题，通过映射到高维空间而变成了线性可分的。就像下图这样： </p>
<p>&nbsp;</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/image_2.png"><img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/image_thumb.png" width="485" border="0" height="308" /></a> </p>
<p>圆形和方形的点各有成千上万个（毕竟，这就是我们训练集中文档的数量嘛，当然很大了）。现在想象我们有另一个训练集，只比原先这个训练集多了一篇文章，映射到高维空间以后（当然，也使用了相同的核函数），也就多了一个样本点，但是这个样本的位置是这样的：</p>
<a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/image_4.png"><img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/image_thumb_1.png" width="485" border="0" height="308" /></a>
<p>&nbsp;</p>
<p>就是图中黄色那个点，它是方形的，因而它是负类的一个样本，这单独的一个样本，使得原本线性可分的问题变成了线性不可分的。这样类似的问题（仅有少数点线性不可分）叫做&#8220;近似线性可分&#8221;的问题。 </p>
<p>以我们人类的常识来判断，说有一万个点都符合某种规律（因而线性可分），有一个点不符合，那这一个点是否就代表了分类规则中我们没有考虑到的方面呢（因而规则应该为它而做出修改）？ </p>
<p>其实我们会觉得，更有可能的是，这个样本点压根就是错误，是噪声，是提供训练集的同学人工分类时一打瞌睡错放进去的。所以我们会简单的忽略这个样本点，仍然使用原来的分类器，其效果丝毫不受影响。 </p>
<p>但这种对噪声的容错性是人的思维带来的，我们的程序可没有。由于我们原本的优化问题的表达式中，确实要考虑所有的样本点（不能忽略某一个，因为程序它怎么知道该忽略哪一个呢？），在此基础上寻找正负类之间的最大几何间隔，而几何间隔本身代表的是距离，是非负的，像上面这种有噪声的情况会使得整个问题无解。这种解法其实也叫做&#8220;硬间隔&#8221;分类法，因为他硬性的要求所有样本点都满足和分类平面间的距离必须大于某个值。 </p>
<p>因此由上面的例子中也可以看出，硬间隔的分类法其结果容易受少数点的控制，这是很危险的（尽管有句话说真理总是掌握在少数人手中，但那不过是那一小撮人聊以自慰的词句罢了，咱还是得民主）。 </p>
<p>但解决方法也很明显，就是仿照人的思路，允许一些点到分类平面的距离不满足原先的要求。由于不同的训练集各点的间距尺度不太一样，因此用间隔（而不是几何间隔）来衡量有利于我们表达形式的简洁。我们原先对样本点的要求是： </p>
<p>&nbsp;</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002_2.gif"><img style="border: 0px none ; display: inline;" title="clip_image002" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002_thumb.gif" width="394" border="0" height="34" hspace="12" /></a></p>
<p>意思是说离分类面最近的样本点函数间隔也要比1大。如果要引入容错性，就给1这个硬性的阈值加一个松弛变量，即允许</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B5%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[5]" alt="clip_image002[5]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B5%5D_thumb.gif" width="448" border="0" height="70" hspace="12" /></a></p>
<p>因为松弛变量是非负的，因此最终的结果是要求间隔可以比1小。但是当某些点出现这种间隔比1小的情况时（这些点也叫离群点），意味着我们放弃了对这些点的精确分类，而这对我们的分类器来说是种损失。但是放弃这些点也带来了好处，那就是使分类面不必向这些点的方向移动，因而可以得到更大的几何间隔（在低维空间看来，分类边界也更平滑）。显然我们必须权衡这种损失和好处。好处很明显，我们得到的分类间隔越大，好处就越多。回顾我们原始的硬间隔分类对应的优化问题：</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B7%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[7]" alt="clip_image002[7]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B7%5D_thumb.gif" width="454" border="0" height="82" hspace="12" /></a></p>
<p>||w||<sup>2</sup>就是我们的目标函数（当然系数可有可无），希望它越小越好，因而损失就必然是一个能使之变大的量（能使它变小就不叫损失了，我们本来就希望目标函数值越小越好）。那如何来衡量损失，有两种常用的方式，有人喜欢用</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B9%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[9]" alt="clip_image002[9]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B9%5D_thumb.gif" width="75" border="0" height="70" hspace="12" /></a></p>
<p>而有人喜欢用</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B11%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[11]" alt="clip_image002[11]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B11%5D_thumb.gif" width="71" border="0" height="68" hspace="12" /></a></p>
<p>其中l都是样本的数目。两种方法没有大的区别。如果选择了第一种，得到的方法的就叫做二阶软间隔分类器，第二种就叫做一阶软间隔分类器。把损失加入到目标函数里的时候，就需要一个<span style="color: #5f48ff;">惩罚因子</span>（cost，也就是libSVM的诸多参数中的C），原来的优化问题就变成了下面这样：</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B13%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[13]" alt="clip_image002[13]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_D32/clip_image002%5B13%5D_thumb.gif" width="523" border="0" height="116" hspace="12" /></a></p>
<p>这个式子有这么几点要注意： </p>
<p>一是并非所有的样本点都有一个松弛变量与其对应。实际上只有&#8220;离群点&#8221;才有，或者也可以这么看，所有没离群的点松弛变量都等于0（对负类来说，离群点就是在前面图中，跑到H2右侧的那些负样本点，对正类来说，就是跑到H1左侧的那些正样本点）。 </p>
<p>二是松弛变量的值实际上标示出了对应的点到底离群有多远，值越大，点就越远。 </p>
<p>三是惩罚因子C决定了你有多重视离群点带来的损失，显然当所有离群点的松弛变量的和一定时，你定的C越大，对目标函数的损失也越大，此时就暗示着你非常不愿意放弃这些离群点，最极端的情况是你把C定为无限大，这样只要稍有一个点离群，目标函数的值马上变成无限大，马上让问题变成无解，这就退化成了硬间隔问题。 </p>
<p>四是惩罚因子C<span style="color: #ff0000;">不</span>是一个变量，整个优化问题在解的时候，C是一个你必须事先指定的值，指定这个值以后，解一下，得到一个分类器，然后用测试数据看看结果怎么样，如果不够好，换一个C的值，再解一次优化问题，得到另一个分类器，再看看效果，如此就是一个参数寻优的过程，但这和优化问题本身决不是一回事，优化问题在解的过程中，C一直是定值，要记住。 </p>
<p>五是尽管加了松弛变量这么一说，但这个优化问题仍然是一个优化问题（汗，这不废话么），解它的过程比起原始的硬间隔问题来说，没有任何更加特殊的地方。 </p>
<p>从大的方面说优化问题解的过程，就是先试着确定一下w，也就是确定了前面图中的三条直线，这时看看间隔有多大，又有多少点离群，把目标函数的值算一算，再换一组三条直线（你可以看到，分类的直线位置如果移动了，有些原来离群的点会变得不再离群，而有的本来不离群的点会变成离群点），再把目标函数的值算一算，如此往复（迭代），直到最终找到目标函数最小时的w。 </p>
<p>啰嗦了这么多，读者一定可以马上自己总结出来，松弛变量也就是个解决线性不可分问题的方法罢了，但是回想一下，核函数的引入不也是为了解决线性不可分的问题么？为什么要为了一个问题使用两种方法呢？ </p>
<p>其实两者还有微妙的不同。一般的过程应该是这样，还以文本分类为例。在原始的低维空间中，样本相当的不可分，无论你怎么找分类平面，总会有大量的离群点，此时用核函数向高维空间映射一下，虽然结果仍然是不可分的，但比原始空间里的要更加接近线性可分的状态（就是达到了近似线性可分的状态），此时再用松弛变量处理那些少数&#8220;冥顽不化&#8221;的离群点，就简单有效得多啦。 </p>
<p>本节中的（式1）也确实是支持向量机最最常用的形式。至此一个比较完整的支持向量机框架就有了，简单说来，支持向量机就是使用了核函数的软间隔线性分类法。 </p>
<p>下一节会说说松弛变量剩下的一点点东西，顺便搞个读者调查，看看大家还想侃侃SVM的哪些方面。  </p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/259786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-03-15 00:57 <a href="http://www.blogjava.net/zhenandaci/archive/2009/03/15/259786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVM入门（七）为何需要核函数</title><link>http://www.blogjava.net/zhenandaci/archive/2009/03/06/258288.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Fri, 06 Mar 2009 10:36:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/03/06/258288.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/258288.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/03/06/258288.html#Feedback</comments><slash:comments>54</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/258288.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/258288.html</trackback:ping><description><![CDATA[<p>生存？还是毁灭？——哈姆雷特 </p>
<p>可分？还是不可分？——支持向量机 </p>
<p>之前一直在讨论的线性分类器,器如其名（汗，这是什么说法啊），只能对线性可分的样本做处理。如果提供的样本线性不可分，结果很简单，线性分类器的求解程序会无限循环，永远也解不出来。这必然使得它的适用范围大大缩小，而它的很多优点我们实在不原意放弃，怎么办呢？是否有某种方法，让线性不可分的数据变得线性可分呢？ </p>
<p>有！其思想说来也简单，来用一个二维平面中的分类问题作例子，你一看就会明白。事先声明，下面这个例子是网络早就有的，我一时找不到原作者的正确信息，在此借用，并加进了我自己的解说而已。 </p>
<p>例子是下面这张图： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image001_2.jpg"><img style="border: 0px none ; display: inline;" title="clip_image001" alt="clip_image001" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image001_thumb.jpg" border="0" height="259" hspace="12" width="402" /></a> </p>
<p>我们把横轴上端点a和b之间红色部分里的所有点定为正类，两边的黑色部分里的点定为负类。试问能找到一个线性函数把两类正确分开么？不能，因为二维空间里的线性函数就是指直线，显然找不到符合条件的直线。 </p>
<p>但我们可以找到一条曲线，例如下面这一条： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002_2.gif"><img style="border: 0px none ; display: inline;" title="clip_image002" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002_thumb.gif" border="0" height="243" hspace="12" width="317" /></a> </p>
<p>显然通过点在这条曲线的上方还是下方就可以判断点所属的类别（你在横轴上随便找一点，算算这一点的函数值，会发现负类的点函数值一定比0大，而正类的一定比0小）。这条曲线就是我们熟知的二次曲线，它的函数表达式可以写为： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B5%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[5]" alt="clip_image002[5]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B5%5D_thumb.gif" border="0" height="40" hspace="12" width="171" /></a> </p>
<p>问题只是它不是一个线性函数，但是，下面要注意看了，新建一个向量y和a： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B7%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[7]" alt="clip_image002[7]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B7%5D_thumb.gif" border="0" height="96" hspace="12" width="259" /></a> </p>
<p>这样g(x)就可以转化为f(y)=&lt;a,y&gt;，你可以把y和a分别回带一下，看看等不等于原来的g(x)。用内积的形式写你可能看不太清楚，实际上f(y)的形式就是： </p>
<p>g(x)=f(y)=ay </p>
<p>在任意维度的空间中，这种形式的函数都是一个线性函数（只不过其中的a和y都是多维向量罢了），因为自变量y的次数不大于1。 </p>
<p>看出妙在哪了么？原来在二维空间中一个线性不可分的问题，映射到四维空间后，变成了线性可分的！因此这也形成了我们最初想解决线性不可分问题的基本思路——向高维空间转化，使其变得线性可分。 </p>
<p>而转化最关键的部分就在于找到x到y的映射方法。遗憾的是，如何找到这个映射，没有系统性的方法（也就是说，纯靠猜和凑）。具体到我们的文本分类问题，文本被表示为上千维的向量，即使维数已经如此之高，也常常是线性不可分的，还要向更高的空间转化。其中的难度可想而知。</p>
<blockquote>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;"><strong>小Tips</strong>:为什么说f(y)=ay是四维空间里的函数?<br />
</span><blockquote><span style="color: #000000;">大家可能一时没看明白。回想一下我们二维空间里的函数定义</span><br />
<span style="color: #000000;">&nbsp; g(x)=ax+b</span><br />
<span style="color: #000000;">变量x是一维的，为什么说它是二维空间里的函数呢？因为还有一个变量我们没写出来，它的完整形式其实是</span><br />
<span style="color: #000000;">&nbsp; y=g(x)=ax+b<br />
即<br />
&nbsp; y=ax+b</span><br />
<span style="color: #000000;">看看，有几个变量？两个。那是几维空间的函数？（作者五岁的弟弟答：五维的。作者：&#8230;&#8230;）</span><br />
再看看<br />
f(y)=ay<br />
里面的y是三维的变量，那f(y)是几维空间里的函数？（作者五岁的弟弟答：还是五维的。作者：&#8230;&#8230;）<br />
</blockquote></div>
</blockquote>
<p> </p>
<p>用一个具体文本分类的例子来看看这种向高维空间映射从而分类的方法如何运作，想象一下，我们文本分类问题的原始空间是1000维的（即每个要被分类的文档被表示为一个1000维的向量），在这个维度上问题是线性不可分的。现在我们有一个2000维空间里的线性函数 </p>
<blockquote>
<p>f(x<sup>&#8217;</sup>)=&lt;w<sup>&#8217;</sup>,x<sup>&#8217;</sup>&gt;+b</p>
</blockquote>
<p>注意向量的右上角有个 &#8217;哦。它能够将原问题变得可分。式中的 w<sup>&#8217;</sup>和x<sup>&#8217;</sup>都是2000维的向量，只不过w<sup>&#8217;</sup>是定值，而x<sup>&#8217;</sup>是变量（好吧,严格说来这个函数是2001维的,哈哈），现在我们的输入呢，是一个1000维的向量x，分类的过程是先把x变换为2000维的向量x<sup>&#8217;</sup>，然后求这个变换后的向量x<sup>&#8217;</sup>与向量w<sup>&#8217;</sup>的内积，再把这个内积的值和b相加，就得到了结果，看结果大于阈值还是小于阈值就得到了分类结果。 </p>
<p>你发现了什么？我们其实只关心那个高维空间里<span style="color: #6871ff;">内积</span>的值，那个值算出来了，分类结果就算出来了。而从理论上说， x<sup>&#8217;</sup>是经由x变换来的，因此广义上可以把它叫做x的函数（有一个x，就确定了一个x<sup>&#8217;</sup>，对吧，确定不出第二个），而w<sup>&#8217;</sup>是常量，它是一个低维空间里的常量w经过变换得到的，所以给了一个w 和x的值，就有一个确定的f(x<sup>&#8217;</sup>)值与其对应。这让我们幻想，是否能有这样一种函数K(w,x),他接受低维空间的输入值，却能算出高维空间的内积值&lt;w<sup>&#8217;</sup>,x<sup>&#8217;</sup>&gt;？ </p>
<p>如果有这样的函数，那么当给了一个低维空间的输入x以后， </p>
<blockquote>
<p>g(x)=K(w,x)+b</p>
</blockquote> <blockquote>
<p>f(x<sup>&#8217;</sup>)=&lt;w<sup>&#8217;</sup>,x<sup>&#8217;</sup>&gt;+b</p>
</blockquote>
<p>这两个函数的计算结果就完全一样，我们也就用不着费力找那个映射关系，直接拿低维的输入往g(x)里面代就可以了（再次提醒，这回的g(x)就不是线性函数啦，因为你不能保证K(w,x)这个表达式里的x次数不高于1哦）。 </p>
<p>万幸的是，这样的K(w,x)确实存在（发现凡是我们人类能解决的问题，大都是巧得不能再巧，特殊得不能再特殊的问题，总是恰好有些能投机取巧的地方才能解决，由此感到人类的渺小），它被称作<span style="color: #6871ff;">核函数</span>（核，kernel），而且还不止一个，事实上，只要是满足了<span style="color: #6871ff;">Mercer条件</span>的函数，都可以作为核函数。核函数的基本作用就是接受两个低维空间里的向量，能够计算出经过某个变换后在高维空间里的向量内积值。几个比较常用的核函数，俄，教课书里都列过，我就不敲了（懒！）。 </p>
<p>回想我们上节说的求一个线性分类器，它的形式应该是： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B9%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[9]" alt="clip_image002[9]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B9%5D_thumb.gif" border="0" height="68" hspace="12" width="297" /></a> </p>
<p>现在这个就是高维空间里的线性函数（为了区别低维和高维空间里的函数和向量，我改了函数的名字，并且给w和x都加上了 &#8217;），我们就可以用一个低维空间里的函数（再一次的，这个低维空间里的函数就不再是线性的啦）来代替， </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B11%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[11]" alt="clip_image002[11]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_10595/clip_image002%5B11%5D_thumb.gif" border="0" height="68" hspace="12" width="261" /></a> </p>
<p>又发现什么了？f(x&#8217;) 和g(x)里的&#945;，y，b全都是一样一样的！这就是说，尽管给的问题是线性不可分的，但是我们就硬当它是线性问题来求解，只不过求解过程中，凡是要求内积的时候就用你选定的核函数来算。这样求出来的&#945;再和你选定的核函数一组合，就得到分类器啦！ </p>
<p>明白了以上这些，会自然的问接下来两个问题： </p>
<p>1． 既然有很多的核函数，针对具体问题该怎么选择？ </p>
<p>2． 如果使用核函数向高维空间映射后，问题仍然是线性不可分的，那怎么办？ </p>
<p>第一个问题现在就可以回答你：对核函数的选择，现在还缺乏指导原则！各种实验的观察结果（不光是文本分类）的确表明，某些问题用某些核函数效果很好，用另一些就很差，但是一般来讲，径向基核函数是不会出太大偏差的一种，首选。（我做文本分类系统的时候，使用径向基核函数，没有参数调优的情况下，绝大部分类别的准确和召回都在85%以上，可见。虽然libSVM的作者林智仁认为文本分类用线性核函数效果更佳，待考证） </p>
<p>对第二个问题的解决则引出了我们下一节的主题：松弛变量。  </p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/258288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-03-06 18:36 <a href="http://www.blogjava.net/zhenandaci/archive/2009/03/06/258288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVM入门（六）线性分类器的求解&amp;mdash;&amp;mdash;问题的转化，直观角度</title><link>http://www.blogjava.net/zhenandaci/archive/2009/03/01/257237.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Sun, 01 Mar 2009 12:48:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/03/01/257237.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/257237.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/03/01/257237.html#Feedback</comments><slash:comments>24</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/257237.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/257237.html</trackback:ping><description><![CDATA[<p>让我再一次比较完整的重复一下我们要解决的问题：我们有属于两个类别的样本点（并不限定这些点在二维空间中）若干，如图， </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/image_2.png"><img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/image_thumb.png" width="484" border="0" height="307" /></a>  </p>
<p>圆形的样本点定为正样本（连带着，我们可以把正样本所属的类叫做正类），方形的点定为负例。我们想求得这样一个线性函数（在n维空间中的线性函数）： </p>
<p>g(x)=wx+b </p>
<p>使得所有属于正类的点<a name="OLE_LINK1">x<sub>+</sub></a>代入以后有g(x<sub>+</sub>)&#8805;1，而所有属于负类的点x<sub>-</sub>代入后有g(x<sub>-</sub>)&#8804;-1（之所以总跟1比较，无论正一还是负一，都是因为我们固定了间隔为1，注意间隔和几何间隔的区别）。代入g(x)后的值如果在1和-1之间，我们就拒绝判断。 </p>
<p>求这样的g(x)的过程就是求w（一个n维向量）和b（一个实数）两个参数的过程（但实际上只需要求w，求得以后找某些样本点代入就可以求得b）。因此在求g(x)的时候，w才是变量。 </p>
<p>你肯定能看出来，一旦求出了w（也就求出了b），那么中间的直线H就知道了（因为它就是wx+b=0嘛，哈哈），那么H1和H2也就知道了（因为三者是平行的，而且相隔的距离还是||w||决定的）。那么w是谁决定的？显然是你给的样本决定的，一旦你在空间中给出了那些个样本点，三条直线的位置实际上就唯一确定了（因为我们求的是最优的那三条，当然是唯一的），我们解优化问题的过程也只不过是把这个确定了的东西算出来而已。 </p>
<p>样本确定了w，用数学的语言描述，就是w可以表示为样本的某种组合： </p>
<p>w=&#945;<sub>1</sub>x<sub>1</sub>+&#945;<sub>2</sub>x<sub>2</sub>+&#8230;+&#945;<sub>n</sub>x<sub>n</sub> </p>
<p>式子中的&#945;<sub>i</sub>是一个一个的数（在严格的证明过程中，这些&#945;被称为<span style="color: #3844ff;">拉格朗日乘子</span>），而x<sub>i</sub>是样本点，因而是向量，n就是总样本点的个数。为了方便描述，以下开始严格区别数字与向量的乘积和向量间的乘积，我会用&#945;<sub>1</sub>x<sub>1</sub>表示数字和向量的乘积，而用&lt;x<sub>1</sub>,x<sub>2</sub>&gt;表示向量x<sub>1</sub>,x<sub>2</sub>的内积（也叫点积，注意与向量叉积的区别）。因此g(x)的表达式严格的形式应该是： </p>
<p>g(x)=&lt;w,x&gt;+b </p>
<p>但是上面的式子还不够好，你回头看看图中正样本和负样本的位置，想像一下，我不动所有点的位置，而只是把其中一个正样本点定为负样本点（也就是把一个点的形状从圆形变为方形），结果怎么样？三条直线都必须移动（因为对这三条直线的要求是必须把方形和圆形的点正确分开）！这说明w不仅跟样本点的位置有关，还跟样本的类别有关（也就是和样本的&#8220;标签&#8221;有关）。因此用下面这个式子表示才算完整： </p>
<p>w=&#945;<sub>1</sub>y<sub>1</sub>x<sub>1</sub>+&#945;<sub>2</sub>y<sub>2</sub>x<sub>2</sub>+&#8230;+&#945;<sub>n</sub>y<sub>n</sub>x<sub>n</sub> （式1） </p>
<p>其中的y<sub>i</sub>就是第i个样本的标签，它等于1或者-1。其实以上式子的那一堆拉格朗日乘子中，只有很少的一部分不等于0（不等于0才对w起决定作用），这部分不等于0的拉格朗日乘子后面所乘的样本点，其实都落在H1和H2上，也正是这部分样本（而不需要全部样本）唯一的确定了分类函数，当然，更严格的说，这些样本的一部分就可以确定，因为例如确定一条直线，只需要两个点就可以，即便有三五个都落在上面，我们也不是全都需要。这部分我们真正需要的样本点，就叫做<span style="color: #3844ff;">支持（撑）向量</span>！（名字还挺形象吧，他们&#8220;撑&#8221;起了分界线） </p>
<p>式子也可以用求和符号简写一下： </p>
<p>&nbsp;</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/clip_image002_2.gif"><img style="border: 0px none ; display: inline;" title="clip_image002" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/clip_image002_thumb.gif" width="136" border="0" height="62" hspace="12" /></a></p>
<p>因此原来的g(x)表达式可以写为： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/clip_image002%5B4%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[4]" alt="clip_image002[4]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/clip_image002%5B4%5D_thumb.gif" width="240" border="0" height="96" hspace="12" /></a></p>
<p>注意式子中x才是变量，也就是你要分类哪篇文档，就把该文档的向量表示代入到 x的位置，而所有的x<sub>i</sub>统统都是已知的样本。还注意到式子中只有x<sub>i</sub>和x是向量，因此一部分可以从内积符号中拿出来，得到g(x)的式子为：</p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/clip_image002%5B6%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[6]" alt="clip_image002[6]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVM_1244A/clip_image002%5B6%5D_thumb.gif" width="344" border="0" height="68" hspace="12" /></a></p>
<p>发现了什么？w不见啦！从求w变成了求&#945;。 </p>
<p>但肯定有人会说，这并没有把原问题简化呀。嘿嘿，其实简化了，只不过在你看不见的地方，以这样的形式描述问题以后，我们的优化问题少了很大一部分不等式约束（记得这是我们解不了极值问题的万恶之源）。但是接下来先跳过线性分类器求解的部分，来看看 SVM在线性分类器上所做的重大改进——<span style="color: #3844ff;">核函数</span>。  </p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/257237.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-03-01 20:48 <a href="http://www.blogjava.net/zhenandaci/archive/2009/03/01/257237.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SVM入门（五）线性分类器的求解&amp;mdash;&amp;mdash;问题的描述Part2</title><link>http://www.blogjava.net/zhenandaci/archive/2009/02/14/254630.html</link><dc:creator>Jasper</dc:creator><author>Jasper</author><pubDate>Fri, 13 Feb 2009 17:34:00 GMT</pubDate><guid>http://www.blogjava.net/zhenandaci/archive/2009/02/14/254630.html</guid><wfw:comment>http://www.blogjava.net/zhenandaci/comments/254630.html</wfw:comment><comments>http://www.blogjava.net/zhenandaci/archive/2009/02/14/254630.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.blogjava.net/zhenandaci/comments/commentRss/254630.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhenandaci/services/trackbacks/254630.html</trackback:ping><description><![CDATA[<p>从最一般的定义上说，一个求最小值的问题就是一个优化问题（也叫寻优问题，更文绉绉的叫法是<span style="color: #505bff;">规划</span>——Programming），它同样由两部分组成，目标函数和约束条件，可以用下面的式子表示： </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMPart2_1603/clip_image002_2.gif"><img style="border: 0px none ; display: inline;" title="clip_image002" alt="clip_image002" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMPart2_1603/clip_image002_thumb.gif" width="272" border="0" height="72" hspace="12" /></a>（式1） </p>
<p>约束条件用函数c来表示，就是constrain的意思啦。你可以看出一共有p+q个约束条件，其中p个是<span style="color: #505bff;">不等式约束</span>，q个<span style="color: #505bff;">等式约束</span>。 </p>
<p>关于这个式子可以这样来理解：式中的x是自变量，但不限定它的维数必须为1（视乎你解决的问题空间维数，对我们的文本分类来说，那可是成千上万啊）。要求f(x)在哪一点上取得最小值（反倒不太关心这个最小值到底是多少，关键是哪一点），但不是在整个空间里找，而是在约束条件所划定的一个有限的空间里找，这个有限的空间就是优化理论里所说的<span style="color: #505bff;">可行域</span>。注意可行域中的每一个点都要求满足所有p+q个条件，而不是满足其中一条或几条就可以（切记，要满足每个约束），同时可行域边界上的点有一个额外好的特性，它们可以使<span style="color: #ff0000;">不等式约束</span>取得等号！而边界内的点不行。 </p>
<p>关于可行域还有个概念不得不提，那就是<span style="color: #505bff;">凸集</span>，凸集是指有这么一个点的集合，其中任取两个点连一条直线，这条线上的点仍然在这个集合内部，因此说&#8220;凸&#8221;是很形象的（一个反例是，二维平面上，一个月牙形的区域就不是凸集，你随便就可以找到两个点违反了刚才的规定）。 </p>
<p>回头再来看我们线性分类器问题的描述，可以看出更多的东西。 </p>
<p><a href="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMPart2_1603/clip_image002%5B5%5D.gif"><img style="border: 0px none ; display: inline;" title="clip_image002[5]" alt="clip_image002[5]" src="http://www.blogjava.net/images/blogjava_net/zhenandaci/WindowsLiveWriter/SVMPart2_1603/clip_image002%5B5%5D_thumb.gif" width="372" border="0" height="67" hspace="12" /></a>（式2） </p>
<p>在这个问题中，自变量就是w，而目标函数是w的二次函数，所有的约束条件都是w的线性函数（哎，千万不要把x<sub>i</sub>当成变量，它代表样本，是已知的），这种规划问题有个很有名气的称呼——<span style="color: #505bff;">二次规划</span>（Quadratic Programming，QP），而且可以更进一步的说，由于它的可行域是一个凸集，因此它是一个<span style="color: #505bff;">凸二次规划</span>。 </p>
<p>一下子提了这么多术语，实在不是为了让大家以后能向别人炫耀学识的渊博，这其实是我们继续下去的一个重要前提，因为在动手求一个问题的解之前（好吧，我承认，是动计算机求&#8230;&#8230;），我们必须先问自己：这个问题是不是有解？如果有解，是否能找到？ </p>
<p>对于一般意义上的规划问题，两个问题的答案都是不一定，但凸二次规划让人喜欢的地方就在于，它有解（教科书里面为了严谨，常常加限定成分，说它有全局最优解，由于我们想找的本来就是全局最优的解，所以不加也罢），而且可以找到！（当然，依据你使用的算法不同，找到这个解的速度，行话叫收敛速度，会有所不同） </p>
<p>对比（式2）和（式1）还可以发现，我们的线性分类器问题只有不等式约束，因此形式上看似乎比一般意义上的规划问题要简单，但解起来却并非如此。 </p>
<p>因为我们实际上并不知道该怎么解一个带约束的优化问题。如果你仔细回忆一下高等数学的知识，会记得我们可以轻松的解一个不带任何约束的优化问题（实际上就是当年背得烂熟的函数求极值嘛，求导再找0点呗，谁不会啊？笑），我们甚至还会解一个只带等式约束的优化问题，也是背得烂熟的，求条件极值，记得么，通过添加拉格朗日乘子，构造拉格朗日函数，来把这个问题转化为无约束的优化问题云云（如果你一时没想通，我提醒一下，构造出的拉格朗日函数就是转化之后的问题形式，它显然没有带任何条件）。 </p>
<p>读者问：如果只带等式约束的问题可以转化为无约束的问题而得以求解，那么可不可以把带不等式约束的问题向只带等式约束的问题转化一下而得以求解呢？ </p>
<p>聪明，可以，实际上我们也正是这么做的。下一节就来说说如何做这个转化，一旦转化完成，求解对任何学过高等数学的人来说，都是小菜一碟啦。  </p>
<img src ="http://www.blogjava.net/zhenandaci/aggbug/254630.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhenandaci/" target="_blank">Jasper</a> 2009-02-14 01:34 <a href="http://www.blogjava.net/zhenandaci/archive/2009/02/14/254630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>