import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as mpatches import scipy.integrate as integrate ''' Monte Carlo method (蒙特卡洛方法,也有翻译成“蒙特卡罗方法”)是以概率和统计的理论、方法为基础的一种数值计算方法, 将所求解的问题同一定的概率模型相联系,用计算机实现统计模拟或抽样,以获得问题的近似解,故又称随机抽样法或统计试验法。 上述就是蒙特卡洛方法的基本概念,比较抽象,下面结合实际工作中的理解,谈一谈对蒙特卡洛方法的一些认识。 (1)数学家冯·诺伊曼(计算机之父)在20世纪40年代中期用驰名世界的赌城摩纳哥的蒙特卡洛来命名这种方法, 说明该方法与赌博中的随机性、概率性有着天然而密切的联系。几乎涉及到概率相关的复杂数值计算的领域(计算物理、经济金融、统计学、机器学习等)。 (2)蒙特卡洛是一种方法或者说策略,没有什么高深的理论支撑(如果有理论也就只有概率论或统计学中的大数定律了)。 蒙特卡洛的基本原理简单描述是先大量模拟,然后计算一个事件发生的次数,再通过这个发生次数除以总模拟次数,得到想要的结果。 例如模拟投N次(随机样本数),统计同时出现6的次数C(C/N即是计算结果)。 (3)蒙特卡洛方法可应用在很多场合(求的是近似解)。模拟样本数越大,越接近与真实值,同时样本数增加会带来计算量的大幅上升。 实例:蒙特卡洛方法求函数y=x^2在[0,2]区间的积分(即求面积)。 备注:直接用数学中的定积分公式算更简单精确。 该红色区域在一个2×4的正方形里面。使用蒙特卡洛方法,随机在这个正方形里面产生大量随机点(数量为N), 计算有多少点(数量为count)落在红色区域内(判断条件为y<x2),count/N就是所要求的积分值,也即红色区域的面积。 ''' np.random.seed(12345) x = np.linspace(0, 2, 1000) # 绘制曲线 y = x ** 2 plt.plot(x, y) plt.fill_between(x, y, where=(y > 0), color='red', alpha=0.5) # 填充颜色 # plt.show() #模拟1000个随机点 N = 1000 points = [[xy[0] * 2, xy[1] * 4] for xy in np.random.rand(N, 2)] plt.scatter([x[0] for x in points], [x[1] for x in points], s=5, c=np.random.rand(N), alpha=0.5) plt.show() #计算落在红色区域的比重 count = 0 for xy in points: if xy[1] < xy[0] ** 2: count += 1 print((count / N) * (2 * 4)) # 2.752 print(integrate.quad(lambda x: x ** 2, 0, 2)[0]) ''' 蒙特卡洛方法有一定的误差,误差的大小与模拟的样本大小直接相关,模拟样本越大,误差越小,但计算量也会大幅上升。 对于简单问题来说,蒙特卡洛是个“笨”办法。 但对于涉及复杂、不可解析函数或概率分布的模拟及计算,蒙特卡洛方法是个有效的方法,有时甚至是唯一可行的方法。 ''' ''' 实例2:套圈圈的游戏,想过为什么你总是套不上吗?用蒙特卡洛方法来算一算。 1.设物品中心点坐标为(0,0),物品半径为5cm。 ''' # circle_target = mpatches.Circle([0, 0], radius=5, edgecolor='r', fill=False) plt.xlim(-80, 80) plt.ylim(-80, 80) plt.axes().add_patch(circle_target) # plt.show() ''' 2.设投圈半径8cm,投圈中心点围绕物品中心点呈二维正态分布,均值μ=0cm,标准差σ=20cm,模拟1000次投圈过程。 上图中红圈为物品,散点图为模拟1000次投圈过程中,投圈中心点的位置散布。 3.计算1000次投圈过程中,投圈套住物品的占比情况。 ''' N = 1000 u, sigma = 0, 20 points = sigma * np.random.randn(N, 2) + u plt.scatter([x[0] for x in points], [x[1] for x in points], c=np.random.rand(N), alpha=0.5) plt.show() print(len([xy for xy in points if xy[0] ** 2 + xy[1] ** 2 < (8 - 5) ** 2]) / N) #输出结果:0.009,即投1000次,有9次能够套住物品,是小概率事件,知道你为什么套不住了吧。 ''' 蒙特卡洛方法本身不是优化方法, 与遗传算法、粒子群算法等智能优化算法有相似之处,比如都属于随机近似方法,都不能保证得到最优解等, 但它们也有着本质的差别。 一是层次不一样,蒙特卡洛只能称之为方法,遗传算法等则属于仿生智能算法,比蒙特卡洛方法要复杂。 二是应用领域不同,蒙特卡洛是一种模拟统计方法,如果问题可描述成某种统计量的形式,就可以用蒙特卡洛方法解决; 遗传算法等适用于大规模的组合优化问题(选址问题、排班问题、管理调度、路线优化)等,及复杂函数求最值、参数优化等。 '''
内容摘自网络