利用Monte Carlo进行数值积分(二)

进步空间很大的算法版本

话说去年6月的一个周六,我很无聊地发了一个帖子,写了一个自己感觉有点无聊的帖子。


Matlab多重积分的两种实现【从六重积分到一百重积分】icon-default.png?t=N7T8https://withstand.blog.csdn.net/article/details/127564478

这个帖子居然成了我这种懒人随性瞎写的博文中阅读量、收藏量和评论量最多的一个。

很多人对我不写说明,不写例子提出了意见,开头我写的那个代码里面还有一个小问题。

时隔7个月之后,我抽出一点时间来看这个算法,发现问题简直是大大的。

function ret = integral6mc(fun, lb, ub, N)

% fun是被积分的函数

% lb和ub是积分变量的范围,每个都是六维数组

% N MC采样的数目,一般取个几千、几万试一下差不多就行

V = prod(abs(ub-lb)); % 计算超立方体的体积,向量化计算每一个维度的长度(绝对值),求所有维度的乘积

n = length(lb); % 维数

sample = (ub-lb) .* rand(N, n) + repmat(lb,N,1); %产生一个Nxn的随机数组,然后转换到lb~ub的范围,repmat函数是复制矩阵,把行向量复制程Nxn



sample_arguments = num2cell(sample, 1);% 把上面的Nxn矩阵换成按列排列的cell(n个元素)

results = cell2mat(arrayfun(fun, sample_arguments{:}, 'UniformOutput', 0));%调用被积函数,被积函数的参数有n个,把cell展开({:}操作),这里arrayfun得到的是cell,再合并成mat,就是N个结果的向量

ret = sum(results) * V / N; % 这是MC的核心算法,乘以体积除以样本数

丑陋的'UniformOutput'以及为什么

首先,这里很无聊的搞了cell2mat,以及'UniformOutput', 0的参数,都是因为没仔细考虑,瞎写的。

这里的核心问题是什么呢?是arrayfun这个函数。

这个函数和并行比如parfor这些没关系,是一个单线程的函数,就是把第一个参数(一个函数句柄)逐次应用到后续参数的每一个对应的元素上去。

这里其实有一个小小的问题,是一位强迫我写一个例子的网友提出来的,很对。

f = @(x, y) x * y

这个函数有两个参数,我们可以看到,如果x和y都是标量(一个数字),这个函数没啥问题。如果x,y是两个size一样的向量或者矩阵或者高维矩阵,那么他计算的就不是简单的乘法。只所以我前面调用arrayfun的过程中,需要设置输出可能不一致,就是因为我的目标函数没有写按元操作。

在采用arrayfun的时候,我们应该给出如此的约束, 目标函数是一个按元操作的函数,也就是,上面的函数应该写成:

f = @(x, y) x .* y

这个问题在我原来用的matlab版本中貌似是个问题,但是今天我更新了matlab,看起来没啥问题了,那种写法都是可以的,最终的计算时间也是相当的,看起来就是arrayfun的内部没有做任何向量化的计算。这个实际上很奇怪,我感觉应该是优化到采用向量化的cpu指令来计算会比较合理……

更好的版本

在这个条件下,我们的mc函数就能够写成:

function ret = mci(fun, lb, ub, N)

% fun是被积分的函数

% lb和ub是积分变量的范围,每个都是六维数组

% N MC采样的数目,一般取个几千、几万试一下差不多就行

V = prod(abs(ub-lb)); % 计算超立方体的体积,向量化计算每一个维度的长度(绝对值),求所有维度的乘积

n = length(lb); % 维数

sample = (ub-lb) .* rand(N, n) + repmat(lb,N,1); %产生一个Nxn的随机数组,然后转换到lb~ub的范围,repmat函数是复制矩阵,把行向量复制程Nxn



sample_arguments = num2cell(sample, 1);% 把上面的Nxn矩阵换成按列排列的cell(n个元素)

results = arrayfun(fun, sample_arguments{:});

ret = sum(results) * V / N; % 这是MC的核心算法,乘以体积除以样本数

