当前位置: 首页 > news >正文

CQF预备知识:Python相关库 -- 准蒙特卡洛方法 scipy.stats

文中内容仅限技术学习与代码实践参考,市场存在不确定性,技术分析需谨慎验证,不构成任何投资建议。

准蒙特卡洛方法

在讨论准蒙特卡洛(Quasi-Monte Carlo,QMC)之前,先简要介绍蒙特卡洛(Monte Carlo,MC)方法。蒙特卡洛方法,或称蒙特卡洛实验,是一类依赖于重复随机抽样以获得数值结果的计算算法。其核心思想是利用随机性来解决本质上可能是确定性的问题。这些方法通常用于物理和数学问题,尤其在难以或无法使用其他方法时最为有用。蒙特卡洛方法主要用于以下三类问题:优化、数值积分以及从概率分布中生成样本。

生成具有特定属性的随机数比听起来要复杂得多。简单的蒙特卡洛方法旨在生成独立同分布(IID)的样本点。但生成多组随机点可能会产生截然不同的结果。

img

在上述图中,两种情况下点都是随机生成的,且不考虑之前已抽取的点。显然,空间的某些区域未被探索到——这在模拟中可能会引发问题,因为特定的一组点可能会导致完全不同的行为。

蒙特卡洛方法的一大优势在于其具有已知的收敛特性。让我们来看一个五维空间中的平方和的均值问题:

f ( x ) = ( ∑ j = 1 5 x j ) 2 , f(\mathbf{x}) = \left( \sum_{j=1}^{5}x_j \right)^2, f(x)=(j=15xj)2,

其中 x j ∼ U ( 0 , 1 ) x_j \sim \mathcal{U}(0,1) xjU(0,1)。该函数的均值是已知的,为 μ = 5 3 + 5 ( 5 − 1 ) 4 \mu = \frac{5}{3} + \frac{5(5-1)}{4} μ=35+45(51)。通过蒙特卡洛抽样,我们可以数值计算该均值,其近似误差的理论收敛率为 O ( n − 1 / 2 ) O(n^{-1/2}) O(n1/2)

img

尽管收敛性得到了保证,但实践者通常希望有一个更具确定性的探索过程。在普通的蒙特卡洛方法中,可以通过设置种子来实现可重复的过程。但固定种子会破坏收敛特性:某个种子可能适用于某一类问题,但对于另一类问题则可能失效。

为了以一种确定性的方式遍历空间,通常会使用覆盖所有参数维度的规则网格,也称为饱和设计。让我们考虑单位超立方体,其所有边界范围均为 0 到 1。现在,如果点之间的距离为 0.1,则填充单位区间的所需点数为 10。在二维超立方体中,相同的间距需要 100 个点,而在三维中则需要 1000 个点。随着维度的增加,填充空间所需的实验次数呈指数增长,这种现象被称为“维度的诅咒”。

>>> import numpy as np
>>> disc = 10
>>> x1 = np.linspace(0, 1, disc)
>>> x2 = np.linspace(0, 1, disc)
>>> x3 = np.linspace(0, 1, disc)
>>> x1, x2, x3 = np.meshgrid(x1, x2, x3)

img

为了缓解这一问题,设计了准蒙特卡洛(QMC)方法。这些方法是确定性的,能够很好地覆盖空间,并且其中一些方法可以继续使用并保持良好的特性。与蒙特卡洛方法的主要区别在于,QMC 方法生成的点并非独立同分布,而是知道之前的点。因此,某些方法也被称为序列。

img

上图展示了两组各包含 256 个点的样本。左侧是普通蒙特卡洛设计,而右侧是使用 Sobol’ 方法的 QMC 设计。我们可以清楚地看到,QMC 版本更加均匀。点在边界附近采样得更好,且几乎没有聚类或间隙。

评估均匀性的一种方法是使用一种称为“离散度”的度量。在这里,Sobol’ 点的离散度优于普通蒙特卡洛。

回到均值计算的问题,QMC 方法的误差收敛率也更好。对于此类函数,它们可以达到 O ( n − 1 ) O(n^{-1}) O(n1) 的收敛率,对于非常光滑的函数,收敛率甚至更好。下图显示了 Sobol’ 方法的收敛率为 O ( n − 1 ) O(n^{-1}) O(n1)

