Vamos a testar los siguientes algoritmos de machine learning para poder compararlos:

  1. Knn
  2. Naive Bayes
  3. Redes Neurales
  4. Support Vector Machines
  5. Arboles de decisión
  6. Random Forests

Para ello vamos a utilizar los datos del artículo D Ayres de Campos et al. (2000) SisPorto 2.0 A Program for Automated Analysis of Cardiotocograms. J Matern Fetal Med 5:311-318 . Los datos corresponden al dataset Cardiotocography que se puede obtener desde la UCI Machine Learning Repository , http://archive.ics.uci.edu/ml

Exploración de los datos

Se realiza una exploración inicial de los datos, para ello lo primero que hacemos es cargar los datos.

##cargar datasets
file <- file.path(params$folder.data, params$file1)
dataset <- read.csv2(file=file)

El fichero CTG.csv está formado por 2126 observaciones y 23 variables.

Tenemos 20 variables del tipo ordinal y tres variable categóricas que nos indican el diagnóstico fetal.

Primero creamos una variable codificando la variable NSP para darle un nombre más entendible

#creamos una columna con las equiquetas
dataset$labels <- dataset$NSP

#codificamos
dataset$labels[dataset$labels==1] <- "normal"
dataset$labels[dataset$labels==2] <- "sospechoso"
dataset$labels[dataset$labels==3] <- "patogenica"

Tabulamos la variable labels creada anteriormente para ver la frecuencia de cada tipo de diagnóstico fetal

#tabulamos
kable(table(dataset$labels))%>%
  kable_styling()
Var1 Freq
normal 1655
patogenica 176
sospechoso 295

Presentamos los primeros diez registros del dataset

#sumario de los datasets
head(dataset[,1:10])
summary(dataset[,1:10])
       LB              AC                 FM                 UC          
 Min.   :106.0   Min.   :0.000000   Min.   :0.000000   Min.   :0.000000  
 1st Qu.:126.0   1st Qu.:0.000000   1st Qu.:0.000000   1st Qu.:0.001876  
 Median :133.0   Median :0.001630   Median :0.000000   Median :0.004482  
 Mean   :133.3   Mean   :0.003170   Mean   :0.009474   Mean   :0.004357  
 3rd Qu.:140.0   3rd Qu.:0.005631   3rd Qu.:0.002512   3rd Qu.:0.006525  
 Max.   :160.0   Max.   :0.019284   Max.   :0.480634   Max.   :0.014925  
       DL                 DS                  DP           
 Min.   :0.000000   Min.   :0.000e+00   Min.   :0.0000000  
 1st Qu.:0.000000   1st Qu.:0.000e+00   1st Qu.:0.0000000  
 Median :0.000000   Median :0.000e+00   Median :0.0000000  
 Mean   :0.001885   Mean   :3.585e-06   Mean   :0.0001566  
 3rd Qu.:0.003264   3rd Qu.:0.000e+00   3rd Qu.:0.0000000  
 Max.   :0.015385   Max.   :1.353e-03   Max.   :0.0053476  
      ASTV            MSTV            ALTV       
 Min.   :12.00   Min.   :0.200   Min.   : 0.000  
 1st Qu.:32.00   1st Qu.:0.700   1st Qu.: 0.000  
 Median :49.00   Median :1.200   Median : 0.000  
 Mean   :46.99   Mean   :1.333   Mean   : 9.847  
 3rd Qu.:61.00   3rd Qu.:1.700   3rd Qu.:11.000  
 Max.   :87.00   Max.   :7.000   Max.   :91.000  

Realizamos una exploración gráfica con un boxplot de las variables numéricas

boxplot(dataset[,1:20],main='Datos sin normalizar',col='goldenrod1',cex.axis=0.4,
        subset=dataset$labels)
abline(h=5,lwd=2)

Se pueden observar con el boxplot las diferencias en la escala de las variables numéricas.

Además se presenta el comportamiento de las primeras 10 variables del dataset CTG.csv en función del tipo de diagnóstico fetal

Transformación de los datos

Debido a que algunos algoritmos necesitan tener las variables normalizadas, otros necesitan que las variables categóricas esten factorizadas y otros no aceptan variables categóricas procedemos a normalizar las variables, factorizar y a crear las nuevas variables binarias a partir de las categóricas.

