Final de Técnicas Avanzadas de Regresión 2022

Corti, JF, Helman, E, Martínez, M

18/11/2022

El presente trabajo utilizará el dataset BostonHousing, cuyas variables se describen a continuación:

  • Variable respuesta

    • medv: Mediana del precio de hogares ocupados por sus dueños (en miles de dolares).
  • Variables predictoras

    • crim: Tasa de crímenes per cápita según ciudad
    • zn: Proporción de suelo residencial con lotes de más de 25.000 pies cuadrados
    • indus: Proporción de acres comerciales no minoristas según ciudad
    • chas: Variable dummy del río Charles (1=frente al río, 0=caso contrario)
    • nox: Concentración de óxidos de nitrógeno (en partes por 10 millones)
    • rm: Número medio de habitaciones por vivienda
    • age: Proporción de unidades ocupadas por sus propietarios construidas antes de 1940
    • dis: Media ponderada de las distancias a cinco centros de empleo de Boston
    • rad: Índice de accesibilidad a las carreteras radiales
    • tax: Tasa de impuestos sobre el valor total por cada u$d 10.000
    • ptratio: Proporción de alumnos por profesor según ciudad
    • black: \(1000(Bk - 0.63)^2\) donde Bk es la proporción de afroamericanos según ciudad
    • lstat: Status menor de la población (en porcentaje)

Basado en el dataset “Boston Housing”, se le pide que:

1) Describa los datos

# Descriptivos

# Rta
tabla <- psych::describe(BostonHousing$medv)[,-1]
rownames(tabla) <- "medv"
kable(tabla)
n mean sd median trimmed mad min max range skew kurtosis se
medv 506 22.53281 9.197104 21.2 21.56232 5.9304 5 50 45 1.101537 1.450984 0.4088611
ggplot(BostonHousing, aes(x=medv, y=1))+
  geom_jitter(width = .25, alpha=1, fill="#4cadb2", color="#4cadb2")+
  geom_violin(alpha=.5, fill="#4cadb2", color="#4cadb2")+
  lims(y=c(0.35,1.65))+xlab("Mediana de precios (u$d 1.000)")+
  ggtitle("Distribución de la variable respuesta (medv)")+
  theme_minimal()+
  theme(axis.title.y = element_blank(),
        axis.text.y = element_blank())

La variable respuesta (medv) es una variable numérica con media 22.53 (DE = 9.2), un rango que va de 5 a 50 y su distribución presenta asimetría a derecha.

# Descriptivos


ggpairs(BostonHousing, columns = c(14,1:7))

ggpairs(BostonHousing, columns = 14:8)

De forma univariada, todas las variables del set de datos se asociaron significativamente con la variable a predecir.

2) Realice un modelo para predecir y explicar medv en función del resto de covariables, usando las siguientes técnicas:

a) Regresión Lineal Clásica

# Lm
ajus.lm <- lm(medv ~  ., data = BostonHousing)

tabla <- kable(as.data.frame(summary(ajus.lm)$coefficients))


for(i in 1:nrow(summary(ajus.lm)$coefficients)){
  if(as.data.frame(summary(ajus.lm)$coefficients)$`Pr(>|t|)`[i]>.05){
    tabla <- row_spec(tabla,i,background = "#e76f51", bold = T)
  }
}

tabla
Estimate Std. Error t value Pr(>|t|)
(Intercept) 36.4594884 5.1034588 7.1440742 0.0000000
crim -0.1080114 0.0328650 -3.2865169 0.0010868
zn 0.0464205 0.0137275 3.3815763 0.0007781
indus 0.0205586 0.0614957 0.3343100 0.7382881
chas1 2.6867338 0.8615798 3.1183809 0.0019250
nox -17.7666112 3.8197437 -4.6512574 0.0000042
rm 3.8098652 0.4179253 9.1161402 0.0000000
age 0.0006922 0.0132098 0.0524024 0.9582293
dis -1.4755668 0.1994547 -7.3980036 0.0000000
rad 0.3060495 0.0663464 4.6128998 0.0000051
tax -0.0123346 0.0037605 -3.2800091 0.0011116
ptratio -0.9527472 0.1308268 -7.2825106 0.0000000
b 0.0093117 0.0026860 3.4667926 0.0005729
lstat -0.5247584 0.0507153 -10.3471458 0.0000000
# indus y age no significativas

