5  Regressão LASSO

A regressçao ridge mantém todas as variáveis no modelo final, memso quando \(k\) é grande. Isso pode ser um problema na interpretação do modelo, por conta da quantidade de variáveis e pelos baixos coeficientes. O lasso pe uma alternativa à regressão ridge que permite obter um modelo final com um subconjunto de variáveis.

Para rodar a regressão Lasso na linguagem R, usaremos o pacote glmnet.

library(readxl)

dados <- read_excel("dados_pinus.xlsx")

5.0.1 Variáveis

Para ilustrar a regressão ridge, vamos começar com um exemplo em que queremos estudar a relação entre DAP (variável preditora \(X_{1}\)) e Volume (variável dependente Y) com uma amostra de 250 arvores.

  • Local: Empresa Duratex Florestal SP
  • Amostra: 20 arvores
  • IAF : Indice Aerea Foliar
  • DAF : Distribuição Angular da Folha
  • GAP :
  • IDADE : Idade em Meses da arvore
  • DAP : Diâmetro a Altura do Peito (1.30 metros do solo)
  • ALTURA : Altura da arvore
  • ÁEREA BASAL : Area Basal da arvore

5.1 Modelo Regressão LASSO Geral

## Modelo Regressão LASSO Geral

library(caret)
library(glmnet)

set.seed(123)
train_index_lasso <- createDataPartition(dados$VOLUME, p = 0.9, list = FALSE)
dados_treino_lasso <- dados[train_index_lasso, ]
dados_teste_lasso  <- dados[-train_index_lasso, ]

x_train_lasso <- model.matrix(VOLUME ~ ., dados_treino_lasso)[, -1]
y_train_lasso <- dados_treino_lasso$VOLUME

x_test_lasso <- model.matrix(VOLUME ~ ., dados_teste_lasso)[, -1]
y_test_lasso <- dados_teste_lasso$VOLUME

# Validação cruzada LASSO
cv_lasso <- cv.glmnet(
  x_train_lasso,
  y_train_lasso,
  alpha = 1,
  standardize = TRUE
)

best_lambda_lasso <- cv_lasso$lambda.min

modelo_lasso <- glmnet(
  x_train_lasso,
  y_train_lasso,
  alpha = 1,
  lambda = best_lambda_lasso,
  standardize = TRUE
)

# Predição
y_pred_lasso <- predict(modelo_lasso, newx = x_test_lasso)

# Métricas
R2_lasso <- cor(y_test_lasso, y_pred_lasso)^2
rmse_lasso <- sqrt(mean((y_test_lasso - y_pred_lasso)^2))
mae_lasso <- mean(abs(y_test_lasso - y_pred_lasso))
mape_lasso <- mean(abs((y_test_lasso - y_pred_lasso) / y_test_lasso)) * 100

# Variáveis selecionadas
coef_lasso <- coef(modelo_lasso)
variaveis_lasso <- rownames(coef_lasso)[
  coef_lasso[, 1] != 0 & rownames(coef_lasso) != "(Intercept)"
]

# ---------------- AIC e BIC ---------------- #
y_fitted_lasso <- predict(modelo_lasso, newx = x_train_lasso)
RSS_lasso <- sum((y_train_lasso - y_fitted_lasso)^2)

df_lasso <- modelo_lasso$df[modelo_lasso$lambda == best_lambda_lasso]
n <- length(y_train_lasso)

AIC_lasso <- n * log(RSS_lasso / n) + 2 * (df_lasso + 1)
BIC_lasso <- n * log(RSS_lasso / n) + log(n) * (df_lasso + 1)

# Resultados
cat("\n--- Modelo LASSO  ---\n")

--- Modelo LASSO  ---
cat(
  "R² =", R2_lasso,
  "\nRMSE =", rmse_lasso,
  "\nMAE =", mae_lasso,
  "\nMAPE =", mape_lasso,
  "\nAIC =", AIC_lasso,
  "\nBIC =", BIC_lasso
)
R² = 0.9199676 
RMSE = 12.2659 
MAE = 10.5483 
MAPE = 23.57098 
AIC = 1055.38 
BIC = 1075.903
cat(
  "\nVariáveis selecionadas:",
  paste(variaveis_lasso, collapse = ", "),
  "\n"
)

