Overview

Vamos a crear un algoritmo para predecir con la mayor precisión, la manera (How well) de realizar ejercicio. Para ello vamos a usar un dataset publico (Weight Lifting Exercises Dataset) y técnicas de Machine Learning, principalmente Random Forest, Generalized Boosted, Linear Discriminant Analysis, Recursive Partitioning And Regression Trees and, of course, Cross Validation.

Exploratory Analysis

Datasets

URL.train <- "https://d396qusza40orc.cloudfront.net/predmachlearn/pml-training.csv"
URL.test <- "https://d396qusza40orc.cloudfront.net/predmachlearn/pml-testing.csv"
Fil.train <- "pml-training.csv"
Fil.test <- "pml-testing.csv"

if(!file.exists(Fil.train))
  download.file(URL.train, destfile = Fil.train)

if(!file.exists(Fil.test))
  download.file(URL.test, destfile = Fil.test)
  
Dat.train <- read.csv(Fil.train, na.strings=c("NA","#DIV/0!","")) 
Dat.test <- read.csv(Fil.test, na.strings=c("NA","#DIV/0!",""))

Bajamos los 2 dataset (training y testing) y los cargamos en memoria. Hemos identificado previamente varios valores residuales y nulos, procedemos a convertirlos en NA.

Pre-Process Training Dataset

set.seed(13)
Spl <- createDataPartition(Dat.train$classe, p = 0.7, list = FALSE)
Dat.train.train <- Dat.train[Spl, ]
Dat.train.valid <- Dat.train[-Spl, ]

Dat.train.train <- Dat.train.train[, -c(1:7)]
Dat.train.valid <- Dat.train.valid[, -c(1:7)]

nz <- nearZeroVar(Dat.train.train)
Dat.train.train <- Dat.train.train[, -nz]
Dat.train.valid <- Dat.train.valid[, -nz]

vna    <- sapply(Dat.train.train, function(x) mean(is.na(x))) > 0.97
Dat.train.train <- Dat.train.train[, vna==FALSE]
Dat.train.valid <- Dat.train.valid[, vna==FALSE]

dim(Dat.train.train)
## [1] 13737    53
dim(Dat.train.valid)
## [1] 5885   53
descrCor <-  cor(Dat.train.train[, -length(Dat.train.train)])
highlyCorDescr <- findCorrelation(descrCor, cutoff = .8)
Dat.train.train <- Dat.train.train[,-highlyCorDescr]
Dat.train.valid <- Dat.train.valid[,-highlyCorDescr]

dim(Dat.train.train)
## [1] 13737    40
dim(Dat.train.valid)
## [1] 5885   40

En un principio los 2 dataset tienen 160 covariables, los datos de training los partimos en 2 trozos, uno con el 70% para construir los modelos, y el otro con el 30% para validarlos y poder elegir el que tiene mas accuracy. A continuación tenemos que eliminar las covariables descriptivas del propio proceso de medicion o las que contengan id’s inútiles para nuestra predicción (las 7 primeras) en segundo lugar las covariables que tengan una variance cercana a cero y en tercer lugar eliminamos las covariables que en su mayoria tienen valor NA (por encima del 97% de los datos).
Por último evaluamos la correlación entre las 53 covariables y fijando un umbral del 80% de correlación absoluta, nos quedamos con 40 covariables que consideramos apropiadas para contruir los modelos de predicción.

Pre-Process Testing Dataset

Dat.test <- Dat.test[, -c(1:7)]
Dat.test <- Dat.test[, -nz]
Dat.test <- Dat.test[, vna==FALSE]
Dat.test <- Dat.test[,-highlyCorDescr]

dim(Dat.test)
## [1] 20 40

Debemos hacer las mismas transformaciones con los datos de testing proporcionados, con los cuales efectuaremos al final del report la predicción de las 20 muestras (individuos).

Build diferent models

vControl <- trainControl(method="cv", number=4, verboseIter = FALSE)
vMetric <- "Accuracy"

Establecemos los parametros generales que usaremos al construir todos los modelos. Vamos a usar Cross Validatión en todos los casos.

1.- Modelo LDA:

Modfit.lda <- train(classe ~ ., method = "lda", data = Dat.train.train, verbose = FALSE, trControl = vControl, metric = vMetric)