indus y age no resultaron significativas en este modelo, por lo que se decide sacarlas y ajustar un nuevo modelo de regresión lineal múltiple.

ajus.lm <- lm(medv ~  crim+zn+chas+nox+rm+dis+rad+tax+ptratio+b+lstat, data = BostonHousing)

tabla <- kable(as.data.frame(summary(ajus.lm)$coefficients))

for(i in 1:nrow(summary(ajus.lm)$coefficients)){
  if(as.data.frame(summary(ajus.lm)$coefficients)$`Pr(>|t|)`[i]>.05){
    tabla <- row_spec(tabla,i,background = "#e76f51", bold = T)
  }
}

tabla
Estimate Std. Error t value Pr(>|t|)
(Intercept) 36.3411450 5.0674922 7.171426 0.0000000
crim -0.1084133 0.0327794 -3.307358 0.0010104
zn 0.0458449 0.0135227 3.390228 0.0007543
chas1 2.7187163 0.8542398 3.182615 0.0015515
nox -17.3760234 3.5352431 -4.915086 0.0000012
rm 3.8015788 0.4063159 9.356215 0.0000000
dis -1.4927115 0.1857308 -8.036963 0.0000000
rad 0.2996085 0.0634021 4.725529 0.0000030
tax -0.0117780 0.0033723 -3.492530 0.0005214
ptratio -0.9465246 0.1290656 -7.333669 0.0000000
b 0.0092908 0.0026739 3.474636 0.0005566
lstat -0.5225535 0.0474244 -11.018672 0.0000000
# # - - - - - - - ECM - - - - - - - - 
# ec <- c()
# for(i in 1:nrow(BostonHousing)){
#   ajus.lm_CV <- lm(medv ~  crim+zn+chas+nox+rm+dis+rad+tax+ptratio+b+lstat, data = BostonHousing)
#   ec[i] <- (predict(ajus.lm_CV, BostonHousing[i,])-BostonHousing$medv[i])^2
#   
#   # Mostrar el proceso
#   cat("Proceso: ", i, "/", nrow(BostonHousing), " (", round(100*i/nrow(BostonHousing),2), "%)\n")
# }
# 
# # Calculo de error cuadratico medio
# ecm_cv_LM <- mean(ec)
# ecm_cv_LM



mae<-c()
for(i in 1:nrow(BostonHousing))
{
  ajus.lm <- lm(medv ~  crim+zn+chas+nox+rm+dis+rad+tax+ptratio+b+lstat, data = BostonHousing[-i,])
  mae[i]<-abs(predict(ajus.lm,BostonHousing[i,])-BostonHousing$medv[i])
}

MAE_lm <- mean(mae)










# Plotear la capacidad predictiva del modelo
graf <- data.frame(Observados=BostonHousing$medv)
graf$Predichos <- predict(ajus.lm, newdata=BostonHousing)

ggplot(graf, aes(x=Observados,y=Predichos))+
  geom_point(alpha=.2)+
  geom_abline(intercept = 0,
              slope = 1,
              color='#4cadb2',
              lwd=1.5)+
  ggtitle("Valores de medv vs. predichos por modelo lineal múltiple")+
  theme_minimal()

A través de la técnica de validación cruzada (LOOCV), el Error Medio Absoluto estimado fue 3.37.

b) Regresión Lineal Robusta

Con las variables indus y age el modelo no converge, por lo que se ajustó un modelo robusto directamente sin esas dos variables.

