多个流
使用多个独立流
MATLAB® 软件提供的生成器算法使您能够创建多个独立的随机数流。例如,支持多个独立流的四种生成器类型是组合多递归 ('mrg32k3a'
)、乘法滞后斐波那契 ('mlfg6331_64'
)、Philox 4x32 ('philox4x32_10
') 和 Threefry 4×64 ('threefry4x64_20
') 生成器。您可以创建保证不重叠的多个独立流,并且已对这些流执行证明流之间值的(伪)独立性的测试。有关支持多个流的生成器算法的详细信息,请参阅创建和控制随机数流中的生成器算法表。
RandStream.create
函数使您能够创建三个流,这些流具有相同的生成器算法和种子值,但在统计上是独立的。
[s1,s2,s3] = RandStream.create('mlfg6331_64','NumStreams',3)
s1 = mlfg6331_64 random stream StreamIndex: 1 NumStreams: 3 Seed: 0 NormalTransform: Ziggurat
s2 = mlfg6331_64 random stream StreamIndex: 2 NumStreams: 3 Seed: 0 NormalTransform: Ziggurat
s3 = mlfg6331_64 random stream StreamIndex: 3 NumStreams: 3 Seed: 0 NormalTransform: Ziggurat
作为独立性证据,可以看到这些流在很大程度上是不相关的。
r1 = rand(s1,100000,1); r2 = rand(s2,100000,1); r3 = rand(s3,100000,1); corrcoef([r1,r2,r3])
ans = 3×3
1.0000 0.0007 0.0052
0.0007 1.0000 0.0000
0.0052 0.0000 1.0000
根据应用的不同,如果需要仿真一些事件,仅创建一组独立流中的部分流可能很有用。指定 StreamIndices
参数,从包含多个流的一组流中仅创建其中的部分流。StreamIndex
属性返回您创建的每个流的索引。
streamNum = 256; streamId = 4; s4 = RandStream.create('mlfg6331_64','NumStreams',streamNum,'StreamIndices',streamId)
s4 = mlfg6331_64 random stream StreamIndex: 4 NumStreams: 256 Seed: 0 NormalTransform: Ziggurat
由于多个流在统计上是独立的,因此可用于验证仿真的精度。例如,可以使用一组独立的流在不同的 MATLAB 会话或不同的处理器中多次重复蒙特卡罗模拟,并确定结果的变化情况。这样使得多个流可用于大规模的并行仿真。
使用种子获得不同结果
对于未明确支持独立流的生成器类型,不同的种子提供了可创建多个流的方法。通过使用不同的种子,可以创建返回不同的值并且各自独立执行的流。但是,更好的选择是使用专为多个独立的流设计的生成器,因为各流的统计学属性已经过谨慎验证。
通过梅森旋转生成器使用不同种子创建两个流。
s1 = RandStream('mt19937ar','Seed',1)
s1 = mt19937ar random stream Seed: 1 NormalTransform: Ziggurat
s2 = RandStream('mt19937ar','Seed',2)
s2 = mt19937ar random stream Seed: 2 NormalTransform: Ziggurat
在一个 MATLAB 会话中使用第一个流来生成随机数。
r1 = rand(s1,100000,1);
在另一个 MATLAB 会话中使用第二个流来生成随机数。
r2 = rand(s2,100000,1);
对于不同的种子,流返回的值通常是不相关的。
corrcoef([r1,r2])
ans = 2×2
1.0000 0.0030
0.0030 1.0000
使用不同种子的两个流可能看起来不相关,因为梅森旋转的状态空间(容纳 个种子)远大于可能的种子数量( 个)。除非使用大量不同种子,否则在不同仿真运行中重叠的可能性非常小。使用间隔很大的种子不会增加随机性水平。事实上,将该策略发挥到极致并在每次调用之前为生成器重新提供种子,可能导致值序列在统计上不独立且分布不一致。
如果您将为流提供种子作为初始化步骤,例如在 MATLAB 启动时或在运行仿真之前,则为流提供种子是最有用的。
使用子流获得不同结果
从流中获得不同结果的另一种方法是使用子流。与种子不同(在种子中,沿随机数序列的位置并不完全已知),子流之间的间隔是已知的,因此可以消除任何重叠的机会。与独立的并行流一样,子流之间的统计独立性已经过研究证明。简而言之,子流能够以更可控的方式完成在传统上用种子所做的许多事情,也是一种比并行流更轻量级的解决方案。
通过子流,可以快速轻松地确保在不同时间从相同的代码中得到不同结果。例如,在循环中生成几个随机数。
defaultStream = RandStream('mlfg6331_64'); RandStream.setGlobalStream(defaultStream) for i = 1:5 defaultStream.Substream = i; z = rand(1,i) end
z = 0.6986
z = 1×2
0.9230 0.2489
z = 1×3
0.0261 0.2530 0.0737
z = 1×4
0.3220 0.7405 0.1983 0.1052
z = 1×5
0.2067 0.2417 0.9777 0.5970 0.4187
在另一个循环中,您可以生成独立于第一组(包含 5 次)迭代的随机值。
for i = 6:10 defaultStream.Substream = i; z = rand(1,11-i) end
z = 1×5
0.2650 0.8229 0.2479 0.0247 0.4581
z = 1×4
0.3963 0.7445 0.7734 0.9113
z = 1×3
0.2758 0.3662 0.7979
z = 1×2
0.6814 0.5150
z = 0.5247
其中每个子流都可以重新生成其循环迭代。例如,您可以返回到循环中的第 6 个子流。
defaultStream.Substream = 6; z = rand(1,5)
z = 1×5
0.2650 0.8229 0.2479 0.0247 0.4581