img

更多数学细节可参考 scipy.stats.qmc 的文档。

计算离散度

让我们考虑两组点。从下图可以看出,左侧的设计比右侧的设计覆盖了更多的空间。这可以通过 scipy.stats.qmc.discrepancy 度量来量化。离散度越低,样本越均匀。

>>> import numpy as np
>>> from scipy.stats import qmc
>>> space_1 = np.array([[1, 3], [2, 6], [3, 2], [4, 5], [5, 1], [6, 4]])
>>> space_2 = np.array([[1, 5], [2, 4], [3, 3], [4, 2], [5, 1], [6, 6]])
>>> l_bounds = [0.5, 0.5]
>>> u_bounds = [6.5, 6.5]
>>> space_1 = qmc.scale(space_1, l_bounds, u_bounds, reverse=True)
>>> space_2 = qmc.scale(space_2, l_bounds, u_bounds, reverse=True)
>>> qmc.discrepancy(space_1)
0.008142039609053464
>>> qmc.discrepancy(space_2)
0.010456854423869011

img

使用 QMC 引擎

这里我们来看两种最常用的 QMC 方法:scipy.stats.qmc.Sobolscipy.stats.qmc.Halton 序列。

"""Sobol' 和 Halton 序列。"""
from scipy.stats import qmc
import numpy as npimport matplotlib.pyplot as pltrng = np.random.default_rng()n_sample = 256
dim = 2sample = {}# Sobol'
engine = qmc.Sobol(d=dim, seed=rng)
sample["Sobol'"] = engine.random(n_sample)# Halton
engine = qmc.Halton(d=dim, seed=rng)
sample["Halton"] = engine.random(n_sample)fig, axs = plt.subplots(1, 2, figsize=(8, 4))for i, kind in enumerate(sample):axs[i].scatter(sample[kind][:, 0], sample[kind][:, 1])axs[i].set_aspect('equal')axs[i].set_xlabel(r'$x_1$')axs[i].set_ylabel(r'$x_2$')axs[i].set_title(f'{kind}—$C^2 = ${qmc.discrepancy(sample[kind]):.2}')plt.tight_layout()
plt.show()

警告

QMC 方法需要特别注意,用户必须阅读文档以避免常见陷阱。例如,Sobol’ 方法要求点的数量必须是 2 的幂。此外,稀疏化、燃烧或其他点的选择方式可能会破坏序列的特性,从而导致生成的点集并不比蒙特卡洛方法更好。

QMC 引擎是状态感知的。这意味着你可以继续生成序列,跳过某些点,或者重置它。让我们从 scipy.stats.qmc.Halton 中取出 5 个点。然后再次请求一组 5 个点:

