首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R:用Mersenne-Twister种子从runif中进行随机值的极端聚集

R:用Mersenne-Twister种子从runif中进行随机值的极端聚集
EN

Stack Overflow用户
提问于 2017-11-02 16:02:30
回答 3查看 368关注 0票数 5

当我们使用R的runif并使用set.seed设置带有kind = NULL选项的种子时(除非我弄错了,否则它将解析为kind = "default";默认情况是"Mersenne-Twister"),这在代码中遇到了一个奇怪的情况。

在调用runif之前,我们使用上游系统生成的(8位)唯一ID来设置种子:

代码语言:javascript
复制
seeds = c(
  "86548915", "86551615", "86566163", "86577411", "86584144", 
  "86584272", "86620568", "86724613", "86756002", "86768593", "86772411", 
  "86781516", "86794389", "86805854", "86814600", "86835092", "86874179", 
  "86876466", "86901193", "86987847", "86988080")

random_values = sapply(seeds, function(x) {
  set.seed(x)
  y = runif(1, 17, 26)
  return(y)
})

这给出了极其组合在一起的值。

代码语言:javascript
复制
> summary(random_values)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  25.13   25.36   25.66   25.58   25.83   25.94 

当我们使用runif时,runif的这种行为就消失了,我们得到的值似乎分布得更加均匀。

代码语言:javascript
复制
random_values = sapply(seeds, function(x) {
  set.seed(x, kind = "Knuth-TAOCP-2002")
  y = runif(1, 17, 26)
  return(y)
})

输出省略。

这里最有趣的事情是,这不是在Windows上发生的--只发生在Ubuntu上(下面是Ubuntu和Windows的sessionInfo输出)。

Windows输出:

代码语言:javascript
复制
> seeds = c(
+   "86548915", "86551615", "86566163", "86577411", "86584144", 
+   "86584272", "86620568", "86724613", "86756002", "86768593", "86772411", 
+   "86781516", "86794389", "86805854", "86814600", "86835092", "86874179", 
+   "86876466", "86901193", "86987847", "86988080")
> 
> random_values = sapply(seeds, function(x) {
+   set.seed(x)
+   y = runif(1, 17, 26)
+   return(y)
+ })
> 
> summary(random_values)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  17.32   20.14   23.00   22.17   24.07   25.90 

有人能帮我弄明白这是怎么回事吗?

Ubuntu

代码语言:javascript
复制
R version 3.4.0 (2017-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 16.04.2 LTS

Matrix products: default
BLAS: /usr/lib/libblas/libblas.so.3.6.0
LAPACK: /usr/lib/lapack/liblapack.so.3.6.0

locale:
[1] LC_CTYPE=en_US.UTF-8          LC_NUMERIC=C                 
 [3] LC_TIME=en_US.UTF-8           LC_COLLATE=en_US.UTF-8       
 [5] LC_MONETARY=en_US.UTF-8       LC_MESSAGES=en_US.UTF-8      
 [7] LC_PAPER=en_US.UTF-8          LC_NAME=en_US.UTF-8          
 [9] LC_ADDRESS=en_US.UTF-8        LC_TELEPHONE=en_US.UTF-8     
[11] LC_MEASUREMENT=en_US.UTF-8    LC_IDENTIFICATION=en_US.UTF-8

attached base packages:
[1] parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] RMySQL_0.10.8               DBI_0.6-1                  
 [3] jsonlite_1.4                tidyjson_0.2.2             
 [5] optiRum_0.37.3              lubridate_1.6.0            
 [7] httr_1.2.1                  gdata_2.18.0               
 [9] XLConnect_0.2-12            XLConnectJars_0.2-12       
[11] data.table_1.10.4           stringr_1.2.0              
[13] readxl_1.0.0                xlsx_0.5.7                 
[15] xlsxjars_0.6.1              rJava_0.9-8                
[17] sqldf_0.4-10                RSQLite_1.1-2              
[19] gsubfn_0.6-6                proto_1.0.0                
[21] dplyr_0.5.0                 purrr_0.2.4                
[23] readr_1.1.1                 tidyr_0.6.3                
[25] tibble_1.3.0                tidyverse_1.1.1            
[27] rBayesianOptimization_1.1.0 xgboost_0.6-4              
[29] MLmetrics_1.1.1             caret_6.0-76               
[31] ROCR_1.0-7                  gplots_3.0.1               
[33] effects_3.1-2               pROC_1.10.0                
[35] pscl_1.4.9                  lattice_0.20-35            
[37] MASS_7.3-47                 ggplot2_2.2.1              