# Robustlm
ajus.lmrob <- lmrob(medv ~  ., data = BostonHousing)
# summary(ajus.lmrob)
# Con indus y age no converge
ajus.lmrob <- lmrob(medv ~  crim+zn+chas+nox+rm+dis+rad+tax+ptratio+b+lstat, data = BostonHousing)
summary(ajus.lmrob)
## 
## Call:
## lmrob(formula = medv ~ crim + zn + chas + nox + rm + dis + rad + tax + ptratio + 
##     b + lstat, data = BostonHousing)
##  \--> method = "MM"
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -14.80831  -1.86264  -0.04985   2.31354  33.13749 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  13.515876   9.064954   1.491 0.136599    
## crim         -0.109638   0.034343  -3.192 0.001501 ** 
## zn            0.033619   0.014536   2.313 0.021145 *  
## chas1         1.263976   0.646051   1.956 0.050973 .  
## nox         -10.044991   2.639202  -3.806 0.000159 ***
## rm            5.429161   1.224246   4.435 1.14e-05 ***
## dis          -0.830972   0.169640  -4.898 1.31e-06 ***
## rad           0.178821   0.054318   3.292 0.001066 ** 
## tax          -0.011710   0.002519  -4.649 4.28e-06 ***
## ptratio      -0.755307   0.089350  -8.453 3.20e-16 ***
## b             0.011174   0.002222   5.030 6.89e-07 ***
## lstat        -0.332847   0.056731  -5.867 8.13e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Robust residual standard error: 3.003 
## Multiple R-squared:  0.8305, Adjusted R-squared:  0.8267 
## Convergence in 44 IRWLS iterations
## 
## Robustness weights: 
##  11 observations c(162,365,366,368,369,370,371,372,373,375,413)
##   are outliers with |weight| = 0 ( < 0.0002); 
##  56 weights are ~= 1. The remaining 439 ones are summarized as
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## 0.001491 0.838600 0.945300 0.867600 0.985200 0.999000 
## Algorithmic parameters: 
##        tuning.chi                bb        tuning.psi        refine.tol 
##         1.548e+00         5.000e-01         4.685e+00         1.000e-07 
##           rel.tol         scale.tol         solve.tol       eps.outlier 
##         1.000e-07         1.000e-10         1.000e-07         1.976e-04 
##             eps.x warn.limit.reject warn.limit.meanrw 
##         1.293e-09         5.000e-01         5.000e-01 
##      nResample         max.it       best.r.s       k.fast.s          k.max 
##            500             50              2              1            200 
##    maxit.scale      trace.lev            mts     compute.rd fast.s.large.n 
##            200              0           1000              0           2000 
##                   psi           subsampling                   cov 
##            "bisquare"         "nonsingular"         ".vcov.avar1" 
## compute.outlier.stats 
##                  "SM" 
## seed : int(0)
tabla <- kable(as.data.frame(summary(ajus.lmrob)$coefficients))

for(i in 1:nrow(summary(ajus.lmrob)$coefficients)){
  if(as.data.frame(summary(ajus.lmrob)$coefficients)$`Pr(>|t|)`[i]>.05){
    tabla <- row_spec(tabla,i,background = "#e76f51", bold = T)
  }
}

tabla
Estimate Std. Error t value Pr(>|t|)
(Intercept) 13.5158761 9.0649537 1.491003 0.1365989
crim -0.1096383 0.0343435 -3.192408 0.0015008
zn 0.0336187 0.0145361 2.312779 0.0211448
chas1 1.2639762 0.6460508 1.956465 0.0509733
nox -10.0449905 2.6392016 -3.806072 0.0001589
rm 5.4291610 1.2242459 4.434698 0.0000114
dis -0.8309719 0.1696402 -4.898438 0.0000013
rad 0.1788206 0.0543180 3.292104 0.0010656
tax -0.0117104 0.0025189 -4.649067 0.0000043
ptratio -0.7553066 0.0893500 -8.453350 0.0000000
b 0.0111741 0.0022216 5.029694 0.0000007
lstat -0.3328470 0.0567314 -5.867073 0.0000000

Si bien la variable chas no resultó significativa, el p-valor asociado a su coeficiente es apenas superior a 0.05, por lo que se decidió mantener la variable en el modelo

