算法统综感悟
1. 大哥 大姐 求一篇 学计算机新技术的感想作文 我们听的是演讲 == 800字左右 拜托 急用啊 .......谢谢了
1.开场
自我介绍, 简单讲述我大学的学习的历程,成果和感想。(1分钟)
我一直都感慨本年级许多同学在大一时因为缺乏好指引,在一开始就对编程很害怕,对计算机的学习没有开好头,动手能力长期跟不上,空会理论,不会实践,一直拖累到大四,最终选择忍痛考研或者抱怨找工作难。我也帮助过不少在这方面比较弱的同学,但是总是因为基础没打好导致难以提高。我也一直希望学校能在大一的时候就让同学们明白学习的重要性,打好扎实的专业基础。现在终于有一次这样的机会站在这里,为指引大家如何在大学专业技术学习的道路上开好头做点贡献。
今天我将结合我自身的经历和我对计算机的理解,我对编程的感悟,我对大学学习的认识,给大家做报告。
首先问三个问题:
1) qq聊天软件是用什么语言写的(第二天要换个问题)
答对的演讲结束后留下来,我要亲自给他传授宝贵经验,没人答的话,很遗憾
2) 谁玩电脑游戏比较牛
恩,人很多,大家很踊跃,很好
展示下我写的人工智能黑白棋游戏,声明真正的编程高手基本从来不玩游戏
(结合大四同学长期沉迷游戏最后找不到工作的例子,说明一个严肃的问题,只会玩游戏没有用,会做游戏才牛,鼓励大家努力学习,让会玩游戏的同学也热爱编程,最后也能自己写游戏)
请大家记住:只会玩游戏没有用,会做游戏才牛
3) 有没有人对计算机特别感兴趣 (为什么感兴趣)
如果有兴趣,对学习计算机有巨大的帮助
兴趣是最好的老师,鼓励他们,勉励其他人,兴趣是可以培养的,要学会培养兴趣
2.概述
计算机"科学"与"技术" 包含两个层面
"科学" 指计算机硬件、软件与应用的理论知识 理论的学习
"技术" 指软件开发、工程实践等技能与方法 能力的培养
我主要讲的是如何学习技术(计算机技术)
讲之前 澄清一个观点 计算机技术 不等于 编程技术
编程只是一个工具,编程没学好不代表你技术就学不好
计算机技术应该是与计算机软件、硬件和网络三个部分相关的各种科技成果和应用的综合,包括了多媒体,数据库,操作系统,嵌入式系统,计算机安全,计算机网络,计算机管理和维护,计算机应用,人工智能,模式识别,管理信息系统等,在我们生活的方方面面计算机技术几乎无处不在。
(举几个例子)在现在社会,它几乎与我们的生活息息相关。
(大学和高中的学习方式的区别)(学好技术的重要性)
在大学,学习的方式与高中或小学是有很大的区别的,大学更大,大学更自由,不再是完全跟着老师,不再是只要吃透了老师教授的内容就万事大吉了,从我这一届的情况看,许多同学特别是女生在大学还沿袭着高中的学习方式,勤奋刻苦,天天自习,非常认真,上课笔记做得秘密麻麻,把理论学得非常扎实,但是却严重地忽略了实践能力的培养,理论考试分数很高,但课程设计做不出东西来,显然这种学习方式是不对的,这和高中的偏科又有什么本质区别呢。
我觉得理论的学习和技术的学习是同等重要的,二者都不应该轻视,没有侧重点是不可能的,至于如何侧重,如何在二者之间找到平衡点就取决于你自己的人生目标了。如果你喜欢研究理论,以后想继续读研深造可以稍微偏向理论,把理论基础打得扎实一些,毕业以后可以留校任教或到科研院所去发展。如果你想走技术路线,那么你就可以稍稍偏向技术,在不落下理论学习的情况下,把技术学好学精,毕业以后可以去IT企业发展,也可以自己创业,有了一身技术不怕没饭吃。切莫完全忽视技术最后变成书呆子或完全不顾理论最后只是个代码搬运工。
大家每个人,从现在开始就要下决心学好技术,那么,如何学好技术呢。
3.如何学好技术
3.1制定好的学习计划
3.1.1大一大二:打好基础
3.1.1.1计算机方面的基本技能的学习
包括计算机众多的应用技术的学习 和 常见的硬件维护
(大家应该尽量多多掌握计算机方面的基本技能,如word excel ppt access* photoshop* flash* dreamveaver* 结合我的经历讲讲,我大一在自己没有电脑的情况下把这些基本全学了 举一个考研的同学不会在excel里找自己的名字的例子,如果这些最基本的技能都不会,只能说计算机还没入门)大二有电脑之后,终于有机会整自己的电脑了,要学习常见的常见的硬件维护(系统崩溃了怎么办,如何安装操作系统,如何分区等)
3.1.1.2专业理论基础和编程基础的学习
技术是将理论运用到实践中去,不能轻视理论,没有理论何来应用。计算机"科学"与"技术" 中的"科学"和"技术"应该是相互依赖和促进的。
先学好《高级语言程序设计》《数据结构》等专业课,理论基础扎实了,学应用性技术就更容易了
编程基础:学精C++(为什么),可以考虑过渡到 java 或 C# (最好只学一个,为什么)
(编程的学习会在后面再详细讲)
3.1.1.3珍惜这两年大学自由学习的黄金时间
(曾经和一家公司的经理开玩笑,总经理感慨的说现在在大学里找一个又能力的学生来帮忙做项目真是很难啊,我说是呀,大学四年,大一的刚进校还在打基础没法做,大二的还刚起步没足够的能力做,大三的课程会很紧没时间做,大四的找工作的找工作去了,考研的考研去了,没人做了),大学四年,实则三年,希望大家不要把最宝贵的时间荒废在游戏和娱乐上
3.1.2大三:深入学习,确定方向(技术方向,职业规划)+多多实践
到了大三,各种专业课会非常多,包括很重要的操作系统,汇编,组成原理,编译原理,数据库,计算机网络,软件工程等等,大家将深入学习计算机的各大核心课程。这时大家的基础打得也差不多了,可以选择一门自己比较感兴趣的技术并确定自己的技术的一个方向,比如选择j2ee, .NET,WEB技术,数据库技术,嵌入式,linux内核开发等等。当然也会有非常丰富多彩的专业选修课可以选择学习。这段时间大家可以利用课程设计的机会好好锻炼自己。
3.1.3大四:实践和进步
大四,如果不打算考研的同学,工作有了着落之后,可以试着做项目,大四基本没什么课,相对轻松,这段时间是获得经验,银子和巨大的进步黄金时期。
3.2重视专业课的学习
要把数据结构、算法、数据库、操作系统原理、计算机体系结构、计算机网络,离散数学等基础课程学好
除非你足够牛,请务必认真听专业课,有些课像《数据结构》,《编译原理》,《组成原理》,《操作系统》等等,这种课老师讲一分钟能让你明白的内容,你自己看要看好几个月
3.3培养好的思维能力
数学是锻炼是思维的最好的东西了,他是你思考问题的最得力的工具,他体现着你的思想,在编程中会思考才能编出好的程序。
此外还要注重离散数学,数值分析,线性代数,数字逻辑等等课程的学习,他们对培养好的思维能力大有裨益
3.4激励创新意识
创新太重要了,不管在哪个学科都重要,计算机同样需要
3.5培养独立分析问题和解决问题的能力
遇到问题,要先学会独立思考,不能凡事依赖他人,尽量自己解决,在独立解决问题过程中能获得更大的进步,实在不能解决再请教别人也不迟
3.6培养自学能力和快速获取知识的能力
自学能力之重要(大学和高中的学习方式的区别)
可以说高中是靠老师,大学是靠自己,要做到严格自律,自我约束,必须要学会自学
学习的过程也是学会学习的过程
要充分利用图书馆和网络上的丰富学习资源, 要培养计算机新知识,新技术方面的自学习能力,要学会如何通过网络,书籍,文献,独立地快速获取自己需要的知识和信息
3.7培养团队协作精神
在一个大型项目中,往往要求各种参与者密切配合才能取得成功。大家要从现在就开始注重团队协作精神的培养,要学会与人沟通,善于表达,要注意提高自己的综合素质,成为综合型人才。
3.8学好英语
包括现在的大学英语和日后的专业英语。
也许有人会问,英语和技术有什么大的关系吗。大家是否知道,计算机的发展飞速,国际上新技术不断涌现,如果今天国外出现了一门新的技术,或者国外某本技术书籍出了新版本,相关资料的中文的翻译不知道要等到什么猴年马月才会出来,现在的许多出版也有了越来越多的英文原版书。
大家要学好英语,培养阅读专业外语资料的能力,开始会看不懂,看多了自然熟练了。
(讲下四六级,四级最好一次就过,六级在大二下结束前最好过)
3.9适时关注新技术
了解学科发展动态,跟上时代步法
3.10勤学苦练,持之以恒
学好技术不是一蹴而就的,要长期坚持。
4.无
5.无
6.关于编程的学习
6.1为什么要学习编程
编程是软件开发的基础,学习计算机,只会编程是千万不行的,但是开发软件,不会编程是万万不行的
(结合本年级的情况将一下现状,学习的重要性等)
6.2编程真的那么难学吗
(讲讲编程的苦与乐)
编程真的那么可怕,那么枯燥,那么没意思吗?假如真是这样,为什么世界上还有那么多优秀的人乐此不疲。
其实编程并不可怕,可怕的是你的心态。
编程固然很苦,编程时长时间对着屏幕,对身体不好,而且,经常因为考虑不周,会遇到各种各样的错误和麻烦,初学者处处容易受挫。
但是其实编程是很有趣的,编程中充满着无穷的快乐
首先,你通过编程得到了想要的成果的过程是一种创造的快乐
(编出了有用的东西的那一刻会有一股美好的成就感)
其次,你开发了有用的软件可以方便自己或他人,方便自己,是一种享受的快乐,方便他人,是一种奉献的快乐
再次,假如你开发的软件得到了用户的认可或好评,会有一种欣慰和满足感
还有,你可以根据自己的意愿写你想要的东西,经过自己的努力亲自实现你心中的愿望
然后,编程也是一个挑战自我的过程,遇到困难想办法解决的过程是思考的过程,思维能得到锻炼
最后,在代码中有一种看不见的美,就像诗一样,美景全是你的,你可以随心所欲
编程真的非常有趣,它不仅满足了我们内心深处进行创造的渴望,让人头脑变得灵活,而且还愉悦了每个人内在的情感。
6.3学好编程的建议
6.3.1请热爱编程
如果想成为编程牛人的话,请热爱编程。有兴趣是最好了,没兴趣也没关系,可以慢慢培养,当你感受到了编程的乐趣的时候你会爱上它。
6.3.2不要畏难
很多初学者往往都在遇到许多困难,遭受多次挫折后,自信心受到打击从而对编程丧失兴趣
这些困难每个人都会遇到,我在初学编程时也遇到过,关键是看你用什么心态对待,是想办法解决困难还是选择逃避。很多问题其实是有很多解决方法的。譬如看书,遇到看不懂的部分,可以暂时跳过,先往后看,看完后面的之后,再回头看前面跳过的部分往往会有一种豁然开朗的感觉。再比如,编程调试时死活找不到错误会很郁闷,这个时候很多同学会束手无策,其实只要在程序不同的地方加上输出语句,然后运行看有哪些输出,这样一步步缩小错误的范围从而确定错误发生的位置。等等。。。
不要畏惧困难,要用你的智慧战胜它。
6.3.3多实践,多交流
学习编程的秘诀是:编程,编程,再编程;(讲讲如何动手实践)
在学校的实验室就算你做错一万次程序都不会有人骂你,如果在公司你试试看!所以多去实验室上机,现在错得多了,毕业后就错得少了。多实践,多从失败中吸取教训,积累经验。要勤奋,三天打鱼两天晒网是学不好的,学会了的东西一段时间不用就容易忘记,实践得越多才能记得越牢。
现在大家是大一,可能有人会说没有电脑不方便,其实实验室不是只有在老师安排的实验时间才可以去的,它是是面向计算机专业的学生免费开放的,大家有时间就去实验机房练习,只要拿着学生证,或者干脆直接跟那个阿姨说你是计算机的就行了。航海楼7楼的机房和图书馆电子阅览室也是可以的。我大一的时候甚至还到阳光网吧编程呢。
到大二大三的时候课程设计就会多起来,大家一定要自己动手做,不要去网上搜一个就完事了。
与人交流,分享自己编程中的乐趣和经验,共同进步。
6.3.4多阅读书籍和代码
编程不是非要在电脑上才能学的,阅读书籍和书中的代码也是一种学习方式,自己还可以尝试着改进那些代码,最后可以把自己的成果拿到电脑上调试
千万不要忽视书后面的习题
6.3.5养成良好习惯
细节很重要
要细心,沉下心来编程,戒骄戒躁
养成良好习惯,注重编程风格,尽量写代码注释,把写过的代码保留下来,以后会有用
6.3.6善于思考
遇到问题动脑筋解决
6.3.7注重基础
打好编程基础,除了熟悉基本的语法之外,要深刻理解指针,引用,面向过程思想,类,模板,标准库,接口,继承机制,面向对象思想等等,课后习题尽量全做一下
刚才说了,有精力的可以学学 photoshop图像处理, flash动画制作,3dmax或maya三维建模,dreamveaver网页设计,但是不要因为他们花费过多的时间而影响了你基础的学习,那些都是些应用技术,你学会了更好,不会也没什么丢人的,基础打好了,以后学啥都轻松。
在基础没打好的情况下,不要觉得你编的程序只能在黑白的DOS窗口了运行就去学VC做漂亮的窗口,3d程序很有意思就去看OpenGL或DirectX,那些都属于高级应用,没有基础学起来会很吃力。
基础要扎实,不要觉得C#中没有指针就扔掉C++, 不要今天看C#,明天搞java
要有明确的方向,计算机技术的发展实在太快,新技术不断涌现,了解一下就可以了,不要随波逐流,要沉得住气
6.3.8选好开发环境
选择一种适当的开发环境并熟悉它就可以了,不要今天摆弄Visual Studio,明天钻研Eclipse,后天来个netbeans,在工具的使用的学习上白白浪费时间。
6.3.9选好编程语言
我在选择语言时,走过一些弯路,浪费了一些精力,我在这里选出一些主流编程语言,对语言特性与环境稍作介绍,希望可以帮助大家,让大家尽早了解与选择,少走弯路
C(多用在性能要求较高的场合,如操作系统,嵌入式等)
C++(应用最广泛、成熟,强大而复杂,兼有性能高和易于构建大型程序的优点,基本是衡量一个国家软件产业发达程度的核心基础)
Java(着名的SUN公司推出的,面向对象、安全、跨平台、强大稳健,需要java虚拟机的支持)
C#(微软推出的完全面向对象,运行在 .NET Framework 环境中新兴、易学、强大语言)
Python(新兴的面向对象脚本语言,跨平台,语法清新易于使用,代码优美得像数学一样,非常容易学)
PHP (目前最流行、强大、稳健的动态网站开发脚本语言,语法类似C++)
ActionScript (Flash的编程脚本,最新版支持面向对象,能基于Flex开发RIA应用)
除此之外,还有vb, vb.net, asp.net, jsp, asp, ruby, Javascript等
这么多五花八门的语言,大家可能都会觉得眼花缭乱了。
其实各种语言之间只是语法不同,编程思想都是相通的,学精一门,了解多门是上策。
" 程序=算法+数据结构 " 其中并没有编程语言,说明语言只是程序员与计算机的编译器沟通的一种工具,程序员用某种语言来表达程序的逻辑结构,计算机中相应的编译器或解释器理解这种语言,编译得到二进制程序或者直接解释执行。
以上这些语言我在大学前三年全部学过了,有的学得很深,有的很浅。因为人的精力毕竟有限,很多语言学过了之后根本就很少用到,几乎是白学了,现在我深深的体会到,
语言并不是学得越多越好,与其泛而不精不如有针对性的先精通一门,其他的触类旁通。
就大家现在的情况,希望大家把当前正在学习的C++学好,学到一定程度的时候,可以继续深入的研究C++的各种库,也可以从上面选择感兴趣的新语言学习,如果把C++基础打好了,后面的学习就会容易得多。
最流行的语言不一定是最好的语言,用的人最多的语言也不一定是最好的语言。
请大家记住,没有最好的语言,只有最适合某个领域的语言, 在不同的环境下选择不同的语言就可以了。
6.3.10重视数据结构和算法
理论上,计算机的任何编程语言都有可能会被淘汰,随着时间的推移和计算机软硬件的飞速发展,不断会有新的语言产生和和旧的语言过时,但不会过时的是数据结构和优秀的算法。真正的高手应该是善于设计优秀的数据结构和算法的,应该是具有独立分析和解决问题的能力并利用计算机程序来实现的,他的思想应该是超脱语言、在更高处的一种升华。
如果某一天,你深切的体会到,真正重要的不是什么语言而是思想的时候,说明你可以出师了。
2. EM算法深度解析
最近在做文本挖掘的时候遇到了EM算法,虽然读书的时候简单地接触过,但当时并没有深入地去了解,导致现在只记得算法的名字。既然EM算法被列为数据挖掘的十大算法之一,正好借这个机会,重新学习一下这个经典的算法。学习的过程中,我发现网上的资料大多讲解地不够细致,很多地方解释得并不明了。因此我决定抛开别人的想法,仅从数学推导本身出发,尽力理解每一个公式的含义,并将其对应到实际的实验过程当中。这篇博客记录了我对与EM算法的思考与理解,也是我人生中的第一篇博客,希望能够对于想要学习EM算法的同学有所帮助。
前面谈到我在做文本挖掘的时候遇到了EM算法,EM算法用于估计模型中的参数。提到参数估计,最常见的方法莫过于极大似然估计——在所有的候选参数中,我们选择的参数应该让样本出现的概率最大。相信看到这篇笔记的同学一定对极大似然估计非常熟悉,而EM算法可以看作是极大似然估计的一个扩充,这里就让我们用极大似然估计来解决一个简单的例子,来开始正式的讨论。
有A,B,C三枚硬币,我们想要估计A,B,C三枚硬币抛出正面的概率 , , 。我们按如下流程进行实验100次:
记录100次实验的结果如下:
我们将上面的实验结果表述如下:
表示第i次实验中,硬币A的结果,1代表正面,0代表反面; 表示第i次实验中,硬币B或硬币C抛出正面的个数,则参数 的极大似然估计分别为:
即硬币A,B,C各自抛出正面的次数占总次数的比例,其中 为指示函数。
实验流程与1相同,但是我们不慎遗失了硬币A的记录结果,导致我们只知道随后十次抛出了多少次正面,多少次反面,却不知道实验结果来自于硬币B还是硬币C。在这种情况下,我们是否还能估计出 , , 的值呢?
这时候利用极大似然估计似乎行不通了, 因为这种情况下,我们不但缺失了硬币A产生的观测值,同时也不知道哪些观测值属于硬币B,哪些观测值属于硬币C。
有些同学可能会提出,虽然我们无法得到三个硬币各自产生的样本,但是我们依然可以得到每个观测值出现的概率。比如在第一次实验中, 我们抛出了5次正面5次反面,我们可以做如下思考:
假设这5次正面由硬币B得到,那么概率应该为 ,而这次观测值来自于硬币B,也就是硬币A抛出正面的概率为
假设这5次正面由硬币C得到,那么概率应该为 ,而这次观测值来自于硬币C,也就是硬币A抛出反面的概率为
综合起来,利用条件概率公式,这个观测值出现的概率就是
因此我们可以将样本整体的概率和似然函数利用 , , 表示出来,通过对似然函数求导,令其关于 的偏导数等于0,我们可以求出三个参数的值。
这个思路听上去十分合理,我们可以顺着这个思路进行数学推导,看看可以得到什么样的结果。首先我们计算样本的概率:
对应的似然函数为
其中 关于 的条件分布为
的分布为
因此我们可以得到
至此,我们成功地得到了似然函数。然而观察可以发现,这个函数是由100项对数函数相加组成,每个对数函数内部包含一个求和,想通过求导并解出导数的零点几乎是不可能的。当然我们可以通过梯度下降来极小化这个函数,借助深度学习库的自动微分系统在实现上也非常容易。但是这种做法过于简单粗暴,有没有办法来优雅地解决这个问题呢?在继续讨论之前,我们先将这类问题进行一般化表述:
我们观测到随机变量 产生的m个相互独立的样本 , 的分布由联合分布 决定, 是缺失数据或无法在实验中被直接观测到,称为 隐变量 ,我们想要从样本中估计出模型参数 的值。在接下来的讨论中,我们假定 的取值是离散的,于是可以得到似然函数如下:
接下来,我们就探讨一下,如何利用EM算法解决这个问题。
这一部分的数学推导,主要参考了吴恩达CS229n的笔记,并且根据个人的思考和理解,尽力对公式的每一步进行详细的解释。我们先简单地介绍一下琴生不等式。
琴生不等式有多种形式,下面给出其离散形式的表述和概率论中的表述:
1.若 为严格凹函数, 为定义域内的n个点, 是n个正实数,且满足 , 则下述不等式成立:
当且仅当 时,不等式取等号。
2.若 为严格凹函数, 为实值随机变量,且期望存在,则下述不等式成立:
当且仅当 ,即 为常数时,不等式取等号。
注: 这里将函数上方为凹集的函数称为凹函数, 例如 函数就是凹函数。
相信大家对琴生不等式都十分熟悉,因此这里就不做过多的说明。接下来,我们将琴生不等式应用到我们的问题中。
回到我们之前的问题上, 我们想要极大化下面这个函数:
但是我们无法对这个函数直接求导,因此我们借助琴生不等式,对这个函数进行变换。为了让过程看上去简洁,下面只对求和中的第 项进行计算。
令 满足 ,且 ,则根据琴生不等式,可以得到:
当且仅当 为常数时,上述不等式取等号。也就是说,对于任意 , 是一个与 无关的量。设对于任意 ,我们可以得到:
因此当 时,不等式 取等号,容易验证此时 , 与 无关。将 综合一下,我们可以得到以下结论:
到这里为止,我们已经拥有了推导出EM算法的全部数学基础,基于 我们可以构建出E步和M步。上面的数学推导虽然看上去略为复杂,但实际上只用到了三个知识点:
1.琴生不等式:
2.条件概率:
3.联合分布求和等于边缘分布:
对上面的数学推导有疑问的同学,可以结合上面这三点,再将整个推导过程耐心地看一遍。
大部分关于EM算法的资料,只是在数学形式上引入了 函数,即 ,以满足琴生不等式的使用条件,却没有过多地解释 函数本身。这导致了很多人完全看懂了算法的推导,却还是不理解这些数学公式究竟在做什么,甚至不明白EM算法为什么叫做EM算法。所以在给出E步和M步之前,我想先谈一谈 函数。
我们回顾一下 函数所满足的条件(暂时不考虑琴生不等式取等号的限制),
在 所有可能的取值处有定义。可以看出, 是 的样本空间上任意的一个概率分布。因此,我们可以对不等式 进行改写。首先我们可以将含有 的求和写成期望的形式:
这里 指的是在概率分布 下,求随机变量 和 的期望。有同学会问,为什么我们平时求期望的时候只要写 ,并没有指明是在哪个概率分布下的期望。这是因为一般情况下,我们都清楚地知道随机变量 所服从的分布 ,并且默认在分布 下求期望。
举个例子,我手上有一个硬币,抛了10次,问抛出正面次数的期望。这种情况下,大部分人会默认硬币是均匀的,也就是说抛出正面的次数 服从二项分布 ,期望 。这时有人提出了质疑,他说我认为你这个硬币有问题,抛出正面的概率只有0.3,那么在他眼里, 期望 。
回到正题,我们利用等式 改写不等式 ,可以得到:
这正是琴生不等式在概率论中的形式。我们可以将不等式倒过来理解:
首先,假定随机变量 服从概率分布 , 是 的样本空间上的任意一个概率分布。这里 可以是一组定值,也可以是关于参数 的函数。
显然,当我们取不同的 时,随机变量 的期望也会随之改变。需要注意的是,由于 与 相关,所以这里的期望不是一个数值,而是关于 的函数。
当我们令 为 的后验分布 时,上面的期望最大。这里有两点需要注意,1. 后验分布 也是一个关于参数 的函数。2. 由于期望是关于 的函数,所以这里的最大指的并非是最大值,而是最大的函数。
若对于每一个 ,我们都令 为 的后验分布 ,则上述期望之和等于我们要极大化的似然函数,即
通过上述分析,我们为寻找似然函数的极大值点 提供了一个思路。我们不去极大化似然函数本身,而是去极大化 。至于如何将这个思路实际应用,就要利用到EM算法中的E-step和M-step。
这一节中,我们先给出E-step和M-step的数学形式,随后在结合抛硬币的例子来解释这两步究竟在做什么。下面进入算法的流程,首先我们任意初始化 ,按下述过程进行迭代直至收敛:
在第 次迭代中,
(E-step)对于每个 ,令
(M-step)更新 的估计值,令
EM算法从任意一点 出发,依次利用E-step优化 ,M-step优化 ,重复上述过程从而逐渐逼近极大值点。而这个过程究竟是怎样的呢,就让我们一步步地揭开EM算法的面纱。
假设我们现在随机初始化了 ,进入第一轮迭代:
(E-step)
由于我们已经假定模型参数为 ,所以此时 不再是与 有关的函数,而是由一组常数构成的概率分布。结合抛硬币的例子来看,这一步是在我们已知模型参数 的基础上(虽然这是我们瞎猜的),去推测每一次的观测值是由哪个硬币产生的,或者说我们对每一次观测值做一个软分类。比如我们根据初始化的参数,计算出 , 。可以解释为第 个观测值有20%的概率来自于硬币B,80%的概率来自于硬币C;或者说硬币A抛出了0.2个正面,0.8个反面。
(M-step)
考虑到 是一组常数,我们可以舍弃常数项,进一步简化上面这个要极大化的函数
由于 不再与 相关,因此上面的函数变成了对数函数求和的形式,这个函数通常来说是容易求导的,令导数等于0,我们可以求出新的参数 。我们仍旧以抛硬币为例进行解释,
令 , 可以得到,
这三个参数的解释是显而易见的。我们在E-step中对每个观测值进行了软分类, 可以看成是硬币A抛出正面的次数,所以 是 的极大似然估计; 是我们抛硬币B的次数, 是硬币B抛出正面的次数,所以 是 的极大似然估计;对于 我们有相同的解释。
我们将这个结果与抛硬币1中极大似然估计的结果相比较可以发现,之前结果中的指示函数 变成了这里的 ,在指示函数下,某个观测值要么来自于硬币B,要么来自于硬币C,因此也称为硬分类。而在 函数下,某个观测值可以一部分来自于硬币B,一部分来自于硬币C,因此也称作软分类。
将上述两步综合起来,EM算法可以总结如下:我们首先初始化模型的参数,我们基于这个参数对每一个隐变量进行分类,此时相当于我们观测到了隐变量。有了隐变量的观测值之后,原来含有隐变量的模型变成了不含隐变量的模型,因此我们可以直接使用极大似然估计来更新模型的参数,再基于新的参数开始新一轮的迭代,直到参数收敛。接来下我们就讨论为什么参数一定会收敛。
前面写了太多的公式,但是这一部分我不打算给出收敛性的数学推导。其实数学上证明EM算法的收敛性很容易,只需要证明每一轮迭代之后,参数的似然函数递增,即