在MATLAB中跨并行调用创建随机矩阵时的可重现结果

时间:2017-03-04 15:10:18

标签: matlab matrix random

我想创建一些随机矩阵,但它们在内存中非常大,所以我想找到一种方法在计算机上重现它们,这样当我需要将它们发送到另一台机器时,我只需要发送代码。 我想这样做:

function [R] = make_random_R(iter,j,n,K,p,R_type)
% Data as code
% R_type: 'posneg' or 'normdist'
% 1 <= iter <= 100
% 1 <= j <= K
% K: Number of classifiers
% n: Number of observations

assert(strcmp(R_type,'posneg') || strcmp(R_type,'normdist'),'R_type must be posneg or normdist');
assert(iter >= 1,'Error: iter >= 1 not satisfied');
assert((1 <= j) && (j <= K),'Error: 1 <= j <= K not satisfied');
assert(K > 0,'Error: K > 0 not satisfied');

globalStream = RandStream.getGlobalStream;
globalState =  globalStream.State;

stream=RandStream('mlfg6331_64','Seed',1);
substream_id = (iter - 1) * K + j;
stream.Substream = substream_id;
RandStream.setGlobalStream(stream);

switch R_type
    case 'posneg'        
        q0=ceil(2*log(n)/0.25^2)+1;
        if (q0 < p)
            q = q0;
        else
            q = ceil(p/2);
        end
        R = randi([0 1],p,q);
        R(R == 0) = -1;
    case 'normdist'        
        q = 2*ceil(log2(p));
        R = normrnd(0,1,[p,q]);    
end
RandStream.setGlobalStream(globalStream);
globalStream.State = globalState;
end

我担心的是parfor循环,无论parfor中的索引顺序如何,我都需要能够重现随机矩阵。所以我决定使用MATLAB流:

  • 保存全局流
  • 创建一个新流,设置种子和适当的子流(取决于iter和j)
  • 做数学
  • 放回全局流

这是我的代码(变量n,p,R_type控制随机矩阵是如何形成的,但它们并不重要,K与上面的变量相同,我需要它在行{{1} }}):

>> iter = 2;
>> j = 3;
>> n=100;
>> K=10;
>> p=6;
>> R_type = 'normdist';
>> for j=1:K
j
make_ran
>> parfor j=1:K
j
make_random_R(iter,j,n,K,p,R_type)
end
Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.

ans =

     7


ans =

   -0.3660    0.8816    1.1754   -0.4987   -1.8612   -0.3683
    0.9504   -0.3067   -0.5156   -0.2383   -1.1661    0.3622
    2.0743   -0.4195    0.5021    0.3954    0.2415   -0.4552
   -0.0474   -0.1645   -0.1725   -0.4938   -0.2559    0.2188
    1.0735    0.3660    0.1043    0.4403   -0.3166    1.1241
   -1.0421   -1.4528   -0.4976   -0.7166   -1.1328   -2.0260


ans =

     2


ans =

   -1.6629    0.0213   -1.8138   -0.4375    0.3575   -0.0353
    0.6653   -1.2662   -0.3977   -0.6540   -1.2131    0.4858
    0.3421    1.1266   -0.6066   -1.2095    1.5496   -0.9341
    0.2145    0.7192   -2.2087    0.7597   -0.0110   -1.1282
   -0.3511   -0.7305   -0.1143    0.0242    0.2431   -0.8612
    0.5875    1.2665   -2.1943   -0.4879    0.0120   -1.1539


ans =

     1


ans =

   -0.5300    2.4077   -0.3478    1.8695   -1.1327   -1.0734
   -0.2540   -1.1265    0.3152    0.4265    1.2777    0.0959
    0.5005   -0.7557    0.6194    1.5873    0.0961   -1.9216
    0.7275    0.5420   -0.6237   -0.2228    0.8915    0.4644
    0.8131   -0.1492    0.9232    0.8410   -0.0637    2.1163
   -1.1995    0.2338   -1.3726    0.1604   -0.1855    1.3826


ans =

     8


ans =

   -0.5146    2.2106    2.7200   -1.2136    1.0004    1.3089
    0.7225    0.2746   -0.8798    0.2978   -0.8490    1.6744
    1.1998   -0.0363    1.9105   -0.7747   -0.8707   -0.6823
    0.6801    1.3194   -0.0685    0.5944    1.5078   -1.6821
    0.0876    1.2150   -0.0747    0.0324   -1.1552    0.0966
   -0.0624   -0.3874   -0.5356    0.6353    1.4090   -1.1014


ans =

     6


ans =

    0.5866   -1.0222   -0.2168    0.8582    1.4360    0.0699
    2.0677   -0.4740   -0.8763    1.7827    0.1930   -1.2167
   -0.3941   -0.5441    0.3719   -0.0609    0.7138   -1.0920
    0.3622   -0.0459   -0.0221    0.2030   -0.7695   -0.8963
   -0.1986   -0.2560    0.6666    0.4831   -1.2028   -0.9423
    0.1656    1.2006   -1.1131    0.7704   -0.6906   -1.3143


ans =

     5