Eliminamos la variable CLASS que no tiene ninguna utilidad a la hora de generar el modelo

#eliminamos la variable class que no nos sirve para predecir
dataset$CLASS <- NULL

Normalizamos los datos

#funcion para normalizar
normalize <- function(x){ return((x-min(x))/ (max(x)- min(x))) }
#aplicacmos la funcion al dataset
datanorm <-  as.data.frame(lapply(dataset[,1:21], normalize)) 

#unimos la columna labels al dataset dataset
datanorm$labels <- dataset$labels

#creamos variables binarias para aquellos algoritmos  que lo necesiten

datanorm$normal <- dataset$NSP ==1
datanorm$sospechoso <- dataset$NSP ==2
datanorm$patogenica <- dataset$NSP ==3

Comprobamos la correcta normalización de los datos mediante el uso de un boxplot

#resumen y distribución de las variables normalizadas
boxplot(datanorm[,1:20],main='Datos Normalizados [0,1]',col='goldenrod1',cex.axis=0.4)
abline(h=0.5,lwd=2)

Observamos que ahora todas las variables las tenemos en escala 0-1

Creación de los sets de test y entrenamiento de los datos

Procedemos a dividir los datos de forma aleatoria con la semilla set.seed(12345)

#semilla aleatoria
set.seed(12345)

smp_size <- floor(0.67 * nrow(dataset))
samples <- sample(seq_len(nrow(dataset)), size = smp_size)
train_pec <- datanorm[samples, ] 
test_pec <- datanorm[-samples, ] 

El 67.67% 1424, para entrenar el modelo, y el resto 702 para evaluarlo

Algoritmo Knn

Para entrenar el modelo Knn seleccionamos las variables a utilizar y creamos las etiquetas, para ello hay que factorizar la variable labels

train_knn <- train_pec[,1:21]
test_knn <- test_pec[,1:21]

#creamos las etiquetas y las factorizamos

train_knn_labels <- as.factor(train_pec[,22])
test_knn_labels <- as.factor(test_pec[,22])

Entrenar el modelo

El modelo creado inicialmente tiene el parámetro k=5 y utilizamos la función knn para ello

set.seed(1234567)
knnpred <- knn(train = train_knn, test = test_knn,
               cl= train_knn_labels, k=5)

Predicción y evaluación del modelo

Para evaluar el modelo knn utilizamos la función confusionMatrix del paquete caret

cf <- confusionMatrix(knnpred, test_knn_labels, positive = "normal") 

kable(cf$table)%>%
  kable_styling()
normal patogenica sospechoso
normal 530 9 43
patogenica 1 33 2
sospechoso 15 9 60

El modelo resultante tiene una accuracy de 0.887 y una kappa de 0.663

Ha clasificado correctamente 623 muestras, es decir el 88.746% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.971 0.667 0.911
Class: patogenica 0.647 0.995 0.917
Class: sospechoso 0.571 0.960 0.714

Mejora del modelo

Para intentar mejorar el modelo de knn vamos a generar un modelo con k=3

set.seed(1234567)
knnpred1 <- knn(train = train_knn, test = test_knn,
             cl= train_knn_labels, k=3)

Evaluamos el modelo generado

cf2 <- confusionMatrix(knnpred1, test_knn_labels, positive = "normal")

kable(cf2$table)%>%
  kable_styling()
normal patogenica sospechoso
normal 527 11 35
patogenica 3 34 3
sospechoso 16 6 67

El modelo resultante tiene una accuracy de 0.895 y una Kappa de 0.692

Ha clasificado correctamente 628 muestras, es decir el 89.459% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.965 0.705 0.920
Class: patogenica 0.667 0.991 0.850
Class: sospechoso 0.638 0.963 0.753

Al utilizar k=3 la accuracy del modelo se ha incrementado en un 0.8 %

Naive Bayes

Como tenemos los datos ya preparados y los datos divididos en los set de entrenamiento y test podemos pasar a entrenar directamente el modelo Naive Bayes con el paramétro laplace=0, utilizamos la función naiveBayes

Entrenar el modelo

