em博客源码
㈠ jQuery源码分析之实例find和filter方法的区别七问
filter()过滤DOM元素包装集,是指操作当前元素集,删除不匹配的元素,得到一个新的集合
$('div').filter('.div1');//选择div标签中class属性为div1的div元素
find()在当前选中元素的上下文中找到符合条件的后代,返回的是子元素
$('div').find('em');//选择div标签中的em标签的元素
filter()是对选中的元素集合操作,得到这些元素中符合条件的元素,而find()是得到选中元素 中符合条件的后代子元素。
㈡ 简易c++斗地主源码,简单的斗地主不需要ui,只要能发牌,随机决定地主,把牌按大小顺序排列
#include <time.h>
#include <iostream>
#include <string>
#include <vector>
enum em_CardClass_t
{
_CC_hearts = 0, // 红桃
_CC_Spade, // 黑桃
_CC_Clubs, // 梅花
_CC_Diamonds, // 方块
_CC_King // 大小王
};
struct st_Card_t
{
em_CardClass_t _emCardClass;
UINT _uCardIndex; // _emCardClass为_CC_King时,有效取值[1,2]
// _emCardClass非_CC_King时,有效取值[1,13]
};
using namespace std;
void InitCard(vector<st_Card_t>& vtCard)
{
st_Card_t card;
for( UINT i=0; i<_CC_King; i++ )
{
card._emCardClass = (em_CardClass_t)i;
for( UINT j=1; j<14; j++ )
{
card._uCardIndex = j;
vtCard.push_back(card);
}
}
card._emCardClass = _CC_King;
card._uCardIndex = 1;
vtCard.push_back(card);
card._uCardIndex = 2;
vtCard.push_back(card);
}
// 分牌
void DealCard(vector<st_Card_t>& vtCard, vector<st_Card_t>& vtPlayer1,
vector<st_Card_t>& vtPlayer2, vector<st_Card_t>& vtPlayer3)
{
srand( (unsigned)time( NULL ) );
for( int i = 0; i < 51; i++ )
{
int iCard = rand() % vtCard.size();
switch( i % 3 )
{
case 0:
vtPlayer1.push_back(vtCard[iCard]);
break;
case 1:
vtPlayer2.push_back(vtCard[iCard]);
break;
default:
vtPlayer3.push_back(vtCard[iCard]);
break;
}
if( iCard != vtCard.size()-1 )
{
vtCard[iCard] = vtCard[vtCard.size()-1];
}
vtCard.pop_back();
}
}
// 叫牌
int Bid(vector<st_Card_t>& vtCard, vector<st_Card_t>& vtPlayer1,
vector<st_Card_t>& vtPlayer2, vector<st_Card_t>& vtPlayer3)
{
srand( (unsigned)time( NULL ) );
int iBider = rand() % 3; // 叫牌者,也就是地主
vector<st_Card_t>* pPlayer = NULL;
switch( iBider )
{
case 0:
pPlayer = &vtPlayer1;
break;
case 1:
pPlayer = &vtPlayer2;
break;
default:
pPlayer = &vtPlayer3;
break;
}
for( UINT i = 0; i < vtCard.size(); i++ )
{
pPlayer->push_back(vtCard[i]);
}
return iBider;
}
// 整牌(按红桃、黑桃、梅花、方块、小大王的花色顺序整理,同一花色再按从小到大的顺序整理)
void SortCard(vector<st_Card_t>& vtPlayer)
{
st_Card_t tmp;
for( UINT i=0; i<vtPlayer.size()-1; i++ )
{
for( UINT j=i+1; j<vtPlayer.size(); j++ )
{
if( vtPlayer[i]._emCardClass < vtPlayer[j]._emCardClass )
{
continue;
}
if( vtPlayer[i]._emCardClass == vtPlayer[j]._emCardClass &&
vtPlayer[i]._uCardIndex < vtPlayer[j]._uCardIndex )
{
continue;
}
tmp = vtPlayer[i];
vtPlayer[i] = vtPlayer[j];
vtPlayer[j] = tmp;
}
}
}
void PrintPlayerCard(const string& sPlayerName,
const vector<st_Card_t>& vtPlayer)
{
cout << sPlayerName << " cards:" << endl;
for( UINT i=0; i< vtPlayer.size(); i++ )
{
switch( vtPlayer[i]._emCardClass )
{
case _CC_hearts:
cout << "红桃";
break;
case _CC_Spade:
cout << "黑桃";
break;
case _CC_Clubs:
cout << "梅花";
break;
case _CC_Diamonds:
cout << "方块";
break;
default:
cout << "King";
break;
}
cout << vtPlayer[i]._uCardIndex<< " ";
}
cout << endl << endl;
}
void main()
{
vector<st_Card_t> vtCard;
vector<st_Card_t> vtPlayer1;
vector<st_Card_t> vtPlayer2;
vector<st_Card_t> vtPlayer3;
InitCard(vtCard);
DealCard(vtCard, vtPlayer1, vtPlayer2, vtPlayer3);
int iBider = Bid(vtCard, vtPlayer1, vtPlayer2, vtPlayer3);
SortCard(vtPlayer1);
SortCard(vtPlayer2);
SortCard(vtPlayer3);
PrintPlayerCard("Player1", vtPlayer1);
PrintPlayerCard("Player2", vtPlayer2);
PrintPlayerCard("Player3", vtPlayer3);
cout <<"地主是Player"<< iBider+1 << endl << endl;
}
㈢ 这个链接下的源代码是什么
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>合租女孩洗澡不关门,用手机拍了几张相片。。【好图共赏】 |女人心情_ 摇篮论坛 </title>
<meta name="keywords" content="" />
<meta name="description" content=" 摇篮论坛 " />
<link rel="archives" title="摇篮论坛" href="http://bbs.yaolan.com/archiver/" />
<link href="http://loginbar.yaolan.com/css/dh.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.dh_nav_r_m .menu input{ margin-top:6px;padding:0;}
</style>
<link rel="stylesheet" type="text/css" href="forumdata/cache/style_7_viewthread.css" />
<link rel="stylesheet" type="text/css" href="forumdata/cache/style_7_common.css" />
<script type="text/javascript">
var discuz_uid = 0;var IMGDIR = 'images/default';var attackevasive = '0';var gid = 0;var STYLEID = '7';
gid = parseInt('204');var fid = parseInt('24');var tid = parseInt('51269126');
</script>
<script src="include/javascript/common.js" type="text/javascript"></script>
<script src="http://bbs.yaolan.com/Js/jAppear.js?v=20081030" type="text/javascript"></script>
<link href="http://bbs.yaolan.com/css/Popo.css?v=20081030" rel="stylesheet" type="text/css" />
</head>
<body onkeydown="if(event.keyCode==27) return false;" onload="ShopAuth(3,'onload');">
<div id="menuinfo" >
<div id="nav_nav">
<script src="http://loginbar.yaolan.com/GetUserInfo.aspx" type="text/javascript"></script>
<script src="http://my.yaolan.com/Message/GetNewInfosCount1.aspx" type="text/javascript"></script>
<script src="http://loginbar.yaolan.com/js/loginbar.js" type="text/javascript"></script>
<ul style="width:450px">
<li class="menu1 wc_nav_bg1"><a href="http://www.yaolan.com/" target="_blank" class="wc_nav_nav">摇篮首页</a></li>
<li class="menu1 wc_nav_bg1"><a href="http://abc.yaolan.com/" target="_blank" class="wc_nav_nav">成长阶梯</a></li>
<li class="menu1 wc_nav_bg1"><a href="http://www.yaolan.com/index/" target="_blank" class="wc_nav_nav">育儿知识</a></li>
<li class="menu2 wc_nav_bg2" onmouseover="this.className='menu1 wc_nav_bg2'" onmouseout="this.className='menu2 wc_nav_bg2'">
<a href="http://ask.yaolan.com/" target="_blank" class="wc_nav_nav">育儿问答</a>
<div class="list">
<a href="http://www.1.yaolan.com/shequ/chat/index.asp" target="_blank">专家在线</a><br />
</div>
</li>
<li class="menu2 wc_nav_bg2" onmouseover="this.className='menu1 wc_nav_bg2'" onmouseout="this.className='menu2 wc_nav_bg2'">
<a href="http://baobao.yaolan.com/" target="_blank" class="wc_nav_nav">宝贝主页</a>
<div class="list">
<a href="http://baobao.yaolan.com/jsp/bloglist/list.jsp" target="_blank">宝宝日记</a><br />
<a href="http://cn.yaolan.com/cn/" target="_blank">宝宝域名</a><br />
<a href="http://diy.yaolan.com/" target="_blank">个性定制</a><br />
<a href="http://bless.yaolan.com/getKnot.aspx" target="_blank">送祝福</a><br />
</div>
</li>
<li class="menu1 wc_nav_bg1"><a href="http://bbs.yaolan.com/" target="_blank" class="wc_nav_nav">
育儿论坛</a></li>
<li class="menu2 wc_nav_bg2" onmouseover="this.className='menu1 wc_nav_bg2'" onmouseout="this.className='menu2 wc_nav_bg2'">
<a href="http://emag.yaolan.com/" target="_blank" class="wc_nav_nav">电子杂志</a>
<div class="list">
<a href="http://emag.yaolan.com/ezine/mama.shtml" target="_blank">准妈妈系列</a><br />
<a href="http://emag.yaolan.com/ezine/0-1.shtml" target="_blank">0-1系列</a><br />
<a href="http://emag.yaolan.com/ezine/1-3.shtml" target="_blank">1-3系列</a><br />
</div>
</li>
</ul>
</div>
</div>
<div id="append_parent"></div><div id="ajaxwaitid"></div>
<div class="wrap">
<div id="header">
<h2><div style="margin-top:15px"><a href="index.html" title="摇篮论坛"><img src="images/default/bbslogo.jpg" alt="摇篮论坛" border="0" /></a></div></h2>
<div id="ad_headerbanner"><iframe id="banner2" width="630" height="65" scrolling="no" frameborder="0" marginheight="0" marginwidth="0" class="left" src="http://adnet.yaolan.com/GetCommonAds.aspx?pos_id=321" ></iframe></div>
</div>
<div style="width:100%; height:30px; background-color:#FFBABC; " >
<form action="http://search.yaolan.com/luntan/ss.jsp" method="get" target="_blank">
<div style="width:205px; height:21px; margin:5px 0 0 15px; float:left;">
<select name="searchfw">
<option value="0" selected="selected">全部</option>
<option value="1">主题</option>
<option value="2">作者</option>
</select>
<input name="searchword" id="searchword" onmouseover="this.select();" onkeydown="checkKey(event, document.getElementById('lnkSearch'))" type="text" style="width:102px; " />
<input value="" type="Submit" class="dzwc_b1" />
</div>
<span style=" height:30px; line-height:30px; float:left;">
</span>
</form>
</div>
<style type="text/css">
.defaultpost { height: auto !important; height:120px; min-height:120px !important; }
</style>
<script src="include/javascript/viewthread.js" type="text/javascript"></script>
<script type="text/javascript">zoomstatus = parseInt(1);</script>
<div id="infosidemain">
<div id="foruminfo">
<div id="nav">
<div class="userinfolist">
<p style="font-size:14px;"><a href="index.html" id="forumlist" onmouseover="showMenu(this.id)" class="dropmenu">摇篮论坛</a> » <a href="board_24.aspx">女人心情</a> » 合租女孩洗澡不关门,用手机拍了几张相片。。【好图共赏】</p>
</div>
</div>
<div id="headsearch">
</div>
</div>
<div id="ad_text"></div>
<div class="pages_btns">
<div class="threadflow"><a href="redirect.php?fid=24&tid=51269126&goto=nextoldset"> ‹‹ 上一主题</a> | <a href="redirect.php?fid=24&tid=51269126&goto=nextnewset">下一主题 ››</a></div>
<div class="pages"><em>44</em><strong>1</strong><a href="thread_51269126_2.aspx" >2</a><a href="thread_51269126_2.aspx" class="next">››</a></div> <a href="#tobottom" style="float:right;margin:10px 0 0 10px; color:#666666; text-decoration:underline">到楼底</a>
<span class="postbtn" id="newspecial" onmouseover="$('newspecial').id = 'newspecialtmp';this.id = 'newspecial';showMenu(this.id)"><a target="_blank" href="post.php?action=newthread&fid=24&extra="><img src="images/default/newtopic.gif" border="0" alt="发新话题" title="发新话题" /></a></span>
<span class="replybtn"><a href="post.php?action=reply&fid=24&tid=51269126&extra="><img src="images/default/reply.gif" border="0" alt="" /></a></span></div>
<ul class="popupmenu_popup newspecialmenu" id="newspecial_menu" style="display: none">
<li><a target="_blank" href="post.php?action=newthread&fid=24&extra=">发新话题</a></li>
<li class="poll"><a target="_blank" href="post.php?action=newthread&fid=24&extra=&special=1">发布投票</a></li> <li class="trade"><a target="_blank" href="post.php?action=newthread&fid=24&extra=&special=2">发布商品</a></li> <li class="reward"><a target="_blank" href="post.php?action=newthread&fid=24&extra=&special=3">发布悬赏</a></li> <li class="activity"><a target="_blank" href="post.php?action=newthread&fid=24&extra=&special=4">发布活动</a></li> <li class="debate"><a target="_blank" href="post.php?action=newthread&fid=24&extra=&special=5">发布辩论</a></li> <li class="video"><a target="_blank" href="post.php?action=newthread&fid=24&extra=&special=6">发布视频</a></li> </ul>
<form method="post" name="modactions">
<input type="hidden" name="formhash" value="7150568c" />
<div class="mainbox viewthread " style=" background:url(images/default/bbs_bg7.gif) repeat-x top" >
<span class="headactions">
</span>
<h1><span class="kv_threadtitle">[主题]<a href="forumdisplay.php?fid=24&filter=type&typeid=48">[家长里短]</a> 合租女孩洗澡不关门,用手机拍了几张相片。。【好图共赏】</span>
</h1>
<table id="pid51598839" summary="pid51598839" cellspacing="0" cellpadding="0">
<tr>
<td class="postauthor">
<div class="online" >
<cite>
<a href="http://space.yaolan.com/50036303" target="_blank" id="userinfo51598839" class="dropmenu" onmouseover="showMenu(this.id)">狂战</a>
<em>其它</em>
</cite>
</div>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top" >
<b style="color:#009900;width:100px;display:block">新生摇精</b>
<a href="http://space.yaolan.com/50036303" target="_blank" >
<a border="0" target="_blank" href="http://space.yaolan.com/50036303"><img src="/uc/images/noavatar_middle.gif" onerror="this.onerror=null;this.src='/uc/images/noavatar_middle.gif'" width="90" height="90"></a>
</a>
<br/>
<a href="http://space.yaolan.com/50036303" target="_blank" border="0"><img src="/images/headpng/head_1_0_0.png" /></a>
<p style="text-align:center;"><a href="http://www.yaolan.com/help/article2007_462561627026.shtml" target="_blank" border="0"><font color="#ff6600" style="font-size:12px;" >新生摇精</font></a></p>
</td>
<td >
<a name="newpost"></a>
<!-- <p><img src="images/default/star_level1.gif" alt="Rank: 1" /></p>-->
<ul>
<li></li>
<li class="pm"><a href="http://my.yaolan.com/Message/NewWriteMessage.aspx?u=50036303" target="_blank">短消息</a></li>
<li class="buddy"><a href="http://space.yaolan.com/50036303/friends/addfriend.html" target="_blank">加好友</a></li>
<li class="space"><a href="http://space.yaolan.com/50036303/BBS" target="_blank">帖子集</a></li>
</ul>
<DIV style="margin:25px 0 0 5px;color:#999">活力: 192</DIV>
<DIV style="margin:0 0 0 5px;color:#999">魅力: 100</DIV>
<DIV style="margin:0 0 0 5px;color:#999">文采: 102</DIV>
</td>
</tr>
</table>
</td>
<td class="postcontent">
<div class="postinfo" style="background:#FFD8D9">
<strong>1<sup>#</sup></strong>
<em title="复制帖子链接到剪贴板" id="postnum51598839" onclick="set('http://bbs.yaolan.com/viewthread.php?tid=51269126&page=1#pid51598839', '帖子链接已经复制到剪贴板')"><a href="#">复制本楼地址</a></em>
<em><a href="viewthread.php?tid=51269126&page=1&authorid=50036303" rel="nofollow">只看该作者</a></em>
发表于 2009-3-16 14:40 浏览:532 回复:43
</div>
<div id="ad_thread2_0"></div> <div class="postmessage defaultpost" style="background:#FFFFFF">
<div id="ad_thread3_0"></div><div id="ad_thread4_0"></div>
<div id="postmessage_51598839" class="t_msgfont" style="padding:10px;"><img src="http://www.funbq.com/img/216/bq51551475.jpg" border="0" onclick="zoom(this, this.src)" onload="attachimg(this, 'load')" alt="" /><br />
一、此贴为调查贴,为配合公安部第二次全国色狼普查实名登记制,特发此贴,被标题吸引进入浏览的,不论男女,皆为色狼. <br />
<br />
二、帖子被浏览数即为色狼数量,统计结果截止到2009年8月31日. <br />
<br />
三、浏览此贴时,系统已自动记录浏览者的ip地址以及论坛id,请勿抱有侥幸心理. <br />
<br />
四、不要说没看清或点错了之类的鬼话来为自己辩解 <br />
<br />
五、请于观看此贴20日内与户口所在地街道办事处或派出所自带小板凳联系备案 <br />
<br />
六、此次调查结果将于2009年中在各地方电视台滚动播出,敬请期待。。。。。。。。<br />
<br />
[<i> 本帖最后由 狂战 于 2009-3-16 15:17 编辑 </i>]</div>
㈣ 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算法的收敛性很容易,只需要证明每一轮迭代之后,参数的似然函数递增,即