ans =

   -0.5782   -0.3634    1.5381   -1.3173   -0.9493    0.8480
    1.5921   -0.4069    0.7795   -0.3390   -0.1071    0.4201
   -0.0184    0.2865   -0.1139   -0.1171    0.2288    0.5511
    0.1787    0.7583    0.3994    1.0457    0.3291   -0.9150
    0.3641   -0.6420   -0.2096    0.7761    0.4022   -0.7478
    0.1165    0.7142    0.7029   -1.1195    0.0905    0.6810


ans =

     4


ans =

    0.1246   -0.3173    0.8068    0.6485   -0.8572    0.2275
    0.3674   -0.0507   -0.9196    0.6161   -0.5821   -0.4291
   -1.0142   -1.1614   -2.5438    1.5915    2.0356    0.4535
   -0.2111   -0.3974    0.0376    0.3825   -1.9702    1.5318
   -0.3890    0.9210   -0.0635    0.3248    1.8666   -0.0160
    1.3908   -0.7204   -0.6772   -0.0713    0.0569    0.5929


ans =

     3


ans =

   -0.1602    0.6891    0.4725    0.0277   -2.0510   -2.2440
   -0.7497    1.8225   -0.4433    0.4090    0.9021   -1.6683
    0.0659    0.3909    0.2043    0.9065    1.4630    0.3091
   -0.3886    0.6715   -0.9742   -0.5468    0.2890    0.5625
   -0.4558    0.4770   -0.1888   -0.6504    0.3281    1.3767
    0.3983    0.5834    0.9360    0.8604   -0.9776    0.6755


ans =

    10


ans =

   -0.4843   -0.4512    0.7544    0.7585   -0.4417   -0.0208
    1.8537   -1.6935   -2.7067   -0.5077    0.9616   -1.7904
   -1.6943   -1.0988    0.1208   -0.8100    1.8778    1.1654
    1.1759   -0.7087   -1.2673   -0.1381   -0.0710    0.5343
    0.2589   -0.5128   -0.3970    0.6737    0.8097    2.7024
   -0.8933    0.2810    0.8117   -0.5428   -0.8782    1.1746


ans =

     9


ans =

    0.0254   -0.7993    1.5164    1.2921   -1.1013    1.8556
   -0.6280    0.9374   -0.1962    0.1685   -0.5079    0.4333
   -0.3962   -0.9977    0.6971   -1.0310   -1.1997   -2.1391
    0.7179    1.0177   -0.8874   -0.6732    0.7295    1.4448
   -1.1793   -1.3210    1.5292    0.2280    1.9337    1.0901
   -0.0926    0.1798   -1.1740    0.3447    2.4578    0.4170

尝试了一些代码,这里是:

awk

我想知道代码是否正确,是否在函数调用后保留了全局流的状态?请帮助我,非常感谢

1 个答案:

答案 0 :(得分:4)

MATLAB从“已知”但“复杂”函数生成随机数,因此您可以生成相同的随机序列!号码。

这样做你应该使用“rng”功能
将rng设置为默认值,以便重置随机数生成。

rng('default');
rand(1,5)
ans=
0.8147  0.9058  0.1270  0.9134  0.6324

然后如果你想重现这个随机数序列你可以写:

rng('default');
rand(1,5)
ans=
    0.8147  0.9058  0.1270  0.9134  0.6324

另一种方法是为随机数生成获取/设置种子:

s=rng;
rand(1,5)
ans= 0.0975  0.2785  0.5469  0.9575  0.9649

并重现相同的seq。

rng(s);
rand(1,5)
ans=
     0.0975  0.2785  0.5469  0.9575  0.9649

noe“rng”本身是一个丰富的功能,您可以在matlab文档中更多地学习它。

(我希望我能正确理解这个问题)

回答来自@ m7913d的评论

  

“默认情况下,MATLAB®客户端和MATLAB工作人员使用不同的   随机数发生器,即使工人是当地人的一部分   与客户端在同一台机器上的集群。对于客户来说,   默认是Mersenne Twister生成器('twister'),并且用于   worker默认为Combined Multiple Recursive生成器   ('CombRecursive'或'mrg32k3a')。如果有必要生成   客户端和工作人员中的数字流相同,您可以设置一个   匹配另一个。“

显然matlab工作者使用matlab本身使用不同的函数(用于生成随机数),所以你也可以在“rng”函数中设置默认函数,

rng(5,'twister') % for using twister method to generate random number

for more info try this doc from matlab

新示例显示您可以在parfor中重现随机数序列:

>> parfor i=1:3
rng(3,'twister');
rand(1,5)
i
end

ans =

    0.5508    0.7081    0.2909    0.5108    0.8929


ans =

     3


ans =

    0.5508    0.7081    0.2909    0.5108    0.8929


ans =

     1


ans =

    0.5508    0.7081    0.2909    0.5108    0.8929


ans =

     2
来自评论的重要部分:

  

关于“客户工作者”,正如我之前所说,matlab使用默认函数为您的所有客户端工作人员,因此结果是完全可重现的,只是创建随机数的默认函数不同于matlab自己的默认函数。你可以在matlab及其具有rng函数的worker中设置默认函数(答案中的最后一个例子)

  

关于使用全局流,使用全局流没有区别,您应该使用rng函数设置种子值以获得相同的可重现结果,全局流只是指示您使用哪个函数生成随机数, matlab有大约6个函数来完成这项工作,但如果你有自己的函数你可以在全局流上设置它,然后再次使用rng函数来获取每次生成随机数时的相同序列