Sejam os seguintes dados:
ggplot(sim1, aes(x, y)) + theme_bw() +
geom_point()
Vamos assumir que não temos acesso ao lm
. Por isso, geramos uma série de modelos lineares aleatórios:
models <- data.frame(a1 = runif(250, -20, 40),
a2 = runif(250, -5, 5))
ggplot(sim1, aes(x, y)) + theme_bw() +
geom_abline(aes(intercept = a1, slope = a2), data = models, alpha = 1/4) +
geom_point()
Qual deles será o melhor? Para decidir qual o melhor precisamos de uma medida:
# Os nossos modelos são descritos por rectas ('a' tem dois parametros)
model.predictor <- function(a, data) {
a[1] + data$x * a[2]
}
# a distância de um modelo aos dados é a soma dos quadrados dos seus erros de predição
distance <- function(model, data) {
diff <- data$y - model.predictor(model, data)
sqrt(mean(diff ^ 2))
}
sim1.distance <- function(a1, a2) {
distance(c(a1, a2), sim1)
}
Vamos então calcular as distâncias dos modelos aleatórios criados:
models %>%
dplyr::mutate(dist = purrr::map2_dbl(a1, a2, sim1.distance)) -> models
head(models)
a1 a2 dist
1 24.613386 0.7827739 14.06255
2 -6.041458 -3.7659989 45.49217
3 -14.711551 -2.1836499 43.99469
4 26.484572 -3.1324231 16.28718
5 27.718388 -2.9621414 15.11741
6 -8.100359 1.6320557 14.83132
E fazer o plot dos melhores:
n.best <- 12
best.models <- dplyr::filter(models, rank(dist) <= n.best)
ggplot(sim1, aes(x, y)) + theme_bw() +
geom_point(size = 2, colour = "grey30") +
geom_abline(aes(intercept = a1, slope = a2, colour = -dist), # mais claro, melhor
data = best.models)
Podemos visualizar todos os modelos gerados e ver onde estão estes melhores no espaço de parametros:
ggplot(models, aes(a1, a2)) + theme_bw() +
geom_point(data = best.models, size = 4, colour = "red") +
geom_point(aes(colour = -dist))
Outra forma de encontrar o modelo empiricamente seria gerar uma grelha de valores possíveis e escolher os melhores:
expand.grid(a1 = seq(-5, 20, length = 25),
a2 = seq( 1, 3, length = 25)) %>%
dplyr::mutate(dist = purrr::map2_dbl(a1, a2, sim1.distance)) -> grid
grid %>%
ggplot(aes(a1, a2)) + theme_bw() +
geom_point(data = dplyr::filter(grid, rank(dist) <= n.best), size = 4, colour = "red") +
geom_point(aes(colour = -dist))
E podemos visualizar os resultados:
ggplot(sim1, aes(x, y)) + theme_bw() +
geom_point(size = 2, colour = "grey30") +
geom_abline(aes(intercept = a1, slope = a2, colour = -dist),
data = dplyr::filter(grid, rank(dist) <= n.best))
Ainda outra forma seria usar a função optim
para encontrar um mínimo para a função distância:
best <- optim(c(0,0), distance, data = sim1)
ggplot(sim1, aes(x, y)) + theme_bw() +
geom_point(size = 2, colour = "grey30") +
geom_abline(intercept = best$par[1], slope = best$par[2], color="navyblue")