library(gamlss.data) ## Pacote do conjunto de dados
library(tidyverse) ## Manipulação e visualização de dados
library(splines) ## Splines
theme_set(theme_classic()) ## Definição do tema dos gráficos ggplotAlém da linearidade
Regressões polinomial e com splines
Pacotes necessários
1 Conjunto de dados
## Conjunto de dados dbbmi
glimpse(dbbmi)# Rows: 7,294
# Columns: 2
# $ age <dbl> 0.03, 0.04, 0.04, 0.04, 0.04, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, …
# $ bmi <dbl> 13.23529, 12.43877, 14.54177, 11.77395, 15.32561, 13.21439, 16.834…
1.1 Divisão entre conjunto de treinamento e validação
## Divisão aleatória (70% treinamento e 30% validação)
set.seed(123); id <- sample(1:nrow(dbbmi), 0.7 * nrow(dbbmi))
train <- dbbmi[id, ]
val <- dbbmi[-id, ]1.2 Estatística descritiva no conjunto de treinamento
## Estatísticas descritivas
summary(dbbmi)# age bmi
# Min. : 0.030 Min. :11.17
# 1st Qu.: 1.863 1st Qu.:15.96
# Median :10.450 Median :17.45
# Mean : 9.291 Mean :18.03
# 3rd Qu.:15.130 3rd Qu.:19.60
# Max. :21.700 Max. :35.42
## Histograma da idade
ggplot(train, aes(x = age)) +
geom_histogram(fill = "white", col = 1, bins = 20) +
labs(x = "Idade", y = "Frequência") ## Histograma do IMC
ggplot(train, aes(x = bmi)) +
geom_histogram(fill = "white", col = 1, bins = 20) +
labs(x = "IMC", y = "Frequência") ## Gráfico de dispersão
ggplot(train, aes(x = age, y = bmi)) +
geom_point(col = "darkgray") +
labs(x = "Idade", y = "IMC")2 Regressão linear simples
O modelo de regressão linear simples explica o IMC do \(i\)-ésimo indivíduo (\(Y_i\)) em função da sua idade (\(x_i\)) como
\[ Y_i = \beta_0 + \beta_1 x_i + \varepsilon_i, \]
em que \(\varepsilon_i\) é uma variável aleatória com média zero e variância constante.
## Ajuste do modelo de regressão linear simples
fit0 <- lm(bmi ~ age, train)
## Reta ajustada
data.frame(age = train$age, bmi = train$bmi, pred = predict(fit0)) %>%
ggplot() +
geom_point(aes(x = age, y = bmi), col = "darkgray") +
geom_line(aes(x = age, y = pred), col = "blue", lwd = 1) +
labs(x = "Idade", y = "IMC")3 Regressão polinomial
O modelo de regressão polinomial para \(Y_i\) é definido por
\[ Y_i = \beta_0 + \beta_1 x_i + \beta_2 x_i^2 + \cdots + \beta_d x_i^d \varepsilon_i, \]
em que \(\varepsilon_i\) é uma variável aleatória com média zero e variância constante.
## Ajustes da regressão polinomial com grau 9 e 10
fitp9 <- lm(bmi ~ poly(age, 9, raw = TRUE), train)
fitp10 <- lm(bmi ~ poly(age, 10, raw = TRUE), train)
## Curva ajustada com d = 9
data.frame(age = train$age, bmi = train$bmi, pred = predict(fitp9)) %>%
ggplot() +
geom_point(aes(x = age, y = bmi), col = "darkgray") +
geom_line(aes(x = age, y = pred), col = "blue", lwd = 1) +
labs(x = "Idade", y = "IMC")## Curva ajustada com d = 10
data.frame(age = train$age, bmi = train$bmi, pred = predict(fitp10)) %>%
ggplot() +
geom_point(aes(x = age, y = bmi), col = "darkgray") +
geom_line(aes(x = age, y = pred), col = "blue", lwd = 1) +
labs(x = "Idade", y = "IMC")4 Regressão com splines
Sejam \(c_1 \leqslant c_2 \leqslant \cdots \leqslant c_K\) os nós. O modelo de regressão com splines para \(Y_i\) é definido por
\[ \begin{array}{ll}\begin{split}Y_i = & \; \beta_0 + \beta_1 x_i + \beta_2 x_i^2 + \cdots + \beta_d x_i^d + \\& \hspace{0.85cm} \; \beta_{d+1} g(x_i, c_1) + \beta_{d+2} g(x_i, c_2) \cdots + \beta_{d+K} g(x_i, c_K) + \varepsilon_i,\end{split}\end{array} \]
em que \(\varepsilon_i\) é uma variável aleatória com média zero e variância constante e
\[ g(x_i, c_j) = \begin{cases}(x_i - c_j)^d, & \text{se } x_i > c_j,\\0, & \text{caso contrário}. \end{cases} \]
## Nós
nos <- c(2, 5, 10, 18)
## Ajustes da regressão com cpline linear, quadrática e cúbica
fitsp1 <- lm(bmi ~ bs(age, knots = nos, degree = 1), train)
fitsp2 <- lm(bmi ~ bs(age, knots = nos, degree = 2), train)
fitsp3 <- lm(bmi ~ bs(age, knots = nos, degree = 3), train)
## Curva ajustada considerando o spline linear
data.frame(age = train$age, bmi = train$bmi, pred = predict(fitsp1)) %>%
ggplot() +
geom_point(aes(x = age, y = bmi), col = "darkgray") +
geom_vline(xintercept = nos, lty = 2) +
geom_line(aes(x = age, y = pred), col = "blue", lwd = 1) +
labs(x = "Idade", y = "IMC")## Curva ajustada considerando o spline quadrático
data.frame(age = train$age, bmi = train$bmi, pred = predict(fitsp2)) %>%
ggplot() +
geom_point(aes(x = age, y = bmi), col = "darkgray") +
geom_vline(xintercept = nos, lty = 2) +
geom_line(aes(x = age, y = pred), col = "blue", lwd = 1) +
labs(x = "Idade", y = "IMC")## Curva ajustada considerando o spline cúbico
data.frame(age = train$age, bmi = train$bmi, pred = predict(fitsp3)) %>%
ggplot() +
geom_point(aes(x = age, y = bmi), col = "darkgray") +
geom_vline(xintercept = nos, lty = 2) +
geom_line(aes(x = age, y = pred), col = "blue", lwd = 1) +
labs(x = "Idade", y = "IMC")5 Comparação
## EQM da regressão linear simples no conjunto de validação
rmse0 <- mean((val$bmi - predict(fit0, newdata = val))^2)
## EQM da regressão polinomial no conjunto de validação
rmsep9 <- mean((val$bmi - predict(fitp9, newdata = val))^2)
rmsep10 <- mean((val$bmi - predict(fitp10, newdata = val))^2)
## EQM da regressão com splines no conjunto de validação
rmses1 <- mean((val$bmi - predict(fitsp1, newdata = val))^2)
rmses2 <- mean((val$bmi - predict(fitsp2, newdata = val))^2)
rmses3 <- mean((val$bmi - predict(fitsp3, newdata = val))^2)
## Tabela
tab <- data.frame(Modelo = c("RLS", paste0("Polinomial - ", 9:10),
"Spline linear", "Spline quadrático", "Spline cúbico"),
EQM = round(c(rmse0, rmsep9, rmsep10,
rmses1, rmses2, rmses3), 3))
tab# Modelo EQM
# 1 RLS 5.308
# 2 Polinomial - 9 4.350
# 3 Polinomial - 10 4.336
# 4 Spline linear 4.517
# 5 Spline quadrático 4.412
# 6 Spline cúbico 4.334
## Ajuste no conjunto de validação
data.frame(age = val$age, bmi = val$bmi,
predsp = predict(fitsp3, val),
predpl = predict(fitp10, val)) %>%
pivot_longer(cols = 3:4, names_to = "model", values_to = "prediction") %>%
mutate(model = factor(model, labels = c("Polinomial (d = 10)",
"Spline cúbico"))) %>%
ggplot() +
geom_point(aes(x = age, y = bmi), col = "darkgray", cex = 1) +
geom_vline(xintercept = nos, lty = 2) +
geom_line(aes(x = age, y = prediction, col = model), lwd = 1) +
scale_color_manual(values = c("red2", "blue")) +
labs(x = "Idade", y = "IMC", col = "Modelo") +
theme(legend.position = "top")