Ejercicio

Estimados alumnos,

A través de un conjunto de datos (TABLON_ENTRENAMIENTO.csv) se debe entrenar un modelo que realice la predicción de la variable TARGET teniendo en cuenta los inputs dados por las variables (VAR1, VAR2, VAR3, VAR4).

Se debe realizar el test del modelo utilizando los datos del fichero TABLON_VALIDACION.csv. Para ello, elija la métrica que mejor se adapte a la naturaleza de los datos. Pista: la variable TARGET es cuantitativa continua.

Este reto se debe resolver en RStudio y presentar los resultados a través de un documento (html o pdf) creado con RMarkdown.

Debe indagar sobre diferentes naturalezas de modelos predictivos y mostrar cuál de ellos es el que mejor resultado arroja para el caso bajo estudio tras realizar la comparación entre las métricas obtenidas.

Cargo librerias

library(ggplot2)
library(dplyr)
library(GGally)
library(rpart)
library(rpart.plot)
library(randomForest)
library(caret)
library(mltools)
library(e1071)
library(Metrics)

Leemos las bases de datos

test = read.csv("~/rstudio/TABLON_VALIDACION.csv",header=T, sep=";")
train = read.csv("~/rstudio/TABLON_ENTRENAMIENTO.csv", header=T, sep=";")

Análisis exploratorio

# Juntamos las dos para crear una base de datos conjunta
total <- bind_rows(train, test) 
head(total)
##     TARGET VAR1 VAR2 VAR3 VAR4
## 1 0.127681    1  0.5    1  300
## 2 0.137929    2  0.5    1  300
## 3 0.166577    3  0.5    1  300
## 4 0.276655    4  0.5    1  300
## 5 0.375599    5  0.5    1  300
## 6 0.537873    6  0.5    1  300
str(total)
## 'data.frame':    5400 obs. of  5 variables:
##  $ TARGET: num  0.128 0.138 0.167 0.277 0.376 ...
##  $ VAR1  : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ VAR2  : num  0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 ...
##  $ VAR3  : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ VAR4  : int  300 300 300 300 300 300 300 300 300 300 ...
# Buscamos si hay Na 
colSums(is.na(total))
## TARGET   VAR1   VAR2   VAR3   VAR4 
##      0      0      0      0      0
colSums(total=="")
## TARGET   VAR1   VAR2   VAR3   VAR4 
##      0      0      0      0      0
# Vemos las variables
apply(total,2,function(x) length(unique(x)))
## TARGET   VAR1   VAR2   VAR3   VAR4 
##   5397     50     12      3      3
# Vemos la Correlación
correlación = cor(total)
print(correlación)
##             TARGET      VAR1          VAR2          VAR3          VAR4
## TARGET  1.00000000 0.9084015  1.275580e-01 -2.439513e-02 -3.366129e-02
## VAR1    0.90840145 1.0000000  0.000000e+00  0.000000e+00  0.000000e+00
## VAR2    0.12755801 0.0000000  1.000000e+00 -6.848732e-19 -4.376592e-20
## VAR3   -0.02439513 0.0000000 -6.848732e-19  1.000000e+00 -1.960702e-21
## VAR4   -0.03366129 0.0000000 -4.376592e-20 -1.960702e-21  1.000000e+00
# Visualizamos en gráficos las relaciones entre el TARGET y las variables
ggplot(total, aes(VAR1, TARGET)) + geom_point() + ggtitle("VAR1 vs TARGET")

ggplot(total, aes(VAR2, TARGET)) + geom_point() + ggtitle("VAR2 vs TARGET")

ggplot(total, aes(VAR3, TARGET)) + geom_point() + ggtitle("VAR3 vs TARGET")

ggplot(total, aes(VAR4, TARGET)) + geom_point() + ggtitle("VAR4 vs TARGET")

Podemos observar viendo estos gráficos que la variable 1 si parece tener una clara pendiente hacia arriba siendo proporcional.

En cambio las otras variables no se ve una clara relación con la variable target

PCA

pca <- prcomp(total,center = T,scale. = T)
summary(pca)
## Importance of components:
##                           PC1    PC2    PC3    PC4     PC5
## Standard deviation     1.3850 1.0000 1.0000 1.0000 0.28591
## Proportion of Variance 0.3836 0.2000 0.2000 0.2000 0.01635
## Cumulative Proportion  0.3836 0.5837 0.7836 0.9837 1.00000
# Vemos que todas las variables tienen importancia por lo que no podemos quitar ninguna.

Regresión lineal

RegresionL = lm(TARGET ~ VAR1 + VAR2 + VAR3 + VAR4,data =  train)
RegresionL
## 
## Call:
## lm(formula = TARGET ~ VAR1 + VAR2 + VAR3 + VAR4, data = train)
## 
## Coefficients:
## (Intercept)         VAR1         VAR2         VAR3         VAR4  
##   0.9167535    0.0868552    0.0574772   -0.0196577   -0.0005762
summary(RegresionL)
## 
## Call:
## lm(formula = TARGET ~ VAR1 + VAR2 + VAR3 + VAR4, data = train)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.31196 -0.49367  0.09087  0.47884  1.00021 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.9167535  0.0552213  16.601  < 2e-16 ***
## VAR1         0.0868552  0.0006762 128.455  < 2e-16 ***
## VAR2         0.0574772  0.0028297  20.312  < 2e-16 ***
## VAR3        -0.0196577  0.0047486  -4.140 3.57e-05 ***
## VAR4        -0.0005762  0.0001195  -4.822 1.49e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.5476 on 3145 degrees of freedom
## Multiple R-squared:  0.8435, Adjusted R-squared:  0.8433 
## F-statistic:  4238 on 4 and 3145 DF,  p-value: < 2.2e-16
# Vemos graficamente la regresión
plot(RegresionL)

