2014-09-04 2 views
1

мне нужно, чтобы генерировать распределение Пуассона в первенствовать и нашел метод (Inverse Transform Method)SAS обработка семян при генерации случайных распределений

сделал это в Excel, а затем в SAS (только для развлечения, так что я не нужен быстрый ответ) для сравнения с функцией sas ranpoi. Вот мой код (который работает):

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; 

Я инициализируется семя в обоих случайных функций для репликации результатов. Странно, что я получаю разные результаты в зависимости от того, отправляю ли я данные шаг с помощью обоих методов или только один из них (комментируя другой), но те же результаты снова и снова для каждого типа представления. Я ожидал тех же результатов! Почему это не так? (я использую sas 9.3) Спасибо! enter image description here

ответ

1

Похоже, что SAS чередует вызовы на PRNG как один поток. Псевдослучайные числа представляют собой последовательность значений, которые фактически детерминированы. Если вы семенируете и используете последовательность в одном алгоритме, вы будете получать одинаковые результаты каждый раз для этого алгоритма. Если вы используете последовательность, чередующуюся между двумя или более алгоритмами, набор алгоритмов всегда будет давать одинаковый набор результатов (что, кажется, имеет место для вас), но результаты для данного алгоритма будут разными, потому что некоторые из основных PRN, которые он рисовал ранее, теперь используются другими алгоритмами. Это является основой требования синхронизации при использовании так называемых методов уменьшения дисперсии на основе common random numbers. В общем случае, если вы хотите получить идентичные результаты, решение состоит в том, чтобы иметь несколько экземпляров вашего PRNG, по одному для каждого «источника» случайности в вашей программе и для засеивания нескольких источников независимо друг от друга, но одинаково во всех прогонах. Похоже, вы пытались это сделать, но SAS не ведет себя так, как вы думаете. Согласно their documentation, кажется, что они создают единый поток 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, то есть единичная входная форма дает единую случайную величину. Цикл, который вы выполняете, на самом деле выполняет прием/отклонение, и вы используете переменное количество униформ, чтобы придумать каждое значение Пуассона.

+0

Спасибо! Метод обратного преобразования просто ссылается на заголовок статьи – user3645882

+0

Yup, я видел. Тот, кто написал это, неверно использовал терминологию. – pjs

0

Ответ PJS в основном правильный, но несколько пояснений.

SAS действительно использует одно семя, когда вы делаете это так, как вы делали; все то, что я называю «примитивными» случайными функциями, работает с одним потоком PRNG, и имеет значение только первое семя (и только в первый раз он встречается).

Однако RANPOI немного отличается - вероятно, из-за того, как SAS создает пуассоны. В документации не указано, но, похоже, он использует два случайных числа (не уверен, что это всегда два или просто совпадение). Смотрите следующий тест:

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, мы видим, первые два ranuni-х, когда, начиная с семени 7, и в самом деле первый один соответствует первый из теста. Однако test3 имеет первые два начала с семенем 8, а второй - , а не, соответствующий одному из test2! test5 показывает, что фактически соответствует третье, что означает, что runpoi в test2 использовал 2 номера из потока.

В любом случае, если вы хотите изменить начальный срез, у вас есть два варианта.

Одним из них является использование CALL RANPOICALL RANUNI), что позволяет хранить семена в переменной. Два - использовать функцию RAND, которая работает с CALL STREAMINIT, чтобы устанавливать семена, когда захотите. Функция RAND считается «лучше», чем более примитивная RANPOI, и такая - она ​​использует лучший алгоритм PRNG.

Смежные вопросы