在生成随机分布时对种子进行sas处理

时间:2014-09-04 13:38:44

标签: random sas random-seed

我需要在excel中生成一个泊松分布并找到一个方法(Inverse Transform Method

在excel中完成,然后在sas中(只是为了好玩,所以我不需要快速回答)与ranpoi sas函数进行比较。 这是我的代码(有效):

data Poisson(keep=mean Poisson PoissonSas);
mean=0.2;
confronta=exp(-mean);
do obs=1 to 100;
    found=0;
    Poisson=0;
    ranuni=1;
    do until(found=1);
        ranuni=ranuni*ranuni(12547);
        if ranuni<confronta then found=1;
        else Poisson=Poisson+1;
    end;
    PoissonSas=ranpoi(012584,mean);
    output;
end;
run;

proc means data=Poisson(drop=mean);run;

因此,我在两个随机函数中初始化种子以复制结果。 奇怪的是,我得到的结果会有所不同,具体取决于我是用两种方法提交数据步骤还是只用其中一种方法提交数据(对另一种方法进行评论),但对于每种类型的提交都会反复提供相同的结果。 我总是期待相同的结果!为什么不是这样? (我使用的是9.3) 谢谢! enter image description here

2 个答案:

答案 0 :(得分:1)

看起来SAS正在将对PRNG的呼叫作为单个流进行交织。伪随机数是实际上是确定性的值序列。如果您在一个算法中播种和使用序列,则每次为该算法获得相同的结果。如果你使用在两个或多个算法之间交替的序列,那么算法集将总是产生相同的结果集(这似乎是你的情况),但是给定算法的结果将是不同的,因为一些基础它之前绘制的PRN现在被其他算法使用。当使用基于common random numbers的所谓方差减少技术时,这是同步要求的核心。一般来说,如果你想要相同的结果,那么解决方案就是拥有PRNG的多个实例,每个实例对应一个&#34;来源&#34;程序中的随机性,以及相互独立的多个源的种子,但在运行中相同。看起来你试图这样做,但SAS并没有像你想象的那样表现。根据{{​​3}},它们似乎根据代码中的第一个种子条目生成单个PRN流!这是他们的一个例子的一个子集:

/* This DATA step calls the RANUNI and the RANNOR functions */
/* and produces a single stream of random numbers based on  */
/* a seed value of 7.                                       */   
data d;
   d = ranuni (7); f = ' '; output;
   d = ranuni (8); f = ' '; output;
   d = rannor (9); f = 'n'; output;
   /* they actually have more... */
run;

顺便说一句,您的泊松算法通常不被视为逆变换算法。反转是1比1,即单个输入均匀产生单个随机变量。您正在执行的循环实际上正在接受/拒绝,并且您使用可变数量的制服来计算每个泊松值。

答案 1 :(得分:0)

PJS的回答基本上是正确的,但有一些澄清。

当你按照自己的方式做事时,确实会使用单个种子;所有我称之为'原始'的随机函数都可以在一个PRNG流中工作,只有第一个种子很重要(并且只在第一次遇到它时才重要)。

然而,RANPOI有点不同 - 可能是因为SAS创造了poissons。它在文档中没有说清楚,但似乎它使用了两个随机数(不确定它是否总是两个,或者只是巧合)。请参阅以下测试:

data test;
U=ranuni(7);
P=ranpoi(8,100);
put u= p=;
run;


data test2;
p=ranpoi(8,100);
u=ranuni(7);
put u= p=;
run;

data test3;
u=ranuni(8);
p=ranuni(7);
put u= p=;=
run;

data test4;
u=ranuni(7);
p=ranuni(8);
put u= p=;
run;

data test5;
do _t = 1 to 5;
 u=ranuni(8);
 put u=;
end;
run;

现在,在test4中,我们看到从种子7开始时的前两个ranuni,实际上第一个与test中的第一个匹配。但是,test3的前两个以种子8开头,而第二个与test2的那个匹配! test5显示实际上第三个​​匹配,意味着test2中的ranpoi从流中使用了2个数字。

无论如何,如果你想更改种子中途,你有两个选择。

一种是使用CALL RANPOI(和CALL RANUNI),它允许您将种子存储在变量中。两个是使用RAND函数,它与CALL STREAMINIT一起设置种子,无论何时你想要。 RAND函数被认为比更原始的RANPOI“更好”,因此它使用更好的PRNG算法。