Gradiente Descendente

Bruna Wundervald

Gradiente Descendente

Batch

\[\beta^{(k+1)} = \beta^{(k)} + \alpha_k \nabla J (\beta^{(k)})\] Onde \(\alpha_k\) é o tamanho do passo utilizado no algoritmo e \(\nabla J (\beta^{(k)})\) é o gradiente da função custo no ponto \(\beta^{(k)}\). O algoritmo exige também um \(\beta_0\), que é o chute inicial para o parâmetro.

E a função custo a ser minimizada é descrita como: \[J(\underset{\sim}{\theta}) = \frac{1}{2m} \sum_{i = 1}^{m} (h_{\theta}(x)^{i}) - y^{(i)})^2\]

Ou seja, \[ \nabla J (\beta_j) = \frac{1}{m} \sum_{i = 1}^{m} (h_{\theta}(x)^{i}) - y^{(i)})(x_{j})^{(i)}\]

# Função custo
cust <- function(theta, x, y){
  m <- length(y)
  b <- (1/2*m)*sum((x%*% theta) - y)^2
  return(b)
} 

# Exemplo--------------------------------------------------------------
x <- cbind(rep(1, length(iris$Sepal.Width)), iris$Sepal.Width)
y <- iris$Petal.Length 

# Coeficientes objetivo
coef(lm(iris$Petal.Length  ~ iris$Sepal.Width))
     (Intercept) iris$Sepal.Width 
        9.063151        -1.735222 
# Custo para valores de theta = 0.1 e 0.5
cust(x = x, y = y, theta = c(0.1, 0.5))
[1] 7651227
#----------------
# Gradiente da função custo: primeira derivada em relação aos betas
d.beta <- function(x, y, theta){
  m <- length(y)
  d <- (1/m)* (t(x) %*% ((x %*% theta) - y))
  return(t(d))
  }

d.beta(x = x, y = y, theta = c(0.1, 0.5))
          [,1]      [,2]
[1,] -2.129333 -6.088267
# Gradiente descendente batch
gd <- function(x, maxit, alpha = 0.01, theta = c(0, 0),...){
  h <- matrix(NA, nrow = maxit, ncol = length(theta))
  custo <- c()
  for(i in 1:maxit){
    theta <- theta - t(alpha*d.beta(x, y, theta))
    h[i, ] <- t(theta)
    custo[i] <- cust(x = x, y = y, theta = as.vector(theta))
    }
  return(list(theta, h, custo))
  }

gd(x = x, y = y, maxit = 1000)[[1]]
          [,1]
[1,] 1.7748561
[2,] 0.6058806
gd(x = x, y = y, maxit = 10000)[[1]]
          [,1]
[1,]  7.613442
[2,] -1.269555
p3 <- gd(x = x, y = y, maxit = 100000) # Convergência Atingida
p3[[1]]
          [,1]
[1,]  9.063150
[2,] -1.735221
# Demonstração de algumas tentativas do algoritmo
plot(iris$Petal.Length  ~ iris$Sepal.Width, xlab = "x",
     ylab = "y")
for(i in c(1, 3, 6, 10, 14, seq(20, 10000, 10))){ abline(
  p3[[2]][i,], col = "turquoise")}
abline(p3[[1]], col = 2, lwd = 3)

# Comportamento da função custo
par(mfrow = c(1, 2))
plot(p3[[3]]~ p3[[2]][, 1], col = 3, 
     xlab = expression("Valores para "~theta[0]),
     ylab = "Valores da função custo")
plot(p3[[3]]~ p3[[2]][, 2], col = 4,
     xlab = expression("Valores para "~theta[1]),
     ylab = "Valores da função custo")

Stochastic

gds <- function(x, maxit, alpha = 0.01, theta = c(0, 0),...){
  h <- matrix(NA, nrow = maxit, ncol = length(theta))
  custo <- c()
  m <- length(y)
  
  the <- as.matrix(cbind(rep(theta[1], maxit), rep(theta[2], maxit)))
  
  for(i in 2:maxit){
    #------ Amostragem
    s <- sample.int(m, 1)
    xx <- x[s, 2]
    yy <- y[s]
    
    the[i, 1] <- (the[i-1, 1] - alpha*(the[i-1, 1] + 
                                         the[i-1, 2]*xx - yy))
    the[i, 2] <- (the[i-1, 2] - alpha*(xx*(the[i-1, 1] + 
                                             the[i-1, 2]*xx - yy)))
    
    custo[i] <- cust(x = xx, y = yy, theta = as.vector(the[i, ]))
    }
  return(list(the, custo))
  }

pp <- gds(x = x, y = y, maxit = 100000)

par(mfrow = c(1, 2))
plot(pp[[1]][,1], col = "turquoise", type = "l", 
     ylab = expression("Valores para "~theta[0]),
     xlab = "Iteração")
plot(pp[[1]][,2], col = "tomato", type = "l", 
     ylab = expression("Valores para "~theta[1]), xlab = "Iteração")

Boosting

Cuja derivada em relação a \(h_{\theta}(x)\) é:

\(\frac{\partial J(\underset{\sim}{\theta})}{\partial h_{\theta}(x)} = h_{\theta}(x) - y\)

Isto é o mesmo que dizer que: \(Resíduos = - \frac{\partial J(\underset{\sim}{\theta})}{\partial h_{\theta}(x)}\)

Até a convergência.

library(mboost)
mb <- glmboost(iris$Petal.Length  ~ iris$Sepal.Width)
coefficients(mb, off2int = TRUE)
     (Intercept) iris$Sepal.Width 
        9.063010        -1.735175 
plot(mb, off2int = TRUE, col = "turquoise", lwd = 2, 
     main = "Convergência dos parâmetros")