如何在R实现的梯度下降算法中添加相似迭代终止机制?
给梯度下降算法添加提前终止的收敛判断
嗨,我来帮你解决这个问题!你现在的梯度下降会跑完所有30000次迭代,哪怕结果已经几乎不变,其实只需要加一个收敛阈值判断,当两次迭代的x值差异小到一定程度时,就提前终止循环就行。
核心思路
我们可以在每次迭代后,计算当前x和上一次迭代x的绝对差值,当这个差值小于我们设定的阈值(比如1e-6,也就是小数点后6位都相同),就认为算法已经收敛,找到了足够接近最小值的解,直接跳出循环。同时保留最大迭代次数的限制,防止算法因为学习率设置不当等原因陷入无限循环。
修改后的完整代码
我先把你的代码补全并修改,加入收敛判断:
# 先把目标函数和导数单独定义,代码更清晰 f <- function(x) 1 - x * exp(-x) grad_f <- function(x) -exp(-x) + x * exp(-x) # f(x)的一阶导数 # 梯度下降参数设置 learning_rate <- 0.02 max_iter <- 30000 converge_threshold <- 1e-6 # 收敛阈值,可根据需求调整(比如1e-8更严格) # 初始化变量 x <- 0 prev_x <- Inf # 初始设为无穷大,确保第一次迭代不会误触发收敛 # 带收敛判断的梯度下降循环 for (i in 1:max_iter) { prev_x <- x # 保存当前x作为上一次迭代的值 grad <- grad_f(x) x <- x - learning_rate * grad # 判断是否收敛:两次x的差值小于阈值就终止 if (abs(x - prev_x) < converge_threshold) { cat("算法在第", i, "次迭代时收敛,最终x值为:", round(x, 6), "\n") break } # 如果到最大迭代次数还没收敛,给出提示 if (i == max_iter) { cat("达到最大迭代次数", max_iter, ",最终x值为:", round(x, 6), "\n") } } # 输出函数最小值 cat("函数最小值为:", round(f(x), 6), "\n")
代码解释
- 收敛阈值:
converge_threshold = 1e-6表示当两次迭代的x差值小于0.000001时就停止,你可以根据需求调整这个值——想要更精确就调小(比如1e-8),想要更快终止就调大(比如1e-4)。 - 迭代判断:每次迭代前把当前x存到
prev_x,计算新x后比较两者的绝对差,满足条件就用break跳出循环。 - 双重保障:既保留了最大迭代次数,又加了收敛判断,避免算法因为异常情况(比如学习率太小导致收敛极慢,或者学习率太大导致震荡)一直跑下去。
另一种实现方式:用while循环
如果你更喜欢把终止条件直接写在循环头部,也可以用while循环实现:
# 初始化变量 x <- 0 prev_x <- Inf iter <- 0 while (iter < max_iter && abs(x - prev_x) >= converge_threshold) { iter <- iter + 1 prev_x <- x grad <- grad_f(x) x <- x - learning_rate * grad } # 输出结果 if (iter < max_iter) { cat("算法在第", iter, "次迭代时收敛,最终x值为:", round(x, 6), "\n") } else { cat("达到最大迭代次数", max_iter, ",最终x值为:", round(x, 6), "\n") } cat("函数最小值为:", round(f(x), 6), "\n")
额外小技巧
除了判断x的变化,你也可以判断函数值的变化,比如比较abs(f(x) - f(prev_x)) < converge_threshold,效果类似,适合对函数值精度有要求的场景。
内容的提问来源于stack exchange,提问作者Phi Lipp
相关产品推荐
相关产品推荐