#podemos utilizar los mismos datos que para el algoritmo knn
set.seed(1234567)
bayesclass <- naiveBayes(train_knn, train_knn_labels, laplace = 0)

Predicción y evaluación del modelo

Predecimos la clasificación con la función predict y evaluamos el rendimiento con la función confusionMatrix

#predicimos la clasificacion del set de test
bayespred <- predict(bayesclass, test_knn)

cf3 <- confusionMatrix(bayespred, test_knn_labels)

kable(cf3$table)%>%
kable_styling()
normal patogenica sospechoso
normal 466 3 15
patogenica 18 32 3
sospechoso 62 16 87

El modelo resultante tiene una accuracy de 0.833 y una Kappa de 0.606

Ha clasificado correctamente 585 muestras, es decir el 83.333% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.853 0.885 0.963
Class: patogenica 0.627 0.968 0.604
Class: sospechoso 0.829 0.869 0.527

Mejora del modelo

Para intentar mejorar el rendimiento del modelo , vamos a utilizar el parámetro laplace =1

#podemos utilizar los mismos datos que para el algoritmo knn
set.seed(1234567)
bayesclass1 <- naiveBayes(train_knn, train_knn_labels, laplace = 1)

Evaluamos el modelo

#predicimos la clasificacion del set de test
bayespred <- predict(bayesclass1, test_knn)
cf4 <- confusionMatrix(bayespred, test_knn_labels)

kable(cf4$table)%>%
kable_styling()
normal patogenica sospechoso
normal 466 3 15
patogenica 18 32 3
sospechoso 62 16 87

El modelo resultante tiene una accuracy de 0.833 y una Kappa de 0.606

Ha clasificado correctamente 585 muestras, es decir el 83.333% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.853 0.885 0.963
Class: patogenica 0.627 0.968 0.604
Class: sospechoso 0.829 0.869 0.527

Comparando los dos modelos hemos obtenido los mismos resultados de clasificación.

Algoritmo ANN

Las redes neurales no admiten variables categóricas, asi que utilizamos las variables binarias creadas anteriormente

Creamos los set de test y entrenamiento

#seleccionamos las variables del set de test y train iniciales
train_ann <- train_pec[,c(1:21,23:25)]
test_ann <- test_pec[,c(1:21,23:25)]

Entrenar el modelo

Entrenamos el modelo con un nodo en la capa intermedia(hidden=1) y se contruye el modelo con el argumento linear.output=FALSE ya que es un problema de clasificación

#Creamos el modelo
set.seed(1234567)
annmodel <- neuralnet(normal+sospechoso+patogenica ~ LB+AC+FM+UC+DL+DS+DP+ASTV+MSTV+ALTV+
                        MLTV+Width+Min+Max+Nmax+Nzeros+Mode+Mean+Median+Variance+
                        Tendency, data = train_ann, hidden = 1,linear.output = FALSE)
#plotmodel

plot(annmodel,rep="best")

Predicción y evaluación del modelo

Evaluamos el rendimiento del modelo con la funcion compute

annresults <- compute(annmodel, test_ann[,1:21])$net.result

#devolvemos la variables binarias a su categoria original 
maxidx <- function(arr) { return(which(arr == max(arr))) }
idx <- apply(annresults, 1, maxidx)

prediction <- c("normal","sospechoso","patogenica")[idx]

res <- table(prediction, test_pec$labels)

cf5 <- confusionMatrix(res)

kable(cf5$table)%>%
kable_styling()
normal patogenica sospechoso
normal 517 7 39
patogenica 6 29 15
sospechoso 23 15 51

El modelo resultante tiene una accuracy de 0.85 y una kappa de 0.575

Ha clasificado correctamente 597 muestras, es decir el 85.043% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.947 0.705 0.918
Class: patogenica 0.569 0.968 0.580
Class: sospechoso 0.486 0.936 0.573

Mejora del modelo

Vamos a intentar mejorar el rendimiento del modelo para ello en esta ocasión vamos a utilizar un modelo de 3 nodos en la capa intermedia usando el valor 3 en el argumento hidden y aumentando el numero de pasos(stepmax) para que pueda converger.

