2016-11-23 6 views
2

데이터 [:, 1]에 저장된 x 변수의 데이터 [:, 4]에 저장된 y 변수를 회귀하기 위해 다음과 같은 그래디언트 디센트 알고리즘을 적용했습니다. 그러나 그래디언트 디센트는 발산하는 것처럼 보입니다. 내가 잘못하고있는 곳을 찾아내는 데 도움이 될만한 점이 많습니다.R의 회귀에 대한 그라데이션 강하가 실패하는 이유는 무엇입니까?

#define the sum of squared residuals 
ssquares <- function(x) 
    { 
    t = 0 
    for(i in 1:200) 
     { 
     t <- t + (data[i,4] - x[1] - x[2]*data[i,1])^2 
     } 
    t/200 
    } 

# define the derivatives 
derivative <- function(x) 
    { 
    t1 = 0 
    for(i in 1:200) 
     { 
     t1 <- t1 - 2*(data[i,4] - x[1] - x[2]*data[i,1]) 
     } 
    t2 = 0 
    for(i in 1:200) 
     { 
     t2 <- t2 - 2*data[i,1]*(data[i,4] - x[1] - x[2]*data[i,1]) 
     } 
    c(t1/200,t2/200) 
    } 

# definition of the gradient descent method in 2D 
gradient_descent <- function(func, derv, start, step=0.05, tol=1e-8) { 
    pt1 <- start 
    grdnt <- derv(pt1) 
    pt2 <- c(pt1[1] - step*grdnt[1], pt1[2] - step*grdnt[2]) 
    while (abs(func(pt1)-func(pt2)) > tol) { 
    pt1 <- pt2 
    grdnt <- derv(pt1) 
    pt2 <- c(pt1[1] - step*grdnt[1], pt1[2] - step*grdnt[2]) 
    print(func(pt2)) # print progress 
    } 
    pt2 # return the last point 
} 

# locate the minimum of the function using the Gradient Descent method 
result <- gradient_descent(
    ssquares, # the function to optimize 
    derivative, # the gradient of the function 
    c(1,1), # start point of theplot_loss(simple_ex) search 
    0.05, # step size (alpha) 
    1e-8) # relative tolerance for one step 

# display a summary of the results 
print(result) # coordinate of fucntion minimum 
print(ssquares(result)) # response of function minimum 
+0

데이터를 공유 할 수 있습니까? –

+0

이것은 내가 사용하는 데이터 집합입니다. http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv 데이터 <- read.csv ("Advertising.csv") [, - 1] – esperanto

+0

그래디언트 디센트의 발산은 일반적으로 학습 속도가 너무 높다는 것을 나타내므로 학습 속도 (α)를 줄여 수렴합니다. –

답변

1

당신이 실제로 무작위로 생성 된 데이터를 수렴하고, 계수 R의 LM 얻은 것들()에 매우 가까이 볼 수있는 당신은, 빠른 구현을 위해 당신의 목적/그라데이션 기능을 벡터화 할 수 있습니다

ssquares <- function(x) { 
    n <- nrow(data) # 200 
    sum((data[,4] - cbind(1, data[,1]) %*% x)^2)/n 
} 

# define the derivatives 
derivative <- function(x) { 
    n <- nrow(data) # 200 
    c(sum(-2*(data[,4] - cbind(1, data[,1]) %*% x)), sum(-2*(data[,1])*(data[,4] - cbind(1, data[,1]) %*% x)))/n 
} 

set.seed(1) 
#data <- matrix(rnorm(800), nrow=200) 

# locate the minimum of the function using the Gradient Descent method 
result <- gradient_descent(
    ssquares, # the function to optimize 
    derivative, # the gradient of the function 
    c(1,1), # start point of theplot_loss(simple_ex) search 
    0.05, # step size (alpha) 
    1e-8) # relative tolerance for one step 

# [1] 2.511904 
# [1] 2.263448 
# [1] 2.061456 
# [1] 1.89721 
# [1] 1.763634 
# [1] 1.654984 
# [1] 1.566592 
# [1] 1.494668 
# ... 

# display a summary of the results 
print(result) # coefficients obtained with gradient descent 
#[1] -0.10248356 0.08068382 

lm(data[,4]~data[,1])$coef # coefficients from R lm() 
# (Intercept) data[, 1] 
# -0.10252181 0.08045722 

# use new dataset, this time it takes quite sometime to converge, but the 
# values GD converges to are pretty accurate as you can see from below. 
data <- read.csv('Advertising.csv') # with advertising data, removing the first rownames column 

# locate the minimum of the function using the Gradient Descent method 
result <- gradient_descent(
    ssquares, # the function to optimize 
    derivative, # the gradient of the function 
    c(1,1), # start point of theplot_loss(simple_ex) search 
    0.00001, # step size (alpha), decreasing the learning rate 
    1e-8) # relative tolerance for one step 

# ... 
# [1] 10.51364 
# [1] 10.51364 
# [1] 10.51364 

print(result) # coordinate of fucntion minimum 
[1] 6.97016852 0.04785365 

lm(data[,4]~data[,1])$coef 
(Intercept) data[, 1] 
7.03259355 0.04753664 
+0

팁을 가져 주셔서 감사합니다.하지만 사용했는데 위에 사용 된 특정 데이터 세트와 여전히 다릅니다. 나는 데이터를 축소하려고 시도하고 그것은 일부 규모 매개 변수에 대해 작동하는 것 같습니다. 하지만 내가 따라야 할 일반적인 규칙이 있습니까? 그리고 "더"수렴 최적화 루틴이 있습니까? – esperanto

+0

사용중인 학습 속도 (알파 또는 스텝 크기)는 학습중인 교육 데이터 세트에 대해 매우 높기 때문에 수렴하지 않습니다. 학습 률 0.00001을 사용하면 수렴하는 데 어느 정도 시간이 걸릴 것이지만 결국 수렴 할 것입니다. (또한 컨버전스에서 약간의 속도 향상을 얻기 위해 컨버전스에 대한 허용치를 조금 높아지거나 1e-8만큼 낮추지 않을 수도 있습니다). –

+0

@esperanto 데이터를 확장 할 필요가 없습니다. 광고 데이터로 코드를 업데이트했는데 훨씬 작은 알파 값으로 수렴하고 더 많은 문제에 직면하면 알려주세요. –