mae<-c()
for(i in 1:nrow(BostonHousing))
{
  ajus.lmrob <- lmrob(medv ~  crim+zn+chas+nox+rm+dis+rad+tax+ptratio+b+lstat, data = BostonHousing[-i,])
  mae[i]<-abs(predict(ajus.lmrob,BostonHousing[i,])-BostonHousing$medv[i])
}

MAE_lmrob <- mean(mae)



# Plotear la capacidad predictiva del modelo
graf <- data.frame(Observados=BostonHousing$medv)
graf$Predichos <- predict(ajus.lmrob, newdata=BostonHousing)

ggplot(graf, aes(x=Observados,y=Predichos))+
  geom_point(alpha=.2)+
  geom_abline(intercept = 0,
              slope = 1,
              color='#4cadb2',
              lwd=1.5)+
  ggtitle("Valores de medv vs. predichos por modelo lineal múltiple robusto")+
  theme_minimal()

A través de la técnica de validación cruzada (LOOCV), el Error Medio Absoluto estimado fue 3.22.

c) Regresión Ridge

# Penalización por Ridge

set.seed(788)
lambda_vals <-rev(seq(0, 6, by = 0.01))
modelo_boston <- glmnet(x=BostonHousing[,c(1:13)],y=BostonHousing[,14],alpha=0,lambda=lambda_vals)
plot(modelo_boston,xvar="lambda",label=TRUE)

cv_bostonridge<-cv.glmnet(x=data.matrix(BostonHousing[,1:13]),y=BostonHousing[,14],alpha=0,type.measure = "mse",lambda=lambda_vals)
lambda_minimo <- cv_bostonridge$lambda.min
plot(cv_bostonridge)

print(cv_bostonridge)
## 
## Call:  cv.glmnet(x = data.matrix(BostonHousing[, 1:13]), y = BostonHousing[,      14], lambda = lambda_vals, type.measure = "mse", alpha = 0) 
## 
## Measure: Mean-Squared Error 
## 
##     Lambda Index Measure    SE Nonzero
## min   0.09   592   23.40 2.468      13
## 1se   3.03   298   25.86 2.633      13
#lambda.min=0.78



# Plotear la capacidad predictiva del modelo
graf <- data.frame(Observados=BostonHousing$medv)
graf$Predichos <- predict(modelo_boston, newx = data.matrix(BostonHousing[,1:13]), s=lambda_minimo)

ggplot(graf, aes(x=Observados,y=Predichos))+
  geom_point(alpha=.2)+
  geom_abline(intercept = 0,
              slope = 1,
              color='#4cadb2',
              lwd=1.5)+
  ggtitle("Valores de medv vs. predichos por modelo lineal múltiple robusto")+
  theme_minimal()

mae <- c()
for(i in 1:nrow(BostonHousing))
{
  modelo_ridge <- glmnet(x=data.matrix(BostonHousing[-i,1:13]),y=BostonHousing[-i,14], alpha=0, lambda=lambda_minimo)
  mae[i]<-abs(predict(modelo_ridge,newx=data.matrix(BostonHousing[i,1:13]))-BostonHousing$medv[i])
}

MAE_ridge <- mean(mae)

A través de la técnica de validación cruzada (LOOCV), el MAE estimado fue 3.365.

d) Regresión LASSO

# Penalización por Lasso

modelo_bostonlasso <- glmnet(x=BostonHousing[,c(1:13)],y=BostonHousing[,14],alpha=1,lambda=lambda_vals)
plot(modelo_bostonlasso, label=TRUE)

cv_boston <- cv.glmnet(x=data.matrix(BostonHousing[,c(1:13)]),y=BostonHousing[,14],alpha=1,type.measure = "mae", lambda=lambda_vals)
lambda_minimo_lasso <- cv_boston$lambda.min
lambda_minimo_lasso
## [1] 0.08
## Lambda minimo = 0.08

plot(cv_boston)