#Creamos el modelo
set.seed(1234567)
annmodel1 <- neuralnet(normal+sospechoso+patogenica ~ LB+AC+FM+UC+DL+DS+DP+ASTV+MSTV+ALTV+
                        MLTV+Width+Min+Max+Nmax+Nzeros+Mode+Mean+Median+Variance+
                        Tendency, data = train_ann, hidden = 3,linear.output = FALSE
                      ,stepmax=500000)

#plotmodel

plot(annmodel1,rep="best")

Evaluamos el modelo generado con tres nodos para ver si aumenta el rendimiento respecto al modelo de un nodo para ello utilizamos el mismo código de R que utilizamos para generar el modelo de un nodo

annresults <- compute(annmodel1, test_ann[,1:21])$net.result

#devolvemos la variables binarias a su categoria original 
maxidx <- function(arr) { return(which(arr == max(arr))) }
idx <- apply(annresults, 1, maxidx)

prediction <- c("normal","sospechoso","patogenica")[idx]

res <- table(prediction, test_pec$labels)

cf6 <- confusionMatrix(res)

kable(cf6$table)%>%
kable_styling()
normal patogenica sospechoso
normal 524 7 30
patogenica 2 34 4
sospechoso 20 10 71

El modelo resultante tiene una accuracy de 0.896 y una kappa de 0.705

Ha clasificado correctamente 629 muestras, es decir el 89.601% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.960 0.763 0.934
Class: patogenica 0.667 0.991 0.850
Class: sospechoso 0.676 0.950 0.703

Al utilizar boosting con 10 intentos la accuracy del modelo se ha incrementado en un 4.6 %

Algorimo SVM

Creamos los set de test y entrenamiento

train_svm <- train_pec[,1:22]
test_svm <- test_pec[,1:22]

Entrenar el modelo

Generamos el modelo con un kernel lineal vanilladot

set.seed(1234567)
svmclass <- ksvm(labels~., data=train_svm,
                 kernel="vanilladot")
 Setting default kernel parameters  
#summary
svmclass
Support Vector Machine object of class "ksvm" 

SV type: C-svc  (classification) 
 parameter : cost C = 1 

Linear (vanilla) kernel function. 

Number of Support Vectors : 310 

Objective Function Value : -32.2704 -204.7326 -66.9574 
Training error : 0.071629 

Predicción y evaluación del modelo

Usamos la funcion predict para evaluar el modelo y factorizamos la variable labels

svmpred <- predict(svmclass, test_svm)

#factorizamos la variable labels

test_svm$labels <- factor(test_svm$labels)

cf7 <-confusionMatrix(svmpred, test_svm$labels)

kable(cf7$table)%>%
kable_styling()
normal patogenica sospechoso
normal 522 9 30
patogenica 1 30 3
sospechoso 23 12 72

El modelo resultante tiene una accuracy de 0.889 y una kappa de 0.684

Ha clasificado correctamente 624 muestras, es decir el 88.889% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.956 0.750 0.930
Class: patogenica 0.588 0.994 0.882
Class: sospechoso 0.686 0.941 0.673

Mejora del modelo

Para intentar mejorar el modelo vamos a utiliar un modelo Gaussiano rbfot

set.seed(1234567)
svmclass1 <- ksvm(labels~., data=train_svm,
                 kernel="rbfdot")

#summary
svmclass1
Support Vector Machine object of class "ksvm" 

SV type: C-svc  (classification) 
 parameter : cost C = 1 

Gaussian Radial Basis kernel function. 
 Hyperparameter : sigma =  0.0472362513785828 

Number of Support Vectors : 438 

Objective Function Value : -60.1926 -213.7619 -72.4375 
Training error : 0.059691 

Usamos la función predict para evaluar el modelo

svmpred <- predict(svmclass1, test_svm)

cf8 <-confusionMatrix(svmpred, test_svm$labels)

kable(cf8$table)%>%
kable_styling()
normal patogenica sospechoso
normal 531 10 36
patogenica 1 30 0
sospechoso 14 11 69

El modelo resultante tiene una accuracy de 0.897 y una kappa de 0.696

Ha clasificado correctamente 630 muestras, es decir el 89.744% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Al utilizar el método Gausiano la accuracy del modelo se ha incrementado en un 0 %

