【问题标题】:For loop is not changing the random values generated at each iteration despite specifying it to尽管将 For 循环指定为
【发布时间】:2018-06-14 11:08:50
【问题描述】:

我目前正在编写代码来运行 2D 空间自适应样条拟合技术的模拟,在此代码中,我有一个 for 循环,它应该更改我在每次迭代中构建模型的 x、y 和 z 值。

注意要运行此代码,您将需要来自 github 的 MRSea 包。这个可以 下载使用: devtools::install_git("https://github.com/lindesaysh/MRSea.git")

在一些非常有用的 cmets 之后(谢谢大家),我将代码简化为:


simulate <- function(niter=5, npoints=10, nknots=9, fitmeasure="AIC", startknots=5, minknots=2,maxknots=9, knotgap=0 ) {
  require(MRSea)
  x <- matrix(nrow=niter, ncol=npoints)
  y <- matrix(nrow=niter, ncol=npoints)
  rnd <- matrix(nrow=niter, ncol=npoints)
  mygrid <- expand.grid(seq(0,1, length=npoints), seq(0,1, length=npoints)) 
  for (i in 1:niter) {
    x[i,] <- runif(npoints)  
    y[i,] <- runif(npoints) 
    mu <- x[i,]*sin(4*pi*y[i,]) 
    sigma <- diff(0.25 * range(mu)) 
    rnd[i,] <- rnorm(npoints)
    z <- mu + sigma*rnd[i,]
    dat <- data.frame(x.pos=x[i,], y.pos=y[i,], response=z)
    init <- glm(response ~ 1, data=dat)
    knotgrid <- getKnotgrid(coordData = cbind(x[i,],y[i,]), numKnots = nknots, plot=F) 
    distMats <- makeDists(cbind(x[i,],y[i,]), na.omit(knotgrid))
    salsa2dlist <-  list(fitnessMeasure = fitmeasure, knotgrid = knotgrid,
                         startKnots=startknots, minKnots=minknots, maxKnots=maxknots, gap=knotgap)
    predgrid <- makeDists(mygrid, na.omit(knotgrid))$dataDist
    sim <- runSALSA2D(model=init, salsa2dlist, d2k=distMats$dataDist,
                      k2k=distMats$knotDist, splineParams=NULL, tol=0, chooserad=F,
                      panels=NULL, suppress.printout=TRUE)

  }
  return(x) # Can return x,y or rnd to see the issue
}
simulate()

我已经确定删除以下代码行允许 runif() 行正确运行并产生不同的值:

sim <- runSALSA2D(model=init, salsa2dlist, d2k=distMats$dataDist,
                      k2k=distMats$knotDist, splineParams=NULL, tol=0, chooserad=F,
                      panels=NULL, suppress.printout=TRUE)

有谁知道为什么这条线可能会导致我的代码出现问题以及解决问题的潜在方法?

谢谢。

【问题讨论】:

  • 我们是否需要所有这些代码才能理解您的问题?你能把它简化为一个最小的可重现的例子吗?
  • 我建议做一个这样的游戏:你可以删除多少行代码并且仍然看到预期的问题?这是一种非常有用的调试技术,如果您自己不解决问题,您将在完成后获得更快的帮助。
  • 但也许您调用的某些函数使用了set.seed,或者将surface 分配给1 以外的其他对象,因此for 循环不会运行,或者... 查找的好方法out 是删除除for 循环之外的所有内容,并一次添加一位,直到观察到问题为止。您还可以在循环中添加一些 print 语句或 browser() 以检查实际情况。
  • 感谢您的帮助,我已经用最简单的情况编辑了问题,我可以找到重现问题并确定导致问题的行。

标签: r function for-loop spline


【解决方案1】:

Something 正在设置随机种子。也许knot.seed 参数?虽然这似乎更有可能是一些结。无论如何,快速解决方法是在生成随机数之前输入set.seed(as.integer(Sys.time()) %% 10000)

明智的做法是深入挖掘以找出是什么功能在播种,因为它可能会也可能不会影响您的结果。

【讨论】:

  • It appears that this only sets the seed to 357 when K-fold cross validation is selected as the measure of fit.选择AIC或BIC等时,不会设置该种子。 span>
【解决方案2】:

“使用来源,卢克……” runSALSA2D 调用 getCVids,这会重置种子。它真的应该只在函数内部执行,而不影响函数外部的种子;您可以提交有关它的错误/功能请求。您可以向该函数发送不同的种子,但由于它使用set.seed,因此没有一种简单的方法可以保持随机数生成器的良好属性。当然,每次使用相同的种子可能会导致其他问题,所以你可能想尝试一下;从帮助文件中,将其传递为 NULL 可能是最好的(除了根本不设置种子!),但这就是 runSALSA2D 在硬设置之前检查的内容。 :(

https://github.com/lindesaysh/MRSea/blob/master/R/runSALSA2D.R https://github.com/lindesaysh/MRSea/blob/master/R/getCVfoldID.R

不过,与此同时,您需要做的就是在每个循环中生成数字后保存种子,然后自行重置。

runif(1)
saved.seed <- .Random.seed
for (i in 1:niter) {
    .Random.seed <- saved.seed
    x[i,] <- runif(npoints)  
    y[i,] <- runif(npoints) 
    mu <- x[i,]*sin(4*pi*y[i,]) 
    sigma <- diff(0.25 * range(mu)) 
    rnd[i,] <- rnorm(npoints)
    saved.seed <- .Random.seed

第一个runif(1)是保证.Random.seed存在;见setting seed locally (not globally) in R

或者(无论如何,对于所写的示例),您不会产生很多积分;您也可以一次生成它们并将它们保存以在您的循环中使用。

编辑:是的,这样做!

无论如何,您已经为顶部的所有随机点分配了空间!因此,他们根本没有理由参与其中。

simulate3 <- function(...) {
  x <- matrix(runif(npoints*niter), nrow=niter, ncol=npoints)
  y <- matrix(runif(npoints*niter), nrow=niter, ncol=npoints)
  rnd <- matrix(rnorm(npoints*niter), nrow=niter, ncol=npoints)
  mygrid <- expand.grid(seq(0,1, length=npoints), seq(0,1, length=npoints)) 
  for(i in 1:niter) {
    mu <- x[i,]*sin(4*pi*y[i,]) 
    sigma <- diff(0.25 * range(mu)) 
    z <- mu + sigma*rnd[i,]

【讨论】:

  • 查看源代码后,runSALSA2D 仅在is.null(panels) != TRUE 时调用getCVids,但在我上面的示例中为panels=NULL。除了getCVids 之外,我找不到任何其他地方可以在runSALSA2D 中设置种子。使用您建议的修复程序我遇到了一个错误:apply(knotDist[point, aR], 1, min): dim(x) must have positive length。感谢您的帮助,我会弄清楚这是从哪里来的,并与包的作者交谈以解决问题
  • 怕你不能怪我;无论您是否包含修复程序,它有时都会发生(取决于随机性)。
  • 你是对的,不过,关于getCVids;看起来它在 return.reg.spline.fit.2d 中,它调用 initialise.measures_2d,默认为 knot.seed = 10
  • 就是这样! runSALSA2Dinitialise=TRUE 调用return.reg.spline.fit.2D,然后调用initialise.measure_2d。作为initialise=TRUE,此函数正在运行set.seed(knot.seed),其中knot.seed = 10。我会把这个转给作者并在接下来的几天里修改它,非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 2012-10-13
  • 2015-12-03
  • 2015-03-17
  • 1970-01-01
相关资源
最近更新 更多