Pre.lda <- predict(Modfit.lda, Dat.train.valid)

confusionMatrix(Pre.lda, Dat.train.valid$classe)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    A    B    C    D    E
##          A 1269  190  102   53   49
##          B  151  657   90   71  185
##          C  147  111  665  114  132
##          D   88   87  142  653  131
##          E   19   94   27   73  585
## 
## Overall Statistics
##                                           
##                Accuracy : 0.6506          
##                  95% CI : (0.6383, 0.6628)
##     No Information Rate : 0.2845          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.5586          
##                                           
##  Mcnemar's Test P-Value : < 2.2e-16       
## 
## Statistics by Class:
## 
##                      Class: A Class: B Class: C Class: D Class: E
## Sensitivity            0.7581   0.5768   0.6481   0.6774  0.54067
## Specificity            0.9064   0.8953   0.8963   0.9090  0.95565
## Pos Pred Value         0.7631   0.5693   0.5689   0.5931  0.73308
## Neg Pred Value         0.9041   0.8981   0.9235   0.9350  0.90230
## Prevalence             0.2845   0.1935   0.1743   0.1638  0.18386
## Detection Rate         0.2156   0.1116   0.1130   0.1110  0.09941
## Detection Prevalence   0.2826   0.1961   0.1986   0.1871  0.13560
## Balanced Accuracy      0.8323   0.7361   0.7722   0.7932  0.74816

Construimos el modelo con el 70% de los datos de training y lo validamos con el 30% restante. En este caso la Accuracy no llega al 70%, pensamos que esta técnica de Machine Learning no es la apropiada para nuestros datos.

2.- Modelo RPART:

Modfit.rpart <- train(classe ~ ., method = "rpart", data = Dat.train.train, trControl = vControl, metric = vMetric)

Pre.rpart <- predict(Modfit.rpart, Dat.train.valid)

confusionMatrix(Pre.rpart, Dat.train.valid$classe)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    A    B    C    D    E
##          A 1513  478  499  375  241
##          B   29  386   24  191  213
##          C  106  234  399   80  222
##          D   25   39  104  234   31
##          E    1    2    0   84  375
## 
## Overall Statistics
##                                           
##                Accuracy : 0.494           
##                  95% CI : (0.4811, 0.5068)
##     No Information Rate : 0.2845          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.3384          
##                                           
##  Mcnemar's Test P-Value : < 2.2e-16       
## 
## Statistics by Class:
## 
##                      Class: A Class: B Class: C Class: D Class: E
## Sensitivity            0.9038  0.33889   0.3889  0.24274  0.34658
## Specificity            0.6217  0.90371   0.8679  0.95956  0.98189
## Pos Pred Value         0.4871  0.45789   0.3833  0.54042  0.81169
## Neg Pred Value         0.9421  0.85065   0.8706  0.86610  0.86963
## Prevalence             0.2845  0.19354   0.1743  0.16381  0.18386
## Detection Rate         0.2571  0.06559   0.0678  0.03976  0.06372
## Detection Prevalence   0.5278  0.14325   0.1769  0.07358  0.07850
## Balanced Accuracy      0.7628  0.62130   0.6284  0.60115  0.66423

De igual manera construimos el modelo con el 70% de los datos de training y lo validamos con el 30% restante. En este caso la Accuracy no llega al 50%, definitivamente esta técnica de Machine Learning no es la apropiada para nuestros datos.

3.- Modelo GBM:

Modfit.gbm <- train(classe ~ ., method = "gbm", data = Dat.train.train, trControl = vControl, metric = vMetric, verbose = FALSE)

Pre.gbm <- predict(Modfit.gbm, Dat.train.valid)

