在使用R runif
并使用set.seed
kind = NULL
设置种子时,我们在代码中遇到了一种奇怪的情况(除非我弄错了,否则会解析为{{1}默认为kind = "default"
)。
我们在调用"Mersenne-Twister"
之前使用上游系统生成的(8位)唯一ID设置种子:
runif
这会将非常聚集在一起的值。
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.
25.13 25.36 25.66 25.58 25.83 25.94
时,runif
的这种行为就会消失,我们会得到看似更均匀分布的值。
kind = "Knuth-TAOCP-2002"
输出省略。
最有趣的是,这不会发生在Windows上 - 只发生在Ubuntu (下面是Ubuntu& Windows的random_values = sapply(seeds, function(x) {
set.seed(x, kind = "Knuth-TAOCP-2002")
y = runif(1, 17, 26)
return(y)
})
输出)。
sessionInfo
有人可以帮助了解发生了什么吗?
> 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
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
答案 0 :(得分:2)
注意:此答案总结了在R-devel邮件列表中对此问题进行讨论的要素。我只是试图捕捉和总结那里最初提出的想法。
尽管您保证这些数字不是特殊构造的边缘情况,但它们的每一个外观都是如此。这是原始序列加上用于检查所产生值的分布的代码:
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)
})}
如上所述,原始序列显示出极小的变异:
summary(checkit(seeds+0))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
##25.13 25.36 25.66 25.58 25.83 25.94
原始序列似乎有一些特殊之处,因为对它的最小修改不会产生同样令人惊讶的结果:
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
在原始序列跨越的范围内的所有种子中,预期数量在观察范围内产生值:
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
然而,原始序列中的所有值都在这个子集中(当然我们已经知道了......)。
table(seeds %in% s25)
##TRUE
## 21
所有这些都指出原始序列实际上是一个(可能是无意的)特殊构造的边缘情况的可能性。
答案 1 :(得分:1)
当您使用Mersenne Twister使用单个种子时,可以合理地假设生成的值大致独立且分布相同。不幸的是,不能保证从不同种子开始的两个流生成的值。例如,请参阅this SC thread。
在您的情况下,我建议使用SC线程中建议的种子选择策略之一,或者切换到PRNG,以更好地保证并行流。一个选择是L&#39; Ecuyer&#34; RngStreams&#34;发生器:
var_dump($terminators);
array(3) {
[0]=>
string(11) "Terminator1"
[1]=>
string(11) "Terminator2"
[2]=>
string(11) "Terminator3"
}
即使有那个PRNG,我也不知道你是否仍然认为你可以用任意种子播种PRNG并获得大致独立的流。
就Ubuntu和Windows之间的区别而言,其中一个系统使用的是32位发生器,而另一个系统使用的是64位。
答案 2 :(得分:1)
作为您的序列是边缘情况的进一步证据,您可以专注于构造的推定随机值的范围。 17和26有点分散注意力。在0和1上使用制服重复实验会产生同样不可能的事情:
f <- function(x) {
set.seed(x)
runif(1)
}
check_range <-function(seeds){
vals <- sapply(seeds,f)
max(vals)-min(vals)
}
当你的种子遭遇时:
> check_range(seeds)
[1] 0.09026112
在21个随机种子上运行时check_range(seeds)
的合理模型是它是抽取大小为21 U(0,1)
的随机样本的样本范围。它的theoretical density由下式给出:
f <- function(x){420*x^19*(1-x)}
我们可以用它来计算观察0.09或更小范围的概率:
> integrate(f,0,0.09)
2.334272e-20 with absolute error < 2.6e-34
如果检查在播种Mersenne Twister时模拟样品范围是合理的,您可以进行以下实验:
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 Twister的一些潜在缺陷。最可能的解释是Mersenne Twister本身参与产生这21个值(但当然不是简单地使用sample()
绘制21个值的天真方式)。