术语是分割圈子的利器(阻碍交流的元凶)。——by狗尾草
一、记一场酒局
在讲蒙特卡洛方法之前,先给大家讲个真事。
几年前的某个夏夜,我和几个同事在撸着串,喝着啤酒,摇着骰子,当时的一段对话是这样的:
甲:“三个不知道”
乙:“四个不知道”
甲:“开,你喊四个我就开!”
乙:“你可真虎!”
甲:“为啥啊,你喊四个肯定赢少输多啊!”
乙:“那不一定,很多时候都是四个!”
甲:“一定啊,6个骰子出四个一样的几率很小啊!”
。。。。。。
然后,三个晕乎乎的渣博士坐在那里口算概率,算了接近一个小时,每个人算的结果都不一样,谁也不知道谁的是对的。
摇骰子的规则特别简单,三颗骰子,摇出来的1是万能的,可以当任何数字使用。
我本身数学是很差的,概率自从考完研之后就全丢掉了,第二天酒醒了之后,这个问题还让我“耿耿于怀”,然后我花了点时间写了个程序验证了一下这个问题的答案,先说答案,答案是如果乙喊4个不知道,甲就开,那么甲赢的可能在63%左右。
我用的方法就是蒙特卡洛方法。
二、蒙特卡罗方法
蒙特卡洛不是一个人,是一个地名Monte Carlo,位于摩纳哥,是一个世界著名的赌城(除了拉斯维加斯),现代计算机的先驱冯诺依曼命名了该方法,平白给这个方法增添了很多神秘的色彩(阅读障碍)。其实这个方法的思想特别朴素和容易理解,也早已经存在了。
注意,蒙特卡洛方法不叫蒙特卡洛算法,是因为它是没有明确的实施步骤的,它只是一种思想,它的思想特别朴素,借用我上面提到的例子:既然我算不出来概率,那么我就放弃计算,直接扔十万次骰子好了,统计一下赢的次数,根据朴素的概率论,只有样本量足够大,我一定会无限逼近于真实概率的。
事实上,历史上的确有人这么干过,例如为了验证抛硬币正反面的概率,据说下面这几个数学家就充满恒心毅力(丧心病狂)的抛过硬币:
德·摩根 抛了4092次,蒲丰 抛了4040次,费勒 抛了10000次,皮尔逊抛了 24000次,罗曼诺夫斯基 抛了80640次。(不知道有没有这个的吉尼斯世界纪录,可以尝试一下)
真的扔十万次骰子,是一个非常可怕的事,光想想就会疯,所以这个方法虽然很早就出现了,但是一直没有流行起来,直到——计算机的出现。用计算机扔骰子,这不是太简单了吗?几十秒就能扔完。
所以,计算机诞生之后,蒙特卡洛方法开始大放异彩,有很多难以用理论计算和推导的东西,没关系,我们用算力解决,因为最终要的也不是精确解,所以有一个近似解就行了。
所以蒙特卡洛方法的朴素思想一句话就可以总结:用(计算机模拟)实验方法求概率。
三、蒙特卡洛方法的应用
蒙特卡洛方法在非常多领域都很有用,而且在某些领域,它还几乎是唯一方法,但是别被我上面的例子和那句定义局限了,以为它就是求概率的,不是的,例如下面的例子。
1. 如果不知道π值,也不知道圆的计算公式,有一个圆,怎么求面积?
一个布满了随机点的圆
蒙特卡洛方法说:简单,先在圆的外面画一个外接正方形,然后生成十万个点随机撒在在这个正方形内部,然后数一数多少个点在圆内部(计算每个点到圆心的距离,如果距离小于半径则代表在圆内部),然后用这个数除10万,再乘正方形面积就好了。
2. 这里有一个诡异的函数,来求积分?
一个诡异的函数
蒙特卡洛方法说:简单,直接在这个区域内随机撒十万个点,数一数函数下方有多少个点(根据当前点的x值计算函数值y’和点的y值做对比,y<y’则代表在函数下方),然后用这个数除10万,在乘区域面积就好了。
3. 有一个机械产品是由10个零件堆起来的,要求整个厚度不超过30mm,但是每个零件厚度都有一定概率出现误差,超出最大范围,请问整个产品最终的合格率能到多少?
蒙特卡洛方法说:简单,随机模拟10万次装配,每次装配的时候按照概率随机给每个零件产生误差,然后统计最终的厚度,把不超过30mm的统计为合格品,求比例即可。
从上面几个例子,大家可以大概了解蒙特卡洛方法的思想了吧,去想想在自己的研究领域有没有应用价值和意义吧。
四、番外篇
自从那次酒局过后,我好像突然发现了选研究生的诀窍,最近几年,碰到来找我的研究生,如果我对他知识背景不是太拿的准,我就会给他抛出去两道编程题,让他用两天时间求解,其中一道就是这个扔骰子求概率的,其实如果C语言底子好,稍微有点思路,完全可以在十几分钟之内解决掉这个问题。遗憾的是,好几年了,也就碰到过一两个人能编程求解这个问题的。