confusionMatrix(Pre.gbm, Dat.train.valid$classe)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    A    B    C    D    E
##          A 1649   32    0    0    2
##          B   16 1064   48    6    8
##          C    5   39  960   40   13
##          D    4    1   15  912   12
##          E    0    3    3    6 1047
## 
## Overall Statistics
##                                          
##                Accuracy : 0.957          
##                  95% CI : (0.9515, 0.962)
##     No Information Rate : 0.2845         
##     P-Value [Acc > NIR] : < 2.2e-16      
##                                          
##                   Kappa : 0.9456         
##                                          
##  Mcnemar's Test P-Value : 5.575e-06      
## 
## Statistics by Class:
## 
##                      Class: A Class: B Class: C Class: D Class: E
## Sensitivity            0.9851   0.9342   0.9357   0.9461   0.9677
## Specificity            0.9919   0.9836   0.9800   0.9935   0.9975
## Pos Pred Value         0.9798   0.9317   0.9082   0.9661   0.9887
## Neg Pred Value         0.9941   0.9842   0.9863   0.9895   0.9927
## Prevalence             0.2845   0.1935   0.1743   0.1638   0.1839
## Detection Rate         0.2802   0.1808   0.1631   0.1550   0.1779
## Detection Prevalence   0.2860   0.1941   0.1796   0.1604   0.1799
## Balanced Accuracy      0.9885   0.9589   0.9579   0.9698   0.9826

Para este modelo hacemos lo mismo, lo construimos con el 70% de los datos de training y lo validamos con el 30% restante. En este caso, la Accuracy es mas que aceptable llegando al 96%, dependiendo del resultado del ultimo modelo este podria ser el elegido.

4.- Modelo RF:

Modfit.rf <- train(classe ~ ., method = "rf", data = Dat.train.train, trControl = vControl, metric = vMetric)

Pre.rf <- predict(Modfit.rf, Dat.train.valid)

confusionMatrix(Pre.rf, Dat.train.valid$classe)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    A    B    C    D    E
##          A 1674    4    0    1    0
##          B    0 1129   11    0    0
##          C    0    6 1009   12    1
##          D    0    0    6  951    0
##          E    0    0    0    0 1081
## 
## Overall Statistics
##                                          
##                Accuracy : 0.993          
##                  95% CI : (0.9906, 0.995)
##     No Information Rate : 0.2845         
##     P-Value [Acc > NIR] : < 2.2e-16      
##                                          
##                   Kappa : 0.9912         
##                                          
##  Mcnemar's Test P-Value : NA             
## 
## Statistics by Class:
## 
##                      Class: A Class: B Class: C Class: D Class: E
## Sensitivity            1.0000   0.9912   0.9834   0.9865   0.9991
## Specificity            0.9988   0.9977   0.9961   0.9988   1.0000
## Pos Pred Value         0.9970   0.9904   0.9815   0.9937   1.0000
## Neg Pred Value         1.0000   0.9979   0.9965   0.9974   0.9998
## Prevalence             0.2845   0.1935   0.1743   0.1638   0.1839
## Detection Rate         0.2845   0.1918   0.1715   0.1616   0.1837
## Detection Prevalence   0.2853   0.1937   0.1747   0.1626   0.1837
## Balanced Accuracy      0.9994   0.9945   0.9898   0.9926   0.9995

Como podemos observar este es el modelo mas exacto, Random Forest, con una Accuracy que supera el 99%, practicamente inmejorable. Es el que usaremos para hacer nuestra predicción de la covariable ‘classe’ que determinará para cada una de las 20 muestras (individuos), su mamera de hacer ejercicio, siendo el valor A la manera correcta, y siendo B, C, D y E los 4 errores mas usuales a la hora de hacer los ejercicios del experimento.

Error

Out of sample error:

Accu <- sum(Pre.rf == Dat.train.valid$classe) / length(Pre.rf)
Accu
## [1] 0.9930331
Error <- 1 - Accu
Error
## [1] 0.006966865
pError <- Error * 100
pError
## [1] 0.6966865

Hemos calculado la tasa de error ‘out-of-sample’ para nuestro modelo construido con Random Forest y como podiamos sospechar es muy baja, por debajo del 1% (0.7%). Podemos tener la seguridad de que el modelo ganador. A parte de ser el mejor de los calculados, tambien tiene un nivel de exactitud muy alto.

Prediction

Testing Dataset

Pre.rf.testing <- predict(Modfit.rf, Dat.test)
Pre.rf.testing
##  [1] B A B A A E D B A A B C B A E E A B B B
## Levels: A B C D E

La predicción de las 20 muestras (individuos) realizada con nuestro modelo ganador son todas correctas. El modelo se ajusta a la realidad de los datos perfectamente. Hemos comprobado que los 20 resultados son correctos introduciendolos en el Atomatized Quiz.