R:直接对函数而不是函数中的数据点执行梯度下降

R: Performing Gradient Descent Directly on Functions Instead of Data Points from the Function

我正在使用 R 编程语言。在 https://www.ocf.berkeley.edu/~janastas/stochastic-gradient-descent-in-r.html 上使用这个 link ,我发现了一个函数,它允许您对来自函数的数据点执行梯度下降:

gradientR<-function(y, X, epsilon,eta, iters){
      epsilon = 0.0001
      X = as.matrix(data.frame(rep(1,length(y)),X))
      N= dim(X)[1]
      print("Initialize parameters...")
      theta.init = as.matrix(rnorm(n=dim(X)[2], mean=0,sd = 1)) # Initialize theta
      theta.init = t(theta.init)
       e = t(y) - theta.init%*%t(X)
       grad.init = -(2/N)%*%(e)%*%X
       theta = theta.init - eta*(1/N)*grad.init
       l2loss = c()
      for(i in 1:iters){
          l2loss = c(l2loss,sqrt(sum((t(y) - theta%*%t(X))^2)))
          e = t(y) - theta%*%t(X)
          grad = -(2/N)%*%e%*%X
          theta = theta - eta*(2/N)*grad
            if(sqrt(sum(grad^2)) <= epsilon){
              break
            }
        }
  print("Algorithm converged")
  print(paste("Final gradient norm is",sqrt(sum(grad^2))))
  values<-list("coef" = t(theta), "l2loss" = l2loss)
  return(values)
}

例如,我尝试使用此函数“优化”y = x^3 - 2x - 5:

x = seq(1,1000, by=1)
y = (x^3) - (2*x) -5

gdec.eta1 = gradientR(y = y, X = x, eta = 100, iters = 1000)

但是,我收到以下错误:

Error in if (sqrt(sum(grad^2)) <= epsilon) { : 
  missing value where TRUE/FALSE needed

有人可以告诉我我做错了什么吗?为什么会产生这个错误?

有谁知道 R 中的其他一些梯度下降函数是否允许您“直接”优化此函数而不是从该函数生成点?

像这样:

func2 <- function(x) {
  x^3 - 2* x - 5
}

gradientR(func2, eta = 100, iters = 1000)

有谁知道这是否可行?

谢谢!

注意: 这适用于以下示例(来自上面 linked 的网站):

> y = rnorm(n = 10000, mean = 0, sd = 1)
> x1 = rnorm(n = 10000, mean = 0, sd = 1)
> x2 = rnorm(n = 10000, mean = 0, sd = 1)
> x3 = rnorm(n = 10000, mean = 0, sd = 1)
> x4 = rnorm(n = 10000, mean = 0, sd = 1)
> x5 = rnorm(n = 10000, mean = 0, sd = 1)
> 
> ptm <- proc.time()
> gdec.eta1 = gradientR(y = y, X = data.frame(x1,x2,x3, x4,x5), eta = 100, iters = 1000)
[1] "Initialize parameters..."
[1] "Algorithm converged"
[1] "Final gradient norm is 9.80308529574335e-05"

我只是不知道为什么它不适用于我的示例。

我们假设 gradientR 解决了您遇到的问题,问题是让它与您的输入一起工作。这里有几个问题:

  1. 不能将函数传递给 gradientR。 y 和 X 必须是向量或矩阵。

  2. 如果给许多优化问题提供非常不同的数字,它们就会出现缩放问题。这个没什么不同。使用 x/1000 而不是 x.

  3. 为了弄清楚要解决的潜在问题是什么,找到一个系数向量 b 使得 在 y 和 x 已知的情况下,残差向量 y - cbind(1, x) %% b 被最小化。一些评论者对问题的解释不同,但如果他们的解释是你想要的,那么 gradientR 不适用,无论如何,最大化或最小化 x^3-2x-5 的问题没有有限的解决方案。

  4. 如果你想传递 func 而不是 y 那么只需编写一个简单的包装器 grad2,如下所示。

要解决缩放问题,请将其与 x/1000 和 y 一起使用,如图所示。

x = seq(1, 1000, by = 1) / 1000
y = (x^3) - (2*x) -5

gdec.eta1 = gradientR(y = y, X = x, eta = 100, iters = 1000)
str(gdec.eta1)
## List of 2
##  $ coef  : num [1:2, 1] -5.2 -1.1 <----------------
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:2] "rep.1..length.y.." "X"
##   .. ..$ : NULL
##  $ l2loss: num [1:260] 101.44 50.34 25.5 13.83 8.86 ...

# check that lm gives the same coefficients
coef(lm(y ~ x))
## (Intercept)           x 
##   -5.200701   -1.098500 <----------------

现在定义一个接受 func 而不是 y 的函数。 func 必须满足 func(x) 为 y。我们在最后对其进行了测试,它给出了相同的结果。

# func must be such that func(X) gives Y
grad2 <- function(func, X, ...) gradientR(func(X), X, ...)

# test
x = seq(1, 1000, by = 1) / 1000
func <- function(x) (x^3) - (2*x) -5

grad2 <- function(func, ...) gradientR(func(x), ...)
gdec.etal2 <- grad2(func, x, eta = 100, iters = 1000)
str(gdec.etal2)
## List of 2
##  $ coef  : num [1:2, 1] -5.2 -1.1  <----------------
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:2] "rep.1..length.y.." "X"
##   .. ..$ : NULL
##  $ l2loss: num [1:238] 141.66 69.93 34.71 17.59 9.57 ...