这里依然有同样的问题,就是num2cell,这个部分利用matlab把函数的多个参数当成cell的调用惯例,也可以写成:

function ret = mci(fun, lb, ub, N)

% fun是被积分的函数

% lb和ub是积分变量的范围,每个都是六维数组

% N MC采样的数目,一般取个几千、几万试一下差不多就行

V = prod(abs(ub-lb)); % 计算超立方体的体积,向量化计算每一个维度的长度(绝对值),求所有维度的乘积

n = length(lb); % 维数

sample = (ub-lb) .* rand(N, n) + repmat(lb,N,1); %产生一个Nxn的随机数组,然后转换到lb~ub的范围,repmat函数是复制矩阵,把行向量复制程Nxn



sample_arguments = cell(n, 1);

for i = 1:n

    sample_arguments{i} = sample(:,i);

end



results = arrayfun(fun, sample_arguments{:});

ret = sum(results) * V / N; % 这是MC的核心算法,乘以体积除以样本数

这两个函数是一毛一样的,用for循环和用num2cell带来的差别微乎其微。

一点点例子以及profile

一维的无聊例子

先搞一个一点也不excited的例子。

f(x) = x

定积分

\int_a^b f(x) = \left.\frac{1}{2}x^2\right|_a^b

如果a=0, b=1,积分结果为0.5。

f = @(x) x;



n = round(logspace(2, 6, 50)); //必须保证是整数

results = arrayfun(@(N)mci(f, lb, ub, N), n);



figure

semilogx(n, results, 'x');

hold on

semilogx([100, 1e6], [0.5, 0.5])

xlabel("N");

ylabel("\int_0^1 x dx")

print -dpng -r300 convergence



figure

loglog(n, abs(results-0.5), '+')

xlabel("N")

ylabel("\sigma")

print -dpng -r300 sigma

收敛的结果如图:

误差的loglog图:


 

二维的略微不那么无聊例子

下面还一点点稍微不无聊一点的。

f(x, y) = x y

积分:

\int_a^b\int_c^d f(x, y) dx dy = \left.\frac{1}{2}x^2\right|_a^b \left.\frac{1}{2}y^2\right|_c^d
 

积分代码:

f = @(x,y) x * y;



n = round(logspace(2, 6, 50)); //必须保证是整数

results = arrayfun(@(N)mci(f, lb, ub, N), n);



figure

semilogx(n, results, 'x');

hold on

semilogx([100, 1e6], [0.25, 0.25])

xlabel("N");

ylabel("\int_0^1\int_0^1 x y dx dy")

print -dpng -r300 convergence



figure

loglog(n, abs(results-0.25), '+')

xlabel("N")

ylabel("\sigma")

print -dpng -r300 sigma

收敛速度:

误差结果:

2维的情况下很快就收敛到3位小数(10000次采样)。

100维的例子

我们弄一个100维的简单函数.

f(x_1, x_2, \ldots, x_{n}) = \sum_{i=1}^{n} x_i^2

[0,1]^n区间积分的真值是n \times 0.33333333\ldots

对应的代码:

function ret = fn(varargin)



n = length(varargin);

vars = zeros(n, 1);

for i=1:n

    vars(i) = varargin{i};

end



ret = sum(vars .^ 2);

对应的收敛性代码。

N = 100;

true_value = N * 1.0 / 3.0;

lb = zeros(1, N); %这里必须是1 * N, 而不是N * 1

ub = ones(1, N);



n = round(logspace(2, 6, 50));

results = arrayfun(@(N)mci(@fn, lb, ub, N), n);



figure

semilogx(n, results, 'x');

hold on

semilogx([100, 1e6], [true_value, true_value])

xlabel("N");

ylabel("\int f")

print -dpng -r300 convergence

figure

loglog(n, abs(results-true_value), '+')

xlabel("N")

ylabel("\sigma")

print -dpng -r300 delta

可以看到蒙特卡洛方法有一个很好很好的特性,就是积分函数的维数跟算法复杂度完全没有关系。就算是100维,一样给它弄到三位有效数字的积分结果。

算法的典型时间特性