Sensitivity Specificity Pos Pred Value
Class: normal 0.973 0.705 0.920
Class: patogenica 0.588 0.998 0.968
Class: sospechoso 0.657 0.958 0.734

Al utilizar el método Gausiano la accuracy del modelo se ha incrementado en un 0.8

Algoritmo Arboles de decision

Seleccionamos las variables que utilizaremos para generar el modelo

#adaptamos los set de test

train_dectree <- train_pec[1:22]
test_dectree <- test_pec[1:22]

Entrenar el modelo

Entrenamos el modelo

train_dectree$labels <- factor(train_dectree$labels)

set.seed(1234567)
treemodel <- C5.0(train_dectree[-22], train_dectree$labels)

#ploteamos el modelo creado
plot(treemodel)

Predicción y evaluación del modelo

Evaluamos el modelo con la función predict y confusionMatrix

treepredict <- predict(treemodel, test_dectree)

#factorizamos variable labels

test_dectree$labels <- factor(test_dectree$labels)

cf9 <- confusionMatrix(treepredict, test_dectree$labels)

kable(cf9$table)%>%
kable_styling()
normal patogenica sospechoso
normal 521 6 22
patogenica 0 40 1
sospechoso 25 5 82

El modelo resultante tiene una accuracy de 0.916 y una kappa de 0.769

Ha clasificado correctamente 643 muestras, es decir el 91.595% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.954 0.821 0.949
Class: patogenica 0.784 0.998 0.976
Class: sospechoso 0.781 0.950 0.732

Mejora del modelo

Para mejorar el modelo vamos a usar el metodo boosting con 10 intentos.

set.seed(1234567)
treemodel1 <- C5.0(train_dectree[-22], train_dectree$labels, trials = 10)

#dibujamos el modelo creado
plot(treemodel1)

Evaluamos el modelo

treepredict <- predict(treemodel1, test_dectree)

cf10 <- confusionMatrix(treepredict, test_dectree$labels)

kable(cf10$table)%>%
kable_styling()
normal patogenica sospechoso
normal 529 1 21
patogenica 4 45 2
sospechoso 13 5 82

El modelo resultante tiene una accuracy de 0.934 y una kappa de 0.819

Ha clasificado correctamente 656 muestras, es decir el 93.447% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.969 0.859 0.960
Class: patogenica 0.882 0.991 0.882
Class: sospechoso 0.781 0.970 0.820

Al utilizar boosting con 10 intentos la accuracy del modelo se ha incrementado en un 1.8 %

Random forest

Podemos utilizar los datos de train y test utilizados para el algoritmo de arboles de decisión

Entrenar el modelo

Entrenamos el modelo con la funcion randomForest

set.seed(1234567)
rf <- randomForest(labels ~., data = train_dectree)

plot(rf)

varImpPlot(rf)

Predicción y evaluación del modelo

Utilizamos la función predict para clasificar los datos del set de test y evaluamos el modelo con la función confusionMatrix

predictrf <- predict(rf, test_dectree)

cf11 <-confusionMatrix(predictrf, test_dectree$labels)

kable(cf11$table)%>%
kable_styling()
normal patogenica sospechoso
normal 538 6 26
patogenica 3 42 1
sospechoso 5 3 78

El modelo resultante tiene una accuracy de 0.937 y una kappa de 0.819

Ha clasificado correctamente 658 muestras, es decir el 93.732% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.985 0.795 0.944
Class: patogenica 0.824 0.994 0.913
Class: sospechoso 0.743 0.987 0.907

Mejora del modelo

Para mejorar el modelo vamos a usar el argumento ntree a 1000 que signi???ca que vamos a usar 1000 árboles de decisión

set.seed(1234567)
rf1 <- randomForest(labels ~., data = train_dectree, ntree=1000)

#mostramos el modelo y la importancia de las variables
plot(rf1)

varImpPlot(rf1)

La linea verde corresponde a la tasa de error a la hora de clasificar el tipo de diagóstico fetal.

Y como es habitual utilizamos la función predict para clasificar los datos del set de test y confusionMatrix para evaluarlo

predictrf <- predict(rf1, test_dectree)