loaded via a namespace (and not attached):
[1] splines_3.4.0      foreach_1.4.3      AUC_0.3.0          modelr_0.1.0      
 [5] gtools_3.5.0       assertthat_0.2.0   stats4_3.4.0       cellranger_1.1.0  
 [9] quantreg_5.33      chron_2.3-50       digest_0.6.10      rvest_0.3.2       
[13] minqa_1.2.4        colorspace_1.3-2   Matrix_1.2-10      plyr_1.8.4        
[17] psych_1.7.3.21     XML_3.98-1.7       broom_0.4.2        SparseM_1.77      
[21] haven_1.0.0        scales_0.4.1       lme4_1.1-13        MatrixModels_0.4-1
[25] mgcv_1.8-17        car_2.1-5          nnet_7.3-12        lazyeval_0.2.0    
[29] pbkrtest_0.4-7     mnormt_1.5-5       magrittr_1.5       memoise_1.0.0     
[33] nlme_3.1-131       forcats_0.2.0      xml2_1.1.1         foreign_0.8-69    
[37] tools_3.4.0        hms_0.3            munsell_0.4.3      compiler_3.4.0    
[41] caTools_1.17.1     rlang_0.1.1        grid_3.4.0         nloptr_1.0.4      
[45] iterators_1.0.8    bitops_1.0-6       tcltk_3.4.0        gtable_0.2.0      
[49] ModelMetrics_1.1.0 codetools_0.2-15   reshape2_1.4.2     R6_2.2.0          
[53] knitr_1.15.1       KernSmooth_2.23-15 stringi_1.1.5      Rcpp_0.12.11  

视窗

