为什么梯度下降几乎每次都会爆炸?

问题描述

我尝试从头开始编写GD算法(实际上,我是从一个Git存储库中借用的代码, 我会很快归功)。问题是它爆炸了(获取`+ Inf或-Inf),我看不出问题出在哪里。尝试将alpha更改为很小的值,尽管它没有爆炸,但仍然没有解决错误的值)。

这是我使用的代码

# features
x <- with(
  data = mtcars,cbind(hp,disp)
)
# target var
y <- mtcars$mpg
N <- length(y)

# optimal values with in-built lm function
res <- lm(y~x)

# define cost function to minimize
cost <- function(X,y,theta){
  sum((X %*% theta - y)^2)/N
}

# training params
alpha = 0.00005
n_max <- 1000

# log the changes
cost_history <- double(n_max)
theta_histoty <- vector("list",n_max)

# initialize the coeffs
theta <- matrix(rep(0,ncol(x) + 1),ncol = 1)
rownames(theta) <- c("(Intercept)","hp","disp")

# add ones to the feature matrix
X <- cbind(1,x)

# train
for(i in seq_len(n_max)){
  error <- (X %*% theta - y)
  delta <- t(X) %*% error / N
  theta <- theta - alpha*delta
  cost_history[[i]] <- cost(X,theta)
  theta_histoty[[i]] <- theta
}

# check
theta;coef(res)

解决方法

问题是您的问题特别不适合梯度下降。很难看到成本函数,但是其轮廓是椭圆形,并且轴长截然不同。除非您采取微小的步骤(alpha = 1e-5对我有用),否则大多数步骤将直接越过山谷,您将获得更差的价值。如果您确实采取了微小的步骤,那么收敛将花费很长时间,因为您正在采取微小的步骤。借助alpha = 1e-5n_max = 1e6,您可以看到事情正在收敛,但距离最佳值还有很长的路要走。

通过标准化预测变量可以大大提高速度。使用

x <- with(
  data = mtcars,cbind(scale(hp),scale(disp))
)  

将使alpha = 1的使用变得非常快。 scale()函数减去平均值,然后除以标准差。