coef_blasso <- coef(modelo_bostonlasso, s=lambda_minimo_lasso)
coef_blasso
## 14 x 1 sparse Matrix of class "dgCMatrix"
##                        s1
## (Intercept)  28.340058177
## crim         -0.080287391
## zn            0.033454814
## indus         .          
## chas          2.618556883
## nox         -14.344875200
## rm            3.983208293
## age           .          
## dis          -1.219107254
## rad           0.168628170
## tax          -0.006327870
## ptratio      -0.899967301
## b             0.008539745
## lstat        -0.522399241
mae<-c()
for(i in 1:nrow(BostonHousing))
{
  modelo_lasso <- glmnet(x=data.matrix(BostonHousing[-i,1:13]),y=BostonHousing[-i,14], alpha=1, lambda=lambda_minimo_lasso)
  mae[i]<-abs(predict(modelo_lasso,newx=data.matrix(BostonHousing[i,1:13]))-BostonHousing$medv[i])
}

MAE_lasso <- mean(mae)

A través de la técnica de validación cruzada (LOOCV), el MAE estimado fue 3.365.

e) Regresión GAM (Generalized Additive Model)

# GAM
#  (Deberíamos meter solo las variables elegidas con lasso y evaluar interacciones ¿con PPR?)
ajus.gam <- gam::gam(medv ~  s(crim) + s(zn) + s(indus) + 
                             s(nox) + s(rm) + s(age) + s(dis) + 
                             s(rad) + s(tax) + s(ptratio) + s(b) +
                             s(lstat), data = BostonHousing)
# la variable chas no entra por ser factor


lineales <- as.data.frame(summary(ajus.gam)$parametric.anova)
tabla <- kable(lineales)

for(i in 1:nrow(lineales)){
  if(!is.na(lineales$`Pr(>F)`[i])&lineales$`Pr(>F)`[i]>.05){
    tabla <- row_spec(tabla,i,background = "#e76f51", bold = T)

  }
}

tabla %>%
   add_header_above(c("Efectos lineales" = 6))
Efectos lineales
Df Sum Sq Mean Sq F value Pr(>F)
s(crim) 1.0000 9658.1173 9658.11735 748.23565 0.0000000
s(zn) 1.0000 2107.7309 2107.73094 163.29056 0.0000000
s(indus) 1.0000 2983.4002 2983.40018 231.13059 0.0000000
s(nox) 1.0000 193.1476 193.14762 14.96357 0.0001255
s(rm) 1.0000 10742.3972 10742.39718 832.23720 0.0000000
s(age) 1.0000 223.5734 223.57338 17.32072 0.0000377
s(dis) 1.0000 1230.4048 1230.40484 95.32218 0.0000000
s(rad) 1.0000 149.4225 149.42250 11.57609 0.0007268
s(tax) 1.0000 197.4234 197.42340 15.29483 0.0001059
s(ptratio) 1.0000 941.2671 941.26712 72.92204 0.0000000
s(b) 1.0000 367.3812 367.38120 28.46183 0.0000002
s(lstat) 1.0000 3205.4023 3205.40233 248.32959 0.0000000
Residuals 456.9997 5898.8853 12.90786 NA NA

Todos los efectos lineales resultaron significativos.

nolineales <- as.data.frame(summary(ajus.gam)$anova)
tabla <- kable(nolineales)

for(i in 1:nrow(nolineales)){
  if(!is.na(nolineales$`Pr(F)`[i])&nolineales$`Pr(F)`[i]>.05){
    tabla <- row_spec(tabla,i,background = "#e76f51", bold = T)

  }
}

tabla %>%
   add_header_above(c("Efectos no lineales" = 4))
Efectos no lineales
Npar Df Npar F Pr(F)
(Intercept) NA NA NA
s(crim) 3 6.184786 0.0003986
s(zn) 3 1.840445 0.1389846
s(indus) 3 1.834620 0.1400254
s(nox) 3 5.151029 0.0016422
s(rm) 3 43.896254 0.0000000
s(age) 3 1.202400 0.3084023
s(dis) 3 8.594925 0.0000146
s(rad) 3 2.518995 0.0574729
s(tax) 3 3.838039 0.0098216
s(ptratio) 3 1.864330 0.1347940
s(b) 3 3.401248 0.0177139
s(lstat) 3 24.828720 0.0000000