代码语言:javascript
复制
> sessionInfo()
R version 3.3.2 (2016-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

locale:
[1] LC_COLLATE=English_India.1252  LC_CTYPE=English_India.1252    LC_MONETARY=English_India.1252
[4] LC_NUMERIC=C                   LC_TIME=English_India.1252    

attached base packages:
[1] graphics  grDevices utils     datasets  grid      stats     methods   base     

other attached packages:
 [1] bindrcpp_0.2         h2o_3.14.0.3         ggrepel_0.6.5        eulerr_1.1.0         VennDiagram_1.6.17  
 [6] futile.logger_1.4.3  scales_0.4.1         FinCal_0.6.3         xml2_1.0.0           httr_1.3.0          
[11] wesanderson_0.3.2    wordcloud_2.5        RColorBrewer_1.1-2   htmltools_0.3.6      urltools_1.6.0      
[16] timevis_0.4          dtplyr_0.0.1         magrittr_1.5         shiny_1.0.5          RODBC_1.3-14        
[21] zoo_1.8-0            sqldf_0.4-10         RSQLite_1.1-2        gsubfn_0.6-6         proto_1.0.0         
[26] gdata_2.17.0         stringr_1.2.0        XLConnect_0.2-12     XLConnectJars_0.2-12 data.table_1.10.4   
[31] xlsx_0.5.7           xlsxjars_0.6.1       rJava_0.9-8          readxl_0.1.1         googlesheets_0.2.1  
[36] jsonlite_1.5         tidyjson_0.2.1       RMySQL_0.10.9        RPostgreSQL_0.4-1    DBI_0.5-1           
[41] dplyr_0.7.2          purrr_0.2.3          readr_1.1.1          tidyr_0.7.0          tibble_1.3.3        
[46] ggplot2_2.2.0        tidyverse_1.0.0      lubridate_1.6.0     

loaded via a namespace (and not attached):
 [1] gtools_3.5.0         assertthat_0.2.0     triebeard_0.3.0      cellranger_1.1.0     yaml_2.1.14         
 [6] slam_0.1-40          lattice_0.20-34      glue_1.1.1           chron_2.3-48         digest_0.6.12.1     
[11] colorspace_1.3-1     httpuv_1.3.5         plyr_1.8.4           pkgconfig_2.0.1      xtable_1.8-2        
[16] lazyeval_0.2.0       mime_0.5             memoise_1.0.0        tools_3.3.2          hms_0.3             
[21] munsell_0.4.3        lambda.r_1.1.9       rlang_0.1.1          RCurl_1.95-4.8       labeling_0.3        
[26] bitops_1.0-6         tcltk_3.3.2          gtable_0.2.0         reshape2_1.4.2       R6_2.2.0            
[31] bindr_0.1            futile.options_1.0.0 stringi_1.1.2        Rcpp_0.12.12.1      
EN

回答 3

Stack Overflow用户

发布于 2017-11-03 23:57:57

注意:这个答案总结了在R邮件列表中讨论这个问题的一些内容。我只是试图捕捉和总结最初阐述的观点。

尽管你保证这些数字不是一个特殊构造的边缘情况,他们有所有的外观就是这样。下面是原始序列加上检查所产生的值的分布的代码:

代码语言:javascript
复制
seeds = c(
    86548915, 86551615, 86566163, 86577411, 86584144, 86584272,
    86620568, 86724613, 86756002, 86768593, 86772411, 86781516,
    86794389, 86805854, 86814600, 86835092, 86874179, 86876466,
    86901193, 86987847, 86988080)
checkit <- function(seeds) {
    sapply(seeds, function(x) {
        set.seed(x)
        y = runif(1, 17, 26)
        return(y)
    })}

正如注意到的那样,原始序列显示出的变化非常小,令人惊讶:

代码语言:javascript
复制
  summary(checkit(seeds+0))
  ## Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  ##25.13   25.36   25.66   25.58   25.83   25.94 

对于最初的序列,似乎确实有一些特别之处,因为对其进行的最小修改不会产生同样令人惊讶的结果:

代码语言:javascript
复制
summary(checkit(seeds+1))
## Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 17.18   19.65   22.75   22.02   24.37   25.79

summary(checkit(seeds-1))
## Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##17.15   18.44   19.92   20.77   22.97   25.95 

在原序列范围内的所有种子中,期望值在观察范围内产生值:

代码语言:javascript
复制
possible.seeds <- min(seeds):max(seeds)

s25 <- Filter(function(s){
    set.seed(s)
    x <- runif(1,17,26)
    x > 25.12 & x < 25.95},
    possible.seeds)

length(s25)/length(possible.seeds)
##[1] 0.09175801

然而,原始序列中的所有值都在这个子集中(当然我们已经知道了.)。

代码语言:javascript
复制
table(seeds %in% s25)

##TRUE 
##  21 

所有这些都指出了一个可能的可能性,即原来的序列实际上是一个(可能是无意的)特殊构造的边缘情况。

票数 3
EN

Stack Overflow用户

发布于 2017-11-04 13:40:12

作为进一步的证据,您的序列是一个边缘大小写,您可以集中精力在范围内的随机值是建立的。17岁和26岁有点让人分心。在0和1上重复你的制服实验会产生同样不可能的结果:

代码语言:javascript
复制
f <- function(x) {
  set.seed(x)
  runif(1)
}

 check_range <-function(seeds){
   vals <- sapply(seeds,f)
   max(vals)-min(vals)
}

当你与种子赛跑时:

代码语言:javascript
复制
> check_range(seeds)
[1] 0.09026112

在21个随机种子上运行check_range(seeds)的一个合理的模型是,它是一个大小为21的随机U(0,1)样本的样本范围。它的theoretical density是通过以下方式提供的:

代码语言:javascript
复制
f <- function(x){420*x^19*(1-x)}

我们可以用它来计算观测范围为0.09或更小的概率:

代码语言:javascript
复制
> integrate(f,0,0.09)
2.334272e-20 with absolute error < 2.6e-34

为了验证在像这样播种Mersenne Twister时对样本范围进行建模是合理的,您可以做以下实验:

代码语言:javascript
复制
ranges <- replicate(1000,check_range(sample(8548915:86988080,21)))
x <- seq(0,1,0.01)
y <- f(x)
hist(ranges,freq = FALSE,xlim =c(0,1))
points(x,y,type = "l")
abline(v=0.09)

输出:

密度直方图较好地符合理论密度。你问题中的21颗种子代表了一个极端的离群点。这不太可能是由于机会,也不太可能是由于梅森扭曲的一些潜在的缺陷。最有可能的解释是,Mersenne本身参与了产生这21个值(当然不是简单地使用sample()绘制21个值的天真方式)。

票数 2
EN

Stack Overflow用户

发布于 2017-11-03 20:05:07

当您使用带有单个种子的Mersenne时,合理的假设是生成的值近似独立且相同分布。不幸的是,对于从不同种子开始的两个流生成的值没有任何保证。参见,例如,this SC thread

在您的情况下,我建议您使用SC线程中建议的种子选择策略之一,或者切换到具有更好的并行流保证的PRNG。一种选择是L‘厄瓜多尔的"RngStreams“发生器:

代码语言:javascript
复制
set.seed(0, kind = "L'Ecuyer-CMRG")

即使有了那个PRNG,我也不知道它还能不能用任意的种子播下PRNG的种子,得到大致独立的流。

就Ubuntu和Windows之间的区别而言,其中一个系统可能使用32位生成器,另一个系统使用64位。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47079702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档