Статьи

Воспроизводимость и случайность

Со  Стефаном Туффери мы на этой неделе работали над главой книги под названием «  Статистическое обучение в актуарной науке» . Глава должна быть основана на R-функциях, и мы хотели воспроизвести некоторые результаты, которые он ранее получил с помощью SAS. Хорошая вещь заключается в том, что даже сложные функции (логистическая регрессия, деревья регрессии и т. Д.) Дают одинаковые результаты. Но мы обнаружили проблему, которую не смогли решить: генерирование идентичных обучающих наборов наблюдений … Из 1000 строк мы подобрали около 600 строк. Проблема в том, что мы не могли генерировать одинаковые наборы индексов как с R, так и с SAS. Даже используя аналогичные генераторы случайных чисел … (кроме случаев, когда мы хотим извлечь 1 или 2 строки, не более).

Давайте попробуем объяснить, что происходит (на основе кода, созданного  Стефаном ). Согласно  Eubank (2010) , в SAS есть (как минимум) два генератора случайных чисел,

Например, для функции RAND, если мы сгенерируем образец Гаусса — с помощью алгоритма Мерсенна-Твистера — код должен быть

%LET SEED =6;
%LET NREP=10;
DATA TESTRANDOM ;
  CALL STREAMINIT(&SEED);
  DO REP = 1 TO &NREP;
   X = RAND ('NORMAL'); 
   OUTPUT;
  END;
RUN;
PROC PRINT DATA = TESTRANDOM ;
RUN ;

И мы здесь

Обсервованный REP Икс
1 1 2,10680
2 2 -0,25604
3 3 0,28692
4 4 -0,22806
5 5 1,34569
6 6 0,16341
7 7 -0,27788
8 8 0,02133
9 9 1,24050
10 10 1,01054

Если мы хотим единообразный образец, он должен быть

%LET SEED =6;
%LET NREP=10;
DATA TESTRANDM ;
CALL STREAMINIT(&SEED);
DO REP = 1 TO &NREP;
  X = RAND ('UNIFORM'); 
  OUTPUT;
END;
RUN;
PROC PRINT DATA = TESTRANDOM ;
RUN ;
Обсервованный REP Икс
1 1 0,66097
2 2 0,48044
3 3 0,87849
4 4 0,19916
5 5 0,04838
6 6 0,19966
7 7 0,81353
8 8 0,53807
9 9 0,01105
10 10 0,53753

Хорошая новость (пока что) в том, что Mersenne-Twister был закодирован в R, в  функции RNGkind

> RNGkind("Mersenne")
> set.seed(6)
> runif(10)
 [1] 0.64357277 0.91590888 0.09523258 0.29537280
 [5] 0.76993170 0.25589353 0.51789573 0.67784993
 [9] 0.14722782 0.70052604

Но результат другой, даже если мы должны начать здесь с одного и того же семени. Теперь, если мы хотим убедиться в том, что здесь сделано, давайте напишем наши собственные коды   алгоритма Фишмана и Мура (1982) (чтобы воспроизвести  вывод SAS ). Версия R

> a = 397204094      # RANUNI multiplier
> seed = 123         # seed
> n = 10             # sample size
> m = (2^31) - 1     # period
> for (i in (1:n-1)) {
+ seed = (a*seed)%%m
+ u = seed / m
+ print(u)
+ }
[1] 0.7503961
[1] 0.3209121
[1] 0.3453204
[1] 0.2683455
[1] 0.241798
[1] 0.9888181
[1] 0.3943279
[1] 0.9710172
[1] 0.001632214
[1] 0.921537

Давайте теперь запустим аналогичный код с SAS,

%LET SEED =123;
%LET NREP=10;
DATA FRANUNI (KEEP = x) ;
seed = &SEED ;
DO REP = 1 TO &NREP;
  CALL RANUNI(seed, x);
  OUTPUT;
END;
RUN;
PROC PRINT DATA = FRANUNI ;
RUN ;

и мы получаем следующий вывод

Обсервованный Икс
1 0,75040
2 0,32091
3 0,17839
4 0,90603
5 0,35712
6 0,22111
7 0,78644
8 0,39808
9 0,12467
10 0,18769

Похоже, здесь мы действительно начинаем с одного и того же начального числа, поскольку первые два сгенерированных числа похожи. Но тогда, похоже, у нас действительно есть случайные числа … Если мы изменим начальное число, первые два числа будут похожи, но это все.

Мы могли бы упустить что-то тривиальное здесь, но мы этого не видели. Так что если у кого-то есть подсказки о проблемах воспроизводимости при генерации случайных выборок с R и SAS, мы заинтересованы!