<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_leftnoteasy</title><subtitle type="text">               关注于 机器学习、数据挖掘、并行计算、数学</subtitle><id>http://feed.cnblogs.com/blog/u/62514/rss</id><updated>2012-02-21T08:00:18Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/62514/rss"/><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2012/02/18/why-yarn.html</id><title type="text">hadoop杂记-为什么会有Map-reduce v2 (Yarn)</title><summary type="text">前言： 有一段时间没有写博客了(发现这是我博客最常见的开头，不过这次间隔真的好长），前段时间事情比较多，所以耽搁得也很多。 现在准备计划写一个新的专题，叫做《hadoop杂记》，里面的文章有深有浅，文章不是按入门-中级-高级的顺序组织的，如果想看看从入门到深入的书，比较推荐《the definitive guide of hadoop》。 今天主要想写写关于map-reduce v2(或者叫map-reduce next generation，或者叫YARN)与之前的map-reduce有什么不同。最近在学习Yarn的过程中，也参考了很多人的博客，里面的介绍都各有所长。不过一个很重要的问...</summary><published>2012-02-18T15:05:00Z</published><updated>2012-02-18T15:05:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2012/02/18/why-yarn.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2012/02/18/why-yarn.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;a name="_GoBack"&gt;&lt;font color="#8fb08c"&gt;&lt;font style="font-weight: bold"&gt;前言：&lt;/font&gt;&lt;/font&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;有一段时间没有写博客了(发现这是我博客最常见的开头，不过这次间隔真的好长），前段时间事情比较多，所以耽搁得也很多。&lt;/p&gt;  &lt;p&gt;现在准备计划写一个新的专题，叫做《hadoop杂记》，里面的文章有深有浅，文章不是按入门-中级-高级的顺序组织的，如果想看看从入门到深入的书，比较推荐《the definitive guide of hadoop》。&lt;/p&gt;  &lt;p&gt;今天主要想写写关于map-reduce v2(或者叫map-reduce next generation，或者叫YARN)与之前的map-reduce有什么不同。最近在学习Yarn的过程中，也参考了很多人的博客，里面的介绍都各有所长。不过一个很重要的问题是，为什么需要一个Yarn，初看之后，也不觉得Yarn有什么特别的，就是把之前设计中的一块拆成了几块，仔细想想，方才明白其中的奥妙。&lt;/p&gt;  &lt;p&gt;理解本文需要对老的Map-reduce框架有一定的了解。有朋友如果对hadoop以及大数据处理的架构、应用的咨询、讨论等等可以按下一段的联系方式与我联系。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;版权声明：&lt;/strong&gt;本文由leftnoteasy发布于&lt;a href="http://leftnoteasy.cnblogs.com/"&gt;http://leftnoteasy.cnblogs.com&lt;/a&gt;，本文可以部分或者全部的被引用，但请注明出处，可以联系wheeleast (at) gmail.com, 也可以加我weibo: &lt;a href="http://weibo.com/leftnoteasy"&gt;http://weibo.com/leftnoteasy&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#8fb08c"&gt;&lt;font style="font-weight: bold"&gt;Why Yarn：&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;strong&gt;Map-reduce&lt;/strong&gt;&lt;strong&gt;老矣，尚能饭否?&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;第一次看到Yarn的问题，就需要问问，为什么要重新设计之前这样一个成熟的架构。&lt;/p&gt;  &lt;p&gt;&amp;#8220;The Apache Hadoop Map-reduce framework is showing it&amp;#8217;s age, clearly&amp;#8221;, 社区的Yarn设计文档 &amp;#8221;&lt;a href="https://issues.apache.org/jira/secure/attachment/12486023/MapReduce_NextGen_Architecture.pdf"&gt;MapReduce_NextGen-Architecture&lt;/a&gt;&amp;#8221;如是说。&lt;/p&gt;  &lt;p&gt;目前的Map-reduce framework碰到了很多的问题，比如说过于大的内存消耗、不合理的线程模型设计、当集群规模增大后，扩展性/稳定性/性能的不足。这是目前hadoop的集群一直停留在Yahoo公布出来的3000台这个数量级上。&lt;/p&gt;  &lt;p&gt;为了克服之前说道的问题，就需要对目前架构上进行重新思考，之后我会对新老Map-reduce架构上进行比较。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;strong&gt;Yarn&lt;/strong&gt;&lt;strong&gt;的设计需求&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;这里放上设计需求不是为了凑字数的，最近越来越发现设计需求是软件开发的灵魂，虽然需求常常变化可以唤醒植物人，不过一份好的设计需求可以让之后怎么走变得非常清晰。参考自Yarn设计文档：&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;最优先的需求：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#183; Reliability&lt;/p&gt;  &lt;p&gt;&amp;#183; Availability &lt;/p&gt;  &lt;p&gt;&amp;#183; Scalability - Clusters of 10000 nodes and 200,000 cores &lt;/p&gt;  &lt;p&gt;&amp;#183; Backward Compatibility - Ensure customers&amp;#8217; Map-Reduce applications can run unchanged in the nextversion of the framework. Also implies forward compatibility. （向前兼容）&lt;/p&gt;  &lt;p&gt;&amp;#183; Evolution &amp;#8211; Ability for customers to control upgrades to the grid software stack. &lt;/p&gt;  &lt;p&gt;&amp;#183; Predictable Latency &amp;#8211; A major customer concern. &lt;/p&gt;  &lt;p&gt;&amp;#183; Cluster utilization&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The second tier of requirements is&lt;/strong&gt;&lt;strong&gt;（优先级低一点的需求）: &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#183; Support for alternate programming paradigms to Map-Reduce &lt;/p&gt;  &lt;p&gt;&amp;#183; Support for limited, short-lived services&lt;/p&gt;  &lt;p&gt;这里解释一下这份需求，首先是可以支持非常大的集群规模，200k cores这个数字的确很惊人。&lt;/p&gt;  &lt;p&gt;然后是向前兼容，之前大家都写了很多在map-reduce上面的程序，如果不能支持这些老的程序，老的用户怎么都不愿意切换到新版本上去。&lt;/p&gt;  &lt;p&gt;另外集群资源最大化利用，这个之后会提一下&lt;/p&gt;  &lt;p&gt;然后值得一提的是，支持增加除了Map-Reduce之外的计算模型，这个彰显了Hadoop想做领域霸主的决心，之前的Hadoop基本上就与Map-Reduce划上了等号，Map-Reduce干不了的事情，Hadoop基本上就干不了。Map-Reduce能做的事情有限（可以参考一下我之前的一篇&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/08/27/why-map-reduce-must-be-future-of-distributed-computing.html"&gt;文章&lt;/a&gt;,在&amp;#8221;hadoop的劣势&amp;#8221;部分），简单的说就是，数据多，但是计算简单的时候，hadoop威力强大。如果计算逻辑复杂，需要搞个迭代至收敛之类的算法之类的，hadoop就玩不动了。如果能够在Hadoop上加入其他的计算模型，支持这种数据量不那么大，但是计算量大的场景，就防止一些挑剔的客户在这个问题上jjyy了。&lt;/p&gt;  &lt;p&gt;最后说的支持limited, short-lived services还没有看到过更详细的说明，如果有人明白欢迎补充&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;strong&gt;老的Map-reduce设计&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;下面给出一个设计图，&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/201202182305036535.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/201202182305096573.png" width="663" height="506" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;简单的介绍一下&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;1. 首先用户程序(Client Program)提交了一个job，job的信息会发送到Job Tracker中，Job Tracker是Map-reduce框架的中心，他需要与集群中的机器定时通信(heartbeat), 需要管理哪些程序应该跑在哪些机器上，需要管理所有job失败、重启等操作。&lt;/p&gt;  &lt;p&gt;2. TaskTracker是Map-reduce集群中每台机器都有的一个部分，他做的事情主要是监视自己所在机器的资源情况（资源的表示是&amp;#8220;本机还能起多少个map-task，多少个reduce-task&amp;#8221;，每台机器起map/reduce task的上限是在建立集群的时候配置的），另外TaskTracker也会监视当前机器的tasks运行状况。&lt;/p&gt;  &lt;p&gt;TaskTracker需要把这些信息通过heartbeat发送给JobTracker，JobTracker会搜集这些信息以给新提交的job分配运行在哪些机器上。上图回形针一样的箭头就是表示消息的发送-接收的过程。&lt;/p&gt;  &lt;p&gt;够简单吧？当前的架构这么两句话就概括出来了，不过当你去看代码的时候，发现代码非常的难读，因为常常一个类3000多行，因为一个class做了太多的事情，这样会造成class的任务不清楚。另外，从我的理解来说，上面的设计至少有下面的几个问题，&lt;/p&gt;  &lt;p&gt;1. JobTracker是Map-reduce的单点，看起来多多少少让人不爽&lt;/p&gt;  &lt;p&gt;2. JobTracker完成了太多的任务，造成了过多的资源消耗，当map-reduce job非常多的时候，会造成很大的内存开销，潜在来说，也增加了很多JobTracker fail的风险&lt;/p&gt;  &lt;p&gt;3. 在TaskTracker端，以map/reduce task的数目作为资源的表示过于简单，没有考虑到cpu/内存的占用情况，如果两个大内存消耗的task被调度到了一块，很容易出现OOM&lt;/p&gt;  &lt;p&gt;4. 在TaskTracker端，把资源强制划分为map task slot和reduce task slot, 如果当系统中只有map task或者只有reduce task的时候，会造成资源的浪费，也就是前面提过的集群资源利用的问题&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/201202182305092494.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/201202182305168761.png" width="145" height="150" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;上面提到的4个问题，在Yarn中，除了第一个属于&amp;#8220;部分完成&amp;#8221;以外，其他的几个问题都已经解决掉了&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold"&gt;看看Map-reduce v2的设计:&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/201202182305188402.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="clip_image003" border="0" alt="clip_image003" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/201202182305191043.jpg" width="618" height="465" /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;首先User还是User，JobTracker和TaskTracker不见了，取而代之的是ResourceManager, Application Master与Node Manager三个部分。我详细的说一下。&lt;/p&gt;  &lt;p&gt;首先Resource Manager是一个中心的服务，它做的事情是调度、启动每一个Job所属的ApplicationMaster、另外监控ApplicationMaster的存在情况。&lt;/p&gt;  &lt;p&gt;细心的朋友已经发现少了点什么，对！Job里面所在的task的监控、重启等等内容不见了。这就是ApplicationMaster存在的原因。&lt;/p&gt;  &lt;p&gt;上图中的MPI Mast(er)与MR Master就是某一个MPI Job或者MR Job的ApplicationMaster，一定要记住，ApplicationMaster是每一个Job（不是每一种）都有的一个部分，ApplicationMaster可以运行在ResourceManager以外的机器上。老的框架中，JobTracker一个很大的负担就是监控job下的tasks的运行状况，现在，这个部分就扔给ApplicationMaster做了，而ResourceManager中有一个模块叫做ApplicationsMaster，它是监测ApplicationMaster的运行状况，如果出问题，会将其在其他机器上重启。&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;设计优点一：&lt;/font&gt;这个设计大大减小了JobTracker（也就是现在的ResourceManager）的资源消耗，并且让监测每一个Job子任务(tasks)状态的程序分布式化了，更安全、更优美&lt;/p&gt;  &lt;p&gt;另外，在新版中，ApplicationMaster是一个可变更的部分，用户可以对不同的编程模型写自己的ApplicationMaster，让更多类型的编程模型能够跑在Hadoop集群中。&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;设计优点二：&lt;/font&gt;能够支持不同的编程模型&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;设计优点三：&lt;/font&gt;对于资源的表示以内存为单位(在目前版本的Yarn中，没有考虑cpu的占用)，比之前以剩余slot数目更合理&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;设计优点四：&lt;/font&gt;既然资源表示成内存量，那就没有了之前的map slot/reduce slot分开造成集群资源闲置的尴尬情况了&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/201202182305206092.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201202/20120218230520859.png" width="152" height="148" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;其实在Yarn中还有很多优美的设计，之后慢慢再给大家说一下&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#8fb08c"&gt;&lt;font style="font-weight: bold"&gt;总结：&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在Hadoop 0.23版中，就已经加入了Yarn，这个改变让Hadoop从单一的&amp;#8220;黑虎掏心&amp;#8221;变成了少林七十二绝学，学习了解Yarn也将是一个合格的hadooper的基本素质&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#8fb08c"&gt;&lt;strong&gt;参考资料：&lt;/strong&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;主要就是官方设计文档：&lt;a href="https://issues.apache.org/jira/secure/attachment/12486023/MapReduce_NextGen_Architecture.pdf"&gt;https://issues.apache.org/jira/secure/attachment/12486023/MapReduce_NextGen_Architecture.pdf&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/2357738.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2012/02/18/why-yarn.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/09/01/2162268.html</id><title type="text">上海Hadoop开发者聚会(EMC赞助，众多业界内资深专家参加）</title><summary type="text">在云计算成为IT业界主流的今天， 大数据处理越来越成为开发者和客户关心的问题。Hadoop应运而生，首先在Yahoo！和Facebook等互联网企业得到成功运用，继而被更多企业，包括大量国内企业作为大数据分析和处理平台。 今年八月我们成功举办了北京Hadoop开发者聚会，有来自百度、搜狐等互联网和CCTV等企业客户参加，反响热烈。此次上海Hadoop开发者聚会，我们更邀请到了EMC Gre...</summary><published>2011-09-01T09:33:00Z</published><updated>2011-09-01T09:33:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/09/01/2162268.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/09/01/2162268.html"/><content type="html">&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201109/201109011732265483.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="494" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201109/201109011732349472.png" width="376" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;在云计算成为IT业界主流的今天， 大数据处理越来越成为开发者和客户关心的问题。Hadoop应运而生，首先在Yahoo！和Facebook等互联网企业得到成功运用，继而被更多企业，包括大量国内企业作为大数据分析和处理平台。&lt;/p&gt;  &lt;p&gt;今年八月我们成功举办了北京Hadoop开发者聚会，有来自百度、搜狐等互联网和CCTV等企业客户参加，反响热烈。此次上海Hadoop开发者聚会，我们更邀请到了EMC Greenplum Hadoop部门资深产品经理和开发总监，以及EMC中国实验室大数据研究部门资深专家参与聚会，与热心Hadoop开发、使用的技术人员和企业客户分享EMC大数据战略，Hadoop产品技术，探讨和分析Hadoop前沿研发项目。我们欢迎热心Hadoop及Hive, HBase, Pig等周边产品开发，使用感兴趣的开发者或用户参加。&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;主题&lt;/b&gt;&lt;b&gt;：&lt;/b&gt;&lt;b&gt;Big Data and Hadoop&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;时间：&lt;/b&gt;&lt;b&gt;2011年9月15日2:00-5:00PM&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;地点：&lt;/b&gt;&lt;b&gt;创智天地&lt;/b&gt;&lt;b&gt;2号2楼衡山会议厅&lt;/b&gt;&lt;b&gt;（&lt;/b&gt;&lt;b&gt;上海市淞沪路&lt;/b&gt;&lt;b&gt;252&lt;/b&gt;&lt;b&gt;号&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;）&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Session 1: Big data and Greeplum Hadoop – &lt;/b&gt;&lt;b&gt;大数据及&lt;/b&gt;&lt;b&gt;Greenplum Hadoop 产品技术 &lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Session 2: Cloud-scale Database on Hadoop &lt;/b&gt;&lt;b&gt;－&lt;/b&gt;&lt;b&gt;EMC中国实验室Hadoop前沿项目技术分享&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;参会专家：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;余家昌（&lt;/b&gt;&lt;b&gt;Andrew Yu)&lt;/b&gt;&lt;b&gt;先生&lt;/b&gt;&lt;b&gt;：&lt;/b&gt; EMC Greenplum Hadoop产品部门研发总监。余先生毕业于加州伯克利分校，过去六年在Yahoo 领导基于Hadoop的International search开发部门。余先生是开源数据库Postgres专家，Founder。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Susheel Kaushik先生&lt;/b&gt;&lt;b&gt;：&lt;/b&gt; EMC Greenplum Hadoop产品管理总监。Susheel Kaushik先生长期活跃于Hadoop社区，过去四年在Yahoo 担任Hadoop产品管理总监，多次组织Bay Area HUG开发者聚会活动。&lt;/p&gt;  &lt;p&gt;&lt;b&gt;陈继东博士&lt;/b&gt;&lt;b&gt;:&lt;/b&gt; EMC中国研究院大数据实验室研究经理， 负责大规模数据的研发项目。陈继东博士的研究成果多次在Geoinformatica, JCST, SIGMOD, SIGIR, VLDB, CIKM, MDM等知名国际期刊和会议上发表，并著有专著&amp;quot;Moving Objects Management: Models, Techniques, and Applications&amp;quot;(Springer和清华大学出版社联合出版)。陈继东博士现任《Future Generation Computer Systems》和 《Systems and Software》等多个国际期刊和VLDB 2010，ACM CIKM 2010 ，CloudDB 2009等国际会议评审委员， DASFAA 2011 Demo程序委员会主席。&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;参会办法：&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;请将您确认参会的意向，意见及建议通过以下方式反馈给我们：&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;１.&lt;/b&gt;&lt;b&gt;网上报名：&lt;/b&gt;&lt;a href="http://hadoop.wufoo.com/forms/big-dataaehadoopaeeeae/"&gt;http://hadoop.wufoo.com/forms/big-dataaehadoopaeeeae/&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;２.&lt;/b&gt;&lt;b&gt;或通过以下地址直接联系我们： &lt;/b&gt;&lt;b&gt;michael.lv@emc.com及phoebe.wang@emc.com，我们会及时联系您。&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;地址信息：创智天地２号&lt;/b&gt;&lt;b&gt;(KIC2)２楼衡山会议厅（上海市淞沪路２５２号，江湾体育场边）&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;电话&lt;/b&gt;&lt;b&gt;: (86-21)60951100-2948&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;交通： 地铁１０号线，江湾体育场站下&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;地图：&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201109/20110901173242265.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="475" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201109/201109011732502486.png" width="543" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/2162268.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/09/01/2162268.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/08/27/why-map-reduce-must-be-future-of-distributed-computing.html</id><title type="text">为什么Hadoop将一定会是分布式计算的未来？</title><summary type="text">今天听同事分享了一篇很有意思的讲座，叫做"Why Map-Reduce Is Not The Solution To Your Big-Data Problem"(为什么Map-Reduce不是你的“大数据”问题的解决方案)。同事很牛，也分享了很多非常有价值的观点，不过他预言Map-Reduce将会在5年之内消失（而且还呼吁有做存储方面的牛人来预言一下，Hdfs将在5年之内消失），这个话题如果成立的话，让我这个目前在Hadoop工程师，感到无比的压力。这里不为了争个你死我活，只是谈谈自己的一些想法。另外由于这位同事的分享是内部进行的，这里就不透露分享中具体的内容了，只谈谈自己的观点。</summary><published>2011-08-27T02:53:00Z</published><updated>2011-08-27T02:53:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/08/27/why-map-reduce-must-be-future-of-distributed-computing.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/08/27/why-map-reduce-must-be-future-of-distributed-computing.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="5"&gt;版权声明：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;写本文由leftnoteasy发布于&lt;a href="http://leftnoteasy.cnblogs.com/"&gt;http://leftnoteasy.cnblogs.com&lt;/a&gt; 本文可以被全部或者部分的使用，但请注明出处，如果有问题，可以联系wheeleast (at) gmail.com, 也可以加我的新浪微博：&lt;a href="http://weibo.com/leftnoteasy"&gt;http://weibo.com/leftnoteasy&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="5"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="5"&gt;前言：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 很久没有写写博客了，之前主要是换工作，耽误了很多的时间，让人也变得懒散，不想花大时间来写东西。另外就是也确实没有什么自己都觉得有意思的东西拿来写写，对一般的知识什么的，我比较倾向于往evernote上面记笔记。不过最近对于Hadoop看得比较多，对它的发展也比较关心，最近了解得越多，也就越相信Hadoop的未来，这里写一篇文章与大家分享分享，为什么我相信Hadoop一定是分布式计算的未来。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="5"&gt;&lt;strong&gt;写在前面的话：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 今天听同事分享了一篇很有意思的讲座，叫做"Why Map-Reduce Is Not The Solution To Your Big-Data Problem"(为什么Map-Reduce不是你的&amp;#8220;大数据&amp;#8221;问题的解决方案)。同事很牛，也分享了很多非常有价值的观点，不过他预言Map-Reduce将会在5年之内消失（而且还呼吁有做存储方面的牛人来预言一下，Hdfs将在5年之内消失），这个话题如果成立的话，让我这个目前在Hadoop工程师，感到无比的压力。这里不为了争个你死我活，只是谈谈自己的一些想法。另外由于这位同事的分享是内部进行的，这里就不透露分享中具体的内容了，只谈谈自己的观点。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; （本文需要对Hadoop有一定的基础方可理解）&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="5"&gt;&lt;strong&gt;Hadoop为何物？&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 虽说Hadoop的名声很大，但是总还是有同学不太了解的，这里一笔带过一下。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; Google分布式计算三驾马车：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Hadoop的创始源头在于当年Google发布的3篇文章，被称为Google的分布式计算三驾马车（Google还有很多很牛的文章，但是在分布式计算方面，应该这三篇的影响力最大了）：&lt;a href="http://blog.sina.com.cn/s/blog_4ed630e801000bi3.html"&gt;http://blog.sina.com.cn/s/blog_4ed630e801000bi3.html&lt;/a&gt;，链接的文章比我介绍得更清晰，当然最好还是看看原文了，这是做分布式系统、分布式计算的工程师必修课。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Google File System用来解决数据存储的问题，采用N多台廉价的电脑，使用冗余（也就是一份文件保存多份在不同的电脑之上）的方式，来取得读写速度与数据安全并存的结果。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Map-Reduce说穿了就是函数式编程，把所有的操作都分成两类，map与reduce，map用来将数据分成多份，分开处理，reduce将处理后的结果进行归并，得到最终的结果。但是在其中解决了容错性的问题。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; BigTable是在分布式系统上存储结构化数据的一个解决方案，解决了巨大的Table的管理、负载均衡的问题。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Google就靠着这几样技术，在搜索引擎和广告方面取得了举世瞩目的成就。不过Google不是傻的，这三篇文章虽然都是干货，但是不是直接就可以用的。话说Google发表了这三篇文章后，在学术界引起了轩然大波，大家对这三样东西提起了浓厚的兴趣，都想着是不是可以实现一下，以为己用。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; Doug Cutting：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Doug Cutting之前是一个非常有名的开源社区的人，创造了nutch与lucene（现在都是在Apache基金会下面的），nutch之前就实现了一个分布式的爬虫抓取系统。等Google的三驾马车发布后，Doug Cutting一看，挖靠这么厉害的技术，于是就实现了一个DFS(distributed file system)与Map-Reduce（大牛风范啊），集成进了Nutch，作为Nutch的一个子项目存在。那时，是2004年左右。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 在互联网这个领域一直有这样的说法：&lt;/p&gt;  &lt;p&gt;&amp;nbsp; &amp;#8220;如果老二无法战胜老大，那么就把老大赖以生存的东西开源吧&amp;#8221;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 当年与Google还是处在强烈竞争关系的Yahoo!于是招了Doug兄进来，把老大赖以生存的DFS与Map-Reduce开源了。开始了Hadoop的童年时期。差不多在2008年的时候，Hadoop才算逐渐成熟。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; 现在的Hadoop:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 现在的Hadoop不仅是当年的老二Yahoo的专用产品了，从Hadoop长长的用户名单中，可以看到Facebook,可以看到Linkedin，可以看到Amazon，可以看到EMC, eBay，Tweeter，IBM, Microsoft, Apple, HP...(后面的一些未必是完全使用)。国内的公司有淘宝、百度等等。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; 我来定义一下Hadoop：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Hadoop是一套开源的、基础是Java的、目前能够让数千台普通、廉价的服务器组成一个稳定的、强大的集群，使其能够对pb级别的大数据进行存储、计算。已经具有了强大稳定的生态系统，也具有很多使用的延伸产品。比如做查询的Pig, 做分布式命名服务的ZooKeeper, 做数据库的Hive等等。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="5"&gt;&lt;strong&gt;为什么世界上只有一个Hadoop？&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 我的前公司是国内某一个著名互联网公司的子公司，专注做云计算，我也在这个公司最兴盛的时候进入，当时宣传的口号是&amp;#8220;做最好的云计算&amp;#8221;，就是希望自己开发一套存储计算系统（就是类似于前面提到过的dfs与map-reduce），并且克服一些Hadoop的缺点（比如说用c++去实现，克服Java的一些性能问题）。后来结局可能大家也猜到了，投入了很多钱，招了不少牛人，确实也做出了还算不错的云计算（至少在国内是数一数二的）。但是最终不管从稳定性还是效率上还是scalable来说，都远远被Hadoop甩在了后面。虽然我前公司这个云计算项目是否会成功，这里没办法预测，但是前途终究还是比较黯淡的。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 最近一年还听说国内不少的互联网巨头都成立了云计算部门，做&amp;#8220;自己的&amp;#8221;云计算，有些小得像创业时期一样的公司，都宁愿自己写一套map-reduce框架，不愿意直接使用Hadoop。可能这个跟国人的想法，武功秘笈一定要自己藏着，不让别人学，传男不传女。对别人白给你的东西，非常不放心，觉得大家都能学到的东西，肯定竞争力是不够的。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 除开心态问题不谈，但从技术实力上来说，一般国内公司的核心开发团队的能力和当年的Yahoo!比，还是有非常大的差距的，至少像是Doug兄这样的大牛是很罕见的，从开发者的实力来说，就差了不止一个档次。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 其次从积累来说，Hadoop从初创到现在也经过了至少7年的积累的，碰到过很多刁钻客户的问题都慢慢克服了（比如Facebook的超大数据存储），带给用户的经验教训是很充足的，比如说性能调优这一块，就有非常多的文章去介绍。而自己开发一个，什么都需要从头再来。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 最后也是最重要的是，Hadoop形成了一个强大稳定的生态系统，里面有生产者（共享改进的代码、fix bug），也有消费者（使用项目并且反馈经验），Hadoop的用户也可以获得较大的经济利益（不花钱买软件，还可以增加效率）。对于一个开源社区来说，构建出一个完整的生态系统是非常非常的困难，一旦构造出来了，项目就会很稳定的往前去进步。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="5"&gt;Hadoop的优势&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 之前分析了一些&amp;#8220;虚&amp;#8221;的东西，比如生态系统什么的，这里说说一些实际的东西。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; Benchmark:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Hadoop现在保持了很多漂亮的记录：&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 存储：现在世界上最大的Hadoop集群目前在Facebook，可以存储30PB的数据&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 计算：Hadoop是目前Terasort记录的保持者（参见：&lt;a href="http://sortbenchmark.org/"&gt;http://sortbenchmark.org/&lt;/a&gt;)，Terasort是给出1TB的随机数据，看谁能够在最短的时间内完成排序，Hadoop使用了1400多个节点，在2分钟内完成1T的数据排序。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 这里顺便说一下，之前给出网站里面有很多的benchmark，可以看到Hadoop的集群是最大的，使用的机器最多的，像是TritonSort这样的集群，使用了区区50多个节点，最终的结果并不比Hadoop差太多，但是这里得注意一下。TritonSort是专门用来做排序的，里面加入了相当多的优化，但是Hadoop是一个通用的集群，并没有为了一种任务进行如此多的优化。从用户的角度上来说，愿意花钱去买一个只会排序的电脑是意义不那么大的。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; &lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201108/201108271053048930.png"&gt;&lt;img title="image" style="border-right-width: 0px; border-right-style: initial; border-top-width: 0px; border-top-style: initial; display: inline; border-left-width: 0px; border-left-style: initial; border-bottom-width: 0px; border-bottom-style: initial; border-color: initial; border-color: initial; border-color: initial; border-color: initial; border-color: initial; border-color: initial; border-color: initial; " height="104" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201108/201108271053068175.png" width="600" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;nbsp; 注：左右两边属于两种不同的terasort，hadoop是其中一种的记录保持者&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; 能做什么？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 前面说的基本的存储和计算Hadoop是一定能胜任的，下面谈谈一些&amp;#8220;高级&amp;#8221;的功能。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 常见的数据库操作，比如orderby、select这样的操作都可以的，Hive就是支持这样的Sql模型，能够将Sql语句最终转化到Map-Reduce程序中去。其性能和可用性已经得到了证明，Facebook就用它做了不少的数据分析的工作&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 常见的机器学习、矩阵分析算法，目前Mahout作为一个发展迅速的项目，在逐渐填补Hadoop在机器学习领域的空白，现在常见的分类、聚类、推荐、主成分分析算法（比如SVD）都已经有相应的Map-Reduce实现了。虽然目前从用户群和效率上来说是不够的，但是从它的发展来说应该会很快的达到工业界的标准&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="5"&gt;&lt;strong&gt;Hadoop的劣势&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 现在Hadoop依然有很多的问题没有解决，这让有些人非常的怀疑Hadoop的未来，这里谈谈Hadoop的一些重要的劣势&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; HA(High Availability)高可用性:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 这一点是Hadoop非常弱的一个缺点，不管是Hdfs还是Map-reduce，都是采用单master的方式，集群中的其他机器都是与一台中心机器进行通信，如果这个中心机器挂了，集群就只有不工作了（不一定数据会丢失，但是至少需要重启等等工作)，让可用性变得更低。这个一般叫做单点失败(single point of failure,SPOF)。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 虽然现在有些公司已经给出了解决方案，比如EMC就有用Vmware搭建虚拟集群，对master节点进行镜像备份，如果master挂掉，那么立刻换上镜像备份的机器，使其可用性变高，不过这个终究不是一个内置的解决方案，而且Vmware这一套东西也并不便宜。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 不过之后这个问题将会得到非常好的解决，我在Hadoop的未来这一章将说以说。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; Hadoop目前解决得不那么好的一些算法：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; Join等:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; Map-Reduce还有一个问题是，对于Join这个最常见的数据库操作，支持力度还是不够，特别是针对那种上TB的数据，Join将会很不给力，现在已经有了一些解决方案，比如说SIGMOD'2010的这篇文章：&lt;/p&gt;  &lt;p&gt;&amp;nbsp; A Comparison of Join Algorithms for Log Processing in MapReduce&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 不过在现在的情况下，只有尽量的避免大数据库的Join操作&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; 需要进行很多轮迭代、循环的算法：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 对于循环，Map-Reduce稍好，比如矩阵计算，高斯消元法这样的，循环的次数的确定的算法，实现起来还是不难，只是有点慢。但是迭代就更麻烦了，因为现在的Map-Reduce的mapper和reducer是不太方便去弄这样的终止条件。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 还有就是迭代次数超多的算法（比如说矩阵的SVD分解），在超大矩阵的情况下，迭代次数可能会上亿次。而Map-Reduce在每次迭代的时候都会把数据往文件里面读写一遍，这样的浪费的时间是巨大的。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 其实Map-Reduce不是绝对没有办法去解决这些问题，而只是现在这个还不是最重要的日程，Hadoop还有很多很多的东西可以优化，比如说前面提到的HA，这些东西只有往后放放，我将在之后的Hadoop的未来部分，谈谈未来版的Hadoop怎么去解决这些问题。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; 编程复杂，学习曲线陡峭：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 对于一般的map-reduce框架，hello world程序就变成了word count，就是给出一堆的文本文件，最终统计出里面每一个不同的单词出现的次数，这样一个简单的任务（可能在linux shell下一行就写出来了），在Map-reduce中需要几十行，一般新人从理解word count到写出自己的word count，到跑通，一个星期是肯定需要的。这样陡峭的学习曲线让许多人难以深入。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 另外还有一点Hadoop被人所诟病的是，代码丑陋，虽然Hadoop是用高级语言Java写成的，但是里面对每一个步骤都要分成mapper和reducer，这个被戏称为新时代的汇编语言。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 一般来说，做数据分析的人程序都写得不咋地（强哥这样的达人除外），能写写matlab，R，或者spss就差不多了，如果要让他们去写map-reduce，那就等于叫他们别干活了。而大数据的重要的作用就是用来做数据分析，Hadoop的未来发展必须得抓住这群数据分析师的心。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 其实现在已经有一些实验中的产品，让用户可以用高级语言编程，不会再看到丑丑的map-reduce了。我在前公司的时候就与团队一起做了还不错的尝试，至少，数据分析师可以用Python来编程了。map-reduce变成了一个底层的东西，现在不是某些人在分析性能的时候就贴上汇编代码吗，之后可能会变成在前段的程序效率不行的时候，就贴上后端Java的map-reduce程序。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 所以对这个难题之后肯定会解决掉，底层分布式程序开发与用户将被清楚的分开，之后想要写word-count一定会像hello world一样简单。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="5"&gt;Hadoop的未来怎么样？&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.slideshare.net/hortonworks/apache-hadoop-023"&gt;http://www.slideshare.net/hortonworks/apache-hadoop-023&lt;/a&gt; (hadoop 0.23)&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 给出这样的一个官方文档，谈谈之后的hadoop的发展。目前的hadoop的稳定版是0.20.x，这个0.23是个未来版，估计将在今年的Q4进行beta的发布（目前看起来，至少代码是写了很多了） 。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; HDFS Federation&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp; 首先是一个叫做HDFS Federation的东西，它将hdfs的命名空间进行了扩展，目前的HDFS的所有文件的meta信息都保存在一台机器的内存中，使得HDFS支持的文件数目是有限的，现在进行了这样改动后，将hdfs的命名空间做成了分布式的，对之后方便对不同的用户文件夹进行管理，还有从HDFS的实现上来说，都会更为简单。&lt;/p&gt;  &lt;p&gt;&amp;nbsp; &lt;a href="http://www.hortonworks.com/wp-content/uploads/2011/08/HDFS_Federation_PNG2.png"&gt;&lt;img title="HDFS_Federation_PNG2" height="236" alt="" src="http://www.hortonworks.com/wp-content/uploads/2011/08/HDFS_Federation_PNG2.png" width="392" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp; 下一代的Map-Reduce：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 节点数：从目前的4000增加到6000-10000台&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 并发的任务数:从目前的40000增加到100000&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 更高级的硬件支持，目前支持的硬件主要是8core, 16G ram, 4T disk, 之后将会支持16+core, 48/96G ram, 24/48T disk&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 架构的改变，对现在的JobTracker-TaskTracker的结构做了很大的改进，现在会用ZooKeeper去保存master的状态，避免了之前提到的SPOF&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 更多的编程模式的支持（这个很重要）&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 比如MPI，迭代程序的处理，并且在Hadoop中运行这些类型的编程模式，并且这些程序将会被Hadoop统一管理&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="5"&gt;&lt;strong&gt;总结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 之前谈了Hadoop的优势、劣势等等，综合来说就是，优势是很明显的（比如这么多牛公司在用，并且也贡献了很多的代码），远远超出了其他的分布式系统，劣势虽然不小，但是改进这些不足的地方是在计划中，已经在实施了。而且Hadoop不仅在学术界或者是工业界，都有很高的地位，综合了这些天时地利人和，那前途还是非常光明的&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/2155368.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/08/27/why-map-reduce-must-be-future-of-distributed-computing.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/05/29/2062293.html</id><title type="text">PyMining-开源中文文本数据挖掘平台 Ver 0.2发布</title><summary type="text">项目首页： http://code.google.com/p/python-data-mining-platform/ （可能需翻墙） 目前比如tutorial, install, release等内容，已经更新到项目首页的wiki中 项目介绍： 这是一个能够根据源数据（比如说用csv格式表示的矩阵，或者中文文档）使用多种多样的算法去得到结果的一个平台。 算法能够通过xml配置文件去一个一个的运行，比如在开始的时候，我们可以先运行一下主成分分析算法去做特种选择，然后我们再运行随机森林算法来做分类。 目前算法主要是针对那些单机能够完成的任务，该架构良好的扩展性能够让你在很短的时间内完成自己想要的</summary><published>2011-05-29T12:24:00Z</published><updated>2011-05-29T12:24:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/29/2062293.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/29/2062293.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;项目首页：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/python-data-mining-platform/"&gt;http://code.google.com/p/python-data-mining-platform/&lt;/a&gt; （可能需翻墙）&lt;/p&gt;  &lt;p&gt;目前比如tutorial, install, release等内容，已经更新到项目首页的wiki中&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;项目介绍：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;这是一个能够根据源数据（比如说用csv格式表示的矩阵，或者中文文档）使用多种多样的算法去得到结果的一个平台。&lt;/p&gt;  &lt;p&gt;算法能够通过xml配置文件去一个一个的运行，比如在开始的时候，我们可以先运行一下主成分分析算法去做特种选择，然后我们再运行随机森林算法来做分类。&lt;/p&gt;  &lt;p&gt;目前算法主要是针对那些单机能够完成的任务，该架构良好的扩展性能够让你在很短的时间内完成自己想要的算法，并且用于工程之中（相信我，肯定比Weka更快更好）。&lt;strong&gt;该项目的另一个特色是能够很好的支持中文文本的分类、聚类&lt;/strong&gt;等操作。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;下图是使用PyMining主成分分析（PCA）算法将一个数千维的数据投影到2维平面的结果&lt;/strong&gt;，也是PyMining中的一个例子，位于example/pca_matplot_example.py。原始数据为文本，每种颜色代表不同分类的文本，可以看出，虽然维度变成了2维，但是不同分类的文本投影后的结果还是有一定的区分度的。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105292104521220.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105292104532267.png" width="436" height="343" /&gt;&lt;/a&gt;&lt;strong&gt;&lt;font color="#ff0000" size="4"&gt;重要：&lt;/font&gt;&lt;/strong&gt;目前项目已经集成了Scipy与Matplotlib，目前PCA调用了Scipy，上面的例子调用了Matplotlib。在Ubuntu下，Scipy的安装可以参考我的另一篇文章：&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/29/2062324.html"&gt;Scipy在Ubuntu上的安装&lt;/a&gt;，Matplotlib的可以使用sudo apt-get install python-matplotlib。&lt;strong&gt;对于其他平台，只有自己去搜索配置一下&lt;/strong&gt;，可以见项目主页中wiki下面的installing页面。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;ChangeLog：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 重大改变：&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;更新项目的组织方式，让package的组织、example的组织等等更合理一点&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 新增Feature：&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;加入了K-Means算法，能够对文本进行聚类&lt;/li&gt;    &lt;li&gt;加入了基于补集的朴素贝叶斯算法，大大提升了分类的准确率，目前该算法在搜狗实验室文本分类数据中，对20000篇、8分类左右的数据的预测准确率在90%左右&lt;/li&gt;    &lt;li&gt;加入了Sogou实验室文本分类数据的导入器，可以进行更多的实验&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Fix Bugs：&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;修正了chi-square在example调用中的一个错误&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;获取PyMining：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 于&lt;a href="http://code.google.com/p/python-data-mining-platform/downloads/detail?name=py_mining_0_2_D.zip&amp;amp;can=2&amp;amp;q=#makechanges"&gt;此处&lt;/a&gt;，可获取目前最新的0.2版&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/2062293.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/29/2062293.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/05/15/pymining-second-edition.html</id><title type="text">PyMining-开源中文文本数据挖掘平台 Ver 0.1发布</title><summary type="text">目前算法主要是针对那些单机能够完成的任务，该架构良好的扩展性能够让你在很短的时间内完成自己想要的算法，并且用于工程之中（相信我，肯定比Weka更快更好）。该项目的另一个特色是能够很好的支持中文文本的分类、聚类等操作。 *当前版新增加入了K-Means算法，能够对文本进行聚类 加入了基于补集的朴素贝叶斯算法，大大提升了分类的准确率，目前该算法在搜狗实验室文本分类数据中，对20000篇、8分类左右的数据的预测准确率在90%左右</summary><published>2011-05-15T14:21:00Z</published><updated>2011-05-15T14:21:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/15/pymining-second-edition.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/15/pymining-second-edition.html"/><content type="html">&lt;p&gt;&lt;font color="#008040" size="4"&gt;&lt;strong&gt;项目首页：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://code.google.com/p/python-data-mining-platform/"&gt;http://code.google.com/p/python-data-mining-platform/&lt;/a&gt; （可能需翻墙）&lt;/p&gt; &lt;p&gt;目前已经在该googlecode中加入了Tutorial等内容，可以在wiki中查看&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font color="#008040" size="4"&gt;&lt;strong&gt;项目介绍（复制自项目首页的说明）：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;这是一个能够根据源数据（比如说用csv格式表示的矩阵，或者中文文档）使用多种多样的算法去得到结果的一个平台。  &lt;/p&gt;&lt;p&gt;算法能够通过xml配置文件去一个一个的运行，比如在开始的时候，我们可以先运行一下主成分分析算法去做特种选择，然后我们再运行随机森林算法来做分类。  &lt;/p&gt;&lt;p&gt;目前算法主要是针对那些单机能够完成的任务，该架构良好的扩展性能够让你在很短的时间内完成自己想要的算法，并且用于工程之中（相信我，肯定比Weka更快更好）。&lt;strong&gt;该项目的另一个特色是能够很好的支持中文文本的分类、聚类&lt;/strong&gt;等操作。  &lt;/p&gt;&lt;p&gt;只需要写下下面的程序，就能够得到神奇的结果（对文本进行特征选择、得到naive bayes分类模型，并且预测）： &lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;#load config&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; config = Configuration.FromFile(&lt;span style="color: #006080"&gt;"conf/test.xml"&lt;/span&gt;)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; PyMining.Init(config, &lt;span style="color: #006080"&gt;"__global__"&lt;/span&gt;)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;#get matrix from source text&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; matCreater = ClassifierMatrix(config, &lt;span style="color: #006080"&gt;"__matrix__"&lt;/span&gt;)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; [trainx, trainy] = matCreater.CreateTrainMatrix(&lt;span style="color: #006080"&gt;"data/train.txt"&lt;/span&gt;)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; &lt;span style="color: #008000"&gt;#get chi square filter&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; chiFilter = ChiSquareFilter(config, &lt;span style="color: #006080"&gt;"__filter__"&lt;/span&gt;)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; chiFilter.TrainFilter(trainx, trainy)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; &lt;span style="color: #008000"&gt;#runs naive-bayes model to get model&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; nbModel = TwcNaiveBayes(config, &lt;span style="color: #006080"&gt;"twc_naive_bayes"&lt;/span&gt;)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; nbModel.Train(trainx, trainy)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt; &lt;span style="color: #008000"&gt;#using the model to predict an unseen doc to target class&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt; [testx, testy] = matCreater.CreatePredictMatrix(&lt;span style="color: #006080"&gt;"data/test.txt"&lt;/span&gt;)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt; [testx, testy] = chiFilter.MatrixFilter(testx, testy)&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt; retY = nbModel.TestMatrix(testx, testy)&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&amp;nbsp;&lt;p&gt;&lt;font color="#008040" size="4"&gt;&lt;strong&gt;目前的版本：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Ver 0.1（第二个开发版）&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#008040" size="4"&gt;Features：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff" size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上一版的Feature：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;能够支持中文文本输入，并且对其进行分词等操作，作为分类的源数据 &lt;/li&gt;&lt;li&gt;带有卡方检测(chi square test)的特征词选择器(feature selector) &lt;/li&gt;&lt;li&gt;参数的调整(parameter tuning)支持通过xml配置文件进行 &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff" size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 新增Feature：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;font color="#ff0000"&gt;加入了K-Means算法，能够对文本进行聚类 &lt;/font&gt;&lt;/li&gt;&lt;li&gt;&lt;font color="#ff0000"&gt;加入了基于补集的朴素贝叶斯算法，大大提升了分类的准确率，目前该算法在搜狗实验室文本分类数据中，对20000篇、8分类左右的数据的预测准确率在90%左右 &lt;/font&gt;&lt;/li&gt;&lt;li&gt;加入了Sogou实验室文本分类数据的导入器，可以进行更多的实验&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;font color="#008040" size="4"&gt;&lt;strong&gt;获取PyMining：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 于&lt;a href="http://code.google.com/p/python-data-mining-platform/downloads/detail?name=pymining_0_1.zip&amp;amp;can=2&amp;amp;q=#makechanges"&gt;http://code.google.com/p/python-data-mining-platform/downloads/detail?name=pymining_0_1.zip&amp;amp;can=2&amp;amp;q=#makechanges&lt;/a&gt;，可获取目前最新的ver 0.1版（可能需要翻墙）&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不用翻墙的版本：&lt;a title="http://files.cnblogs.com/LeftNotEasy/pymining_0_1.zip" href="http://files.cnblogs.com/LeftNotEasy/pymining_0_1.zip"&gt;http://files.cnblogs.com/LeftNotEasy/pymining_0_1.zip&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/2047135.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/15/pymining-second-edition.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html</id><title type="text">机器学习中的算法(2)-支持向量机(SVM)基础</title><summary type="text">版权声明： 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用，但请注明出处，如果有问题，请联系wheeleast@gmail.com 前言： 又有很长的一段时间没有更新博客了，距离上次更新已经有两个月的时间了。其中一个很大的原因是，不知道写什么好-_-，最近一段时间看了看关于SVM(Support Vector Machine)的文章，觉得SVM是一个非常有趣，而且自成一派的方向，所以今天准备写一篇关于关于SVM的文章。 关于SVM的论文、书籍都非常的多，引用强哥的话“SVM是让应用数学家真正得到应用的一种算法”</summary><published>2011-05-02T12:56:00Z</published><updated>2011-05-02T12:56:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font color="#008000" size="4"&gt;版权声明：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 本文由LeftNotEasy发布于&lt;/font&gt;&lt;a href="http://leftnoteasy.cnblogs.com/"&gt;&lt;font size="4"&gt;http://leftnoteasy.cnblogs.com&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;, 本文可以被全部的转载或者部分使用，但请注明出处，如果有问题，请联系&lt;/font&gt;&lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#119;&amp;#104;&amp;#101;&amp;#101;&amp;#108;&amp;#101;&amp;#97;&amp;#115;&amp;#116;&amp;#64;&amp;#103;&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#46;&amp;#99;&amp;#111;&amp;#109;"&gt;&lt;font size="4"&gt;wheeleast@gmail.com&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#008000" size="4"&gt;前言：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 又有很长的一段时间没有更新博客了，距离上次更新已经有两个月的时间了。其中一个很大的原因是，不知道写什么好-_-，最近一段时间看了看关于SVM(Support Vector Machine)的文章，觉得SVM是一个非常有趣，而且自成一派的方向，所以今天准备写一篇关于关于SVM的文章。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 关于SVM的论文、书籍都非常的多，引用强哥的话&amp;#8220;SVM是让应用数学家真正得到应用的一种算法&amp;#8221;。SVM对于大部分的普通人来说，要完全理解其中的数学是非常困难的，所以要让这些普通人理解，得要把里面的数学知识用简单的语言去讲解才行。而且想明白了这些数学，对学习其他的内容也是大有裨益的。我就是属于绝大多数的普通人，为了看明白SVM，看了不少的资料，这里把我的心得分享分享。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实现在能够找到的，关于SVM的中文资料已经不少了，不过个人觉得，每个人的理解都不太一样，所以还是决定写一写，一些雷同的地方肯定是不可避免的，不过还是希望能够写出一点与别人不一样的地方吧。另外本文准备不谈太多的数学（因为很多文章都谈过了），尽量简单地给出结论，就像题目一样-机器学习中的&lt;strong&gt;算法&lt;/strong&gt;（之前叫做机器学习中的数学），&lt;strong&gt;所以本系列的内容将更偏重应用一些。如果想看更详细的数学解释，可以看看参考文献中的资料。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#008000" size="4"&gt;一、线性分类器：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;首先给出一个非常非常简单的分类问题（线性可分）&lt;/strong&gt;，我们要用一条直线，将下图中黑色的点和白色的点分开，很显然，图上的这条直线就是我们要求的直线之一（可以有无数条这样的直线）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055565831.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055571894.png" width="240" height="230" /&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假如说，我们令黑色的点 = -1， 白色的点 =&amp;nbsp; +1，直线f(x) = w.x + b，这儿的x、w是向量，其实写成这种形式也是等价的f(x) = w1x1 + w2x2 &amp;#8230; + wnxn + b, 当向量x的维度=2的时候，f(x) 表示二维空间中的一条直线， 当x的维度=3的时候，f(x) 表示3维空间中的一个平面，当x的维度=n &amp;gt; 3的时候，表示n维空间中的n-1维超平面。这些都是比较基础的内容，如果不太清楚，可能需要复习一下微积分、线性代数的内容。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 刚刚说了，我们令黑色白色两类的点分别为+1, -1，所以当有一个新的点x需要预测属于哪个分类的时候，我们用sgn(f(x))，就可以预测了，sgn表示符号函数，当f(x) &amp;gt; 0的时候，sgn(f(x)) = +1, 当f(x) &amp;lt; 0的时候sgn(f(x)) = &amp;#8211;1。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但是，我们怎样才能取得一个最优的划分直线f(x)呢？下图的直线表示几条可能的f(x)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055574369.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055574336.png" width="240" height="225" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一个很直观的感受是，让这条直线到给定样本中最近的点最远，这句话读起来比较拗口，下面给出几个图，来说明一下：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第一种分法：&lt;/font&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055573224.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055589287.png" width="240" height="231" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第二种分法：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055585350.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055589777.png" width="240" height="233" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这两种分法哪种更好呢？从直观上来说，就是分割的间隙越大越好，把两个类别的点分得越开越好。就像我们平时判断一个人是男还是女，就是很难出现分错的情况，这就是男、女两个类别之间的间隙非常的大导致的，让我们可以更准确的进行分类。&lt;strong&gt;在SVM中，称为Maximum Marginal，是SVM的一个理论基础之一。&lt;/strong&gt;选择使得间隙最大的函数作为分割平面是由很多道理的，比如说从概率的角度上来说，就是使得置信度最小的点置信度最大（听起来很拗口），从实践的角度来说，这样的效果非常好，等等。这里就不展开讲，作为一个结论就ok了，:)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上图被红色和蓝色的线圈出来的点就是所谓的支持向量(support vector)。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055584204.png"&gt;&lt;font color="#000000" size="4"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055599155.png" width="445" height="154" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上图就是一个对之前说的类别中的间隙的一个描述。Classifier Boundary就是f(x)，红色和蓝色的线（plus plane与minus plane）就是support vector所在的面，红色、蓝色线之间的间隙就是我们要最大化的分类间的间隙。&lt;/font&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022055592153.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056007660.png" width="373" height="154" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里直接给出M的式子：（从高中的解析几何就可以很容易的得到了，也可以参考后面Moore的ppt）&lt;/font&gt;&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056009056.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056005675.png" width="115" height="59" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另外支持向量位于wx + b = 1与wx + b = -1的直线上，我们在前面乘上一个该点所属的类别y（还记得吗?y不是+1就是-1），就可以得到支持向量的表达式为：y(wx + b) = 1，这样就可以更简单的将支持向量表示出来了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当支持向量确定下来的时候，分割函数就确定下来了，两个问题是等价的。得到支持向量，还有一个作用是，让支持向量后方那些点就不用参与计算了。这点在后面将会更详细的讲讲。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在这个小节的最后，给出我们要优化求解的表达式：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056002611.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056009546.png" width="240" height="60" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||w||的意思是w的二范数，跟上面的M表达式的分母是一个意思，之前得到，M = 2 / ||w||，最大化这个式子等价于最小化||w||, 另外由于||w||是一个单调函数，我们可以对其加入平方，和前面的系数，熟悉的同学应该很容易就看出来了，这个式子是为了方便求导。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个式子有还有一些限制条件，完整的写下来，应该是这样的：（&lt;strong&gt;&lt;font color="#0000ff"&gt;原问题&lt;/font&gt;&lt;/strong&gt;）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056018433.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/20110502205601593.png" width="352" height="47" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; s.t的意思是subject to，也就是在后面这个限制条件下的意思，这个词在svm的论文里面非常容易见到。这个其实是一个带约束的二次规划(quadratic programming, QP)问题，是一个凸问题，凸问题就是指的不会有局部最优解，可以想象一个漏斗，不管我们开始的时候将一个小球放在漏斗的什么位置，这个小球最终一定可以掉出漏斗，也就是得到全局最优解。s.t.后面的限制条件可以看做是一个凸多面体，我们要做的就是在这个凸多面体中找到最优解。这些问题这里不展开，因为展开的话，一本书也写不完。如果有疑问请看看wikipedia。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#008000" size="4"&gt;二、转化为对偶问题，并优化求解:&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个优化问题可以用&lt;a href="http://en.wikipedia.org/wiki/Lagrange_multiplier"&gt;拉格朗日乘子法&lt;/a&gt;去解，使用了&lt;a href="http://en.wikipedia.org/wiki/Karush%E2%80%93Kuhn%E2%80%93Tucker_conditions"&gt;KKT条件&lt;/a&gt;的理论，这里直接作出这个式子的拉格朗日目标函数：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056015020.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056017495.png" width="374" height="50" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 求解这个式子的过程需要&lt;/font&gt;&lt;a href="http://en.wikipedia.org/wiki/Quadratic_programming#Lagrangian_duality"&gt;&lt;font size="4"&gt;拉格朗日对偶性&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;的相关知识（另外pluskid也有&lt;a href="http://blog.pluskid.org/?p=702"&gt;一篇文章&lt;/a&gt;专门讲这个问题），并且有一定的公式推导，如果不感兴趣，&lt;strong&gt;可以直接跳到后面&lt;/strong&gt;用&lt;font color="#0000ff"&gt;&lt;strong&gt;蓝色公式&lt;/strong&gt;&lt;/font&gt;表示的结论，该部分推导主要参考自&lt;/font&gt;&lt;a href="http://blog.pluskid.org/?p=682"&gt;&lt;font size="4"&gt;plukids的文章&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先让L关于w，b最小化，分别令L关于w，b的偏导数为0，得到关于&lt;strong&gt;原问题&lt;/strong&gt;的一个表达式&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056032314.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056034789.png" width="187" height="107" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 将两式带回L(w,b,a)得到对偶问题的表达式&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056037264.png" width="381" height="62" /&gt; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 新问题加上其限制条件是（&lt;font color="#0000ff"&gt;&lt;strong&gt;对偶问题&lt;/strong&gt;&lt;/font&gt;）:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056041691.png"&gt;&lt;font color="#000000" size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056046118.png" width="295" height="151" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个就是我们需要最终优化的式子。至此，&lt;strong&gt;得到了线性可分问题的优化式子&lt;/strong&gt;。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 求解这个式子，有很多的方法，比如&lt;a href="http://en.wikipedia.org/wiki/Sequential_minimal_optimization"&gt;SMO&lt;/a&gt;等等，个人认为，求解这样的一个带约束的凸优化问题与得到这个凸优化问题是比较独立的两件事情，所以在这篇文章中准备完全不涉及如何求解这个话题，如果之后有时间可以补上一篇文章来谈谈:)。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#008000" size="4"&gt;三、线性不可分的情况（软间隔）：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来谈谈线性不可分的情况，因为&lt;strong&gt;线性可分这种假设实在是太有局限性&lt;/strong&gt;了：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下图就是一个典型的线性不可分的分类图，我们没有办法用一条直线去将其分成两个区域，每个区域只包含一种颜色的点。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056043054.png"&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056045213.png" width="240" height="236" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 要想在这种情况下的分类器，有两种方式，&lt;strong&gt;一种是用曲线&lt;/strong&gt;去将其完全分开，曲线就是一种&lt;strong&gt;非线性&lt;/strong&gt;的情况，跟之后将谈到的&lt;strong&gt;核函数&lt;/strong&gt;有一定的关系：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056057688.png"&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056056576.png" width="240" height="226" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;另外一种还是用直线，不过不用去保证可分性&lt;/strong&gt;，就是包容那些分错的情况，不过我们得加入惩罚函数，使得点分错的情况越合理越好。其实在很多时候，不是在训练的时候分类函数越完美越好，因为训练函数中有些数据本来就是噪声，可能就是在人工加上分类标签的时候加错了，如果我们在训练（学习）的时候把这些错误的点学习到了，那么模型在下次碰到这些错误情况的时候就难免出错了（假如老师给你讲课的时候，某个知识点讲错了，你还信以为真了，那么在考试的时候就难免出错）。这种学习的时候学到了&amp;#8220;噪声&amp;#8221;的过程就是一个过拟合（over-fitting），这在机器学习中是一个大忌，我们宁愿少学一些内容，也坚决杜绝多学一些错误的知识。还是回到主题，用直线怎么去分割线性不可分的点：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们可以为分错的点加上一点惩罚，对一个分错的点的&lt;strong&gt;惩罚函数&lt;/strong&gt;就是&lt;strong&gt;这个点到其正确位置的距离：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056057099.png"&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056051526.png" width="240" height="214" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在上图中，&lt;font color="#0000ff"&gt;蓝色&lt;/font&gt;、&lt;font color="#ff0000"&gt;红色&lt;/font&gt;的直线分别为支持向量所在的边界，&lt;font color="#008000"&gt;绿色&lt;/font&gt;的线为决策函数，那些&lt;font color="#800080"&gt;紫色&lt;/font&gt;的线&lt;strong&gt;表示分错的点到其相应的决策面的距离&lt;/strong&gt;，这样我们可以在原函数上面加上一个惩罚函数，并且带上其限制条件为：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056054001.png" width="406" height="47" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 公式中蓝色的部分为在线性可分问题的基础上加上的惩罚函数部分，当xi在正确一边的时候，&amp;#949;=0，R为全部的点的数目，C是一个由用户去指定的系数，表示对分错的点加入多少的惩罚，当C很大的时候，分错的点就会更少，但是过拟合的情况可能会比较严重，当C很小的时候，分错的点可能会很多，不过可能由此得到的模型也会不太正确，所以如何选择C是有很多学问的，不过在大部分情况下就是通过经验尝试得到的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来就是同样的，求解一个拉格朗日对偶问题，得到一个原问题的对偶问题的表达式：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056067556.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/20110502205606347.png" width="265" height="139" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 蓝色的部分是与线性可分的对偶问题表达式的不同之处。在线性不可分情况下得到的对偶问题，不同的地方就是&amp;#945;的范围从[0, +&amp;#8734;)，变为了[0, C]，增加的惩罚&amp;#949;没有为对偶问题增加什么复杂度。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#008000" size="4"&gt;四、核函数：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 刚刚在谈不可分的情况下，提了一句，如果使用某些非线性的方法，可以得到将两个分类完美划分的曲线，比如接下来将要说的核函数。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/strong&gt;我们可以&lt;strong&gt;让空间从原本的线性空间变成一个更高维的空间&lt;/strong&gt;，&lt;strong&gt;在这个高维的线性空间下，再用一个超平面进行划分&lt;/strong&gt;。这儿举个例子，来理解一下如何利用空间的维度变得更高来帮助我们分类的（例子以及图片来自&lt;/font&gt;&lt;a href="http://blog.pluskid.org/?p=685"&gt;&lt;font size="4"&gt;pluskid的kernel函数部分&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;）：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下图是一个典型的线性不可分的情况&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056068362.png"&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056079965.png" width="240" height="188" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但是当我们把这两个类似于椭圆形的点映射到一个高维空间后，映射函数为：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056071361.png"&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056078296.png" width="240" height="37" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 用这个函数可以将上图的平面中的点映射到一个三维空间（z1,z2,z3)，并且对映射后的坐标加以旋转之后就可以得到一个线性可分的点集了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056107476.gif"&gt;&lt;font size="4"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="rotate" alt="rotate" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056122751.gif" width="240" height="192" /&gt;&lt;/font&gt;&lt;/a&gt;    &lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 用另外一个哲学例子来说：世界上本来没有两个完全一样的物体，对于所有的两个物体，我们可以通过增加维度来让他们最终有所区别，比如说两本书，从(颜色，内容)两个维度来说，可能是一样的，我们可以加上 &lt;strong&gt;作者&lt;/strong&gt; 这个维度，是在不行我们还可以加入 &lt;strong&gt;页码&lt;/strong&gt;，可以加入 &lt;strong&gt;拥有者&lt;/strong&gt;，可以加入 &lt;strong&gt;购买地点&lt;/strong&gt;，可以加入 &lt;strong&gt;笔记内容&lt;/strong&gt;等等。&lt;strong&gt;当维度增加到无限维的时候，一定可以让任意的两个物体可分了&lt;/strong&gt;。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 回忆刚刚得到的对偶问题表达式：&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056126306.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056134322.png" width="255" height="137" /&gt;&lt;/a&gt; &lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们可以将红色这个部分进行改造，令：&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056135717.png"&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056132652.png" width="178" height="36" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个式子所做的事情就是将线性的空间映射到高维的空间,k(x, xj)有很多种，下面是比较典型的两种：&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056135128.png"&gt;&lt;font size="4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201105/201105022056149239.png" width="240" height="90" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面这个核称为多项式核，下面这个核称为高斯核，高斯核甚至是将原始空间映射为无穷维空间，另外核函数有一些比较好的性质，比如说不会比线性条件下增加多少额外的计算量，等等，这里也不再深入。一般对于一个问题，不同的核函数可能会带来不同的结果，一般是需要尝试来得到的。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#008000" size="4"&gt;&lt;strong&gt;五、一些其他的问题：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1）如何进行多分类问题：&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面所谈到的分类都是2分类的情况，当N分类的情况下，主要有两种方式，一种是1 vs (N &amp;#8211; 1)一种是1 vs 1，前一种方法我们需要训练N个分类器，第i个分类器是看看是属于分类i还是属于分类i的补集（出去i的N-1个分类）。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 后一种方式我们需要训练N * (N &amp;#8211; 1) / 2个分类器，分类器(i,j)能够判断某个点是属于i还是属于j。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这种处理方式不仅在SVM中会用到，在很多其他的分类中也是被广泛用到，从林教授（libsvm的作者）的结论来看，1 vs 1的方式要优于1 vs (N &amp;#8211; 1)。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2）SVM会overfitting吗？&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SVM避免overfitting，一种是调整之前说的惩罚函数中的C，另一种其实从式子上来看，min ||w||^2这个看起来是不是很眼熟？在最小二乘法回归的时候，我们看到过这个式子，这个式子可以让函数更平滑，所以SVM是一种不太容易over-fitting的方法。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#008000" size="4"&gt;&lt;strong&gt;参考文档：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 主要的参考文档来自4个地方，wikipedia（在文章中已经给出了超链接了），&lt;a href="http://blog.pluskid.org/?page_id=683"&gt;pluskid关于SVM的博文&lt;/a&gt;，&lt;a href="http://www.autonlab.org/tutorials/svm15.pdf"&gt;Andrew moore的ppt&lt;/a&gt;（文章中不少图片都是引用或者改自Andrew Moore的ppt，以及prml&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/2034566.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/03/07/random-forest-and-gbdt.html</id><title type="text">机器学习中的算法(1)-决策树模型组合之随机森林与GBDT</title><summary type="text">在最近几年的paper上，如iccv这种重量级的会议，iccv 09年的里面有不少的文章都是与Boosting与随机森林相关的。模型组合+决策树相关的算法有两种比较基本的形式 - 随机森林与GBDT((Gradient Boost Decision Tree)，其他的比较新的模型组合+决策树的算法都是来自这两种算法的延伸。本文主要侧重于GBDT，对于随机森林只是大概提提，因为它相对比较简单。在看本文之前，建议先看看机器学习与数学(3)与其中引用的论文，本文中的GBDT主要基于此，而随机森林相对比较独立。</summary><published>2011-03-07T15:53:00Z</published><updated>2011-03-07T15:53:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/03/07/random-forest-and-gbdt.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/03/07/random-forest-and-gbdt.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font size="5"&gt;版权声明：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 本文由LeftNotEasy发布于&lt;/font&gt;&lt;a href="http://leftnoteasy.cnblogs.com/"&gt;&lt;font size="4"&gt;http://leftnoteasy.cnblogs.com&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;, 本文可以被全部的转载或者部分使用，但请注明出处，如果有问题，请联系&lt;/font&gt;&lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#119;&amp;#104;&amp;#101;&amp;#101;&amp;#108;&amp;#101;&amp;#97;&amp;#115;&amp;#116;&amp;#64;&amp;#103;&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#46;&amp;#99;&amp;#111;&amp;#109;"&gt;&lt;font size="4"&gt;wheeleast@gmail.com&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;前言：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 决策树这种算法有着很多良好的特性，比如说训练时间复杂度较低，预测的过程比较快速，模型容易展示（容易将得到的决策树做成图片展示出来）等。但是同时，单决策树又有一些不好的地方，比如说容易over-fitting，虽然有一些方法，如剪枝可以减少这种情况，但是还是不够的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 模型组合（比如说有Boosting，Bagging等）与决策树相关的算法比较多，这些算法最终的结果是生成N(可能会有几百棵以上）棵树，这样可以大大的减少单决策树带来的毛病，有点类似于三个臭皮匠等于一个诸葛亮的做法，虽然这几百棵决策树中的每一棵都很简单（相对于C4.5这种单决策树来说），但是他们组合起来确是很强大。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在最近几年的paper上，如iccv这种重量级的会议，&lt;/font&gt;&lt;a href="http://www.cvpapers.com/iccv2009.html"&gt;&lt;font size="4"&gt;iccv 09&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;年的里面有不少的文章都是与Boosting与随机森林相关的。模型组合+决策树相关的算法有两种比较基本的形式 - 随机森林与GBDT((Gradient Boost Decision Tree)，其他的比较新的模型组合+决策树的算法都是来自这两种算法的延伸。本文主要侧重于GBDT，对于随机森林只是大概提提，因为它相对比较简单。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在看本文之前，建议先看看&lt;/font&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/02/machine-learning-boosting-and-gradient-boosting.html"&gt;&lt;font size="4"&gt;机器学习与数学(3)&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;与其中引用的论文，本文中的GBDT主要基于此，而随机森林相对比较独立。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;基础内容：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里只是准备简单谈谈基础的内容，主要参考一下别人的文章，对于随机森林与GBDT，有两个地方比较重要，首先是information gain，其次是决策树。这里特别推荐Andrew Moore大牛的&lt;a href="http://www.autonlab.org/tutorials/dtree.html"&gt;Decision Trees Tutorial&lt;/a&gt;，与&lt;a href="http://www.autonlab.org/tutorials/infogain.html"&gt;Information Gain Tutorial&lt;/a&gt;。Moore的&lt;a href="http://www.autonlab.org/tutorials/"&gt;Data Mining Tutorial系列&lt;/a&gt;非常赞，看懂了上面说的两个内容之后的文章才能继续读下去。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 决策树实际上是将空间用超平面进行划分的一种方法，每次分割的时候，都将&lt;strong&gt;当前的&lt;/strong&gt;空间一分为二，比如说下面的决策树：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353099568.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="169" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353099220.png" width="240" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 就是将空间划分成下面的样子：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353092567.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="221" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353097550.png" width="240" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这样使得&lt;strong&gt;每一个叶子节点都是在空间中的一个不相交的区域&lt;/strong&gt;，在进行决策的时候，会根据输入样本每一维feature的值，一步一步往下，最后使得样本落入N个区域中的一个（假设有N个叶子节点）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;随机森林(Random Forest):&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 随机森林是一个最近比较火的算法，它有很多的优点：&lt;/font&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在数据集上表现良好&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在当前的很多数据集上，相对其他算法有着很大的优势&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 它能够处理很高维度（feature很多）的数据，并且不用做特征选择&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在训练完后，它能够给出哪些feature比较重要&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在创建随机森林的时候，对generlization error使用的是无偏估计&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 训练速度快&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在训练过程中，能够检测到feature间的互相影响&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 容易做成并行化方法&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 实现比较简单&lt;/font&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 随机森林顾名思义，是用随机的方式建立一个森林，森林里面有很多的决策树组成，随机森林的每一棵决策树之间是没有关联的。在得到森林之后，当有一个新的输入样本进入的时候，就让森林中的每一棵决策树分别进行一下判断，看看这个样本应该属于哪一类（对于分类算法），然后看看哪一类被选择最多，就预测这个样本为那一类。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在建立每一棵决策树的过程中，有两点需要注意 - 采样与完全分裂。首先是两个随机采样的过程，random forest对输入的数据要进行行、列的采样。对于行采样，采用有放回的方式，也就是在采样得到的样本集合中，可能有重复的样本。假设输入样本为N个，那么采样的样本也为N个。这样使得在训练的时候，每一棵树的输入样本都不是全部的样本，使得相对不容易出现over-fitting。然后进行列采样，从M个feature中，选择m个(m &amp;lt;&amp;lt; M)。之后就是对采样之后的数据使用完全分裂的方式建立出决策树，这样决策树的某一个叶子节点要么是无法继续分裂的，要么里面的所有样本的都是指向的同一个分类。一般很多的决策树算法都一个重要的步骤 - 剪枝，但是这里不这样干，由于之前的两个随机采样的过程保证了随机性，所以就算不剪枝，也不会出现over-fitting。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 按这种算法得到的随机森林中的每一棵都是很弱的，但是大家组合起来就很厉害了。我觉得可以这样比喻随机森林算法：每一棵决策树就是一个精通于某一个窄领域的专家（因为我们从M个feature中选择m让每一棵决策树进行学习），这样在随机森林中就有了很多个精通不同领域的专家，对一个新的问题（新的输入数据），可以用不同的角度去看待它，最终由各个专家，投票得到结果。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 随机森林的过程请参考&lt;a href="https://cwiki.apache.org/MAHOUT/random-forests.html"&gt;Mahout的random forest&lt;/a&gt;&lt;/font&gt;&lt;font size="4"&gt; 。这个页面上写的比较清楚了，其中可能不明白的就是Information Gain，可以看看之前推荐过的Moore的页面。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;Gradient Boost Decision Tree:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; GBDT是一个应用很广泛的算法，可以用来做分类、回归。在很多的数据上都有不错的效果。&lt;/font&gt;&lt;font size="4"&gt;GBDT这个算法还有一些其他的名字，比如说MART(Multiple Additive Regression Tree)，GBRT(Gradient Boost Regression Tree)，Tree Net等，其实它们都是一个东西（参考自&lt;a href="http://en.wikipedia.org/wiki/Gradient_boosting"&gt;wikipedia &amp;#8211; Gradient Boosting&lt;/a&gt;)，发明者是Friedman&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; Gradient Boost其实是一个框架，里面可以套入很多不同的算法，可以参考一下机器学习与数学(3)中的讲解。Boost是"提升"的意思，一般Boosting算法都是一个迭代的过程，每一次新的训练都是为了改进上一次的结果。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; 原始的Boost算法是在算法开始的时候，为每一个样本赋上一个权重值，初始的时候，大家都是一样重要的。在每一步训练中得到的模型，会使得数据点的估计有对有错，我们就在每一步结束后，增加分错的点的权重，减少分对的点的权重，这样使得某些点如果老是被分错，那么就会被&amp;#8220;严重关注&amp;#8221;，也就被赋上一个很高的权重。然后等进行了N次迭代（由用户指定），将会得到N个简单的分类器（basic learner），然后我们将它们组合起来（比如说可以对它们进行加权、或者让它们进行投票等），得到一个最终的模型。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; 而Gradient Boost与传统的Boost的区别是，每一次的计算是为了减少上一次的残差(residual)，而为了消除残差，我们可以在&lt;strong&gt;残差减少的梯度(Gradient)方向&lt;/strong&gt;上建立一个新的模型。所以说，在Gradient Boost中，每个新的模型的简历是为了使得之前模型的残差往梯度方向减少，与传统Boost对正确、错误的样本进行加权有着很大的区别。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; 在分类问题中，有一个很重要的内容叫做Multi-Class Logistic，也就是多分类的Logistic问题，它适用于那些类别数&amp;gt;2的问题，并且在分类结果中，样本x不是一定只属于某一个类可以得到样本x分别属于多个类的概率（也可以说样本x的估计y符合某一个几何分布），这实际上是属于Generalized Linear Model中讨论的内容，这里就先不谈了，以后有机会再用一个专门的章节去做吧。这里就用一个结论：&lt;strong&gt;如果一个分类问题符合几何分布，那么就可以用Logistic变换来进行之后的运算&lt;/strong&gt;。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; 假设对于一个样本x，它可能属于K个分类，其估计值分别为F1(x)&amp;#8230;FK(x)，&lt;strong&gt;Logistic变换如下&lt;/strong&gt;，logistic变换是一个平滑且将数据规范化（使得向量的长度为1）的过程，结果为属于类别k的概率pk(x)，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353094170.png"&gt;&lt;font color="#000000" size="4"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="65" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353109154.png" width="337" border="0" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; 对于Logistic变换后的结果，损失函数为：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/20110307235310549.png"&gt;&lt;font color="#000000" size="4"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="62" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353101944.png" width="306" border="0" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其中，yk为输入的样本数据的估计值，当一个样本x属于类别k时，yk = 1，否则yk = 0。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 将Logistic变换的式子带入损失函数，并且对其求导，可以得到&lt;strong&gt;损失函数的梯度&lt;/strong&gt;：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353106928.png"&gt;&lt;font color="#000000" size="4"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="75" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353105499.png" width="597" border="0" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面说的比较抽象，下面举个例子：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设输入数据x可能属于5个分类（分别为1,2,3,4,5），训练数据中，x属于类别3，则y = (0, 0, 1, 0, 0)，假设模型估计得到的F(x) = (0, 0.3, 0.6, 0, 0)，则经过Logistic变换后的数据p(x) = (0.16,0.21,0.29,0.16,0.16)，y - p得到梯度g：(-0.16, -0.21, 0.71, -0.16, -0.16)。观察这里可以得到一个比较有意思的结论：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设gk为样本当某一维（某一个分类）上的梯度:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gk&amp;gt;0时，越大表示其在这一维上的概率p(x)越应该提高，比如说上面的第三维的概率为0.29，就应该提高，属于&lt;strong&gt;应该往&amp;#8220;正确的方向&amp;#8221;前进&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 越小表示这个估计越&amp;#8220;准确&amp;#8221;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gk&amp;lt;0时，越小，负得越多表示在这一维上的概率应该降低，比如说第二维0.21就应该得到降低。属于&lt;strong&gt;应该朝着&amp;#8220;错误的反方向&amp;#8221;前进&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 越大，负得越少表示这个估计越&amp;#8220;不错误 &amp;#8221;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 总的来说，&lt;strong&gt;对于一个样本，最理想的梯度是越接近0的梯度&lt;/strong&gt;。所以，我们要能够让函数的估计值能够使得梯度往反方向移动（&amp;gt;0的维度上，往负方向移动，&amp;lt;0的维度上，往正方向移动）最终使得梯度尽量=0），并且&lt;strong&gt;该算法在会严重关注那些梯度比较大的样本，跟Boost的意思类似&lt;/strong&gt;。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 得到梯度之后，就是如何让梯度减少了。这里是用的一个&lt;strong&gt;迭代+决策树&lt;/strong&gt;的方法，当初始化的时候，随便给出一个估计函数F(x)（可以让F(x)是一个随机的值，也可以让F(x)=0），然后之后每迭代一步就根据当前每一个样本的梯度的情况，建立一棵决策树。就让函数往梯度的反方向前进，最终使得迭代N步后，梯度越小。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里建立的决策树和普通的决策树不太一样，首先，这个决策树是一个叶子节点数J固定的，当生成了J个节点后，就不再生成新的节点了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 算法的流程如下:（参考自treeBoost论文）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353101878.png"&gt;&lt;font color="#000000" size="4"&gt;&lt;/font&gt;&lt;/a&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/201103072353119893.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="360" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201103/20110307235312285.png" width="630" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0. 表示给定一个初始值&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1. 表示建立M棵决策树（迭代M次）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2. 表示对函数估计值F(x)进行Logistic变换&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3. 表示对于K个分类进行下面的操作（其实这个for循环也可以理解为向量的操作，每一个样本点xi&lt;/font&gt;&lt;font size="4"&gt;都对应了K种可能的分类yi，所以yi, F(xi), p(xi)都是一个K维的向量，这样或许容易理解一点）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4. 表示求得残差减少的梯度方向&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5. 表示根据每一个样本点x，与其残差减少的梯度方向，得到一棵由J个叶子节点组成的决策树&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6. &lt;strong&gt;为当决策树建立完成后，通过这个公式，可以得到每一个叶子节点的增益（这个增益在预测的时候用的）&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 每个增益的组成其实也是一个K维的向量，表示如果在决策树预测的过程中，如果某一个样本点掉入了这个叶子节点，则其对应的K个分类的值是多少。比如说，GBDT得到了三棵决策树，一个样本点在预测的时候，也会掉入3个叶子节点上，其增益分别为（假设为3分类的问题）：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (0.5, 0.8, 0.1),&amp;nbsp; (0.2, 0.6, 0.3),&amp;nbsp; (0.4, 0.3, 0.3)，那么这样最终得到的分类为第二个，因为选择分类2的决策树是最多的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7. 的意思为，将当前得到的决策树与之前的那些决策树合并起来，作为新的一个模型(跟6中所举的例子差不多)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;GBDT的算法大概就讲到这里了，希望能够弥补一下上一篇文章中没有说清楚的部分：）&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;实现：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 看明白了算法，就需要去实现一下，或者看看别人实现的代码，这里推荐一下wikipedia中的gradient boosting页面，下面就有一些开源软件中的一些实现，比如说下面这个：&lt;/font&gt;&lt;a href="http://elf-project.sourceforge.net/"&gt;&lt;font size="4"&gt;http://elf-project.sourceforge.net/&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="5"&gt;&lt;strong&gt;参考资料：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 除了文章中的引用的内容（已经给出了链接）外，主要还是参考Friedman大牛的文章：Greedy function approximation : A Gradient Boosting Machine&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/1976562.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/03/07/random-forest-and-gbdt.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/02/27/py_mining_first_release.html</id><title type="text">支持中文文本的数据挖掘平台开源项目PyMining发布</title><summary type="text">项目目前主要关注中文文本的数据挖掘算法。由于每种数据挖掘算法的局限性都很大，就拿分类算法一样，决策树、朴素贝叶斯这两种算法都有着自己的特性，只能在某一种类型的类型的数据上应用比较良好，比如朴素贝叶斯，就对于那些短文本的分类比较适合，而决策树对于短文本、稀疏情况下就效果欠佳了，特别是在数据比较稀疏的情况。在这种情况下，当有一个数据挖掘任务的时候，怎样去找到一个合适的算法就非常重要了。如果从头开发算法，是一个成本很高的事情，特别是对文本来说就更麻烦，需要在前面做一些如分词、去停用词等等操作。如果有一个平台，可以支持快速的开发，让用户能够快速的看到，针对自己的数据，什么样的算法比较合适，就是本项目的一个初衷。</summary><published>2011-02-27T06:33:00Z</published><updated>2011-02-27T06:33:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/02/27/py_mining_first_release.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/02/27/py_mining_first_release.html"/><content type="html">&lt;p&gt;&lt;font face="黑体" color="#0080ff" size="5"&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最近一个月，过年的时候天天在家里呆着，年后公司的事情也不断，有一段时间没有更新博客了。PyMining是我最近一段时间构思的一个项目，虽然目前看来比较微型。该项目主要是针对中文文本的数据挖掘算法的实验与应用。从项目的目标来说，希望使用者可以很方便的使用现有的数据挖掘、机器学习算法与添加需要的算法。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font face="黑体" color="#0080ff" size="5"&gt;项目概述&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;项目目前主要关注中文文本的数据挖掘算法&lt;/strong&gt;。由于&lt;strong&gt;每种数据挖掘算法的局限性都很大&lt;/strong&gt;，就拿分类算法一样，决策树、朴素贝叶斯这两种算法都有着自己的特性，只能在某一种类型的类型的数据上应用比较良好，比如朴素贝叶斯，就对于那些短文本的分类比较适合，而决策树对于短文本、稀疏情况下就效果欠佳了，特别是在数据比较稀疏的情况。在这种情况下，当有一个数据挖掘任务的时候，怎样去找到一个合适的算法就非常重要了。如果从头开发算法，是一个成本很高的事情，特别是对文本来说就更麻烦，需要在前面做一些如分词、去停用词等等操作。如果有一个平台，可以支持快速的开发，让用户能够快速的看到，针对自己的数据，什么样的算法比较合适，就是本项目的一个初衷。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在这个角度上来说，还是有一些开源的数据挖掘工具，如weka是一个很全面的工具，里面支持几十上百种数据挖掘（机器学习）的算法。不过从我之前使用weka的经验来说，weka对于中文的支持非常糟糕，而且对于稍大一点的数据，就直接罢工不干了（我记得尝试过一个40M左右的文本的聚类任务，weka直接死掉了）。所以开发出一个&lt;strong&gt;支持中文、能够支持更大数据量&lt;/strong&gt;的平台就很有必要了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另外项目目前规划上来说，主要是针对单机上能够运行的任务。虽然分布式机器学习算法（换个更fashion的名字是云计算），是目前最热门的一个话题，但是对于大多数的任务来说，单机版也足够了。对于算法的学习、试验来说，单机版可以更简单、方便的将算法的特性展示出来。当了解了怎样写单机版后，将其改写为简单的分布式版本(比如mpi或者map-reduce)，并不是那么复杂的一个事情。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 目前项目使用Python作为开发语言，虽然之前只写过c++，但是从接触Python开始，就觉得Python语言在快速开发、可读性方面非常的适合，而且极其良好的跨平台型也是Python的优势，我平时的开发环境是在linux(ubuntu)下进行。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 项目的名字是PyMining，这个取这个名字是为了能够简单的说明项目的开发语言与用途，Py是指的Python，Mining是指的Data Mining（数据挖掘）。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PyMining与我的工作：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 由于我的工作就是分布式数据挖掘，而且中文的数据挖掘也是我的工作的方向之一，这里就谈谈PyMining与我工作的关系。&lt;strong&gt;PyMining是我完全利用下班后的时间开发&lt;/strong&gt;，对于我实现的算法，我将会尽量的参考经典的实现（已经公开的论文、网页等内容），而非公司那些我平时接触的算法的实现。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另外对于分词词典、测试数据等比较&amp;#8220;贵重&amp;#8221;的内容，&lt;strong&gt;我也不会使用任何受保护的数据&lt;/strong&gt;，我会选择那些网上比较容易找到的内容并且加以提炼与修改作为项目的一部分。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="黑体" color="#0080ff" size="5"&gt;&lt;strong&gt;License&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 目前使用&lt;a href="http://www.opensource.org/licenses/bsd-license.php"&gt;BSD&lt;/a&gt;作为项目的License，简单来说，就是本项目的源代码可以被商业、非商业自由的使用，也可以将其修改作为二进制和源代码再次发布，但是保留原源代码（或者原源代码编译的二进制程序）的BSD协议，并且不能使用原作者（机构）名字来作为产品的市场推广，更详细的信息请参见发布包内的文档。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="黑体" color="#0080ff" size="5"&gt;&lt;strong&gt;中文文本的数据挖掘基础&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 想了想，还是先科普一下中文文本的数据挖掘基础吧。一个典型的文本分类的数据挖掘流程：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201102/201102271433165574.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="476" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201102/201102271433165541.png" width="714" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面这张图初看有点乱，我这里解释一下，红色的部分是训练时候调用的模块，绿色是测试时候调用的模块，而蓝色的部分是训练的时候生成的中间文件，它们联系着训练、测试两个部分。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 从左到右看是算法运行的流程，&lt;strong&gt;首先用户给出原始的用于训练的中文文本，&lt;/strong&gt;然后进行分词等操作。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 经过了生成矩阵这个步骤，文本就转化成了数学语言了，之后的算法都是运行在这个数学语言之上，&lt;strong&gt;之后的算法就不再关心输入的数据是否是文档了&lt;/strong&gt;，换句话来说，生成矩阵这个模块相当于是一道门，门内是纯数学表示的算法，门外是原始的文本语料。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 图上的特征选择、朴素贝叶斯分类器就是属于门内的内容，具体的算法具体分析。对于&lt;/font&gt;&lt;a href="http://en.wikipedia.org/wiki/Feature_selection"&gt;&lt;font size="4"&gt;特征选择算法&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;和&lt;/font&gt;&lt;a href="http://en.wikipedia.org/wiki/Naive_Bayes_classifier"&gt;&lt;font size="4"&gt;朴素贝叶斯分类器&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;，可以点链接，看看wikipedia的定义。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="黑体" color="#0080ff" size="5"&gt;&lt;strong&gt;如何使用PyMining：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如何获取项目（目前版本0.0.0.1，第一个开发版）&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GoogleCode地址：&lt;a title="https://python-data-mining-platform.googlecode.com/svn/trunk" href="https://python-data-mining-platform.googlecode.com/svn/trunk"&gt;https://python-data-mining-platform.googlecode.com/svn/trunk&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 直接下载的zip包地址：&lt;a href="http://code.google.com/p/python-data-mining-platform/downloads/detail?name=py_mining_0.0.0.1.zip&amp;amp;can=2&amp;amp;q=#makechanges"&gt;http://code.google.com/p/python-data-mining-platform/downloads/detail?name=py_mining_0.0.0.1.zip&amp;amp;can=2&amp;amp;q=#makechanges&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 给出一段示例代码：&lt;/font&gt;&lt;/p&gt; &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;  &lt;div class="csharpcode"&gt;   from matrix import Matrix  from classifier_matrix import ClassifierMatrix  from segmenter import Segmenter  from py_mining import PyMining  from configuration import Configuration  from chisquare_filter import ChiSquareFilter  from naive_bayes import NaiveBayes  &amp;nbsp;  &lt;span class="kwrd"&gt;if&lt;/span&gt; __name__ == &lt;span class="str"&gt;"__main__"&lt;/span&gt;:      config = Configuration.FromFile(&lt;span class="str"&gt;"conf/test.xml"&lt;/span&gt;)      PyMining.Init(config, &lt;span class="str"&gt;"__global__"&lt;/span&gt;)      matCreater = ClassifierMatrix(config, &lt;span class="str"&gt;"__matrix__"&lt;/span&gt;)      [trainx, trainy] = matCreater.CreateTrainMatrix(&lt;span class="str"&gt;"data/train.txt"&lt;/span&gt;)      chiFilter = ChiSquareFilter(config, &lt;span class="str"&gt;"__filter__"&lt;/span&gt;)      chiFilter.TrainFilter(trainx, trainy)  &amp;nbsp;      nbModel = NaiveBayes(config, &lt;span class="str"&gt;"naive_bayes"&lt;/span&gt;)      nbModel.Train(trainx, trainy)  &amp;nbsp;      [testx, testy] = matCreater.CreatePredictMatrix(&lt;span class="str"&gt;"data/test.txt"&lt;/span&gt;)      [testx, testy] = chiFilter.TestFilter(testx, testy)      [resultY, precision] = nbModel.Test(testx, testy)            print precision&lt;/div&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这段代码分成了训练和测试两个阶段，首先值得注意的是，项目的模块需要的参数都是从一个xml格式的配置文件中得到的，也就是代码中的test.conf。代码最开始，调用Configuration.FromFile函数，从xml配置文件中解析出需要的dom tree。之后的那些模块初始化的时候，都将获取这个配置信息类Configuration的实例config中指定的标签的信息，比如ClassifiterMatrix类初始化的时候，将使用标签为__matrix__的信息，待会我将贴出xml的代码，可以更清楚的看到。初始化的时候，可以指定最后一个布尔参数(isFromFile)，这个参数的意思是，是否这个模块从配置类中指定的文件中载入得到。一般在训练的时候，指定这个参数为False，而在单独测试的时候，需要指定这个参数为True，因为需要从训练的时候生成的文件中载入训练的模型才能够进行测试。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&lt;strong&gt;&amp;nbsp;&amp;nbsp; 首先谈谈训练的过程：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后调用PyMining.Init, PyMining是一个全局模块的参数，里面放置着一些在全局中都有用的一些参数，目前里面有4个dictionary，term-to-id(从单词的str到单词的id), id-to-term，id-to-doc-count（某一个单词的id对应了多少篇文档），class-to-doc-count（某一个分类里面有多少篇文档），这些信息在特征选择、预测、以及结果的展示中将起到很重要的作用。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来的ClassifierMatrix就是前面图片中的&amp;#8220;构成矩阵&amp;#8221;这个模块，在其CreateTrainMatrix方法中，将会从原始的训练语料train.txt中，进行分词等操作，生成矩阵trainx, trainy。trainx是一个m * n的矩阵，表示数据的部分，每一行表示一篇文档，每一列表示一个feature（单词）。trainy是一个m * 1的矩阵，表示每篇文档对应的分类id。从生成矩阵之后，算法看到的信息就只有矩阵了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来生成了一个chiFilter，也就是chi-square的feature selection（可参考前面的wikipedia的链接），chiFilter将使用算法来看看哪些特征（列）是没有什么必要的，并且将其过滤掉，其Create方法传入的参数就是之前的trainx, trainy，结果将是一个保存在chiFilter实例中的一个黑名单，表示哪些feature-id是需要过滤掉的。其TestFilter方法就是使用之前得到的黑名单来过滤掉矩阵中不重要的列。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最后就是分类算法了，这里是使用的朴素贝叶斯(NaiveBayes)算法。调用其Train方法可以得到一个模型并且保存到实例中。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后是预测（测试）的过程：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PyMining的训练、测试的过程可以独立的运行，可以先训练出一个模型，等到有需要的时候再进行测试，所以在训练的过程中，有一些数据（比如说chi-square filter）中的黑名单，将会保存到文件中去。如果想单独的运行测试程序，请参考下面的一段代码，调用了NaiveBayes.Test方法后，返回的resultY就是一个m * 1的矩阵（m是测试文档的个数），表示对于每一篇测试文档使用模型测试得到的标签（属于0，1，2，3）中的哪一个，precision是测试的准确率。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 单独运行测试（从文件中载入训练的结果）的代码如下：&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  from matrix import Matrix  from classifier_matrix import ClassifierMatrix  from segmenter import Segmenter  from py_mining import PyMining  from configuration import Configuration  from chisquare_filter import ChiSquareFilter  from naive_bayes import NaiveBayes  &amp;nbsp;  &lt;span class="kwrd"&gt;if&lt;/span&gt; __name__ == &lt;span class="str"&gt;"__main__"&lt;/span&gt;:      config = Configuration.FromFile(&lt;span class="str"&gt;"conf/test.xml"&lt;/span&gt;)      PyMining.Init(config, &lt;span class="str"&gt;"__global__"&lt;/span&gt;, True)      matCreater = ClassifierMatrix(config, &lt;span class="str"&gt;"__matrix__"&lt;/span&gt;, True)      chiFilter = ChiSquareFilter(config, &lt;span class="str"&gt;"__filter__"&lt;/span&gt;, True)  &amp;nbsp;      nbModel = NaiveBayes(config, &lt;span class="str"&gt;"naive_bayes"&lt;/span&gt;, True)  &amp;nbsp;      [testx, testy] = matCreater.CreatePredictMatrix(&lt;span class="str"&gt;"data/test.txt"&lt;/span&gt;)      [testx, testy] = chiFilter.TestFilter(testx, testy)      [resultY, precision] = nbModel.Test(testx, testy)            print precision&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;下面是配置文件，这里大概的讲讲：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;config&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;__segmenter__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;main_dict&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;dict/dict.main&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;main_dict&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;__segmenter__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;__matrix__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;__matrix__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;__global__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;term_to_id&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/term_to_id&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;term_to_id&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;id_to_term&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/id_to_term&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;id_to_term&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;id_to_doc_count&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/id_to_doc_count&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;id_to_doc_count&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;class_to_doc_count&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/class_to_doc_count&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;class_to_doc_count&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;__global__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;__filter__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;rate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;0.5&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;rate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;method&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;max&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;method&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;log_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/filter.log&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;log_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;model_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/filter.model&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;model_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;__filter__&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;naive_bayes&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;model_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/naive_bayes.model&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;model_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;log_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;mining/naive_bayes.log&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;log_path&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;naive_bayes&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;config&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;style type="text/css"&gt;&lt;br/&gt;.csharpcode, .csharpcode pre&lt;br/&gt;{&lt;br/&gt;font-size: small;&lt;br/&gt;color: black;&lt;br/&gt;font-family: consolas, "Courier New", courier, monospace;&lt;br/&gt;background-color: #ffffff;&lt;br/&gt;/*white-space: pre;*/&lt;br/&gt;}&lt;br/&gt;.csharpcode pre { margin: 0em; }&lt;br/&gt;.csharpcode .rem { color: #008000; }&lt;br/&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br/&gt;.csharpcode .str { color: #006080; }&lt;br/&gt;.csharpcode .op { color: #0000c0; }&lt;br/&gt;.csharpcode .preproc { color: #cc6633; }&lt;br/&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br/&gt;.csharpcode .html { color: #800000; }&lt;br/&gt;.csharpcode .attr { color: #ff0000; }&lt;br/&gt;.csharpcode .alt &lt;br/&gt;{&lt;br/&gt;background-color: #f4f4f4;&lt;br/&gt;width: 100%;&lt;br/&gt;margin: 0em;&lt;br/&gt;}&lt;br/&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 里面的每一个二级标签就是一个模块的熟悉，比如说__segmenter__里面的信息就是分词器所需要的一些配置信息，有些名字是加上了__xxx__的样子，表示是默认的模块，__segmenter__里面main_dict为主词典&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __global__里面是几个全局的表，也就是之前提到的PyMining模块中的内容，mining/term_to_id表示保存到文件的路径。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __filter__表示过滤器，rate表示选择百分之多少的feature，method有两种max与avg，这里具体请参考wiki中的文档，log_path表示该模块运行的时候，输出的日志信息的路径。model_path表示训练过程中得到的黑名单的输出的路径。如果有需要，我们可以从文件中载入训练的结果。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; naive_bayes跟filter差不多，这里就不再多说了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff" size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#000000"&gt;PyMining中有哪些模块：&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 目前PyMining中具有下面的模块。具体的api请参考源文件，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;Segmenter&lt;/strong&gt;: 一个非常简单的分词器，采用贪心法进行分词。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;ClassifierMatrix&lt;/strong&gt;: 生成分类算法中需要的矩阵&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;ChisquareFilter&lt;/strong&gt;: chisquare 的feature selector&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;NaiveBayes&lt;/strong&gt;: 朴素贝叶斯分类器&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 运行PyMining：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 调用python naive_bayes_train_test.py，将会输出 0.86。这是分类的准确率。PyMining中目前的训练测试数据是东东提供的，来自团购网站的标题的分类，0表示美食、1表示美容美发、2表示休闲娱乐、3表示其他，训练数据看起来是这个样子：&lt;/font&gt;&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;  &lt;p&gt;&lt;font color="#000080"&gt;仅售28元！原价最高466元的&amp;#8220;兰彩鸣量贩KTV&amp;#8221;两小时豪华欢唱套餐一份：两个小时不限时段欢唱+不限包房类型+可连续累计消费+爆米花一份+VC一扎！（豪华包最多容纳45人，最小包可容纳4人）邀请好友返利10元！&amp;nbsp;&amp;nbsp;&amp;nbsp; 2       &lt;br /&gt;仅售39元！原价113元的&amp;#8220;北京铭豪苑火锅烧烤城&amp;#8221;馋嘴锅双人套餐一份：干锅鸭翅（2.5斤左右）+羊肉（300g）+野山笋（300g）+鱼丸虾丸双拼（500g）+7元双拼+6元双拼+杂面一份！邀请好友返利10元！&amp;nbsp;&amp;nbsp;&amp;nbsp; 0       &lt;br /&gt;仅售10元！原价176元的&amp;#8220;水星健身&amp;#8221;双日健身体验卡一张！&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 运行完后，将会在mining目录下得到一些文件，这就是在训练过程中的一些日志、模型文件，可以打开来看看训练的结果。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; filter.log里面记录的是chisquare feature selector的结果，看起来是下面的样子：&lt;/font&gt;&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;  &lt;p&gt;&lt;font color="#000080"&gt;chiSquare info:      &lt;br /&gt;=======selected========      &lt;br /&gt;护理 139.541924743      &lt;br /&gt;美容 109.728270833      &lt;br /&gt;美发 99.0576860046      &lt;br /&gt;染发 80.5718475073      &lt;br /&gt;入住 65.4600301659      &lt;br /&gt;烫发 62.3015873016      &lt;br /&gt;面部 61.8500831431      &lt;br /&gt;早餐 54.3178973717      &lt;br /&gt;欧莱雅 53.246124031      &lt;br /&gt;男女 45.6000719014&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;&amp;#8230;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;豆沙 2.71349224717      &lt;br /&gt;水煮鱼 2.71349224717      &lt;br /&gt;琵琶 2.71349224717      &lt;br /&gt;蛋挞 2.71349224717      &lt;br /&gt;新增 2.71349224717      &lt;br /&gt;接待 2.71349224717      &lt;br /&gt;酒楼 2.71349224717      &lt;br /&gt;12人 2.71349224717      &lt;br /&gt;吉列 2.71349224717      &lt;br /&gt;香菜 2.71349224717      &lt;br /&gt;鸡排 2.71349224717      &lt;br /&gt;========unselected=======      &lt;br /&gt;春卷 2.71349224717      &lt;br /&gt;木瓜 2.71349224717      &lt;br /&gt;鳕鱼 2.71349224717      &lt;br /&gt;鳗鱼 2.71349224717      &lt;br /&gt;手卷 2.71349224717&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;&amp;#8230;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000080"&gt;广场店 0.441547518923      &lt;br /&gt;实惠 0.441547518923      &lt;br /&gt;亲情 0.441547518923      &lt;br /&gt;青岛 0.441547518923      &lt;br /&gt;百纳 0.441547518923      &lt;br /&gt;米兰 0.441547518923      &lt;br /&gt;感受 0.441547518923      &lt;br /&gt;大海 0.441547518923      &lt;br /&gt;旗 0.441547518923      &lt;br /&gt;亚洲 0.441547518923&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个列表上，越往上越是对分类有帮助的词，越往下，越是没有什么意义的词，单词后面的数字表示chisquare分数，越高说明单词越有意义。=====unselected=======表示一个分界线，分界线下面的词是被过滤掉的词。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其他的信息可以看看其他的log文件，也会发现一些有趣的地方。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff" size="5"&gt;&lt;strong&gt;PyMining下一步的开发计划（需要更多你的参与）&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PyMining之后会支持更多的算法（包括分类、聚类等算法），会支持更多的用法，会支持更丰富的文本格式。另外，之后可能会调用NumPy与SciPy，以进行更强大的矩阵计算。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果对希望参与开发的朋友可以联系我：&lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#119;&amp;#104;&amp;#101;&amp;#101;&amp;#108;&amp;#101;&amp;#97;&amp;#115;&amp;#116;&amp;#64;&amp;#103;&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#46;&amp;#99;&amp;#111;&amp;#109;"&gt;wheeleast@gmail.com&lt;/a&gt;，要求Python有一定的开发经验，对机器学习 or 数据挖掘 or 模式识别算法有兴趣。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对项目有任何其他问题的朋友可以联系我。&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/1966264.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/02/27/py_mining_first_release.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html</id><title type="text">机器学习中的数学(5)-强大的矩阵奇异值分解(SVD)及其应用</title><summary type="text">版权声明： 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用，但请注明出处，如果有问题，请联系wheeleast@gmail.com 前言： 上一次写了关于PCA与LDA的文章，PCA的实现一般有两种，一种是用特征值分解去实现的，一种是用奇异值分解去实现的。在上篇文章中便是基于特征值分解的一种解释。特征值和奇异值在大部分人的印象中，往往是停留在纯粹的数学计算中。而且线性代数或者矩阵论里面，也很少讲任何跟特征值与奇异值有关的应用背景。奇异值分解是一个有着很明显的物理意义的一种方法，它可以将一个比较复杂的矩阵用更小</summary><published>2011-01-19T14:27:00Z</published><updated>2011-01-19T14:27:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="4"&gt;版权声明：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 本文由LeftNotEasy发布于&lt;a href="http://leftnoteasy.cnblogs.com/"&gt;http://leftnoteasy.cnblogs.com&lt;/a&gt;, 本文可以被全部的转载或者部分使用，但请注明出处，如果有问题，请联系&lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#119;&amp;#104;&amp;#101;&amp;#101;&amp;#108;&amp;#101;&amp;#97;&amp;#115;&amp;#116;&amp;#64;&amp;#103;&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#46;&amp;#99;&amp;#111;&amp;#109;"&gt;wheeleast@gmail.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="4"&gt;前言：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上一次写了关于&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/08/lda-and-pca-machine-learning.html"&gt;PCA与LDA&lt;/a&gt;的文章，PCA的实现一般有两种，一种是用特征值分解去实现的，一种是用奇异值分解去实现的。在上篇文章中便是基于特征值分解的一种解释。特征值和奇异值在大部分人的印象中，往往是停留在纯粹的数学计算中。而且线性代数或者矩阵论里面，也很少讲任何跟特征值与奇异值有关的应用背景。奇异值分解是一个有着很明显的物理意义的一种方法，它可以将一个比较复杂的矩阵用更小更简单的几个子矩阵的相乘来表示，这些小矩阵描述的是矩阵的重要的特性。就像是描述一个人一样，给别人描述说这个人长得浓眉大眼，方脸，络腮胡，而且带个黑框的眼镜，这样寥寥的几个特征，就让别人脑海里面就有一个较为清楚的认识，实际上，人脸上的特征是有着无数种的，之所以能这么描述，是因为人天生就有着非常好的抽取重要特征的能力，让机器学会抽取重要的特征，SVD是一个重要的方法。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在机器学习领域，有相当多的应用与奇异值都可以扯上关系，比如做feature reduction的PCA，做数据压缩（以图像压缩为代表）的算法，还有做搜索引擎语义层次检索的LSI（Latent Semantic Indexing）&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另外在这里抱怨一下，之前在百度里面搜索过SVD，出来的结果都是俄罗斯的一种狙击枪（AK47同时代的），是因为穿越火线这个游戏里面有一把狙击枪叫做SVD，而在Google上面搜索的时候，出来的都是奇异值分解（英文资料为主）。想玩玩战争游戏，玩玩COD不是非常好吗，玩山寨的CS有神马意思啊。国内的网页中的话语权也被这些没有太多营养的帖子所占据。真心希望国内的气氛能够更浓一点，搞游戏的人真正是喜欢制作游戏，搞Data Mining的人是真正喜欢挖数据的，都不是仅仅为了混口饭吃，这样谈超越别人才有意义，中文文章中，能踏踏实实谈谈技术的太少了，改变这个状况，从我自己做起吧。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 前面说了这么多，本文主要关注奇异值的一些特性，另外还会稍稍提及奇异值的计算，不过本文不准备在如何计算奇异值上展开太多。另外，本文里面有部分不算太深的线性代数的知识，如果完全忘记了线性代数，看本文可能会有些困难。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0080ff" size="4"&gt;一、奇异值与特征值基础知识：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 特征值分解和奇异值分解在机器学习领域都是属于满地可见的方法。两者有着很紧密的关系，我在接下来会谈到，特征值分解和奇异值分解的目的都是一样，就是提取出一个矩阵最重要的特征。先谈谈特征值分解吧：&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp; 1）&lt;strong&gt;特征值：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果说一个向量v是方阵A的特征向量，将一定可以表示成下面的形式：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226321862.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="34" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110119222632467.png" width="84" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这时候&amp;#955;就被称为特征向量v对应的特征值，一个矩阵的一组特征向量是一组正交向量。特征值分解是将一个矩阵分解成下面的形式：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226321023.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="38" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226327992.png" width="112" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其中Q是这个矩阵A的特征向量组成的矩阵，&amp;#931;是一个对角阵，每一个对角线上的元素就是一个特征值。我这里引用了一些参考文献中的内容来说明一下。首先，要明确的是，一个矩阵其实就是一个线性变换，因为一个矩阵乘以一个向量后得到的向量，其实就相当于将这个向量进行了线性变换。比如说下面的一个矩阵：&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110119222632500.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="55" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226323008.png" width="105" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 它其实对应的线性变换是下面的形式：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226326073.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="170" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226323913.png" width="371" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 因为这个矩阵M乘以一个向量(x,y)的结果是：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226334470.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="58" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226335026.png" width="162" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面的矩阵是对称的，所以这个变换是一个对x，y轴的方向一个拉伸变换（每一个对角线上的元素将会对一个维度进行拉伸变换，当值&amp;gt;1时，是拉长，当值&amp;lt;1时时缩短），当矩阵不是对称的时候，假如说矩阵是下面的样子：&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226337534.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="53" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226336454.png" width="100" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 它所描述的变换是下面的样子：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226333107.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="171" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226334536.png" width="366" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这其实是在平面上对一个轴进行的拉伸变换（如蓝色的箭头所示），在图中，蓝色的箭头是一个最&lt;strong&gt;主要的&lt;/strong&gt;变化方向（变化方向可能有不止一个），&lt;strong&gt;如果我们想要描述好一个变换，那我们就描述好这个变换主要的变化方向就好了&lt;/strong&gt;。反过头来看看之前特征值分解的式子，分解得到的&amp;#931;矩阵是一个对角阵，里面的特征值是由大到小排列的，这些特征值所对应的特征向量就是描述这个矩阵变化方向（从主要的变化到次要的变化排列）&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当矩阵是高维的情况下，那么这个矩阵就是高维空间下的一个线性变换，这个线性变化可能没法通过图片来表示，但是可以想象，这个变换也同样有很多的变换方向，我们通过特征值分解得到的前N个特征向量，那么就对应了这个矩阵最主要的N个变化方向。我们利用这前N个变化方向，就可以近似这个矩阵（变换）。也就是之前说的：&lt;strong&gt;提取这个矩阵最重要的特征。&lt;/strong&gt;总结一下，特征值分解可以得到特征值与特征向量，特征值表示的是这个特征到底有多重要，而特征向量表示这个特征是什么，可以将每一个特征向量理解为一个线性的子空间，我们可以利用这些线性的子空间干很多的事情。不过，&lt;strong&gt;特征值分解也有很多的局限，比如说变换的矩阵必须是方阵。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; （说了这么多特征值变换，不知道有没有说清楚，请各位多提提意见。）&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp; 2）奇异值：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下面谈谈奇异值分解。特征值分解是一个提取矩阵特征很不错的方法，但是它只是对方阵而言的，在现实的世界中，我们看到的大部分矩阵都不是方阵，比如说有N个学生，每个学生有M科成绩，这样形成的一个N * M的矩阵就不可能是方阵，&lt;strong&gt;我们怎样才能描述这样普通的矩阵呢的重要特征呢？&lt;/strong&gt;奇异值分解可以用来干这个事情，&lt;strong&gt;奇异值分解是一个能适用于任意的矩阵的一种分解的方法&lt;/strong&gt;：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226335092.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="40" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226332060.png" width="118" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设A是一个N * M的矩阵，那么得到的U是一个N * N的方阵（里面的向量是正交的，U里面的向量称为左奇异向量），&amp;#931;是一个N * M的矩阵（除了对角线的元素都是0，对角线上的元素称为奇异值），V&amp;#8217;(V的转置)是一个N * N的矩阵，里面的向量也是正交的，V里面的向量称为右奇异向量），从图片来反映几个相乘的矩阵的大小可得下面的图片&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226341537.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="152" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226342650.png" width="439" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么奇异值和特征值是怎么对应起来的呢？首先，我们将一个矩阵A的转置 * A，将会得到一个方阵，我们用这个方阵求特征值可以得到：&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226349618.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="44" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226348223.png" width="153" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里得到的v，就是我们上面的右奇异向量。此外我们还可以得到：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226344111.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="104" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226346304.png" width="100" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里的&amp;#963;就是上面说的奇异值，u就是上面说的左奇异向量。奇异值&amp;#963;跟特征值类似，在矩阵&amp;#931;中也是从大到小排列，而且&amp;#963;的减少特别的快，&lt;strong&gt;在很多情况下，前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上了&lt;/strong&gt;。也就是说，我们也可以用前r大的奇异值来近似描述矩阵，这里定义一下&lt;strong&gt;部分奇异值分解&lt;/strong&gt;：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226359684.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="45" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226358289.png" width="204" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; r是一个远小于m、n的数，这样矩阵的乘法看起来像是下面的样子：&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226359717.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="184" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226356370.png" width="352" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 右边的三个矩阵相乘的结果将会是一个接近于A的矩阵，在这儿，r越接近于n，则相乘的结果越接近于A。而这三个矩阵的面积之和（在存储观点来说，矩阵面积越小，存储量就越小）要远远小于原始的矩阵A，我们如果想要压缩空间来表示原矩阵A，我们存下这里的三个矩阵：U、&amp;#931;、V就好了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="4"&gt;&lt;strong&gt;二、奇异值的计算：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 奇异值的计算是一个难题，是一个O(N^3)的算法。在单机的情况下当然是没问题的，matlab在一秒钟内就可以算出1000 * 1000的矩阵的所有奇异值，但是当矩阵的规模增长的时候，计算的复杂度呈3次方增长，就需要并行计算参与了。Google的&lt;strong&gt;吴军&lt;/strong&gt;老师在&lt;strong&gt;数学之美&lt;/strong&gt;系列谈到SVD的时候，说起Google实现了SVD的并行化算法，说这是对人类的一个贡献，但是也没有给出具体的计算规模，也没有给出太多有价值的信息。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实SVD还是可以用并行的方式去实现的，在解大规模的矩阵的时候，一般使用迭代的方法，当矩阵的规模很大（比如说上亿）的时候，迭代的次数也可能会上亿次，如果使用Map-Reduce框架去解，则每次Map-Reduce完成的时候，都会涉及到写文件、读文件的操作。个人猜测Google云计算体系中除了Map-Reduce以外应该还有类似于MPI的计算模型，也就是节点之间是保持通信，数据是常驻在内存中的，这种计算模型比Map-Reduce在解决迭代次数非常多的时候，要快了很多倍。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://en.wikipedia.org/wiki/Lanczos_algorithm"&gt;Lanczos迭代&lt;/a&gt;就是一种解&lt;strong&gt;对称方阵部分特征值&lt;/strong&gt;的方法（之前谈到了，解A&amp;#8217;* A得到的对称方阵的特征值就是解A的右奇异向量），是将一个对称的方程化为一个三对角矩阵再进行求解。按网上的一些文献来看，Google应该是用这种方法去做的奇异值分解的。请见Wikipedia上面的一些引用的论文，如果理解了那些论文，也&amp;#8220;几乎&amp;#8221;可以做出一个SVD了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 由于奇异值的计算是一个很枯燥，纯数学的过程，而且前人的研究成果（论文中）几乎已经把整个程序的流程图给出来了。更多的关于奇异值计算的部分，将在后面的参考文献中给出，这里不再深入，我还是focus在奇异值的应用中去。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="4"&gt;&lt;strong&gt;三、奇异值与主成分分析（PCA）：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 主成分分析在上一节里面也讲了一些，这里主要谈谈如何用SVD去解PCA的问题。PCA的问题其实是一个基的变换，使得变换后的数据有着最大的方差。方差的大小描述的是一个变量的信息量，我们在讲一个东西的稳定性的时候，往往说要减小方差，如果一个模型的方差很大，那就说明模型不稳定了。但是对于我们用于机器学习的数据（主要是训练数据），方差大才有意义，不然输入的数据都是同一个点，那方差就为0了，这样输入的多个数据就等同于一个数据了。以下面这张图为例子：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226359750.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="184" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226357275.png" width="240" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个假设是一个摄像机采集一个物体运动得到的图片，上面的点表示物体运动的位置，假如我们想要用一条直线去拟合这些点，那我们会选择什么方向的线呢？当然是图上标有signal的那条线。如果我们把这些点单纯的投影到x轴或者y轴上，最后在x轴与y轴上得到的方差是相似的（因为这些点的趋势是在45度左右的方向，所以投影到x轴或者y轴上都是类似的），如果我们使用原来的xy坐标系去看这些点，容易看不出来这些点真正的方向是什么。但是如果我们进行坐标系的变化，横轴变成了signal的方向，纵轴变成了noise的方向，则就很容易发现什么方向的方差大，什么方向的方差小了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一般来说，方差大的方向是信号的方向，方差小的方向是噪声的方向，我们在数据挖掘中或者数字信号处理中，往往要提高信号与噪声的比例，也就是信噪比。对上图来说，如果我们只保留signal方向的数据，也可以对原数据进行不错的近似了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PCA的全部工作简单点说，就是对原始的空间中顺序地找一组相互正交的坐标轴，第一个轴是使得方差最大的，第二个轴是在与第一个轴正交的平面中使得方差最大的，第三个轴是在与第1、2个轴正交的平面中方差最大的，这样假设在N维空间中，我们可以找到N个这样的坐标轴，我们取前r个去近似这个空间，这样就从一个N维的空间压缩到r维的空间了，但是我们选择的r个坐标轴能够使得空间的压缩使得数据的损失最小。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 还是假设我们矩阵每一行表示一个样本，每一列表示一个feature，用矩阵的语言来表示，将一个m * n的矩阵A的进行坐标轴的变化，P就是一个变换的矩阵从一个N维的空间变换到另一个N维的空间，在空间中就会进行一些类似于旋转、拉伸的变化。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226367831.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="44" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226366436.png" width="160" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 而将一个m * n的矩阵A变换成一个m * r的矩阵，这样就会使得本来有n个feature的，变成了有r个feature了（r &amp;lt; n)，这r个其实就是对n个feature的一种提炼，我们就把这个称为feature的压缩。用数学语言表示就是：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226361452.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="43" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226364833.png" width="167" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但是这个怎么和SVD扯上关系呢？之前谈到，SVD得出的奇异向量也是从奇异值由大到小排列的，按PCA的观点来看，就是方差最大的坐标轴就是第一个奇异向量，方差次大的坐标轴就是第二个奇异向量&amp;#8230;我们回忆一下之前得到的SVD式子：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226363437.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="43" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226366818.png" width="224" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在矩阵的两边同时乘上一个矩阵V，由于V是一个正交的矩阵，所以V转置乘以V得到单位阵I，所以可以化成后面的式子&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226365422.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="81" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226374899.png" width="304" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 将后面的式子与A * P那个m * n的矩阵变换为m * r的矩阵的式子对照看看，在这里，其实V就是P，也就是一个变化的向量。这里是将一个m * n 的矩阵压缩到一个m * r的矩阵，也就是对列进行压缩，如果我们想对行进行压缩（在PCA的观点下，对行进行压缩可以理解为，将一些相似的sample合并在一起，或者将一些没有太大价值的sample去掉）怎么办呢？同样我们写出一个通用的行压缩例子：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226375455.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="39" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226374060.png" width="164" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这样就从一个m行的矩阵压缩到一个r行的矩阵了，对SVD来说也是一样的，我们对SVD分解的式子两边乘以U的转置U'&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226377440.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="51" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226374408.png" width="240" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这样我们就得到了对行进行压缩的式子。可以看出，其实PCA几乎可以说是对SVD的一个包装，如果我们实现了SVD，那也就实现了PCA了，而且更好的地方是，有了SVD，我们就可以得到两个方向的PCA，如果我们对A&amp;#8217;A进行特征值的分解，只能得到一个方向的PCA。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="4"&gt;&lt;strong&gt;四、奇异值与潜在语义索引LSI：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 潜在语义索引（Latent Semantic Indexing）与PCA不太一样，至少不是实现了SVD就可以直接用的，不过LSI也是一个严重依赖于SVD的算法，之前吴军老师在&lt;a href="http://www.google.com.hk/ggblog/googlechinablog/2006/12/blog-post_8935.html"&gt;矩阵计算与文本处理中的分类问题&lt;/a&gt;中谈到：&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;font size="4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#8220;三个矩阵有非常清楚的物理含义。第一个矩阵X中的每一行表示意思相关的一类词，其中的每个非零元素表示这类词中每个词的重要性（或者说相关性），数值越大越相关。最后一个矩阵Y中的每一列表示同一主题一类文章，其中每个元素表示这类文章中每篇文章的相关性。中间的矩阵则表示类词和文章雷之间的相关性。因此，我们只要对关联矩阵A进行一次奇异值分解，w 我们就可以同时完成了近义词分类和文章的分类。（同时得到每类文章和每类词的相关性）。&amp;#8221;&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面这段话可能不太容易理解，不过这就是LSI的精髓内容，我下面举一个例子来说明一下，下面的例子来自LSA tutorial，具体的网址我将在最后的引用中给出：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226379109.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="285" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226386634.png" width="316" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这就是一个矩阵，不过不太一样的是，这里的一行表示一个词在哪些title中出现了（一行就是之前说的一维feature），一列表示一个title中有哪些词，（这个矩阵其实是我们之前说的那种一行是一个sample的形式的一种转置，这个会使得我们的左右奇异向量的意义产生变化，但是不会影响我们计算的过程）。比如说T1这个title中就有guide、investing、market、stock四个词，各出现了一次，我们将这个矩阵进行SVD，得到下面的矩阵：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226389491.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="266" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226397148.png" width="624" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 左奇异向量表示词的一些特性，右奇异向量表示文档的一些特性，中间的奇异值矩阵表示左奇异向量的一行与右奇异向量的一列的重要程序，数字越大越重要。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 继续看这个矩阵还可以发现一些有意思的东西，首先，左奇异向量的第一列表示每一个词的出现频繁程度，虽然不是线性的，但是可以认为是一个大概的描述，比如book是0.15对应文档中出现的2次，investing是0.74对应了文档中出现了9次，rich是0.36对应文档中出现了3次；&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其次，右奇异向量中一的第一行表示每一篇文档中的出现词的个数的近似，比如说，T6是0.49，出现了5个词，T2是0.22，出现了2个词。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后我们反过头来看，我们可以将左奇异向量和右奇异向量都取后2维（之前是3维的矩阵），投影到一个平面上，可以得到：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110119222640769.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="390" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101192226404739.png" width="497" border="0" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在图上，每一个红色的点，都表示一个词，每一个蓝色的点，都表示一篇文档，这样我们可以对这些词和文档进行聚类，比如说stock 和 market可以放在一类，因为他们老是出现在一起，real和estate可以放在一类，dads，guide这种词就看起来有点孤立了，我们就不对他们进行合并了。按这样聚类出现的效果，可以提取文档集合中的近义词，这样当用户检索文档的时候，是用语义级别（近义词集合）去检索了，而不是之前的词的级别。这样一减少我们的检索、存储量，因为这样压缩的文档集合和PCA是异曲同工的，二可以提高我们的用户体验，用户输入一个词，我们可以在这个词的近义词的集合中去找，这是传统的索引无法做到的。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不知道按这样描述，再看看吴军老师的文章，是不是对SVD更清楚了？:-D&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0080ff" size="4"&gt;&lt;strong&gt;参考资料：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;1）A Tutorial on Principal Component Analysis, Jonathon Shlens   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这是我关于用SVD去做PCA的主要参考资料    &lt;br /&gt;2）&lt;a href="http://www.ams.org/samplings/feature-column/fcarc-svd"&gt;http://www.ams.org/samplings/feature-column/fcarc-svd&lt;/a&gt;    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 关于svd的一篇概念好文，我开头的几个图就是从这儿截取的    &lt;br /&gt;3）&lt;a href="http://www.puffinwarellc.com/index.php/news-and-articles/articles/30-singular-value-decomposition-tutorial.html"&gt;http://www.puffinwarellc.com/index.php/news-and-articles/articles/30-singular-value-decomposition-tutorial.html&lt;/a&gt;    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另一篇关于svd的入门好文    &lt;br /&gt;4）&lt;a href="http://www.puffinwarellc.com/index.php/news-and-articles/articles/33-latent-semantic-analysis-tutorial.html"&gt;http://www.puffinwarellc.com/index.php/news-and-articles/articles/33-latent-semantic-analysis-tutorial.html&lt;/a&gt;    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; svd与LSI的好文，我后面LSI中例子就是来自此    &lt;br /&gt;5）&lt;a href="http://www.miislita.com/information-retrieval-tutorial/svd-lsi-tutorial-1-understanding.html"&gt;http://www.miislita.com/information-retrieval-tutorial/svd-lsi-tutorial-1-understanding.html&lt;/a&gt;    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另一篇svd与LSI的文章，也还是不错，深一点，也比较长    &lt;br /&gt;6）Singular Value Decomposition and Principal Component Analysis, Rasmus Elsborg Madsen, Lars Kai Hansen and Ole Winther, 2004    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 跟1）里面的文章比较类似&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/1939687.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/LeftNotEasy/archive/2011/01/08/lda-and-pca-machine-learning.html</id><title type="text">机器学习中的数学(4)-线性判别分析（LDA）, 主成分分析(PCA)</title><summary type="text">版权声明： 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用，但请注明出处，如果有问题，请联系wheeleast@gmail.com 前言： 第二篇的文章中谈到，和部门老大一宁出去outing的时候，他给了我相当多的机器学习的建议，里面涉及到很多的算法的意义、学习方法等等。一宁上次给我提到，如果学习分类算法，最好从线性的入手，线性分类器最简单的就是LDA，它可以看做是简化版的SVM，如果想理解SVM这种分类器，那理解LDA就是很有必要的了。 谈到LDA，就不得不谈谈PCA，PCA是一个和LDA非常相关的算法，从</summary><published>2011-01-08T06:56:00Z</published><updated>2011-01-08T06:56:00Z</updated><author><name>LeftNotEasy</name><uri>http://www.cnblogs.com/LeftNotEasy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/08/lda-and-pca-machine-learning.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/08/lda-and-pca-machine-learning.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;版权声明：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 本文由LeftNotEasy发布于&lt;a href="http://leftnoteasy.cnblogs.com/"&gt;http://leftnoteasy.cnblogs.com&lt;/a&gt;, 本文可以被全部的转载或者部分使用，但请注明出处，如果有问题，请联系&lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#119;&amp;#104;&amp;#101;&amp;#101;&amp;#108;&amp;#101;&amp;#97;&amp;#115;&amp;#116;&amp;#64;&amp;#103;&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#46;&amp;#99;&amp;#111;&amp;#109;"&gt;wheeleast@gmail.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;前言：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2010/12/19/mathmatic_in_machine_learning_2_regression_and_bias_variance_trade_off.html"&gt;第二篇&lt;/a&gt;的文章中谈到，和部门老大一宁出去outing的时候，他给了我相当多的机器学习的建议，里面涉及到很多的算法的意义、学习方法等等。一宁上次给我提到，如果学习分类算法，最好从线性的入手，线性分类器最简单的就是LDA，它可以看做是简化版的SVM，如果想理解SVM这种分类器，那理解LDA就是很有必要的了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 谈到LDA，就不得不谈谈PCA，PCA是一个和LDA非常相关的算法，从推导、求解、到算法最终的结果，都有着相当的相似。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 本次的内容主要是以推导数学公式为主，都是从算法的物理意义出发，然后一步一步最终推导到最终的式子，LDA和PCA最终的表现都是解一个矩阵特征值的问题，但是理解了如何推导，才能更深刻的理解其中的含义。本次内容要求读者有一些基本的线性代数基础，比如说特征值、特征向量的概念，空间投影，点乘等的一些基本知识等。除此之外的其他公式、我都尽量讲得更简单清楚。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;LDA：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LDA的全称是Linear Discriminant Analysis（线性判别分析），&lt;strong&gt;是一种supervised learning。&lt;/strong&gt;有些资料上也称为是Fisher&amp;#8217;s Linear Discriminant，因为它被Ronald Fisher发明自1936年，Discriminant这次词我个人的理解是，一个模型，不需要去通过概率的方法来训练、预测数据，比如说各种贝叶斯方法，就需要获取数据的先验、后验概率等等。LDA是在&lt;strong&gt;目前机器学习、数据挖掘领域经典且热门&lt;/strong&gt;的一个算法，据我所知，百度的商务搜索部里面就用了不少这方面的算法。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LDA的原理是，将带上标签的数据（点），通过投影的方法，投影到维度更低的空间中，使得投影后的点，会形成按类别区分，一簇一簇的情况，相同类别的点，将会在投影后的空间中更接近。要说明白LDA，首先得弄明白线性分类器(&lt;a href="http://en.wikipedia.org/wiki/Linear_classifier"&gt;Linear Classifier&lt;/a&gt;)：因为LDA是一种线性分类器。对于K-分类的一个分类问题，会有K个线性函数：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455463969.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455464493.png" width="153" border="0" height="33" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当满足条件：对于所有的j，都有Yk &amp;gt; Yj,的时候，我们就说x属于类别k。对于每一个分类，都有一个公式去算一个分值，在所有的公式得到的分值中，找一个最大的，就是所属的分类了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上式实际上就是一种投影，是将一个高维的点投影到一条高维的直线上，LDA最求的目标是，给出一个标注了类别的数据集，投影到了一条直线之后，能够使得点尽量的按类别区分开，当k=2即二分类问题的时候，如下图所示：&lt;/p&gt;  &lt;p&gt;&lt;a href="file:///C:/Documents%20and%20Settings/Administrator/Local%20Settings/Temp/WindowsLiveWriter-429641856/supfiles4CEE5/image%5b15%5d.png"&gt;&lt;img title="clip_image002" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="clip_image002" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455475507.gif" width="328" border="0" height="318" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 红色的方形的点为0类的原始点、蓝色的方形点为1类的原始点，经过原点的那条线就是投影的直线，从图上可以清楚的看到，红色的点和蓝色的点被&lt;strong&gt;原点&lt;/strong&gt;明显的分开了，这个数据只是随便画的，如果在高维的情况下，看起来会更好一点。下面我来推导一下二分类LDA问题的公式：&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设用来区分二分类的直线（投影函数)为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455476902.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455471885.png" width="84" border="0" height="32" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LDA分类的一个目标是使得不同类别之间的距离越远越好，同一类别之中的距离越近越好，所以我们需要定义几个关键的值。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 类别i的原始中心点为：（Di表示属于类别i的点)&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455476869.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455478264.png" width="106" border="0" height="55" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 类别i投影后的中心点为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455473248.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455488231.png" width="105" border="0" height="41" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 衡量类别i投影后，类别点之间的分散程度（方差）为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110108145548391.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455487326.png" width="163" border="0" height="62" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最终我们可以得到一个下面的公式，表示LDA投影到w后的损失函数：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455487850.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455484785.png" width="159" border="0" height="73" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 我们&lt;strong&gt;分类的目标是，使得类别内的点距离越近越好（集中），类别间的点越远越好。&lt;/strong&gt;分母表示每一个类别内的方差之和，方差越大表示一个类别内的点越分散，分子为两个类别各自的中心点的距离的平方，我们最大化J(w)就可以求出最优的w了。想要求出最优的w，可以使用拉格朗日乘子法，但是现在我们得到的J(w)里面，w是不能被单独提出来的，我们就得想办法将w单独提出来。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 我们定义一个投影前的各类别分散程度的矩阵，这个矩阵看起来有一点麻烦，其实意思是，如果某一个分类的输入点集Di里面的点距离这个分类的中心店mi越近，则Si里面元素的值就越小，如果分类的点都紧紧地围绕着mi，则Si里面的元素值越更接近0.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455491720.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455498656.png" width="212" border="0" height="54" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 带入Si，将J(w)分母化为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455497751.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110108145549226.png" width="521" border="0" height="57" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455507161.png" width="314" border="0" height="42" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 同样的将J(w)分子化为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455509636.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455508524.png" width="383" border="0" height="41" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 这样损失函数可以化成下面的形式：&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455509047.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455505982.png" width="139" border="0" height="56" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 这样就可以用最喜欢的拉格朗日乘子法了，但是还有一个问题，如果分子、分母是都可以取任意值的，那就会使得有无穷解，我们将分母限制为长度为1（这是用拉格朗日乘子法一个很重要的技巧，在下面将说的PCA里面也会用到，如果忘记了，请复习一下高数），并作为拉格朗日乘子法的限制条件，带入得到：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455513997.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455518425.png" width="266" border="0" height="123" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 这样的式子就是一个求特征值的问题了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 对于N(N&amp;gt;2)分类的问题，我就直接写出下面的结论了：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455514488.png"&gt;&lt;img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455516963.png" width="240" border="0" height="143" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 这同样是一个求特征值的问题，我们求出的第i大的特征向量，就是对应的Wi了。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 这里想多谈谈特征值，特征值在纯数学、量子力学、固体力学、计算机等等领域都有广泛的应用，特征值表示的是矩阵的性质，当我们取到矩阵的前N个最大的特征值的时候，我们可以说提取到的矩阵主要的成分（这个和之后的PCA相关，但是不是完全一样的概念）。在机器学习领域，不少的地方都要用到特征值的计算，比如说图像识别、pagerank、LDA、还有之后将会提到的PCA等等。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp; 下图是图像识别中广泛用到的特征脸（eigen face），提取出特征脸有两个目的，首先是为了压缩数据，对于一张图片，只需要保存其最重要的部分就是了，然后是为了使得程序更容易处理，在提取主要特征的时候，很多的噪声都被过滤掉了。跟下面将谈到的PCA的作用非常相关。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455522470.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455526341.png" width="192" border="0" height="230" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 特征值的求法有很多，求一个D * D的矩阵的时间复杂度是O(D^3), 也有一些求Top M的方法，比如说&lt;a href="http://en.wikipedia.org/wiki/Power_method"&gt;power method&lt;/a&gt;，它的时间复杂度是O(D^2 * M), 总体来说，求特征值是一个很费时间的操作，如果是单机环境下，是很局限的。 &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;PCA：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 主成分分析（PCA）与LDA有着非常近似的意思，LDA的输入数据是带标签的，而PCA的输入数据是不带标签的，所以PCA是一种unsupervised learning。LDA通常来说是作为一个独立的算法存在，给定了训练数据后，将会得到一系列的判别函数（discriminate function），之后对于新的输入，就可以进行预测了。而PCA更像是一个预处理的方法，它可以将原本的数据降低维度，而使得降低了维度的数据之间的方差最大（也可以说投影误差最小，具体在之后的推导里面会谈到）。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 方差这个东西是个很有趣的，有些时候我们会考虑减少方差（比如说训练模型的时候，我们会考虑到方差-偏差的均衡），有的时候我们会尽量的增大方差。方差就像是一种信仰（强哥的话），不一定会有很严密的证明，从实践来说，通过尽量增大投影方差的PCA算法，确实可以提高我们的算法质量。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 说了这么多，推推公式可以帮助我们理解。&lt;strong&gt;我下面将用两种思路来推导出一个同样的表达式。首先是最大化投影后的方差，其次是最小化投影后的损失（投影产生的损失最小）。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最大化方差法：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设我们还是将一个空间中的点投影到一个向量中去。首先，给出原空间的中心点：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455521324.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455522720.png" width="113" border="0" height="61" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设u1为投影向量，投影之后的方差为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455537703.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455539863.png" width="240" border="0" height="60" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面这个式子如果看懂了之前推导LDA的过程，应该比较容易理解，如果线性代数里面的内容忘记了，可以再温习一下，优化上式等号右边的内容，还是用拉格朗日乘子法：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455531258.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455531781.png" width="162" border="0" height="38" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 将上式求导，使之为0，得到：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455537637.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455532621.png" width="79" border="0" height="33" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这是一个标准的特征值表达式了，&amp;#955;对应的特征值，u对应的特征向量。上式的左边取得最大值的条件就是&amp;#955;1最大，也就是取得最大的特征值的时候。假设我们是要将一个D维的数据空间投影到M维的数据空间中（M &amp;lt; D)， 那我们取前M个特征向量构成的投影矩阵就是能够使得方差最大的矩阵了。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最小化损失法：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设输入数据x是在D维空间中的点，那么，我们可以用D个正交的D维向量去完全的表示这个空间（这个空间中所有的向量都可以用这D个向量的线性组合得到）。在D维空间中，有无穷多种可能找这D个正交的D维向量，哪个组合是最合适的呢？&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 假设我们已经找到了这D个向量，可以得到：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455549240.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110108145554636.png" width="100" border="0" height="58" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们可以用近似法来表示投影后的点：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455545619.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455546143.png" width="191" border="0" height="68" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上式表示，得到的新的x是由前M 个基的线性组合加上后D - M个基的线性组合，注意这里的z是对于每个x都不同的，而b对于每个x是相同的，这样我们就可以用M个数来表示空间中的一个点，也就是使得数据降维了。但是这样降维后的数据，必然会产生一些扭曲，我们用J描述这种扭曲，我们的目标是，使得J最小：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455541126.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455548061.png" width="163" border="0" height="58" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上式的意思很直观，就是对于每一个点，将降维后的点与原始的点之间的距离的平方和加起来，求平均值，我们就要使得这个平均值最小。我们令：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455556633.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455555520.png" width="344" border="0" height="50" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 将上面得到的z与b带入降维的表达式：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110108145555504.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455557439.png" width="240" border="0" height="57" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 将上式带入J的表达式得到：&lt;/p&gt;  &lt;p&gt;&amp;nbsp; &lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455552422.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455564898.png" width="366" border="0" height="66" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 再用上拉普拉斯乘子法（此处略），可以得到，取得我们想要的投影基的表达式为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455565977.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/20110108145556961.png" width="85" border="0" height="41" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里又是一个特征值的表达式，我们想要的前M个向量其实就是这里最大的M个特征值所对应的特征向量。证明这个还可以看看，我们J可以化为：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455565944.png"&gt;&lt;img title="image" style="border: 0px none; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="http://images.cnblogs.com/cnblogs_com/LeftNotEasy/201101/201101081455567340.png" width="85" border="0" height="60" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 也就是当误差J是由最小的D - M个特征值组成的时候，J取得最小值。跟上面的意思相同。&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下图是PCA的投影的一个表示，黑色的点是原始的点，带箭头的虚线是投影的向量，Pc1表示特征值最大的特征向量，pc2表示特征值次大的特征向量，两者是彼此正交的，因为这原本是一个2维的空间，所以最多有两个投影的向量，如果空间维度更高，则投影的向量会更多。&lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" src="http://lion.cs.uiuc.edu/projects/wmn/fig2.jpg" width="284" height="208"  alt="" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;总结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 本次主要讲了两种方法，PCA与LDA，两者的思想和计算方法非常类似，但是一个是作为独立的算法存在，另一个更多的用于数据的预处理的工作。另外对于PCA和LDA还有核方法，本次的篇幅比较大了，先不说了，以后有时间再谈：&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;strong&gt;参考资料：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; prml bishop，introduce to LDA（对不起，这个真没有查到出处）&lt;/p&gt;&lt;img src="http://www.cnblogs.com/LeftNotEasy/aggbug/1930645.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/LeftNotEasy/archive/2011/01/08/lda-and-pca-machine-learning.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
