题目:Matlab中随机数生成控制
这里不讨论各随机数生成函数的使用方法(例如rand, randn, randi, randperm等),重点讨论如何重复生成一样的随机数,因为很多算法中存在随机数生成环节,每次运行程序的结果都不一样,那么自然地就希望能够控制随机数的生成过程,以保证结果能够复现。
以两个程序说明。首先运行如下程序:
%demo_randomseed1.m
clc;clear;close all;
%在程序开始前记录当前随机数生成器状态
scurr = rng;
%接下来写你的程序(包含随机数生成环节)
R1 = rand(5);%随机生成0~1之间的5*5矩阵
R2 = randn(5);%随机生成正态分布的5*5矩阵
%保存实验结果(含随机数生成器状态)
save('demo_rng.mat','R1', 'R2', 'scurr');
为了复现如上程序中的实验结果(R1和R2),可以运行如下程序:
%demo_randomseed2.m
clc;clear;close all;
demo_res = load('demo_rng.mat');
%在程序开始前按前面的记录设置当前随机数生成器状态
rng(demo_res.scurr);
%接下来写你的程序(包含随机数生成环节)
R1 = rand(5);%随机生成0~1之间的5*5矩阵
R2 = randn(5);%随机生成正态分布的5*5矩阵
%检验结果是否完全复现
norm(R1 - demo_res.R1)
norm(R2 - demo_res.R2)
可以发现第二段程序生成的R1和R2与第一段程序中的R1和R2完全相同。
因此,如果需要复现带有随机数生成环节的程序结果,只需在此程序开始时记录随机数生成状态(并将该状态保存):
scurr = rng;
当需要重复运行这段程序时,将保存好的随机数生成状态加载进来,在此程序开始时设置为当前的随机数生成状态即可:
rng(scurr);
Matlab内置函数rng的使用说明可以通过“help rng”来查看帮助文档,亦可访问如下链接:
中文版:控制随机数生成器 - MATLAB rng- MathWorks 中国
英文版:Control random number generator - MATLAB rng- MathWorks China
然而,在旧版本的Matlab中并不含有rng函数(rng函数在 R2011a 中推出,旧版本指R2011a之前的Matlab),个人常用的设置方法包括:
rand('seed',sd)
randn('seed',sd)
rand('state',s)
randn('state',s)
这种写法在新版Matlab中已不再推荐,根据官方文档说明,不推荐继续使用的理由包括:
- 对于生成器来说,'seed' 和 'state' 的说法具有误导性。
- 所有生成器('twister' 除外)都有缺陷。
- 它们对 rand 和 randn 使用不同的生成器,但这没有必要。
但有时如果想复现过去曾在老版本中的实验结果,就需要搞清楚以上写法与新版Matlab中rng设置方法的对应关系,具体如下:
rand/randn 所用生成器的名称 | rng 所用生成器的名称 |
'seed' | 'v4' |
'state' | 'v5uniform'(对于 rand) |
'twister' | 'twister'(推荐) |
也就是说:
rand('seed',sd)和randn('seed',sd)等价于rng(sd,'v4')
rand('state',s)和randn('state',s)分别等价于rng(s, 'v5uniform')和rng(s, 'v5normal')
rand('twister',5489)等价于rng(0,'twister');
可以试验一下,以下每两行代码输出的5*5矩阵是一样的:
rand('seed',0);rand(5)
rng(0,'v4');rand(5)
randn('seed',0);randn(5)
rng(0,'v4');randn(5)
rand('state',0);rand(5)
rng(0,'v5uniform');rand(5)
randn('state', 0);randn(5)
rng(0,'v5normal');randn(5)
rand('twister',5489);rand(5)
rng(5489,'twister');rand(5)
注意1:目前没有深究梅森旋转生成器twister的原理,只是尝试到rand('twister',twid);和rng(twid,'twister');两条指令中,当twid从1到5489变化时二者是等价的。
注意2:老版本中rand 和 randn 分别使用不同的生成器,如果你设置了rand(‘state’, 0), 但对于randn函数是不起作用的;同理,如果你设置了randn(‘state’, 0), 对于rand, randi, randperm等函数也是不起作用的。
关于新老版本的对应关系可以访问如下链接:
中文版:更换不推荐的 rand 和 randn 语法- MATLAB & Simulink- MathWorks 中国
英文版:Replace Discouraged Syntaxes of rand and randn- MATLAB & Simulink- MathWorks China