示例数据
X<-matrix(c(rep(1,97),runif(97)) , nrow=97, ncol=2)
y<-matrix(runif(97), nrow= 97 , ncol =1)
我成功创建了成本函数
COST<-function(theta,X,y){
### Calculate half MSE
sum((X %*% theta - y)^2)/(2*length(y))
}
当我运行此函数时,似乎无法收敛超过100次迭代。
theta <- matrix (0, nrow=2,ncol=1)
num.iters <- 1500
delta = 0
GD<-function(X,y,theta,alpha,num.iters){
for (i in num.iters){
while (max(abs(delta)) < tolerance){
error <- X %*% theta - y
delta <- (t(X) %*% error) / length(y)
theta <- theta - alpha * delta
cost_histo[i] <- COST(theta,X,y)
theta_histo[[i]] <- theta
}
}
return (list(cost_histo, theta_histo))
}
有人可以帮助我吗?
干杯
答案 0 :(得分:2)
您的实施的算法部分是正确的。问题在于
GD
中的循环结构不正确; for
循环是冗余的,变量缺乏正确的初始化。alpha
简单地实现梯度下降是危险的。通常建议选择alpha
这个alpha
小到足以希望我们总是搜索目标函数。然而,这在实践中很少见。例如,多小就足够了?如果它很小,那么收敛速度就是一个问题;但如果它很大,我们可能会被困在一个“锯齿状”中。寻找路径甚至分歧!这是渐强下降的强大版本,用于估计线性回归。改进来自逐步减半策略,以避免&#34; zig-zag&#34;或分歧。查看代码中的注释。根据此策略,使用大# theta: initial guess on regression coef
# alpha: initial step scaling factor
GD <- function(X, y, theta, alpha) {
cost_histo <- numeric(0)
theta_histo <- numeric(0)
# an arbitrary initial gradient, to pass the initial while() check
delta <- rep(1, ncol(X))
# MSE at initial theta
old.cost <- COST(theta, X, y)
# main iteration loop
while (max(abs(delta)) > 1e-7) {
# gradient
error <- X %*% theta - y
delta <- crossprod(X, error) / length(y)
# proposal step
trial.theta <- theta - alpha * c(delta)
trial.cost <- COST(trial.theta, X, y)
# step halving to avoid divergence
while (trial.cost >= old.cost) {
trial.theta <- (theta + trial.theta) / 2
trial.cost <- COST(trial.theta, X, y)
}
# accept proposal
cost_histo <- c(cost_histo, trial.cost)
theta_histo <- c(theta_histo, trial.theta)
# update old.cost and theta
old.cost <- trial.cost
theta <- trial.theta
}
list(cost_histo, theta_histo = matrix(theta_histo, nrow = ncol(X)))
}
是安全的。 保证融合。
cost_histo
返回时,
theta_histo
的长度告诉您已经进行了多少次迭代(不包括减半); theta
的每一列每次迭代都会COST
。实际上,减半实际上可以大大加快收敛速度。如果对COST<-function(theta,X, y) {
c(crossprod(X %*% theta - y)) /(2*length(y))
}
使用更快的计算方法,则可以获得更高的效率。 (对大型数据集最有用。请参阅)
X
现在,让我们考虑一下您的示例y
,oo <- GD(X, y, c(0,0), 5)
。
plot(oo[[1]])
经过107次迭代后,它会收敛。我们可以查看MSE的踪迹:
oo[[2]][, 107]
请注意,在最初的几个步骤中,MSE降低得非常快,但随后几乎持平。这揭示了梯度下降算法的根本缺点:当我们越来越接近最小值时,收敛越来越慢。
现在,我们提取最终的估计系数:
.lm.fit(X, y)$coef
我们还可以将其与QR分解的直接估计进行比较:
.left-borderPane{ /*this is style class for Vbox */
/*something so similar: */
-fx-min-width:30% ;
-fx-max-width:30% ;
}
.icon-settings{/*this is style class for buttons*/
-fx-shape:"M72.5,65.9 M90,50c0,8.6-2.5,16.9-7.3,24.1c-0.4,0.6-1,0.9-1.7,0.9c-0.4,0-0.8-0.1-1.1-0.3c-0.9-0.6-1.2-1.8-0.6-2.50zM69.6,50c0,3.2-0.6,6.2-1.8,9.1c-0.3,0.8-1.1,1.2-1.8,1.2c-0.2,0-0.5,0-0.8-0.1c-1-0.4c0.6-0.6,1.4-0.7,2.2-0.4C57.5,14.5,58,15.2,58,16z M35,37H14v26h21V37z M54,20.8l-15,15v28.3l15,15V20.8z";
/*something so similar: */
-fx-min-width:80% ;
-fx-max-width:80% ;
}
他们非常接近。
答案 1 :(得分:0)