走出无限循环

时间:2016-09-13 00:50:37

标签: r loops while-loop

while循环卡在R中的无限循环中时,有什么最好的方法可以识别?

这是我的情况:

diff_val = Inf
last_val = 0

while(diff_val > 0.1){

    ### calculate val from data subset that is greater than the previous iteration's val
    val = foo(subset(data, col1 > last_val))

    diff_val = abs(val - last_val) ### how much did this change val?
    last_val = val ### set last_val for the next iteration
}

目标是让val越来越接近稳定值,并且当val在最后一次迭代中val的0.1之内时,则认为足够稳定并从while循环释放。我的问题是,对于某些数据集,val在两个值之间来回交替卡住。例如,在27.0和27.7之间来回迭代。因此,它永远不会稳定。如果发生这种情况,我怎么能打破while循环?

我知道break,但不知道如何告诉循环何时使用它。我想在之前保持两次迭代的值,但是我不知道在两次迭代之前保持值的方法......

while(diff_val > 0.1){

    val = foo(subset(data, col1 > last_val))

    diff_val = abs(val - last_val)
    last_val = val

    if(val == val_2_iterations_ago) break
}

如何创建val_2_iterations_ago

对不可重现的代码表示歉意。复制情况所需的真实foo()data并非我可以分享......但是,控制流程并不是解决这个问题的关键。

3 个答案:

答案 0 :(得分:3)

我不知道只是跟踪前两次迭代实际上是否足够,但为此添加逻辑并不是太麻烦。

逻辑是,在每次迭代时,倒数第二个值成为最后一个值,最后一个值成为当前值,当前值来自foo()。请考虑以下代码:

while (diff_val > 0.1) {
    val <- foo(subset(data, col1 > last_val))

    if (val == val_2_iterations_ago) break

    diff_val = abs(val - last_val)
    val_2_iterations_ago <- last_val
    last_val <- val
}

答案 1 :(得分:2)

另一种方法,或许更一般,可以跟踪迭代并设置最大值。

将这与蒂姆的好答案配对:

iter = 0
max_iter = 1e6
while (diff_val > 0.1 & iter < max_iter) {
    val <- foo(subset(data, col1 > last_val))

    if (val == val_2_iterations_ago) break

    diff_val = abs(val - last_val)
    val_2_iterations_ago <- last_val
    last_val <- val
    iter = iter + 1
}

答案 2 :(得分:2)

通常如何做到这一点:

  • 收敛容差,因此当您的目标函数没有明显变化时,该算法被认为已收敛
  • 对迭代次数的限制,以确保代码最终终止
  • 检查目标函数是否实际减少,以捕捉其发散/循环的情况(设计了许多优化算法,因此不应该发生这种情况,但在您的情况下确实会发生)< / LI>

伪代码:

oldVal <- Inf
for(i in 1:NITERS)
{
    val <- objective(x)
    diffVal <- val - oldVal
    converged <- (diffVal <= 0 && abs(diffVal) < TOL)
    if(converged || diffVal > 0)
        break
    oldVal <- val
}