Los efectos no lineales de gran parte de las variables resultaron significativos.

plot(ajus.gam)

mae<-c()
for(i in 1:nrow(BostonHousing))
{
  modelo_gam <- gam::gam(medv ~  s(crim) + s(zn) + s(indus) + 
                             s(nox) + s(rm) + s(age) + s(dis) + 
                             s(rad) + s(tax) + s(ptratio) + s(b) +
                             s(lstat), data = BostonHousing[-i,])
  mae[i]<-abs(predict(modelo_gam,BostonHousing[i,])-BostonHousing$medv[i])
}

MAE_gam <- mean(mae)



# Plotear la capacidad predictiva del modelo
graf <- data.frame(Observados=BostonHousing$medv)
graf$Predichos <- ajus.gam$fitted.values

ggplot(graf, aes(x=Observados,y=Predichos))+
  geom_point(alpha=.2)+
  geom_abline(intercept = 0,
              slope = 1,
              color='#4cadb2',
              lwd=1.5)+
  ggtitle("Valores de medv vs. predichos por modelo GAM")+
  theme_minimal()

A través de la técnica de validación cruzada (LOOCV), el MAE estimado fue 2.54.

f) Regresión PPR (Projection Pursuit Regression)

# PPR
ajus.ppr <- ppr(medv ~ crim+zn+indus+nox+rm+age+dis+rad+tax+ptratio+b+lstat, data=BostonHousing, 
                nterms = 3, 
                max.terms = 4,
                trace=F)



tabla <- kable(as.data.frame(ajus.ppr$alpha))

tabla %>%
   add_header_above(c("Vectores de dirección de proyección" = 4))
Vectores de dirección de proyección
term 1 term 2 term 3
crim -0.0440060 -0.0176963 -0.0285437
zn 0.0014893 0.0008133 0.0450182
indus 0.0051115 -0.0331969 0.2619574
nox -0.8697229 -0.3474701 -0.6852594
rm 0.3538888 0.9134186 -0.1572422
age 0.0014518 -0.0161475 -0.0806768
dis -0.1770129 -0.0391480 0.1109961
rad 0.0516876 -0.0371793 0.5723939
tax -0.0010574 -0.0036423 -0.0359565
ptratio -0.1467212 0.0262017 -0.2268376
b 0.0018410 -0.0017500 -0.0091868
lstat -0.2466597 0.1990894 0.1869096
tabla <- kable(as.data.frame(ajus.ppr$beta))

tabla %>%
   add_header_above(c("Coeficientes de los términos de ridge" = 2))
Coeficientes de los términos de ridge
ajus.ppr$beta
term 1 8.388353
term 2 2.286249
term 3 1.248440
plot(ajus.ppr)

A partir de los gráficos (particularmente el segundo), se infiere una interacción entre las variables de mayor peso en el segundo término (nox, rm y lstat).

mae<-c()
for(i in 1:nrow(BostonHousing))
{
  ajus.ppr <- ppr(medv ~ crim+zn+indus+nox+rm+age+dis+rad+tax+ptratio+b+lstat, data=BostonHousing[-i,], 
                nterms = 3, 
                max.terms = 4,
                trace=F)
  mae[i]<-abs(predict(ajus.ppr,BostonHousing[i,])-BostonHousing$medv[i])
}

MAE_ppr <- mean(mae)




# Plotear la capacidad predictiva del modelo
graf <- data.frame(Observados=BostonHousing$medv)
graf$Predichos <- predict(ajus.ppr, newdata=BostonHousing)

ggplot(graf, aes(x=Observados,y=Predichos))+
  geom_point(alpha=.2)+
  geom_abline(intercept = 0,
              slope = 1,
              color='#4cadb2',
              lwd=1.5)+
  ggtitle("Valores de medv vs. predichos por modelo GAM")+
  theme_minimal()

