R 梯度下降计算中的误差
我试图写一个函数来计算线性回归模型的梯度下降。然而,我得到的答案与我使用正态方程方法得到的答案不匹配 我的样本数据是:R 梯度下降计算中的误差,r,gradient-descent,R,Gradient Descent,我试图写一个函数来计算线性回归模型的梯度下降。然而,我得到的答案与我使用正态方程方法得到的答案不匹配 我的样本数据是: df <- data.frame(c(1,5,6),c(3,5,6),c(4,6,8)) 我得到的结果是 c(0.9165891,0.6115482,0.5652970) 当我使用正规方程法时,我得到 c(2,1,0). 希望有人能解释一下我在这个函数中的错误所在。您似乎还没有实现一个偏差术语。在这样的线性模型中,您总是希望有一个附加的加法常数,即,您的模型应该是
df <- data.frame(c(1,5,6),c(3,5,6),c(4,6,8))
我得到的结果是
c(0.9165891,0.6115482,0.5652970)
当我使用正规方程法时,我得到
c(2,1,0).
希望有人能解释一下我在这个函数中的错误所在。您似乎还没有实现一个偏差术语。在这样的线性模型中,您总是希望有一个附加的加法常数,即,您的模型应该是
w_0 + w_1*x_1 + ... + w_n*x_n.
如果没有
w\u 0
术语,您通常不会得到很好的匹配。您使用了停止标准
old parameters - new parameters <= 0.0000001
这不是一个好的停止标准:它只是告诉你进度已经放缓,而不是它已经足够准确了。试着简单地迭代一个固定的迭代次数。不幸的是,在这里给出一个好的、普遍适用的梯度下降停止标准并不是那么容易。我知道这已经有几个星期了,但我想尝试一下以下几个原因,即
- 对R来说比较新,所以破译代码并重写它对我来说是一个很好的实践
- 研究一个不同的梯度下降问题,这对我来说是新鲜的
- 需要堆栈流点和
- 据我所知,你从来没有得到一个有效的答案
X
矩阵(大写,因为它的组件“特征”被称为X
下标i
)和y
解向量开始会容易得多
X <- cbind(c(1,5,6),c(3,5,6))
y <- c(4,6,8)
关于您的代码,R的优点之一是它可以执行矩阵乘法,这比使用循环要快得多
lm_gradient_descent <- function(X, y, learning_rate, scale=TRUE){
if(scale==TRUE){X <- scale(X)}
X <- cbind(1, X)
theta <- rep(0, ncol(X)) #your old temp_arr
diff <- 1
old.error <- sum( (X %*% theta - y)^2 ) / (2*length(y))
while(diff>0.000000001){
theta <- theta - learning_rate * t(X) %*% (X %*% theta - y) / length(y)
new.error <- sum( (X %*% theta - y)^2 ) / (2*length(y))
diff <- abs(old.error - new.error)
old.error <- new.error
}
return(theta)
}
与预期的(-4,-1,3)
尽管我同意@cfh的观点,我更喜欢迭代次数已定义的循环,但实际上我不确定您是否需要abs
函数。如果diff<0
,则函数不收敛
最后,我建议使用记录所有错误的向量,而不是像
old.error
和new.error
这样的东西。然后,您可以绘制该向量,以查看函数收敛的速度。请将预期结果和实际结果添加到您的问题中。@belwood,谢谢您的回答,我将结果添加到了问题中。谢谢您的回答!如果我正确理解你的观点,我应该在这里有截距项,因为我在数据矩阵中添加了一列1,并在函数中使用了矩阵乘法。有了这两个自变量,我应该得到3个参数。@meri:对不起,我没读到,我不太懂R。您能否在问题中提供打印(diff)
的输出?非常感谢您指出这一点!我尝试了一个小得多的错误项作为停止标准(0.00000000000001),得到了正确的答案。为什么建议对固定的迭代次数进行迭代?我如何才能选择适当的迭代次数,以便知道答案已经收敛?再次感谢@梅里:只是因为使用固定数量的迭代,当某些东西不收敛时,你就可以轻松地转动螺丝。很难制定一个适用于所有情况的停止标准。您还可以在每次迭代中打印均方误差,以便更好地了解发生了什么。@meri:噢,如果答案解决了您的问题,请记住将其标记为已接受。
abs(old parameters - new parameters) <= 0.0000001
X <- cbind(c(1,5,6),c(3,5,6))
y <- c(4,6,8)
> lm(y~X)
Call:
lm(formula = y ~ X)
Coefficients:
(Intercept) X1 X2
-4 -1 3
> lm(y~scale(X))
Call:
lm(formula = y ~ scale(X))
Coefficients:
(Intercept) scale(X)1 scale(X)2
6.000 -2.646 4.583
lm_gradient_descent <- function(X, y, learning_rate, scale=TRUE){
if(scale==TRUE){X <- scale(X)}
X <- cbind(1, X)
theta <- rep(0, ncol(X)) #your old temp_arr
diff <- 1
old.error <- sum( (X %*% theta - y)^2 ) / (2*length(y))
while(diff>0.000000001){
theta <- theta - learning_rate * t(X) %*% (X %*% theta - y) / length(y)
new.error <- sum( (X %*% theta - y)^2 ) / (2*length(y))
diff <- abs(old.error - new.error)
old.error <- new.error
}
return(theta)
}
> lm_gradient_descent(X, y, .01, 0)
[,1]
[1,] -3.9360685
[2,] -0.9851775
[3,] 2.9736566