En la gráfica de los residuos vemos que no hay un patron linear claro. En el QQ entre los valores -2 y 2 si tiene una normalidad pero en los extremos vemos claras desviaciones. En el gráfico de SCale location los residuos toman una forma un tanto extraña que no tiene normalidad ninguna y que es incluso peor y mas dispersa en el Residuals vs Leverage

# Vemos las predicciones de la Regresión lineal
predict_RL = predict(RegresionL, newdata = test)
summary(predict_RL)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.6435  1.9862  3.0757  3.0747  4.1576  5.5268
# Gráfico de valores observados vs. predichos
plot(test$TARGET, predict_RL, main = "Valores Observados vs. Predichos",
     xlab = "Valores Observados", ylab = "Valores Predichos", pch = 16, col = "blue")

# Gráfico de residuos
plot(RegresionL, which = 1, pch = 16, col = "green", main = "Gráfico de residuos")

KNN

trainControl <- trainControl(method="repeatedcv", number=10, repeats=3)
knn<- train(TARGET~., data=train, method="knn", metric="RMSE", trControl=trainControl)
knn
## k-Nearest Neighbors 
## 
## 3150 samples
##    4 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 3 times) 
## Summary of sample sizes: 2834, 2836, 2834, 2836, 2834, 2834, ... 
## Resampling results across tuning parameters:
## 
##   k  RMSE       Rsquared   MAE       
##   5  0.1138630  0.9936088  0.08455356
##   7  0.1229306  0.9924444  0.08994268
##   9  0.1160065  0.9931360  0.08139617
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was k = 5.
plot(knn)

# Vemos la predicción del KNN
predict_knn <- predict(knn, test, type = "raw")
summary(predict_knn)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.1505  2.2878  3.6771  3.1242  4.2491  4.5987

SVM

trainControl <- trainControl(method="repeatedcv", number=10, repeats=3)
svm = train(TARGET~., data=train, method="svmLinear", metric="RMSE", trControl=trainControl)
svm
## Support Vector Machines with Linear Kernel 
## 
## 3150 samples
##    4 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 3 times) 
## Summary of sample sizes: 2835, 2836, 2834, 2835, 2835, 2836, ... 
## Resampling results:
## 
##   RMSE       Rsquared   MAE      
##   0.5707867  0.8421164  0.4679391
## 
## Tuning parameter 'C' was held constant at a value of 1
# Realizamos la predicción del SVM
predict_svm <- predict(svm,test,type = "raw")
summary(predict_svm)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.8856  2.2051  3.1858  3.1894  4.1868  5.5162

Random Forest

rf = randomForest(x=train, y=train$TARGET, importance=TRUE)
rf
## 
## Call:
##  randomForest(x = train, y = train$TARGET, importance = TRUE) 
##                Type of random forest: regression
##                      Number of trees: 500
## No. of variables tried at each split: 1
## 
##           Mean of squared residuals: 0.07573328
##                     % Var explained: 96.04
plot(rf)

random_forest_model <- randomForest(TARGET ~ VAR1 + VAR2 + VAR3 + VAR4, train)
summary(random_forest_model)
##                 Length Class  Mode     
## call               3   -none- call     
## type               1   -none- character
## predicted       3150   -none- numeric  
## mse              500   -none- numeric  
## rsq              500   -none- numeric  
## oob.times       3150   -none- numeric  
## importance         4   -none- numeric  
## importanceSD       0   -none- NULL     
## localImportance    0   -none- NULL     
## proximity          0   -none- NULL     
## ntree              1   -none- numeric  
## mtry               1   -none- numeric  
## forest            11   -none- list     
## coefs              0   -none- NULL     
## y               3150   -none- numeric  
## test               0   -none- NULL     
## inbag              0   -none- NULL     
## terms              3   terms  call

Podemos ver que no hay mucha mejoria despues de 70 árboles.

predict_rf = predict(random_forest_model, test)
summary(predict_rf)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.9532  2.0890  3.5542  3.1278  3.8932  4.0824

calculando R2, MSE, RMSE

## R2 reg lineal: 0.8442649
## R2 random forest: 0.9644573
## R2 knn: 0.9985039
## R2 svm: 0.8423358
## [1] "RMSE Regresión Lineal: 0.560182407753489"
## [1] "RMSE Random Forest: 0.470580431168614"
## [1] "RMSE k-NN: 0.0621587465708928"
## [1] "RMSE svm: 0.573226790676544"

Conclusión

El RMSE (Root Mean Squared Error) es una métrica comúnmente utilizada para evaluar la precisión de un modelo de regresión. Podemos ver que son mas o menos parecidos en nuestro caso siendo el mas bajo el del Random Forest. El RMSE mide la diferencia entre los valores predichos por el modelo y los valores observados (reales) en términos de la raíz cuadrada de la media de los errores cuadrados.

R2(R-cuadrado) es una medida estadística que proporciona información sobre la proporción de la variabilidad de la variable dependiente que es explicada por el modelo de regresión. En otras palabras, r2 indica cuánto mejor es el modelo en comparación con un modelo simple que predice el valor medio de la variable dependiente para todas las observaciones. En nuestro caso el R2 es muy parecido y superior para los modelos de KNN y de Random Forest.

Conclusiones Generales: El modelo k-NN parece ser el que mejor se ajusta a los datos según el R2, pero el RMSE extremadamente bajo puede indicar un sobreajuste. El modelo Random Forest muestra un buen equilibrio entre R2 y RMSE, lo que sugiere un rendimiento robusto. La regresión lineal y SVM tienen resultados similares, pero el modelo SVM tiene un R2 ligeramente más bajo.