cf12 <-confusionMatrix(predictrf, test_dectree$labels)

kable(cf12$table)%>%
kable_styling()
normal patogenica sospechoso
normal 537 6 25
patogenica 3 41 1
sospechoso 6 4 79

El modelo resultante tiene una accuracy de 0.936 y una kappa de 0.815

Ha clasificado correctamente 657 muestras, es decir el 93.59% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.984 0.801 0.945
Class: patogenica 0.804 0.994 0.911
Class: sospechoso 0.752 0.983 0.888

Los modelos generados nos han dado exactamente el mismo resultado

Paquete caret

De forma opcional se van a reproducir de nuevo todos los modelos generados anteriormente, pero esta vez vamos a utilizar el paquete caret para ello y así poder compararlos. Para todos los algoritmos se va a efectuar el modelo con 5-crossfold validation.

Creamos los datos de training para todos, ya que el paquete caret acepta todo tipo de datos

Transformación de los datos

train_caret <- train_pec[,1:22]
test_caret <- test_pec[,1:22]

#factorizamos la variable labels
train_caret$labels <- factor(train_caret$labels)
test_caret$labels <- factor(test_caret$labels)

Knn

Entrenamos el modelo

set.seed(1234567)
knncaret <- train(labels~., data = train_caret, method="knn",
                  trControl= trainControl(method='cv', number=5))

Evaluamos

predictknn <- predict(knncaret, test_caret)

cf13 <- confusionMatrix(predictknn, test_caret$labels)

kable(cf13$table)%>%
kable_styling()
normal patogenica sospechoso
normal 530 9 41
patogenica 1 33 2
sospechoso 15 9 62

El modelo resultante tiene una accuracy de 0.89y una kappa de 0.673

Ha clasificado correctamente 625 muestras, es decir el 89.031% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.971 0.679 0.914
Class: patogenica 0.647 0.995 0.917
Class: sospechoso 0.590 0.960 0.721

Naive Bayes

Entrenamos el modelo

set.seed(1234567)
nbcaret <- train(labels~., data = train_caret, method="nb",
                  trControl= trainControl(method='cv', number=5))

Evaluamos el modelo

predictnb <- predict(nbcaret, test_caret)
Warning in FUN(X[[i]], ...): Numerical 0 probability for all classes with
observation 142
cf14 <- confusionMatrix(predictnb, test_caret$labels)

kable(cf14$table)%>%
kable_styling()
normal patogenica sospechoso
normal 490 7 24
patogenica 8 28 2
sospechoso 48 16 79

El modelo resultante tiene una accuracy de 0.85y una kappa de 0.615

Ha clasificado correctamente 597 muestras, es decir el 85.043% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.897 0.801 0.940
Class: patogenica 0.549 0.985 0.737
Class: sospechoso 0.752 0.893 0.552

ANN

Entrenamos el modelo

set.seed(1234567)
anncaret <- train(labels~., data = train_caret, method="nnet",
                  trControl= trainControl(method='cv', number=5))
                

plotnet(anncaret)

Evaluamos

predictann <- predict(anncaret, test_caret)
cf15 <- confusionMatrix(predictann, test_caret$labels)

kable(cf15$table)%>%
kable_styling()
normal patogenica sospechoso
normal 526 6 29
patogenica 1 36 2
sospechoso 19 9 74

El modelo resultante tiene una accuracy de 0.906y una kappa de 0.733

Ha clasificado correctamente 636 muestras, es decir el 90.598% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.963 0.776 0.938
Class: patogenica 0.706 0.995 0.923
Class: sospechoso 0.705 0.953 0.725

SVM

Entrenamos el modelo

set.seed(1234567)
svmcaret <- train(labels~., data = train_caret, method="svmLinear",
                  trControl= trainControl(method='cv', number=5))

Evaluamos

predictsvm <- predict(svmcaret, test_caret)
cf16 <- confusionMatrix(predictsvm, test_caret$labels)
  
kable(cf16$table)%>%
kable_styling()
normal patogenica sospechoso
normal 522 9 30
patogenica 1 30 3
sospechoso 23 12 72

El modelo resultante tiene una accuracy de 0.889y una kappa de 0.684