这个函数中一半的时间都在调用fn函数,这个函数一点也不美……

好吧,看起来100层并没有什么,也不需要那么多考虑。

GPU版本

当然,我还很无聊地写了一个gpu版本,效果简直是碉堡了。

这里就不多说,上个代码就算了。

function ret = mci_gpu(fun, lb, ub, N)

% fun是被积分的函数

% lb和ub是积分变量的范围,每个都是六维数组

% N MC采样的数目,一般取个几千、几万试一下差不多就行

V = prod(abs(ub-lb)); % 计算超立方体的体积,向量化计算每一个维度的长度(绝对值),求所有维度的乘积

n = length(lb); % 维数

sample = (ub-lb) .* rand(N, n, 'gpuArray') + repmat(lb,N,1); %产生一个Nxn的随机数组,然后转换到lb~ub的范围,repmat函数是复制矩阵,把行向量复制程Nxn

args = cell(n, 1);

for i = 1:n

    args{i} = sample(:,i);

end

results = arrayfun(fun, args{:});%调用被积函数

ret = gather(sum(results) * V / N); % 这是MC的核心算法,乘以体积除以样本数

调用的方法跟前面那个函数一样,就是有一个问题,在gpu中计算时,不能调用100维的那个函数,因为要使用动态输入参数个数。

gpu版本的唯一不同就是把数组创建在显存中,最终这个计算里面最花时间的就是创建数组,实际的arrayfun的时间基本可以忽略,也是一个挺有意思的事情。最终用gather函数把结果从显存中取出来。

一点都不想参考的参考文献

[1] 张艳. 利用蒙特卡罗方法求解数值积分[J]. 高等数学研究, 2023, 26(1): 44-46+61.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/318924.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ESU毅速丨制造企业需不需要建设增材制造中心?

随着科技的不断发展,增材制造技术已经成为制造行业的新宠。越来越多的企业开始考虑建设增材制造中心,以提高生产效率、降低成本、加速产品创新。但是,对于制造企业来说,是否需要建设增材制造中心呢? 首先,我…

计算机网络安全教程(第三版)课后简答题答案大全[6-12章]

