Vamos a testar los siguientes algoritmos de machine learning para poder compararlos:
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
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
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
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
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])
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)
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 |
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 %
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
#podemos utilizar los mismos datos que para el algoritmo knn
set.seed(1234567)
bayesclass <- naiveBayes(train_knn, train_knn_labels, laplace = 0)
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 |
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.
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)]
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")
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 |
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 %
Creamos los set de test y entrenamiento
train_svm <- train_pec[,1:22]
test_svm <- test_pec[,1:22]
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
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 |
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
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]
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)
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 |
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 %
Podemos utilizar los datos de train y test utilizados para el algoritmo de arboles de decisión
Entrenamos el modelo con la funcion randomForest
set.seed(1234567)
rf <- randomForest(labels ~., data = train_dectree)
plot(rf)
varImpPlot(rf)
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 |
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
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
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)
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 |
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 |
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 |
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 |
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:
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 |
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.
(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.