Variáveis selecionadas: IDADE, DAP, ALTURA, DAF, AREA_BASAL 

5.2 Lasso Trace Plot

library(dplyr)
library(tidyr)
library(ggplot2)
library(glmnet)


lasso_seq <- glmnet(x_train_lasso, 
                    y_train_lasso, 
                    alpha = 1, 
                    standardize = TRUE)

# Índice do lambda ótimo
id_best <- which.min(abs(lasso_seq$lambda - best_lambda_lasso))

# Coeficientes no lambda ótimo
coef_best <- as.matrix(lasso_seq$beta)[, id_best]

# Variáveis selecionadas (≠ 0)
vars_selected <- names(coef_best[coef_best != 0])

# Construir data frame dos coeficientes ao longo do caminho
df_lasso_path <- as.data.frame(t(as.matrix(lasso_seq$beta)))
df_lasso_path$log_lambda <- log(lasso_seq$lambda)

# Manter apenas variáveis selecionadas no modelo final
df_lasso_path <- df_lasso_path %>%
  select(log_lambda, all_of(vars_selected)) %>%
  pivot_longer(
    cols = -log_lambda,
    names_to = "Variavel",
    values_to = "Coeficiente"
  )

# Gráfico LASSO TRACE – MODELO ESCOLHIDO
ggplot(
  df_lasso_path,
  aes(x = log_lambda, y = Coeficiente, color = Variavel)
) +
  geom_line(size = 1.3) +
  geom_vline(
    xintercept = log(best_lambda_lasso),
    linetype = "dashed",
    linewidth = 1,
    color = "black"
  ) +
  labs(
    title = "LASSO Trace Plot",
    subtitle = expression(paste(
      ""
    )),
    x = expression(log(lambda)),
    y = "Coeficiente"
  ) +
  scale_color_brewer(palette = "Dark2") +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 13, color = "gray40"),
    legend.title = element_blank(),
    panel.grid.minor = element_blank()
  )

5.3 MODELO MLP (REDE NEURAL)

library(caret)
library(nnet)
library(dplyr)


set.seed(123)

train_index_nn <- createDataPartition(dados$VOLUME, p = 0.9, list = FALSE)

dados_treino_nn <- dados[train_index_nn, ]
dados_teste_nn  <- dados[-train_index_nn, ]

preproc <- preProcess(dados_treino_nn[, -which(names(dados) == "VOLUME")],
                      method = c("center", "scale"))

x_train_nn <- predict(preproc, dados_treino_nn)
x_test_nn  <- predict(preproc, dados_teste_nn)



set.seed(123)

ctrl <- trainControl(method = "cv", number = 10)

grid_mlp <- expand.grid(
  size = c(3, 5, 7),
  decay = c(0.001, 0.01, 0.1)
)

modelo_mlp <- train(
  VOLUME ~ .,
  data = x_train_nn,
  method = "nnet",
  tuneGrid = grid_mlp,
  trControl = ctrl,
  linout = TRUE,
  trace = FALSE,
  maxit = 500
)


y_pred_mlp <- predict(modelo_mlp, newdata = x_test_nn)

R2_mlp   <- cor(dados_teste_nn$VOLUME, y_pred_mlp)^2
rmse_mlp <- RMSE(y_pred_mlp, dados_teste_nn$VOLUME)
mae_mlp  <- MAE(y_pred_mlp, dados_teste_nn$VOLUME)



cat("\n--- REDE NEURAL (MLP) ---\n")

--- REDE NEURAL (MLP) ---
cat("R²:", R2_mlp,
    "\nRMSE:", rmse_mlp,
    "\nMAE:", mae_mlp,
    "\nMelhores parâmetros:",
    "\nNeurônios ocultos:", modelo_mlp$bestTune$size,
    "\nDecay:", modelo_mlp$bestTune$decay,
    "\n")
R²: 0.9180618 
RMSE: 12.37432 
MAE: 10.42029 
Melhores parâmetros: 
Neurônios ocultos: 3 
Decay: 0.1