目录 第 6 章 网络后门与网络隐身 第 7 章 恶意代码分析与防治 第 8 章 操作系统安全基础 第 9 章 密码学与信息加密 第 10 章 防火墙与入侵检测 第 11 章 IP安全与Web安全 第 12 章 网络安全方案设计 链接:计算机网络安全教程(第三版)课后简答题答案大全[1-5…

引领行业赛道!聚铭网络入选安全419年度策划“2023年教育行业优秀解决方案”

近日,由网络安全产业资讯媒体安全419主办的《年度策划》2023年度优秀解决方案评选结果正式出炉,聚铭网络「高校大日志留存分析及实名审计解决方案」从众多参选方案中脱颖而出,被评为“教育行业优秀解决方案”,以硬核实力引领行业赛…

2024年AMC8历年真题练一练和答案详解(7),以及全真模拟题

今天是1月14日,2024年AMC8正式比赛的备考时间余额不多了,这两天大家都记得抽空参加官方的模拟考试,尤其是第一次参赛的孩子,家长一定要指导孩子自己参加模拟题,熟悉考试流程和环境,否则正式比赛不小心违规就…

强化学习应用(六):基于Q-learning的无人机物流路径规划研究(提供Python代码)

一、Q-learning简介 Q-learning是一种强化学习算法,用于解决基于马尔可夫决策过程(MDP)的问题。它通过学习一个价值函数来指导智能体在环境中做出决策,以最大化累积奖励。 Q-learning算法的核心思想是通过不断更新一个称为Q值的…

快速了解——逻辑回归及模型评估方法

一、逻辑回归 应用场景:解决二分类问题 1、sigmoid函数 1. 公式: 2. 作用:把 (-∞,∞) 映射到 (0, 1) 3. 数学性质:单调递增函数,拐点在x0,y0.5的位置 4. 导函数公式:f…

Python新年文字烟花简单代码

简单的Python新年烟花代码示例: import random import timedef create_firework():colors [红色, 橙色, 黄色, 绿色, 蓝色, 紫色]flashes [爆裂, 闪光, 旋转, 流星, 喷射]color random.choice(colors)flash random.choice(flashes)print(f"发射一枚{color…

imgaug库指南(22):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里,数据是模型训练的基石,其质量与数量直接影响着模型的性能。然而,获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此,数据增强技术应运而生,成为了解决这一问题的…

汽车雷达:实时SAR成像的实现

摘要: 众所周知,点云成像是目前实现汽车雷达感知最流行的方案,尤其是采用多级联实现的4D点云成像雷达,这是目前最有希望实现产品落地的技术方案之一。 今天重点分享关于汽车雷达SAR成像相关技术内容,这也证实了4D点云成像雷达并不一定就是汽车雷达成像唯一的方案,在业内…

CPU告警不用愁,用C语言编写CPU使用率限制程序

现在云服务已经深入千家万户了,不仅商用,私用也很多。很多云服务厂商也都有配套的服务器安全模块,可以检测网络流量异常、内存占用量和CPU占用率,并且允许人工设置告警阈值。例如,CPU持续大于90%10分钟,那么…

14、强化学习Soft Actor-Critic算法:推导、理解与实战

基于LunarLander登陆器的Soft Actor-Critic强化学习(含PYTHON工程) Soft Actor-Critic算法是截至目前的T0级别的算法了,当前正在学习,在此记录一下下。 其他算法: 07、基于LunarLander登陆器的DQN强化学习案例&#…

微信小程序(三)页面配置与全局配置

注释很详细,直接上代码 新增内容: 页面导航栏的属性配置全局页面注册配置全局导航栏配置样式版本 源码:(标准的json是不能加注释的,但为了方便理解咱做个违背标准的决定) 页面:index.json {//这里是页面的配置文件&am…

LAMA Inpaint:大型掩模修复

文章目录 一、大掩模修复(LaMa)简介二、大掩模修复(LaMa)的主要方法三、快速傅里叶卷积的修补网络四、损失函数五、训练中的动态掩膜生成 一、大掩模修复(LaMa)简介 LaMa方法的提出背景:现代图…

py连接sqlserver数据库报错问题处理。20009

报错 pymssql模块连接sqlserver出现如下错误: pymssql._pymssql.OperationalError) (20009, bDB-Lib error message 20009, severity 9:\nUnable to connect: Adaptive Server is unavailable or does not exist (passwordlocalhost)\n) 解决办法: 打…

【蓝桥杯日记】第一篇——系统环境的搭建

目录 前言 环境相关文件 学生机环境-Web应用开发环境(第十五届大赛) 学生机环境-Java编程环境(第十五届大赛) 学生机环境-C/C编程环境(第十五届大赛) 学生机环境-Python编程环境 (第十五届…

【数据结构】八大排序之计数排序算法

🦄个人主页:修修修也 🎏所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.计数排序简介及思想 二.计数排序代码实现 三.计数排序复杂度分析 📌时间复杂度 📌空间复杂度 结语 一.计数排序简介及思想 计数排序(Cou…

一个月带你手撕LLM理论与实践,并获得面试or学术指导!

大家好,我是zenRRan,是本号的小号主。 从该公众号的名字就能看出,运营已经好多年了,这些年当中直接或间接帮助很多同学从NLP入门到进阶,理论到实践,学校到企业,本科到硕士甚至博士。 每天习惯性…

【K12】Python写分类电阻问题的求解思路解析

分压电阻类电路问题python程序写法 一个灯泡的电阻是20Ω,正常工作的电压是8V,正常工作时通过它的电流是______A。现在把这个灯泡接到电压是9V的电源上,要使它正常工作,需要给它______联一个阻值为______的分压电阻。 解决思想 …

深度学习基本介绍-李沐

目录 AI分类:模型分类:广告案例: bilibili视频链接:https://www.bilibili.com/video/BV1J54y187f9/?p2&spm_id_frompageDriver&vd_sourcee6a6e7fec41c59c846c142eb5ef1da0b AI分类: 模型分类: 图…

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(3)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…