Considerações sobre Random Forest em simulação relacionada às finanças
Análise de Modelos
Random Forest
Bibliotecas necessárias
Code
library(randomForest)randomForest 4.7-1.2Type rfNews() to see new features/changes/bug fixes.Code
library(tidyr)
library(rpart)
library(glmnet)Carregando pacotes exigidos: Matrix
Anexando pacote: 'Matrix'Os seguintes objetos são mascarados por 'package:tidyr':
expand, pack, unpackLoaded glmnet 4.1-10Code
options(scipen = 999)Base de dados
Code
source("C:/Users/Thomas/Desktop/FGC/Códigos/Base de dados.R")Modelando Random Forest
Ajustando Modelo
Code
rf_fit <- randomForest(
retorno ~ .,
data = df_retorno,
ntree = 500,
mtry = floor(sqrt(ncol(df_retorno) - 1)),
maxnodes = 50,
importance = TRUE,
na.action = na.omit
)
#| label: setup
library(rpart)
library(randomForest)
# split
set.seed(123)
idx <- sample(1:nrow(df_retorno), 0.7 * nrow(df_retorno))
train <- df_retorno[idx, ]
test <- df_retorno[-idx, ]
# árvore
tree_single <- rpart(retorno ~ ., data = train)
pred_tree_test <- predict(tree_single, newdata = test)Primeiros resultados
Resumo do modelo
Code
rf_fit
Call:
randomForest(formula = retorno ~ ., data = df_retorno, ntree = 500, mtry = floor(sqrt(ncol(df_retorno) - 1)), maxnodes = 50, importance = TRUE, na.action = na.omit)
Type of random forest: regression
Number of trees: 500
No. of variables tried at each split: 5
Mean of squared residuals: 0.001508512
% Var explained: 50.3Importância das variáveis
Code
importance_mdi <- importance(rf_fit, type = 1)
importance_df <- data.frame(
variavel = rownames(importance_mdi),
importancia = importance_mdi[,1]
)
importance_df <- importance_df[order(-importance_df$importancia), ]
importance_df variavel importancia
crescimento_lucro crescimento_lucro 12.6348315
pe_ratio pe_ratio 11.6867617
retorno_12m retorno_12m 10.0517246
roe roe 8.1181106
margem_liquida margem_liquida 7.0453340
setor setor 6.8652137
margem_bruta margem_bruta 6.2803747
alavancagem alavancagem 6.0778847
market_cap market_cap 5.4127845
tamanho tamanho 5.0502150
roa roa 4.8228949
pb_ratio pb_ratio 4.5521337
retorno_6m retorno_6m 4.0749226
giro_ativos giro_ativos 3.9117809
volume_medio volume_medio 3.8245617
setorEnergia setorEnergia 3.8105361
setorIndustria setorIndustria 3.7688328
liq_diaria liq_diaria 3.2946993
free_float free_float 2.6944693
price_sales price_sales 2.2431753
intensidade_capital intensidade_capital 1.8912538
capex_receita capex_receita 1.8306600
setorFinanceiro setorFinanceiro 1.7382822
setorTecnologia setorTecnologia 1.5637343
volatilidade volatilidade 1.1178894
retorno_1m retorno_1m 0.9946446
ev_ebitda ev_ebitda 0.9341098
cobertura_juros cobertura_juros 0.8793166
crescimento_receita crescimento_receita 0.4668721
beta_mercado beta_mercado 0.4192277
dividend_yield dividend_yield 0.4008306
downside_risk downside_risk 0.1129489
turnover turnover -0.1852425
payout payout -1.3098328Code
par(cex = 0.6)
varImpPlot(
rf_fit,
type = 2,
main = "Importância de Variáveis (Permutação)",
cex = 0.5,
cex.axis = 0.5
)![Falha ao fazer o upload do arquivo "". Invalid response: Error code = 7, Path = /_/BloggerUi/data/batchexecute, Message = There was an error during the transport or processing of this request., Unknown HTTP error in underlying XHR (HTTP Status: 0) (XHR Error Code: 6) (XHR Error Message: ' [0]')](https://www.blogger.com/img/transparent.gif)
Explicação
Regressão:
“Cada 1 ponto de ROE aumenta retorno em 0.5%”
Random Forest:
“Empresas com ROE alto têm retorno maior — mas o efeito depende do contexto”
ROE é importante NÃO diz quanto ele aumenta o retorno
Regressão mede “quanto muda” Random forest mede “o que importa”
Fazendo Previsões
Code
set.seed(123)
idx <- sample(1:nrow(df_retorno), 0.7 * nrow(df_retorno))
train <- df_retorno[idx, ]
test <- df_retorno[-idx, ]
tree_single <- rpart(retorno ~ ., data = train)
rf_fit <- randomForest(
retorno ~ .,
data = train,
ntree = 500,
mtry = floor(sqrt(ncol(train) - 1))
)
pred_test <- predict(rf_fit, newdata = test)
rmse <- sqrt(mean((test$retorno - pred_test)^2))
r2 <- cor(test$retorno, pred_test)^2
paste("RMSE = ",rmse)[1] "RMSE = 0.0385210612043032"Code
paste("R² = ",r2)[1] "R² = 0.600250808531214"Code
plot(sqrt(rf_fit$mse), type = "l",
xlab = "Número de árvores",
ylab = "RMSE (OOB)",
main = "RMSE vs Número de Árvores")Code
plot(test$retorno, pred_test,
xlab = "Retorno Real",
ylab = "Retorno Previsto",
main = "Previsto vs Real (Out-of-Sample)")
abline(0, 1, col = "red", lwd = 2)Explicação
Eixo X (horizontal) → retorno real
Eixo Y (vertical) → retorno previsto pelo modelo
Cada ponto = uma empresa no conjunto de teste
Se o modelo fosse perfeito:
- todos os pontos estariam exatamente sobre a linha
- valores altos (ex: 0.20) → o modelo prevê menos que isso
- valores baixos → o modelo prevê mais que isso
Isso significa:
o modelo está “puxando tudo para a média”. O modelo está sendo: Conservador
subestima retornos muito altos
superestima retornos muito baixos
Isso é típico de random forest. Porque o random forest faz:
média de várias árvores
E cada árvore prevê:
média dos valores dentro de uma região
Comparando com árvore individual
Estimando árvore individual
Code
tree_single <- rpart(retorno ~ ., data = train,
control = rpart.control(maxdepth = 7))
pred_tree_single <- predict(tree_single, newdata = test)
rmse_tree_single <- sqrt(mean((test$retorno - pred_tree_test)^2))
r2_ar <- cor(test$retorno, pred_tree_single)^2
r2_ar[1] 0.3535545Resultado da árvore individual
Code
paste("RMSE = ", rmse_tree_single)[1] "RMSE = 0.0531672818463887"Comparando resultados
Code
# Comparação
cat("RMSE Árvore Individual:", rmse_tree_single, "
")RMSE Árvore Individual: 0.05316728 Code
cat("RMSE Random Forest: ", rmse, "
")RMSE Random Forest: 0.03852106 Code
cat("Redução relativa: ",
round(100 * (rmse_tree_single - rmse) / rmse_tree_single, 2), "%
")Redução relativa: 27.55 %Explicação
A árvore individual, ao ser avaliada corretamente (out-of-sample), revelou sua fragilidade:
alta sensibilidade aos dados de treino
captura de ruído
O Random Forest, ao agregar múltiplas árvores:
suaviza flutuações idiossincráticas → previsões mais estáveis
Uma redução de ~28% no RMSE não é trivial.
Em muitos contextos aplicados (especialmente financeiros, como sugere sua variável retorno):
isso representa um ganho preditivo bastante relevante
Estimando a quantidade ideal de árvores
Estimando quantidade ideal
Code
ntrees <- seq(10, 300, by = 10) # espaço de busca global
n_rep <- 20 # número de repetições
rmse_mat <- matrix(NA, nrow = length(ntrees), ncol = n_rep)
set.seed(123)
for (j in 1:n_rep) {
idx <- sample(1:nrow(df_retorno), 0.7 * nrow(df_retorno))
train <- df_retorno[idx, ]
test <- df_retorno[-idx, ]
for (i in seq_along(ntrees)) {
rf_temp <- randomForest(
retorno ~ .,
data = train,
ntree = ntrees[i],
mtry = floor(sqrt(ncol(train) - 1))
)
pred <- predict(rf_temp, newdata = test)
rmse_mat[i, j] <- sqrt(mean((test$retorno - pred)^2))
}
}Resultados
Code
rmse_mean <- rowMeans(rmse_mat)
rmse_sd <- apply(rmse_mat, 1, sd)
best_ntree_global <- ntrees[which.min(rmse_mean)]
cat("Ótimo global (esperado):", best_ntree_global, "\n")Ótimo global (esperado): 210 Code
cat("RMSE no ótimo global:", min(rmse_mean), "\n")RMSE no ótimo global: 0.03900742 Code
plot(ntrees, rmse_mean, type = "l",
xlab = "Número de árvores",
ylab = "RMSE médio (teste)",
main = "RMSE esperado vs Número de Árvores")
lines(ntrees, rmse_mean + rmse_sd, lty = 2)
lines(ntrees, rmse_mean - rmse_sd, lty = 2)
abline(v = best_ntree_global, col = "red", lty = 2)
points(best_ntree_global,
min(rmse_mean),
col = "red", pch = 19)Outros Resultados
Retorno esperado x var. importantes
Retorno esperado com base em variáveis selecionadas.
Melhores empresas
Previsão com base em random forest.
Code
pred_all <- predict(rf_fit, newdata = df_retorno)
ranking <- df_retorno[order(-pred_all), ]
head(ranking, 10) # Top 10 retorno roe roa margem_liquida margem_bruta crescimento_receita
118 0.224 0.185 0.129 0.134 0.421 0.224
31 0.222 0.179 0.112 0.124 0.447 0.202
72 0.218 0.177 0.137 0.180 0.425 0.107
34 0.212 0.163 0.107 0.198 0.399 0.054
74 0.200 0.198 0.097 0.125 0.380 0.142
51 0.204 0.167 0.092 0.127 0.498 0.197
33 0.212 0.197 0.131 0.159 0.450 0.061
100 0.193 0.217 0.177 0.181 0.535 0.113
110 0.187 0.183 0.120 0.149 0.493 0.103
24 0.176 0.213 0.097 0.118 0.365 0.206
crescimento_lucro payout dividend_yield alavancagem cobertura_juros
118 0.231 0.42 0.045 1.58 6.84
31 0.204 0.13 0.019 1.32 6.05
72 0.151 0.08 0.025 1.15 8.34
34 0.164 0.50 0.051 1.07 8.47
74 0.185 0.25 0.020 0.87 6.06
51 0.207 0.51 0.048 1.21 6.02
33 0.204 0.52 0.052 0.99 7.71
100 0.267 0.26 0.024 0.54 8.72
110 0.160 0.61 0.058 0.97 8.36
24 0.237 0.72 0.067 1.27 4.74
pe_ratio pb_ratio ev_ebitda price_sales tamanho market_cap free_float
118 45.00 3.31 14.58 6.85 9.68 4778435222 0.42
31 45.00 3.80 10.70 6.90 9.56 3650203775 0.46
72 44.86 3.36 3.00 2.61 9.94 8793566444 0.23
34 45.00 2.56 6.32 0.85 9.58 3819773952 0.38
74 45.00 2.77 8.65 2.62 9.86 7231846827 0.41
51 45.00 1.99 10.98 5.76 9.80 6270866003 0.51
33 45.00 4.69 8.54 1.58 9.97 9330565767 0.42
100 45.00 5.42 4.10 3.45 10.15 14203155127 0.40
110 40.77 2.93 7.53 1.44 9.56 3666951679 0.44
24 45.00 2.94 9.84 6.88 9.07 1162869303 0.35
liq_diaria volume_medio turnover beta_mercado volatilidade downside_risk
118 7119876 6384998 0.005 0.36 0.260 0.280
31 27032817 21021346 0.011 0.30 0.232 0.311
72 30036673 24913998 0.006 1.32 0.328 0.275
34 10410787 6367443 0.005 0.30 0.126 0.214
74 31850550 29777151 0.005 0.30 0.139 0.247
51 50778855 80996548 0.005 0.76 0.276 0.261
33 12784375 18517269 0.007 0.89 0.329 0.335
100 67495852 60500488 0.008 1.09 0.301 0.306
110 16369725 12923027 0.005 0.30 0.148 0.185
24 6298821 4963078 0.013 0.48 0.294 0.328
retorno_1m retorno_6m retorno_12m intensidade_capital capex_receita
118 0.141 0.304 0.332 0.52 0.116
31 0.015 0.197 0.044 0.49 0.093
72 0.098 0.220 0.289 0.52 0.077
34 0.058 0.169 0.376 0.46 0.094
74 0.107 0.236 0.233 0.29 0.064
51 0.018 0.100 0.306 0.49 0.083
33 0.142 0.186 0.281 0.32 0.056
100 0.039 0.175 0.303 0.37 0.035
110 0.066 0.354 0.236 0.43 0.091
24 0.180 0.203 0.261 0.60 0.112
giro_ativos setor setorEnergia setorFinanceiro setorIndustria
118 1.05 Energia 1 0 0
31 1.23 Energia 1 0 0
72 1.42 Tecnologia 0 0 0
34 1.60 Financeiro 0 1 0
74 1.52 Consumo 0 0 0
51 1.28 Consumo 0 0 0
33 1.47 Financeiro 0 1 0
100 1.72 Tecnologia 0 0 0
110 1.46 Consumo 0 0 0
24 1.17 Energia 1 0 0
setorTecnologia
118 0
31 0
72 1
34 0
74 0
51 0
33 0
100 1
110 0
24 0Code
tail(ranking, 10) # Bottom 10 retorno roe roa margem_liquida margem_bruta crescimento_receita
64 0.041 0.109 0.068 0.087 0.368 0.058
123 0.025 0.168 0.089 0.137 0.388 0.067
76 0.049 0.039 0.016 0.038 0.177 0.016
125 0.010 0.128 0.070 0.126 0.392 0.079
35 0.040 0.090 0.057 0.049 0.317 0.104
81 0.027 0.092 0.016 0.061 0.223 0.079
79 0.029 0.080 0.037 0.113 0.270 0.119
83 0.024 0.092 0.052 0.076 0.270 0.121
36 0.007 0.036 0.054 0.085 0.261 0.041
41 0.015 0.074 0.051 0.052 0.247 0.108
crescimento_lucro payout dividend_yield alavancagem cobertura_juros
64 0.095 0.36 0.031 1.85 5.95
123 0.107 0.48 0.056 1.47 4.98
76 0.040 0.71 0.074 2.03 4.10
125 0.109 0.55 0.041 1.63 5.55
35 0.100 0.32 0.038 1.89 7.09
81 0.099 0.59 0.063 1.65 4.96
79 0.098 0.25 0.027 1.86 4.44
83 0.097 0.37 0.035 2.19 4.65
36 0.058 0.36 0.045 1.75 4.99
41 0.038 0.35 0.051 2.00 5.04
pe_ratio pb_ratio ev_ebitda price_sales tamanho market_cap free_float
64 11.23 1.17 8.30 2.36 9.57 3723545599 0.50
123 23.13 3.72 4.02 2.33 10.25 17619344430 0.33
76 4.00 0.40 7.19 0.30 9.78 6057781590 0.32
125 18.02 2.52 5.16 1.69 9.10 1247425146 0.21
35 9.04 0.40 8.85 3.15 10.31 20243199524 0.54
81 8.65 1.75 4.55 1.52 9.92 8354646277 0.51
79 10.57 0.40 9.45 3.10 10.49 31094360875 0.45
83 6.04 0.51 15.30 2.35 9.84 6950550894 0.29
36 4.00 0.40 5.15 0.30 9.53 3405403137 0.26
41 4.00 0.72 8.31 3.27 10.46 28760739176 0.69
liq_diaria volume_medio turnover beta_mercado volatilidade downside_risk
64 13002352 10265137 0.005 0.30 0.217 0.192
123 49700043 53625653 0.005 1.27 0.366 0.283
76 33149709 36368526 0.005 0.55 0.275 0.229
125 2573619 3203734 0.005 1.26 0.334 0.343
35 49034464 43855250 0.005 1.38 0.340 0.360
81 81506966 75941006 0.005 0.71 0.263 0.270
79 100995342 123089245 0.006 1.61 0.379 0.344
83 14112619 19112091 0.005 0.74 0.299 0.345
36 13281224 14280059 0.005 0.34 0.213 0.222
41 63236125 87761590 0.006 1.35 0.357 0.325
retorno_1m retorno_6m retorno_12m intensidade_capital capex_receita
64 0.090 0.152 0.128 0.50 0.091
123 0.062 0.140 0.045 0.47 0.064
76 0.101 0.125 -0.005 0.46 0.061
125 0.063 0.129 0.104 0.59 0.070
35 0.029 0.070 0.017 0.43 0.101
81 -0.066 0.007 0.031 0.37 0.053
79 0.058 0.169 0.153 0.53 0.069
83 0.025 -0.058 0.135 0.45 0.100
36 0.083 0.007 -0.085 0.60 0.062
41 0.042 -0.001 0.186 0.40 0.066
giro_ativos setor setorEnergia setorFinanceiro setorIndustria
64 0.98 Consumo 0 0 0
123 1.20 Industria 0 0 1
76 0.85 Consumo 0 0 0
125 1.37 Industria 0 0 1
35 1.05 Consumo 0 0 0
81 1.06 Consumo 0 0 0
79 0.76 Industria 0 0 1
83 1.13 Industria 0 0 1
36 1.05 Industria 0 0 1
41 0.86 Consumo 0 0 0
setorTecnologia
64 0
123 0
76 0
125 0
35 0
81 0
79 0
83 0
36 0
41 0Regressão Linear
Estimando regressão
Code
lm_fit <- lm(retorno ~ ., data = train)
pred_lm <- predict(lm_fit, newdata = test)
rmse_lm <- sqrt(mean((test$retorno - pred_lm)^2))
r2_lm <- cor(test$retorno, pred_lm)^2Comparando com árvores
Code
cat("RMSE Árvore:", rmse_tree_single, "\n")RMSE Árvore: 0.05316728 Code
cat("RMSE Random Forest:", rmse, "\n")RMSE Random Forest: 0.03852106 Code
cat("RMSE Regressão:", rmse_lm, "\n\n")RMSE Regressão: 0.05054714 Code
cat("RMSE Árvore:", r2_ar, "\n")RMSE Árvore: 0.3535545 Code
cat("R² Random Forest:", r2, "\n")R² Random Forest: 0.6002508 Code
cat("R² Regressão:", r2_lm, "\n")R² Regressão: 0.2661825 Coeficientes das variáveis
Code
summary(lm_fit)
Call:
lm(formula = retorno ~ ., data = train)
Residuals:
Min 1Q Median 3Q Max
-0.088099 -0.015447 -0.002155 0.018376 0.073263
Coefficients: (4 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.055107315610454 0.308846204117828 -0.178 0.8590
roe 0.107249127142272 0.211087697028102 0.508 0.6134
roa -0.173613633357377 0.274139852747045 -0.633 0.5292
margem_liquida 0.103489076385502 0.233271603925358 0.444 0.6590
margem_bruta 0.038613866260513 0.099108286986395 0.390 0.6983
crescimento_receita -0.021198550838721 0.250990743642754 -0.084 0.9330
crescimento_lucro -0.066268654914055 0.170426431927382 -0.389 0.6989
payout -0.020013951368129 0.050589482695361 -0.396 0.6939
dividend_yield -0.099366117055482 0.572781097434476 -0.173 0.8629
alavancagem -0.043544740019271 0.021661898696970 -2.010 0.0493 *
cobertura_juros -0.001426757455814 0.005964695627351 -0.239 0.8118
pe_ratio 0.001580114695989 0.000808028099671 1.956 0.0556 .
pb_ratio -0.001995816099361 0.006837659357208 -0.292 0.7715
ev_ebitda 0.001454714153875 0.002112992543474 0.688 0.4941
price_sales 0.000814065450844 0.005862833964212 0.139 0.8901
tamanho 0.009860157787834 0.031985152726584 0.308 0.7590
market_cap -0.000000000001308 0.000000000001875 -0.697 0.4885
free_float -0.006903960176814 0.054989075453527 -0.126 0.9005
liq_diaria -0.000000000138415 0.000000000267006 -0.518 0.6063
volume_medio -0.000000000076537 0.000000000198777 -0.385 0.7017
turnover -0.141558477300292 2.090839270265971 -0.068 0.9463
beta_mercado 0.021789511494080 0.033436775060467 0.652 0.5173
volatilidade -0.195824992095012 0.233506841786750 -0.839 0.4053
downside_risk 0.197838204398160 0.155225981708926 1.275 0.2078
retorno_1m -0.132925864692983 0.111363593586788 -1.194 0.2377
retorno_6m 0.053318345344792 0.073623263067820 0.724 0.4720
retorno_12m 0.056435685308295 0.059021275803553 0.956 0.3432
intensidade_capital 0.111674553550194 0.065954242163290 1.693 0.0961 .
capex_receita -0.078908936124126 0.298243503119102 -0.265 0.7923
giro_ativos 0.037816219254301 0.030024679329861 1.260 0.2132
setorEnergia 0.021237401665962 0.019947576928591 1.065 0.2917
setorFinanceiro 0.017845076386871 0.017430887843918 1.024 0.3104
setorIndustria -0.037785504435944 0.016786265330397 -2.251 0.0284 *
setorTecnologia 0.009407480671922 0.018373709487851 0.512 0.6107
setorEnergia NA NA NA NA
setorFinanceiro NA NA NA NA
setorIndustria NA NA NA NA
setorTecnologia NA NA NA NA
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.03736 on 55 degrees of freedom
Multiple R-squared: 0.7563, Adjusted R-squared: 0.6101
F-statistic: 5.173 on 33 and 55 DF, p-value: 0.00000004435Comentários
Sua regressão mostra:
R² = 0.756 (in-sample)
R² = 0.266 (out-of-sample)
👉 Isso é um diagnóstico clássico:
overfitting estrutural + instabilidade dos coeficientes
Ou seja:
o modelo “explica bem” dentro da amostra
mas falha em generalizar
coeficientes instáveis
sinais pouco confiáveis
p-values inflados
Lasso
Estimando o modelo
Code
x_train <- model.matrix(retorno ~ ., train)[, -1]
y_train <- train$retorno
x_test <- model.matrix(retorno ~ ., test)[, -1]
y_test <- test$retornoCoeficientes das variáveis
Code
set.seed(123)
lasso_cv <- cv.glmnet(
x_train, y_train,
alpha = 1, # Lasso
nfolds = 10
)
best_lambda <- lasso_cv$lambda.min
coef(lasso_cv, s = "lambda.min")38 x 1 sparse Matrix of class "dgCMatrix"
lambda.min
(Intercept) 0.082066817608004466
roe 0.105272540995267533
roa .
margem_liquida .
margem_bruta 0.001217598166731726
crescimento_receita .
crescimento_lucro .
payout .
dividend_yield .
alavancagem -0.029630578227862095
cobertura_juros .
pe_ratio 0.001472439631984189
pb_ratio .
ev_ebitda .
price_sales .
tamanho .
market_cap -0.000000000001160637
free_float .
liq_diaria -0.000000000041696761
volume_medio -0.000000000023433138
turnover .
beta_mercado .
volatilidade .
downside_risk 0.018741068842953873
retorno_1m .
retorno_6m .
retorno_12m 0.024376771310056840
intensidade_capital 0.007434071812512003
capex_receita .
giro_ativos 0.022342046171543829
setorEnergia 0.014912573979217190
setorFinanceiro .
setorIndustria -0.025073923409735306
setorTecnologia 0.004793075237009337
setorEnergia .
setorFinanceiro .
setorIndustria -0.000036574332628236
setorTecnologia 0.000000022073694698Comparações
Code
pred_lasso <- predict(lasso_cv, s = "lambda.min", newx = x_test)
rmse_lasso <- sqrt(mean((y_test - pred_lasso)^2))
r2_lasso <- cor(y_test, pred_lasso)^2
cat("RMSE Regressão:", rmse_lm, "\n")RMSE Regressão: 0.05054714 Code
cat("RMSE Lasso:", rmse_lasso, "\n")RMSE Lasso: 0.03960081 Code
cat("RMSE Random Forest:", rmse, "\n\n")RMSE Random Forest: 0.03852106 Code
cat("R² Regressão:", r2_lm, "\n")R² Regressão: 0.2661825 Code
cat("R² Lasso:", r2_lasso, "\n")R² Lasso: 0.3333849 Code
cat("R² Random Forest:", r2, "\n")R² Random Forest: 0.6002508 Ridge
Estimando modelo
Code
set.seed(123)
ridge_cv <- cv.glmnet(
x_train, y_train,
alpha = 0, # Ridge
nfolds = 10
)
best_lambda_ridge <- ridge_cv$lambda.minCoeficientes das variáveis
Code
pred_ridge <- predict(ridge_cv, s = "lambda.min", newx = x_test)
rmse_ridge <- sqrt(mean((y_test - pred_ridge)^2))
r2_ridge <- cor(y_test, pred_ridge)^2
coef(ridge_cv, s = "lambda.min")38 x 1 sparse Matrix of class "dgCMatrix"
lambda.min
(Intercept) 0.0855309193492710673
roe 0.0834265816229555063
roa 0.0663588595419826871
margem_liquida 0.0828179296518122554
margem_bruta 0.0371959671281663143
crescimento_receita 0.0674360469900480292
crescimento_lucro 0.0584120979283184460
payout -0.0045743299965871204
dividend_yield -0.1381782928759840434
alavancagem -0.0225148173940401090
cobertura_juros 0.0013821091837038304
pe_ratio 0.0005444504545149758
pb_ratio 0.0022422180172897198
ev_ebitda 0.0002801907990725817
price_sales 0.0006802390131784736
tamanho -0.0068781020698232345
market_cap -0.0000000000005890674
free_float -0.0017096803640096027
liq_diaria -0.0000000000679181277
volume_medio -0.0000000000587050556
turnover -0.4547145188164948837
beta_mercado 0.0012318609192911460
volatilidade -0.0354444294747081889
downside_risk 0.0541208593602293536
retorno_1m -0.0522772184683747976
retorno_6m 0.0152274475605262069
retorno_12m 0.0310916944819384158
intensidade_capital 0.0330293409663580395
capex_receita 0.0786582833794073621
giro_ativos 0.0276547775250127852
setorEnergia 0.0098027330403938576
setorFinanceiro 0.0047515097892812021
setorIndustria -0.0140302958640639019
setorTecnologia 0.0050747984689695916
setorEnergia 0.0098042689873498751
setorFinanceiro 0.0047530831043705486
setorIndustria -0.0140331743858793778
setorTecnologia 0.0050723620024720152Comparações
Code
cat("RMSE Regressão:", rmse_lm, "\n")RMSE Regressão: 0.05054714 Code
cat("RMSE Lasso:", rmse_lasso, "\n")RMSE Lasso: 0.03960081 Code
cat("RMSE Ridge:", rmse_ridge, "\n")RMSE Ridge: 0.04050553 Code
cat("RMSE Random Forest:", rmse, "\n\n")RMSE Random Forest: 0.03852106 Code
cat("R² Regressão:", r2_lm, "\n")R² Regressão: 0.2661825 Code
cat("R² Lasso:", r2_lasso, "\n")R² Lasso: 0.3333849 Code
cat("R² Ridge:", r2_ridge, "\n")R² Ridge: 0.3088375 Code
cat("R² Random Forest:", r2, "\n")R² Random Forest: 0.6002508 Conclusão
De início, estimou-se uma modelo de random forest genérico, embora robusto, com 500 árvores aleatórias. A finalidade do modelo, que se entende por conservador, é observar a média de resultados dessas árvores. Assim, obtém-se resultado conservador, visto que o modelo centra-se na média, o que nos leva a resultados viesados, a despeito de se reduzir a variância, potencializando retornos menores e deprimindo retornos maiores. Ainda, diz-se que o modelo é genérico porque foi a primeira tentativa relacionada a random forest, inclusive sem nenhuma comparação com outros modelos.
Em face de outros modelos, percebe-se, de imediato, que o modelo random forest carece de interpretabilidade, como uma regressão linear convecional. Podemos elencar a importância de cada variável para o modelo, não obstante, não se tem demonstração do sinal de cada uma dessas variáveis - o que nos faz considerar a necessidade de uma regressão simples com a finalidade de verificar o sinal de cada variável (e, apenas para isso, como se justificará).
Também foi perceptível que o número de 500 árvores foi supérfluo, sobretudo por ser um valor escolhido de modo discricionário. Após análise posterior, ficou mostrado que um número menor de árvores era suficiente. Parece-nos, agora, que é mais interessante verificar primeiro o número ótimo de árvores, considerando, se necessário, algum threshold grande. Ainda, tal medida favorece especialmente a simplicidade do modelo.
Comparando-se com outros modelos, a saber, com regressão linear multivariada, regressão do tipo Lasso e do tipo Ridge, percebe-se através de nossos resultados que o random forest obtém resultados superiores a todos. Inclusive, observando uma única árvore, também o random forest tem desempenho muito superior. O caso da única árvore é interessante pois tem desempenho inferior a regressão OLS.
Comentários
Postar um comentário