A través de la técnica de validación cruzada (LOOCV), el MAE estimado fue 2.612.

g) Regresión mediante ANN (Artificial Neural Networks)

# ANN
set.seed(195)
ajus.nnet <- nnet(medv ~ ., # Formula
                  data=BostonHousing, # Datos 
                  size=5, # Cantidad de neuronas 
                  decay=0.5, 
                  maxit=3000, # Epocas 
                  linout=1, 
                  trace=F) # No muestra por donde va
plotnet(ajus.nnet)

mae<-c()
for(i in 1:nrow(BostonHousing))
{
  
  set.seed(195)
  ajus.nnet <- nnet(medv ~ ., # Formula
                  data=BostonHousing[-i,], # Datos 
                  size=5, # Cantidad de neuronas 
                  decay=0.5, 
                  maxit=3000, # Epocas 
                  linout=1, 
                  trace=F) # No muestra por donde va
  mae[i]<-abs(predict(ajus.nnet,BostonHousing[i,])-BostonHousing$medv[i])

}

MAE_nnet <- mean(mae)



# Plotear la capacidad predictiva del modelo
graf <- data.frame(Observados=BostonHousing$medv)
graf$Predichos <- predict(ajus.nnet, newdata=BostonHousing)

ggplot(graf, aes(x=Observados,y=Predichos))+
  geom_point(alpha=.2)+
  geom_abline(intercept = 0,
              slope = 1,
              color='#4cadb2',
              lwd=1.5)+
  ggtitle("Valores de medv vs. predichos por modelo GAM")+
  theme_minimal()

A través de la técnica de validación cruzada (LOOCV), el MAE estimado fue 2.683.

3) ¿ Cual es el mejor modelo predictivo ?

A partir de esta primera ronda de análisis, el mejor modelo predictivo considerando el MAE es el modelo de GAM (MAE = 2.54). Sin embargo, todavía sería necesario evaluar los primeros modelos, pero incluyendo la interacción triple detectada por PPR.

# Lineal
mae<-c()
for(i in 1:nrow(BostonHousing))
{
  ajus.lm <- lm(medv ~  (nox*rm*lstat)+crim+zn+chas+dis+rad+tax+ptratio+b, data = BostonHousing[-i,])
  mae[i]<-abs(predict(ajus.lm,BostonHousing[i,])-BostonHousing$medv[i])
}

MAE_lm2 <- mean(mae)




# Robusto
mae<-c()
for(i in 1:nrow(BostonHousing))
{
  ajus.lmrob <- lmrob(medv ~  (nox*rm*lstat)+crim+zn+chas+dis+rad+tax+ptratio+b, data = BostonHousing[-i,])
  mae[i]<-abs(predict(ajus.lmrob,BostonHousing[i,])-BostonHousing$medv[i])
}

MAE_lmrob2 <- mean(mae)




# GAM

mae<-c()
for(i in 1:nrow(BostonHousing))
{
  modelo_gam <- gam::gam(medv ~  s(nox*rm*lstat) + 
                             s(crim) + s(zn) + s(indus) + 
                             s(nox) + s(rm) + s(age) + s(dis) + 
                             s(rad) + s(tax) + s(ptratio) + s(b) +
                             s(lstat), data = BostonHousing[-i,])
  mae[i]<-abs(predict(modelo_gam,BostonHousing[i,])-BostonHousing$medv[i])
}

MAE_gam2 <- mean(mae)

Al incluir la interacción en los modelos, el MAE disminuye. De todos modos, el modelo de GAM (con la interacción) sigue siendo el mejor modelo predictivo.

4) ¿ Que variables explican el valor de las propiedades ?

A partir de los resultados hallados ajustando el modelo con la técnica de Lasso, las variables que parecieran explicar mejor el valor de las propiedades son la concentración de óxidos de nitrógeno (nox), el número medio de habitaciones por vivienda (rm), la cercanía al río Charles (chas) y la distancia a los centros de empleo de Boston (dis).