Ha clasificado correctamente 624 muestras, es decir el 88.889% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.956 0.750 0.930
Class: patogenica 0.588 0.994 0.882
Class: sospechoso 0.686 0.941 0.673

Decision Trees

Entrenamos

set.seed(1234567)
grid_c50 <- expand.grid(.model = "tree",.trials = c(10, 20, 30, 40),.winnow = "FALSE")


dectreecaret <- train(labels~., data = train_caret, method="C5.0",metric="Kappa",
                  trControl= trainControl(method='cv', number=5))

Evaluamos

predictdectree <- predict(dectreecaret, test_caret)
cf17 <- confusionMatrix(predictdectree, test_caret$labels)

kable(cf17$table)%>%
kable_styling()
normal patogenica sospechoso
normal 533 2 16
patogenica 3 45 2
sospechoso 10 4 87

El modelo resultante tiene una accuracy de 0.947y una kappa de 0.855

Ha clasificado correctamente 665 muestras, es decir el 94.729% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Random Forests

Entrenamos

set.seed(1234567)
rfcaret <- train(labels~., data = train_caret, method="rf",metric="Kappa",
                  trControl= trainControl(method='cv', number=5))

Evaluamos

predictrf <- predict(rfcaret, test_caret)
cf18 <- confusionMatrix(predictrf, test_caret$labels)

kable(cf18$table)%>%
kable_styling()
normal patogenica sospechoso
normal 534 2 20
patogenica 3 45 2
sospechoso 9 4 83

El modelo resultante tiene una accuracy de 0.943y una kappa de 0.841

Ha clasificado correctamente 662 muestras, es decir el 94.302% de las observaciones de forma correcta

La sensibilidad la especificidad asi como los valores predictivos positivos y negativos para cada tipo de cáncer son los siguientes:

Sensitivity Specificity Pos Pred Value
Class: normal 0.978 0.859 0.960
Class: patogenica 0.882 0.992 0.900
Class: sospechoso 0.790 0.978 0.865

Resultados

Como podemos observar en el gráfico de barras todos los modelos generados tienen una accuracy por encima del 80% siendo el modelo generado por el algoritmo de árboles de decisión con boosting de 10 intentos junto a los tres modelos generados por el algoritmo de random forests los que mayor potencia de clasificación tienen con una accuracy del 93.4%.

Para esta clasificación en concreto los modelos que ha tenido menos potencia de clasificación han sido los generados por el algoritmo de Naive Bayes, por debajo del 85% de accuracy. El algortimo Naive Bayes tiene problemes y no es ideal cuando el dataset utlizado se compone de muchas variables numéricas, en este caso concreto de 20.

No encontramos diferencias significativas a la hora de generar el modelo con paquetes específicos de cada algoritmo o utilizando el paquete caret. Tenemos resultados muy homogéneos entre ellos.

Las tablas las hemos dividido en dos, la primera para los modelos generados con paquetes especificos para cada algoritmo, y la segunda para agrupar los resultados de los modelos creados con el paquete caret. Si las observamos vemos, que los algoritmos con mayor sensibilidad, especificidad y el valor predictivo positivo corresponde a los algoritmos de árboles de decisión y random forests indistintamente de que paquete se utilice para generarlos. El algoritmo con peores números es el generado por Naive Bayes.

Incidir también en que solo se han probado dos métodos distintos para cada algoritmo, por lo que probando más parámetros de los modelos estos resultados podrían cambiar.

Después de analizar el resultado de todos los modelos generados podemos concluir que los mejores algoritmos a utilizar en este problema de clasificación concreto serian el algoritmo de árboles de decisión y el algoritmo de Random forests, indistintamente del paquete que utilizemos para generarlo.

Referencias

(Lantz 2015; Diogo et al., n.d.)

Diogo, Ayres‐de‐Campos, Bernardes João, Garrido Antonio, Marques‐de‐Sá Joaquim, and Pereira‐Leite Luis. n.d. “Sisporto 2.0: A Program for Automated Analysis of Cardiotocograms.” The Journal of Maternal-Fetal Medicine 9 (5): 311–18.

Lantz, Brett. 2015. Machine Learning with R. Packt Publishing Ltd. http://www.packtpub.com/books/content/machine-learning-r.