>>> from scipy.stats import qmc
>>> engine = qmc.Halton(d=2)
>>> engine.random(5)
array([[0.22166437, 0.07980522],  # random[0.72166437, 0.93165708],[0.47166437, 0.41313856],[0.97166437, 0.19091633],[0.01853937, 0.74647189]])
>>> engine.random(5)
array([[0.51853937, 0.52424967],  # random[0.26853937, 0.30202745],[0.76853937, 0.857583  ],[0.14353937, 0.63536078],[0.64353937, 0.01807683]])

现在我们重置序列。再次请求 5 个点,将得到相同的前 5 个点:

>>> engine.reset()
>>> engine.random(5)
array([[0.22166437, 0.07980522],  # random[0.72166437, 0.93165708],[0.47166437, 0.41313856],[0.97166437, 0.19091633],[0.01853937, 0.74647189]])

这里我们通过快速前进序列来获取相同的第二组 5 个点:

>>> engine.reset()
>>> engine.fast_forward(5)
>>> engine.random(5)
array([[0.51853937, 0.52424967],  # random[0.26853937, 0.30202745],[0.76853937, 0.857583  ],[0.14353937, 0.63536078],[0.64353937, 0.01807683]])

注意

默认情况下,scipy.stats.qmc.Sobolscipy.stats.qmc.Halton 均为随机化的。随机化版本的收敛特性更好,并且可以防止在高维中出现条纹或明显的点模式。实际上没有理由不使用随机化版本。

创建 QMC 引擎,即继承 QMCEngine

要创建自己的 scipy.stats.qmc.QMCEngine,需要定义一些方法。以下是一个基于 numpy.random.Generator 的示例:

>>> import numpy as np
>>> from scipy.stats import qmc
>>> class RandomEngine(qmc.QMCEngine):
...     def __init__(self, d, seed=None):
...         super().__init__(d=d, seed=seed)
...         self.rng = np.random.default_rng(self.rng_seed)
...
...
...     def _random(self, n=1, *, workers=1):
...         return self.rng.random((n, self.d))
...
...
...     def reset(self):
...         self.rng = np.random.default_rng(self.rng_seed)
...         self.num_generated = 0
...         return self
...
...
...     def fast_forward(self, n):
...         self.random(n)
...         return self

然后像使用其他 QMC 引擎一样使用它:

>>> engine = RandomEngine(2)
>>> engine.random(5)
array([[0.22733602, 0.31675834],  # random[0.79736546, 0.67625467],[0.39110955, 0.33281393],[0.59830875, 0.18673419],[0.67275604, 0.94180287]])
>>> engine.reset()
>>> engine.random(5)
array([[0.22733602, 0.31675834],  # random[0.79736546, 0.67625467],[0.39110955, 0.33281393],[0.59830875, 0.18673419],[0.67275604, 0.94180287]])

使用 QMC 的指南

  • QMC 有规则!务必阅读文档,否则你可能无法获得比蒙特卡洛方法更好的效果。

  • 如果需要 恰好 2 m 2^m 2m 个点,请使用 scipy.stats.qmc.Sobol

  • scipy.stats.qmc.Halton 允许采样或跳过任意数量的点,但代价是收敛速度比 Sobol’ 更慢。

  • 永远不要删除序列的前几个点。这会破坏其特性。

  • 总是使用随机化版本。

  • 如果使用基于拉丁超立方采样的方法,则无法在不失去拉丁超立方特性的情况下添加点。(有一些方法可以做到,但尚未实现。)

风险提示与免责声明
本文内容基于公开信息研究整理,不构成任何形式的投资建议。历史表现不应作为未来收益保证,市场存在不可预见的波动风险。投资者需结合自身财务状况及风险承受能力独立决策,并自行承担交易结果。作者及发布方不对任何依据本文操作导致的损失承担法律责任。市场有风险,投资须谨慎。

相关文章:

  • MySQL常用函数详解之数值函数
  • 【FastAPI高级实战】结合查询参数与SQLModel Joins实现高效多表查询(分页、过滤、计数)
  • 用AI配合MCP快速生成n8n工作流
  • 本地访问远程vps中的sqlite数据库中的内容之(二)使用Python和web访问远程sqlite
  • Go语言2个协程交替打印
  • 使用Netlify进行简单部署
  • Git+Jenkins-Docker搭建企业级CI/CD平台
  • 基于OpenManus的跨平台部署方案及远程访问安全机制
  • CSS 第四天 复合选择器、CSS特性、背景属性、显示模式
  • P6 QT项目----汽车仪表盘(6.2)
  • 原型模式Prototype Pattern
  • 第二十九场 蓝桥算法赛
  • 华为OD机试_2025 B卷_运维日志排序(Python,100分)(附详细解题思路)
  • 136. 只出现一次的数字
  • CSP 2024 入门级第一轮(88.5)
  • NodeJS中老生代和新生代和垃圾回收机制
  • Luckfox Pico Pi RV1106学习<3>:支持IMX415摄像头
  • 深度学习:PyTorch自动微分模块
  • 修改了xml布局代码,页面使用了databinding,此时不开启kapt也可以吗
  • Yolo11改进策略:Block改进|MKP,多尺度卷积核级联结构,增强感受野适应性|即插即用|AAAI 2025
  • 山东网站开发学校/网站安全查询系统
  • php语言的网站建设/游戏优化是什么意思
  • wordpress 在线浏览/连云港seo
  • 动易网站怎么进入后台/深圳百度首页优化
  • 做软件赚钱的网站有哪些/现在阳性最新情况
  • 微信游戏网站源码怎么做/友链提交入口