使用梯度下降(最速下降)估计线性回归

时间:2017-04-04 20:59:47

标签: r regression linear-regression gradient-descent

示例数据

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))
  }

有人可以帮助我吗?

干杯

2 个答案:

答案 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)) } 使用更快的计算方法,则可以获得更高的效率。 (对大型数据集最有用。请参阅enter image description here

X

现在,让我们考虑一下您的示例yoo <- 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)

crossprod比以前的方法慢得多:

以前的方法(14秒意味着50次迭代):

enter image description here

Crossprod方法(50次迭代意味着16秒):

enter image description here