ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

蒙特卡罗与网格搜索:从数学建模题看数值优化基础方法

蒙特卡罗与网格搜索:从数学建模题看数值优化基础方法 1. 从一道“简单”的数学建模题说起最近在数学建模清风老师的公众号上看到一道关于“挑战篇”的习题题目本身不长但解题思路却非常有意思它把蒙特卡罗思想、枚举法和网格搜索法这几个听起来高大上的概念巧妙地融合在了一个看似简单的实际问题里。题目大意是假设我们有一个函数f(x, y) sin(x) cos(y) 0.1 * (x^2 y^2)我们需要在定义域x ∈ [-5, 5],y ∈ [-5, 5]的范围内找到使得函数值f(x, y)最小的点(x*, y*)并给出此时的最小值f_min。很多同学第一眼看到这个题目可能会觉得这不就是个二元函数求最小值嘛求个偏导令其为零解方程组不就行了但仔细一看函数里既有三角函数又有二次项求导后得到的方程组cos(x) 0.2x 0和-sin(y) 0.2y 0是超越方程没有解析解。这就尴尬了我们熟悉的微积分工具在这里“失灵”了。这正是数学建模中经常遇到的情况实际问题建立的模型往往是非线性的、复杂的无法通过纯数学推导得到精确解。这时候数值计算方法就成了我们的“救命稻草”。而这道题就是引导我们探索几种基础的数值优化思想蒙特卡罗随机采样、枚举法系统遍历和网格搜索法分层采样。它们虽然“笨”但在特定场景下却非常有效和可靠。这道题的价值不在于答案本身毕竟我们可以用更高级的优化算法得到更精确的结果而在于理解这几种基础方法的思想内核、适用场景以及它们之间的微妙差异。理解这些你就能在面对一个全新的、没有现成求解器的模型时知道如何迈出第一步如何设计一个虽然粗糙但能快速验证想法的方案。今天我就结合这道题把这三种方法掰开揉碎了讲清楚不仅给出代码实现更重要的是分享每种方法背后的思考逻辑、参数设置的“小心机”以及在实践中如何选择与搭配使用。2. 蒙特卡罗思想用随机性对抗复杂性当我们面对一个复杂空间比如这里的二维区域寻找最优解时最朴素的想法之一就是“撒点”。蒙特卡罗方法的核心思想正是如此通过生成大量随机样本用统计规律来近似求解确定性问题。在这个求最小值的问题中我们不需要知道函数的具体形状只需要在定义域内随机扔一大堆点进去然后找出所有点中函数值最小的那个它就是我们找到的“近似最优点”。2.1 核心实现与代码解析蒙特卡罗方法的实现极其直观。我们首先需要确定采样范围x和y都在[-5, 5]之间然后决定采样点的数量。采样数量N是这种方法的核心参数它直接决定了结果的精度和计算成本。import numpy as np import matplotlib.pyplot as plt def f(x, y): return np.sin(x) np.cos(y) 0.1 * (x**2 y**2) # 蒙特卡罗方法寻找最小值 def monte_carlo_min(N10000): # 1. 在定义域内生成N个随机点 x_vals np.random.uniform(-5, 5, N) y_vals np.random.uniform(-5, 5, N) # 2. 计算所有点的函数值 f_vals f(x_vals, y_vals) # 3. 找到最小函数值及其对应的点 min_index np.argmin(f_vals) x_min, y_min x_vals[min_index], y_vals[min_index] f_min f_vals[min_index] return x_min, y_min, f_min, x_vals, y_vals, f_vals # 执行一次蒙特卡罗搜索 x_mc, y_mc, f_mc, x_all, y_all, f_all monte_carlo_min(10000) print(f蒙特卡罗结果 (N10000): 最优点 ({x_mc:.4f}, {y_mc:.4f}), 最小值 {f_mc:.6f})这段代码的逻辑非常清晰生成随机点、计算函数值、找最小值。但这里有几个关键点需要深入理解为什么用均匀分布在这个问题中我们对目标函数的先验知识为零不知道最小值可能出现在哪个区域。均匀采样能保证在整个定义域内的“探索”是公平的避免因采样偏差而错过潜在的最优区域。这是一种“无信息先验”下的最稳妥选择。np.random.uniform的边界注意我们传入的参数是-5和5numpy的均匀分布函数默认区间是[low, high)即包含左边界但不包含右边界。对于连续优化问题边界差一个无穷小的点对结果影响微乎其微可以接受。如果严格要求闭区间可以做一些技术处理但通常没必要。2.2 精度、代价与“运气”成分蒙特卡罗方法的结果是随机的。每次运行由于生成的随机点集不同找到的“最优点”和“最小值”都会略有差异。为了评估其效果我们通常需要多次运行观察结果的分布。def evaluate_monte_carlo(trials50, N10000): results [] for i in range(trials): x, y, f_min, _, _, _ monte_carlo_min(N) results.append(f_min) results np.array(results) print(f运行 {trials} 次蒙特卡罗 (N{N})) print(f 找到的最小值均值: {results.mean():.6f}) print(f 最小值标准差: {results.std():.6f}) print(f 最佳的一次结果: {results.min():.6f}) print(f 最差的一次结果: {results.max():.6f}) return results mc_results evaluate_monte_carlo(50, 10000)运行这段代码你可能会发现50次试验得到的最小值在-1.89到-1.86之间波动。这个波动就是蒙特卡罗方法的“运气”成分。采样点数量N是平衡精度和计算代价的杠杆N太小如100结果极不稳定很可能完全找不到真正的最小值区域。N增大如1万结果稳定性显著提高多次运行的结果会聚集在某个值附近。N极大如100万结果会非常稳定接近方法的极限精度但计算时间也线性增长。实操心得在实际应用中我通常会先用一个中等规模的N比如1万快速跑几次看看结果的波动范围。如果波动在可接受范围内那么这个规模就足够了。如果要求更高精度再酌情增加N。记住蒙特卡罗的精度提升与1/sqrt(N)成正比这意味着想将误差减半你需要将采样点增加到原来的4倍。性价比需要权衡。2.3 可视化直观感受随机采样的覆盖度一图胜千言。我们可以把随机采样的点和找到的“最优点”画出来直观感受其分布。def plot_monte_carlo(x_vals, y_vals, f_vals, x_best, y_best): plt.figure(figsize(10, 4)) # 散点图用颜色表示函数值高低 plt.subplot(1, 2, 1) scatter plt.scatter(x_vals, y_vals, cf_vals, cmapviridis, s5, alpha0.6) plt.colorbar(scatter, labelf(x,y)) plt.scatter(x_best, y_best, colorred, s100, marker*, labelFound Minimum) plt.xlabel(x) plt.ylabel(y) plt.title(Monte Carlo Sampling Points) plt.legend() plt.grid(True, alpha0.3) plt.axis(equal) # 函数值分布的直方图 plt.subplot(1, 2, 2) plt.hist(f_vals, bins50, edgecolorblack, alpha0.7) plt.axvline(f(x_best, y_best), colorred, linestyle--, labelMin Value Found) plt.xlabel(f(x,y)) plt.ylabel(Frequency) plt.title(Distribution of Sampled Function Values) plt.legend() plt.grid(True, alpha0.3) plt.tight_layout() plt.show() # 使用之前一次运行的数据绘图 plot_monte_carlo(x_all, y_all, f_all, x_mc, y_mc)从左图可以看到随机点均匀地铺满了整个正方形区域。红五星标记的点是本次采样中找到的函数值最小的点。右图展示了所有采样点函数值的分布情况红色虚线标出了最小值的位置。你会发现大部分点的函数值都分布在较高的区域只有很少一部分点落在了函数值较低的“山谷”里。蒙特卡罗方法就是通过“广撒网”的方式希望有足够多的点能落到这个“山谷”附近。采样的随机性决定了有时你的点刚好在谷底有时则在半山腰。3. 网格搜索法系统性的暴力美学如果说蒙特卡罗是“随机撒网”那么网格搜索就是“犁地”。它在定义域内按照固定的间隔生成一个规整的网格然后计算网格上每一个交叉点处的函数值。这是一种完全系统、无随机性的遍历方法。3.1 实现网格与步长的选择网格搜索的实现关键在于确定每个维度上的分段数或步长。对于区间[-5, 5]如果我们决定在每个维度上均匀分成n段那么就会产生(n1)个格点包含边界。总采样点数为(n1)^2。def grid_search(n100): # n是每个维度划分的段数 # 1. 生成网格点坐标 # np.linspace 生成包含起点和终点的n1个等差点 x_grid np.linspace(-5, 5, n1) y_grid np.linspace(-5, 5, n1) # 2. 构建网格矩阵 (meshgrid) X, Y np.meshgrid(x_grid, y_grid) # 3. 计算所有网格点上的函数值 F f(X, Y) # 4. 找到最小值及其索引 min_index_flat np.argmin(F) # 将二维数组展平后找最小值的索引 min_index_2d np.unravel_index(min_index_flat, F.shape) # 将一维索引转回二维索引 x_min X[min_index_2d] y_min Y[min_index_2d] f_min F[min_index_2d] return x_min, y_min, f_min, X, Y, F # 执行网格搜索 x_gs, y_gs, f_gs, X_grid, Y_grid, F_grid grid_search(100) total_points (1001)**2 print(f网格搜索结果 (n100, 共{total_points}个点):) print(f 最优点 ({x_gs:.4f}, {y_gs:.4f}), 最小值 {f_gs:.6f})这里n100意味着在x和y方向上都产生了101个点总共10201个采样点。网格搜索的结果是确定的只要n固定无论运行多少次结果都一模一样。3.2 步长与精度、计算成本的三角关系网格搜索的精度直接由步长step 区间长度 / n决定。在我们的例子中区间长度是10n100时步长为0.1。这意味着我们找到的“最优点”一定是某个格点它与真实的最优点之间的最大可能误差就是步长的一半0.05。这就是网格搜索的离散化误差。步长、点数和计算量的关系步长减小一半n翻倍每个维度的点数变为2n1总点数从(n1)^2暴增到大约(2n1)^2 ≈ 4n^2计算量变为原来的4倍。对于d维问题计算量随n^d增长这就是著名的“维数灾难”。在二维情况下尚可接受一旦维度上升到5维、10维网格搜索所需的计算资源将变得无法承受。注意事项选择n时你需要明确你的精度要求。例如如果你希望找到的最优点坐标误差不超过0.01那么步长至少需要设为0.02对应的n 10 / 0.02 500总点数将达到501^2 ≈ 25万。计算一下函数值需要的时间是否可接受。通常网格搜索适用于低维1-3维且函数计算不昂贵的初步探索。3.3 网格搜索的可视化与“视野局限”网格搜索的结果看起来非常规整但它有一个天生的局限视野被限制在网格线上。def plot_grid_search(X, Y, F, x_best, y_best): plt.figure(figsize(12, 5)) # 三维曲面图带网格点 ax1 plt.subplot(1, 2, 1, projection3d) surf ax1.plot_surface(X, Y, F, cmapcoolwarm, alpha0.8, linewidth0, antialiasedFalse) ax1.scatter(x_best, y_best, f(x_best, y_best), colorred, s200, marker*, labelGrid Min) ax1.set_xlabel(x) ax1.set_ylabel(y) ax1.set_zlabel(f(x,y)) ax1.set_title(Function Surface with Grid Points) plt.colorbar(surf, axax1, shrink0.5, aspect10) # 二维等高线图显示网格 plt.subplot(1, 2, 2) contour plt.contour(X, Y, F, levels20, cmapRdYlBu) plt.clabel(contour, inlineTrue, fontsize8) plt.scatter(X, Y, colorblack, s1, alpha0.5, labelGrid Points) # 画出所有网格点 plt.scatter(x_best, y_best, colorred, s200, marker*, labelGrid Min) plt.xlabel(x) plt.ylabel(y) plt.title(Contour Plot with Search Grid) plt.legend() plt.grid(True, alpha0.3) plt.axis(equal) plt.tight_layout() plt.show() plot_grid_search(X_grid, Y_grid, F_grid, x_gs, y_gs)从等高线图上可以清晰地看到黑色的网格点。红五星落在其中一个网格点上。一个残酷的事实是真实的最小值点很可能不在任何网格交叉点上而是位于某个网格内部。网格搜索找到的只是所有格点中的最优者它可能非常接近真实最优点但几乎永远不是精确解。这是系统误差无法通过增加运行次数来消除只能通过减小步长增加点数来降低。4. 枚举法穷举思想的终极体现在计算机科学和优化领域“枚举法”通常指系统地遍历所有可能的候选解。在这个连续函数优化的问题中“所有可能的解”是无穷多的无法真正枚举。因此题目中的“枚举法”更准确地应理解为一种离散化后的穷举搜索它和网格搜索在思想上非常接近都是对连续空间进行离散采样后遍历。两者的区别更多在于表述的侧重点网格搜索强调“按网格系统采样”这一采样策略。枚举法强调“遍历所有采样点”这一搜索动作。在实际代码实现上用于解决本问题的“枚举法”和网格搜索几乎是一样的。但我们不妨拓宽一下思路考虑一个略微不同的场景如果变量的取值不是连续区间而是一个有限的离散集合那么枚举法就是唯一且完美的选择。4.1 离散集合上的真正枚举假设题目变一下x和y只能从集合{-5, -2.5, 0, 2.5, 5}中取值。那么候选解的总数就是5 * 5 25个。枚举法就是毫不留情地计算这25个点的函数值然后找出最小的那个。def enumeration_discrete(x_candidates, y_candidates): 在给定的离散候选值集合上进行枚举。 x_candidates: x所有可能取值的列表/数组 y_candidates: y所有可能取值的列表/数组 min_val float(inf) best_x, best_y None, None # 双重循环遍历所有组合 for x in x_candidates: for y in y_candidates: current_val f(x, y) if current_val min_val: min_val current_val best_x, best_y x, y return best_x, best_y, min_val # 定义离散的候选集 x_options [-5, -2.5, 0, 2.5, 5] y_options [-5, -2.5, 0, 2.5, 5] x_enum, y_enum, f_enum enumeration_discrete(x_options, y_options) print(f离散枚举结果: 最优点 ({x_enum}, {y_enum}), 最小值 {f_enum:.6f})这种方法简单、粗暴、绝对准确对于给定的离散集。它的计算量是O(m*n)其中m和n分别是x和y候选值的个数。当候选集很大时计算量会很大但逻辑清晰不会遗漏任何可能。4.2 连续问题中“枚举法”的实践理解回到我们的连续问题当我们说“用枚举法求解”时本质上就是先进行离散化设定一个步长生成一个离散的候选点集然后遍历它。这个过程和网格搜索的生成网格点并计算是完全一致的。所以在这个特定上下文中我们可以认为网格搜索是实现“枚举法”的一种具体技术手段。那么为什么还要区分这两个概念呢关键在于思维的起点当你从“如何系统地遍历这个区域”出发你可能会设计一个网格这就是网格搜索。当你从“我要检查所有可能的情况。”出发然后意识到“所有情况”是无限的于是你将其转化为“检查所有按某种规则如固定间隔选取的情况”这就是枚举思想。个人体会在实际建模中我通常这样区分使用场景。如果我的参数本身来自一个有限的选项列表比如选择使用算法A、B或C或者某个资源分配只能是几个特定值我会毫不犹豫地用枚举法循环遍历。如果我的参数是连续值我需要先确定一个我关心的精度比如小数点后两位然后在这个精度下生成所有可能的数值组合进行枚举这其实就自动形成了一个网格。此时“枚举”更侧重于“遍历”这个动作而“网格”描述了这些点的空间结构。5. 方法对比与实战选择指南我们已经在概念和代码上了解了这三种方法。现在让我们把它们放在一起从多个维度进行直接对比并给出在真实数学建模或编程项目中如何选择的建议。5.1 核心特性对比表特性维度蒙特卡罗方法网格搜索法枚举法针对离散集核心思想随机采样统计近似系统采样遍历网格点遍历所有给定候选解确定性非确定结果随机波动确定相同参数下结果唯一确定遍历固定集合采样点分布均匀随机分布规则网格分布用户定义的离散点集优点1. 实现简单逻辑直观。2. 不受维度灾难的指数增长影响但仍有影响。3. 容易并行化。4. 对函数形态无要求甚至不要求连续。1. 结果稳定可重现。2. 能系统性地覆盖整个区域。3. 采样均匀无遗漏区域在网格尺度上。4. 易于实现和理解。1. 绝对准确对于给定集合。2. 逻辑最简单不会出错。3. 适用于解空间天然离散的问题。缺点1. 结果有随机性精度不稳定。2. 收敛速度慢与1/sqrt(N)成正比。3. 在低维问题上效率通常低于系统方法。1. 受“维数灾难”影响严重高维不可行。2. 存在离散化误差最优解可能不在网格上。3. 不适用于非均匀重要性的问题浪费点在无关区域。1. 仅适用于候选解数量有限的情况。2. 候选解集很大时计算量巨大。3. 对于连续问题需要先离散化面临和网格搜索同样的问题。最佳适用场景1. 高维优化问题初步探索。2. 函数计算非常耗时只能承受少量采样。3. 对全局最优解的位置毫无先验知识。4. 需要快速得到一个“还不错”的近似解。1. 低维1-3维优化问题。2. 需要稳定、可重复的结果。3. 函数计算相对较快可以承受万级采样。4. 作为更高级优化算法的初始点提供者。1. 参数本身来自有限集合如选择算法类型、整数规划。2. 问题规模很小可以穷举。3. 作为验证其他算法结果的基准方法。5.2 性能与精度实测对比让我们用代码来做一个简单的对比实验看看在相近的计算量下哪种方法能找到更小的函数值。import time def compare_methods(target_points10000): 在相近采样点数下比较三种方法枚举法用等间距离散点模拟 print(f\n--- 在约 {target_points} 个采样点下的对比 ---) # 1. 蒙特卡罗 start time.time() x_mc, y_mc, f_mc, _, _, _ monte_carlo_min(target_points) t_mc time.time() - start # 2. 网格搜索计算需要的n使得 (n1)^2 接近 target_points n int(np.sqrt(target_points)) - 1 actual_points_grid (n1)**2 start time.time() x_gs, y_gs, f_gs, _, _, _ grid_search(n) t_gs time.time() - start # 3. “枚举法”这里模拟为在x和y方向上取相同数量的离散点总数为 m*m m int(np.sqrt(target_points)) x_discrete np.linspace(-5, 5, m) y_discrete np.linspace(-5, 5, m) start time.time() # 这里直接用网格搜索的逻辑来模拟枚举遍历 X, Y np.meshgrid(x_discrete, y_discrete) F f(X, Y) min_idx np.unravel_index(np.argmin(F), F.shape) x_em, y_em, f_em X[min_idx], Y[min_idx], F[min_idx] t_em time.time() - start print(f蒙特卡罗 (N{target_points}):) print(f 最优点: ({x_mc:.4f}, {y_mc:.4f}), 最小值: {f_mc:.6f}, 耗时: {t_mc:.4f}s) print(f网格搜索 (n{n}, 点数{actual_points_grid}):) print(f 最优点: ({x_gs:.4f}, {y_gs:.4f}), 最小值: {f_gs:.6f}, 耗时: {t_gs:.4f}s) print(f枚举/离散采样 (m{m}, 点数{m*m}):) print(f 最优点: ({x_em:.4f}, {y_em:.4f}), 最小值: {f_em:.6f}, 耗时: {t_em:.4f}s) # 找出本次对比中最好的结果 methods [(MC, f_mc), (GS, f_gs), (EM, f_em)] best_method, best_val min(methods, keylambda item: item[1]) print(f\n本次对比中{best_method} 方法找到了最小的函数值: {best_val:.6f}) return { MC: (f_mc, t_mc), GS: (f_gs, t_gs), EM: (f_em, t_em) } # 运行对比 results compare_methods(10000)运行几次这个对比函数你会发现一个有趣的现象在采样点数相近的情况下网格搜索以及等效的离散枚举找到的最小值通常比单次蒙特卡罗搜索的结果要好而且更稳定。这是因为网格搜索的系统性覆盖确保了在给定的分辨率下没有任何区域被“幸运”或“不幸”地多采样或少采样。而蒙特卡罗的随机性可能导致某次运行恰好错过了低值区域。然而蒙特卡罗有一次运行就非常接近最优解的可能性靠运气而网格搜索的精度上限则被步长锁死。这引出了另一个重要策略混合使用。5.3 进阶策略混合方法与精细化搜索在实际应用中我们很少只使用一种方法就止步。更常见的策略是分层优化第一阶段粗搜全局探索目的快速定位最优解可能存在的区域缩小搜索范围。方法选择如果维度高3优先用蒙特卡罗用相对较少的点如1万进行初步探索。如果维度低≤3可以用较粗的网格搜索n20或50速度更快且结果稳定。输出得到一个或多个“潜力区域”例如x ∈ [-1, 1], y ∈ [-2, 0]。第二阶段精搜局部挖掘目的在潜力区域内以更高精度寻找最优解。方法选择精细网格搜索在第一阶段缩小的区域内使用更小的步长更大的n进行网格搜索。因为区域变小了即使步长很小总点数也不会爆炸。局部蒙特卡罗在缩小后的区域内进行密集的随机采样。这可以避免网格搜索可能错失非格点最优解的问题。调用专业优化器如果函数性质较好如连续、可微可以在这个小区域内使用更高效的局部优化算法如梯度下降、Nelder-Mead单纯形法等它们能更快地收敛到精确的极值点。def two_stage_optimization(): 演示两阶段优化策略粗搜精搜 print(\n 两阶段优化策略演示 ) # 第一阶段粗搜用蒙特卡罗旨在发现潜力区域 print(第一阶段蒙特卡罗粗搜 (N5000)) x_coarse, y_coarse, f_coarse, x_vals, y_vals, f_vals monte_carlo_min(5000) # 根据粗搜结果确定一个较小的潜力区域例如取最优点附近±2的范围 range_buffer 2.0 x_low, x_high x_coarse - range_buffer, x_coarse range_buffer y_low, y_high y_coarse - range_buffer, y_coarse range_buffer # 确保区域仍在原定义域内 x_low, x_high max(x_low, -5), min(x_high, 5) y_low, y_high max(y_low, -5), min(y_high, 5) print(f 粗搜找到的潜力区域: x ∈ [{x_low:.2f}, {x_high:.2f}], y ∈ [{y_low:.2f}, {y_high:.2f}]) # 第二阶段精搜在潜力区域内用精细网格搜索 print(第二阶段精细网格搜索 (在潜力区域内n200)) # 在潜力区域内生成精细网格 n_fine 200 x_fine_grid np.linspace(x_low, x_high, n_fine1) y_fine_grid np.linspace(y_low, y_high, n_fine1) X_fine, Y_fine np.meshgrid(x_fine_grid, y_fine_grid) F_fine f(X_fine, Y_fine) min_idx_fine np.unravel_index(np.argmin(F_fine), F_fine.shape) x_fine, y_fine X_fine[min_idx_fine], Y_fine[min_idx_fine] f_fine F_fine[min_idx_fine] print(f 精搜最终结果: 最优点 ({x_fine:.6f}, {y_fine:.6f}), 最小值 {f_fine:.8f}) # 对比如果在全域做同样密度的网格搜索需要多少点 # 全域步长 10 / 200 0.05 # 潜力区域步长 (x_high-x_low) / 200 ≈ 4 / 200 0.02 (更精细) # 但潜力区域点数 201*201 ≈ 4万而全域同样0.05步长需要 201*2014万点。 # 这里优势在于我们在潜力区域用了更精细的步长(0.02)计算量却和全域粗步长(0.05)一样。 return x_fine, y_fine, f_fine final_x, final_y, final_f two_stage_optimization()这种“由粗到细”的策略结合了蒙特卡罗的全局探索能力和网格搜索的局部精确性是实践中非常有效且常用的方法。它既避免了单一方法在高精度要求下的计算瓶颈又提高了搜索的效率和最终结果的可靠性。6. 从这道题延伸开的实战思考这道习题虽然简单但它揭示的正是数学建模和科学计算中最核心的思维模式当没有现成的解析路径时如何利用计算工具去逼近答案。掌握了蒙特卡罗、枚举/网格搜索你就拥有了解决一大类优化、积分、模拟问题的“瑞士军刀”。几个关键的实战心得没有“最好”只有“最合适”。不要迷信任何一种方法。评估你的问题维度高低函数计算成本对结果确定性的要求需要的精度根据这些条件选择方法的组合。蒙特卡罗的“随机”不是缺点而是特性。它的随机性使其非常适合用来评估风险、计算概率、进行敏感性分析。例如你可以用蒙特卡罗模拟来评估一个方案在不同随机参数下的表现分布。网格搜索是调试和理解的利器。当你对一个黑盒函数完全不了解时做一个低分辨率的网格搜索并可视化结果如等高线图能让你迅速把握函数的整体形态、大致极值位置这对后续选择更高级的优化算法非常有帮助。始终关注计算成本。在动手前先估算一下计算量。一个O(n^d)复杂度的算法在d变大时会变得极其恐怖。这时候随机采样蒙特卡罗的O(N)与维度呈线性关系就显得格外可贵尽管它的精度提升较慢。验证验证再验证。对于重要的结果不要只依赖一种方法。可以用另一种独立的方法进行交叉验证。比如用蒙特卡罗找到一个近似解后可以以此为中心用小范围网格搜索去确认或者用不同的随机种子多跑几次蒙特卡罗看结果是否稳定。最后这道题给出的函数最小值通过更精确的数值优化算法如scipy.optimize.minimize可以找到约在(x≈-0.4502, y≈-1.5708)处最小值约为-1.913。你可以用这个值来检验上面各种方法得到的结果的接近程度。你会发现只要采样点足够多网格搜索和蒙特卡罗都能得到非常接近这个值的结果。这个过程本身就是计算科学魅力的一部分用简单而强大的思想去解开复杂世界的谜题。
返回列表