Introducción a los Modelos de Clasificación en R

Ronald Delgado
Ciencia y Datos
Published in
14 min readApr 17, 2019
En esta oportunidad implementaremos un Bosque Aleatorio, entro otros modelos de Clasificación

Continuando con la serie que comencé con el artículo Introducción a los Modelos de Regresión en R, en esta oportunidad veremos una introducción práctica a los Modelos de Clasificación en R. De modo que, sin más preámbulo, comencemos.

Introducción

En esta sesión práctica de programación en R, realizaremos una introducción básica a la implementación de modelos de clasificación (supervisada), entre ellos la Regresión Logística, las Máquinas de Soporte Vectorial o SVM por sus siglas en inglés (Support Vector Machines), así como los Árboles de Decisión y los Bosques Aleatorios, entre otros. A lo largo de la práctica mostraremos cómo se definen y aplican estos modelos en R, y analizaremos su desempeño partiendo del conjunto de datos Predicting a Pulsar Star. Tanto éste como muchos otros conjuntos de datos reales y útiles se encuentran diponibles en el portal Kaggle.

Nota: a efectos de esta práctica, se trabajarán los modelos de clasificación en sus versiones básicas sin mayores ajustes de sus parámetros. La idea es aprender el cómo se implementan lo modelos, más que estudiar las técnicas que existen para mejorar su desempeño. De modo que en la práctica no se mencionará nada sobre técnicas para evitar el sobre entrenamiento o el sub entrenamiento, validación cruzada (cross-validation), ajuste de hiper parámetros, ingeniería de variables (features engineering) o cualquier otro método específico para evaluación y mejora de modelos de clasificación.

Conjunto de Datos

En primer lugar, vamos a establecer nuestro directorio de trabajo, cargar el conjunto de datos, y realizar un análisis exploratorio de los datos:

setwd("D:/ProgramasR/Practicas/ModelosClasificacion")
dataset <- read.csv("pulsar_stars.csv")

Haciendo uso de la función str, podemos explorar la estructura del dataframe que contiene el conjunto de datos:

str(dataset)## 'data.frame':    17898 obs. of  9 variables:
## $ Mean.of.the.integrated.profile : num 140.6 102.5 103 136.8 88.7 ...
## $ Standard.deviation.of.the.integrated.profile: num 55.7 58.9 39.3 57.2 40.7 ...
## $ Excess.kurtosis.of.the.integrated.profile : num -0.2346 0.4653 0.3233 -0.0684 0.6009 ...
## $ Skewness.of.the.integrated.profile : num -0.7 -0.515 1.051 -0.636 1.123 ...
## $ Mean.of.the.DM.SNR.curve : num 3.2 1.68 3.12 3.64 1.18 ...
## $ Standard.deviation.of.the.DM.SNR.curve : num 19.1 14.9 21.7 21 11.5 ...
## $ Excess.kurtosis.of.the.DM.SNR.curve : num 7.98 10.58 7.74 6.9 14.27 ...
## $ Skewness.of.the.DM.SNR.curve : num 74.2 127.4 63.2 53.6 252.6 ...
## $ target_class

Como podemos observar, el conjunto de datos tiene 17898 observaciones y 9 variables en cada una. Específicamente, este dataset contiene información estadística de estrellas pulsares obtenidos por el trabajo High Time Resolution Universe Survey, y cuyas variables son:

  • Media del perfil integrado
  • Desviaciación estándar del perfil integrado
  • Exceso de curtosis del perfil integrado
  • Asimetría del perfil integrado
  • Media de la curva DM-SNR
  • Desviación estánndar de la curva DM-SNR
  • Exceso de curtosis de la curva DM-SNR
  • Asimetría de la curva DM-SNR
  • Clase de la estrella

En este caso, la clase especifica con 1 si se trata de una estrella pulsar, y con 0 si no lo es.

Nuestro objetivo en esta práctica será hacer uso de todas estas variables para construir modelos de clasificación capaces de predecir si una estrella es Pulsar o NoPulsar.

A partir de la tabla anterior, también podemos ver que, a excepción de la variable target_class, todos los demás registros son numéricos. Sin embargo, ya que se trata de un problema de clasificación, es conveniente que nuestra variable a predecir, es decir la variable dependiente target_class, sea un Factor o variable categórica. Vamos entonces a convertir esta variable, así como asignarle el nombre TipoDeEstrella a la columna:

colnames(dataset)[9] <- "TipoEstrella"
dataset$TipoEstrella <- factor(dataset$TipoEstrella, levels = c("0", "1"), labels = c("NoPulsar", "Pulsar"))

Si ahora hacemos uso de la función summary podemos tener un resumen estadístico de las variables del dataset:

summary(dataset)
## Mean.of.the.integrated.profile
## Min. : 5.812
## 1st Qu.:100.930
## Median :115.078
## Mean :111.080
## 3rd Qu.:127.086
## Max. :192.617
## Standard.deviation.of.the.integrated.profile
## Min. :24.77
## 1st Qu.:42.38
## Median :46.95
## Mean :46.55
## 3rd Qu.:51.02
## Max. :98.78
## Excess.kurtosis.of.the.integrated.profile
## Min. :-1.8760
## 1st Qu.: 0.0271
## Median : 0.2232
## Mean : 0.4779
## 3rd Qu.: 0.4733
## Max. : 8.0695
## Skewness.of.the.integrated.profile Mean.of.the.DM.SNR.curve
## Min. :-1.7919 Min. : 0.2132
## 1st Qu.:-0.1886 1st Qu.: 1.9231
## Median : 0.1987 Median : 2.8018
## Mean : 1.7703 Mean : 12.6144
## 3rd Qu.: 0.9278 3rd Qu.: 5.4643
## Max. :68.1016 Max. :223.3921
## Standard.deviation.of.the.DM.SNR.curve
## Min. : 7.37
## 1st Qu.: 14.44
## Median : 18.46
## Mean : 26.33
## 3rd Qu.: 28.43
## Max. :110.64
## Excess.kurtosis.of.the.DM.SNR.curve Skewness.of.the.DM.SNR.curve
## Min. :-3.139 Min. : -1.977
## 1st Qu.: 5.782 1st Qu.: 34.961
## Median : 8.434 Median : 83.065
## Mean : 8.304 Mean : 104.858
## 3rd Qu.:10.703 3rd Qu.: 139.309
## Max. :34.540 Max. :1191.001
## TipoEstrella
## NoPulsar:16259
## Pulsar : 1639
##
##
##
##

A partir del resumen, podemos ver que el conjunto de datos incluye registros de 16259 estrellas que no son pulsares, mientras que 1639 de ellas sí lo son.

Por otro lado, se observa también que existe cierta variabilidad y diferencias de escala entre los valores mínimos y máximos de los registros medidos, por lo que es conveniente, antes de aplicar los modelos de regresión, el rescalar las variables numéricas a fin de que ninguna tenga mayor influencia sobre otra como predictor al momento de construir los modelos de clasificación. Entonces, usemos la función scale:

dataset[, c(1:8)] <- scale(dataset[, c(1:8)])
summary(dataset)
## Mean.of.the.integrated.profile
## Min. :-4.1035
## 1st Qu.:-0.3957
## Median : 0.1559
## Mean : 0.0000
## 3rd Qu.: 0.6239
## Max. : 3.1785
## Standard.deviation.of.the.integrated.profile
## Min. :-3.18236
## 1st Qu.:-0.60988
## Median : 0.05815
## Mean : 0.00000
## 3rd Qu.: 0.65374
## Max. : 7.63232
## Excess.kurtosis.of.the.integrated.profile
## Min. :-2.212200
## 1st Qu.:-0.423630
## Median :-0.239293
## Mean : 0.000000
## 3rd Qu.:-0.004259
## Max. : 7.134757
## Skewness.of.the.integrated.profile Mean.of.the.DM.SNR.curve
## Min. :-0.5775 Min. :-0.4208
## 1st Qu.:-0.3176 1st Qu.:-0.3628
## Median :-0.2548 Median :-0.3329
## Mean : 0.0000 Mean : 0.0000
## 3rd Qu.:-0.1366 3rd Qu.:-0.2426
## Max. :10.7543 Max. : 7.1516
## Standard.deviation.of.the.DM.SNR.curve
## Min. :-0.9736
## 1st Qu.:-0.6106
## Median :-0.4040
## Mean : 0.0000
## 3rd Qu.: 0.1079
## Max. : 4.3304
## Excess.kurtosis.of.the.DM.SNR.curve Skewness.of.the.DM.SNR.curve
## Min. :-2.53941 Min. :-1.0030
## 1st Qu.:-0.55970 1st Qu.:-0.6562
## Median : 0.02884 Median :-0.2046
## Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 0.53248 3rd Qu.: 0.3234
## Max. : 5.82240 Max. :10.1971
## TipoEstrella
## NoPulsar:16259
## Pulsar : 1639
##
##
##
##

Por último, vamos a crear un conjunto de entrenamiento (75%) y un conjunto de validación (25%) a partir de nuestro dataset original, esto con la intención de validar la calidad de la clasificación de los modelos que implementemos. Para esto, hagamos uso de la función sample.split del paquete caTools:

library(caTools)
set.seed(1234)
split <- sample.split(dataset$TipoEstrella, SplitRatio = 0.75)
training_set <- subset(dataset, split == TRUE)
test_set <- subset(dataset, split == FALSE)

A fin de asegurarnos de que la proporción de estrellas pulsares y no pulsares es aproximadamente la misma en ambos conjuntos de datos, veamos la distribución de los tipos de estrella en cada uno:

table(training_set$TipoEstrella)
##
## NoPulsar Pulsar
## 12194 1229
table(test_set$TipoEstrella)
##
## NoPulsar Pulsar
## 4065 410

En efecto, vemos que para ambos conjuntos, la relación NoPulsar/Pulsar es alrededor de 9.9, de modo que la proporción se mantiene.

Ya que nuestro conjunto de datos está listo y preparado, podemos comenzar a construir nuestros modelos de clasificación.

Regresión Logística (Logistic Regression Classifier)

La Regresión Logística es un tipo de modelo de regresión que se emplea para predecir variables categóricas, es decir, relaciones entre variales independientes y una variable dependiente que solo puede tomar un valor entero y finito de clases. En términos generales, la regresión logística calcula las probabilidades de ocurrencia de alguna de las clases del modelo a partir del uso de la función logística.

Para crear y entrenar nuestro modelo de regresión logística, vamos a hacer uso de la función glm del paquete stats:

clasificadorRL <- glm(TipoEstrella ~ ., family = binomial, data = training_set)

Aplicando ahora la función summary podemos observar los resultados estadísticos del entrenamiento:

summary(clasificadorRL)
##
## Call:
## glm(formula = TipoEstrella ~ ., family = binomial, data = training_set)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -4.3224 -0.1587 -0.0966 -0.0548 3.6329
##
## Coefficients:
## Estimate Std. Error z value
## (Intercept) -4.37605 0.10743 -40.733
## Mean.of.the.integrated.profile 0.83332 0.17883 4.660
## Standard.deviation.of.the.integrated.profile -0.26539 0.08491 -3.125
## Excess.kurtosis.of.the.integrated.profile 6.92404 0.37368 18.529
## Skewness.of.the.integrated.profile -3.78412 0.28349 -13.348
## Mean.of.the.DM.SNR.curve -0.82311 0.11736 -7.014
## Standard.deviation.of.the.DM.SNR.curve 0.90550 0.16868 5.368
## Excess.kurtosis.of.the.DM.SNR.curve -0.24943 0.51650 -0.483
## Skewness.of.the.DM.SNR.curve -0.23377 0.48008 -0.487
## Pr(>|z|)
## (Intercept) < 2e-16 ***
## Mean.of.the.integrated.profile 3.16e-06 ***
## Standard.deviation.of.the.integrated.profile 0.00178 **
## Excess.kurtosis.of.the.integrated.profile < 2e-16 ***
## Skewness.of.the.integrated.profile < 2e-16 ***
## Mean.of.the.DM.SNR.curve 2.32e-12 ***
## Standard.deviation.of.the.DM.SNR.curve 7.96e-08 ***
## Excess.kurtosis.of.the.DM.SNR.curve 0.62915
## Skewness.of.the.DM.SNR.curve 0.62631
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 8218.4 on 13422 degrees of freedom
## Residual deviance: 1894.3 on 13414 degrees of freedom
## AIC: 1912.3
##
## Number of Fisher Scoring iterations: 8

El resumen para este clasificador nos muestra, en primer lugar, los valores de los residuales que arroja el modelo, y luego tenemos tanto los estimados de los coeficientes del ajuste para cada variable independiente, así como su p-value (Pr(>|z|) en la tabla), que representa la relevancia estadística de la variable independiente como elemento predictivo. En este sentido, todas las variables que en la tabla tienen símbolos asteríscos tiene gran relevancia como predictores del modelo (de dos a tres *).

Una vez que el clasificador está entrenado, podemos usarlo para predecir tanto las clases del conjunto de entrenamiento como de validación. Ya que la regresión logística ofrece como resultado las probabilidades de ocurrencia de cada clase, vamos a tomar como umbral el valor de 0.5 de modo que cualquier valor por encima de esa probabilidad se tome como 1 o Sano, y cualquier valor por debajo como 0 o Enfermo:

pred_train <- predict(clasificadorRL, type = 'response', ndata = training_set)
pred_train <- ifelse(pred_train > 0.5, 1, 0)
pred_train <- factor(pred_train, levels = c("0", "1"), labels = c("NoPulsar", "Pulsar"))

Ahora, podemos construir la matriz de confusión para evaluar la calidad de la predicción:

matrizConfusion <- table(training_set$TipoEstrella, pred_train)
matrizConfusion
## pred_train
## NoPulsar Pulsar
## NoPulsar 12127 67
## Pulsar 206 1023

Para el caso del conjunto de entrenamiento, tendremos un total de 13150 predicciones correctas, mientras que habrá un total de 273 predicciones incorrectas. Esto nos da una precisión de predicción de 0.979 y un error de predicción de 0.02.

Ahora bien, al aplicar el clasificador al conjunto de validación:

pred_valid <- predict(clasificadorRL, type = 'response', newdata = test_set)
pred_valid <- ifelse(pred_valid > 0.5, 1, 0)
pred_valid <- factor(pred_valid, levels = c("0", "1"), labels = c("NoPulsar", "Pulsar"))
matrizConfusion <- table(test_set$TipoEstrella, pred_valid)
matrizConfusion
## pred_valid
## NoPulsar Pulsar
## NoPulsar 4047 18
## Pulsar 80 330

Tenemos 4377 predicciones correctas, y 98 incorrectas, lo que representa una precisión de predicción de 97.8% y un error de predicción del 2.2%.

Haciendo uso del paquete ROCR podemos graficar la curva ROC, la cual nos da una idea de la calidad del modelo a partir de las relaciones entre Falsos Positivos (False Positives) y Verdaderos Positivos (True Positives) obtenidos sobre el conjunto de validación:

library(ROCR)
pred1 <- prediction(as.numeric(pred_valid), as.numeric(test_set$TipoEstrella))
perf1 <- performance(pred1, "tpr", "fpr")
plot(perf1)

Como podemos ver, la línea resultante está bastante alejada de la diagonal que, para este tipo de curvas, representa la selección completamente al azar de las clases, lo que refleja entonces un buen desempeño del clasificador para este conjunto de datos. A fin de comparar este con los demás clasificadores a implementar, nos basaremos en el estudio de los resultados de clasificación con el conjunto de validación, así como la curva ROC.

k — Vecinos Cercanos (k-NN Classifier)

La clasificación por k vecinos cercanos o k-NN es un modelo de clasificación que basa su entrenamiento en el cálculo de las distancias de un nuevo dato o dato al que se desee asignar a una clase, con la mayoría de clases a las que pertenezcan sus k vecinos más cercanos, siendo k un parámetro del algoritmo.

Para construir el clasificador k-NN vamos a hacer uso de la función knn del paquete class, y tomaremos como valor de k = 10:

library(class)
set.seed(1234)
pred_valid_knn <- knn(training_set[, -9],
test_set[, -9],
cl = training_set[, 9],
k = 10)

Y una vez contamos con las predicciones para el conjunto de validación, podemos crear nuestra matriz de confusión:

matrizConfusion <- table(test_set$TipoEstrella, pred_valid_knn)
matrizConfusion
## pred_valid_knn
## NoPulsar Pulsar
## NoPulsar 4041 24
## Pulsar 83 327

Lo que nos arroja una precisión de predicción de 97.61% y un error de predicción de 2.39% para el conjunto de validación.

Si generamos la curva ROC para este caso, obtenemos:

Lo que demuestra del mismo modo un buen desempeño en la clasificación de los tipos de estrella para el modelo k-NN.

Máquina de Soporte Vectorial con Kernel (Kernel SVM Classifier)

Las Máquinas de Vectores de Soporte son modelos capaces de generar clasificaciones o regresiones de datos no lineales a partir de la transformación de los datos de entrada a otros espacios de mayores dimensiones. En el caso de la clasificación, la SVM busca encontrar aquella curva que sea capaz de separar y clasificar los datos de entrenamiento garantizando que la separación entre ésta y ciertas observaciones del conjunto de entrenamiento (los vectores de soporte) sea la mayor posible. Para entender mejor el concepto, recomiendo echarle un ojo al video Support Vector Machine (SVM) — Fun and Easy Machine Learning. Por su parte, la aplicación de Kernels a los SVM consiste en valerse de funciones especiales que, de hecho, son los que llevan los datos de entrada a dimensiones superiores en donde existe separabilidad lineal y, por lo tanto, solución al problema de clasificación.

En R, vamos a implementar la clasificación SVM haciendo uso de la función svm del paquete e1071:

library(e1071)
set.seed(1234)
clasificadorSVM <- svm(TipoEstrella ~ ., data = training_set,
type = 'C-classification', kernel = 'radial')

En este caso, los parámetros C-classification y radial hacen referencia al tipo de clasificador que se construye, y que el Kernel empleado es radial o Gaussiano.

La predicción sobre los valores del conjunto de validación será entonces:

pred_valid_svm <- predict(clasificadorSVM, newdata = test_set)

Lo que produce la siguiente matriz de confusión:

matrizConfusion <- table(test_set$TipoEstrella, pred_valid_svm)
matrizConfusion
## pred_valid_svm
## NoPulsar Pulsar
## NoPulsar 4045 20
## Pulsar 82 328

Tenemos entonces una precisión de predicción del 97.72% y un error de predicción del 2.27%. La curva ROC será:

library(ROCR)
pred1 <- prediction(as.numeric(pred_valid_svm), as.numeric(test_set$TipoEstrella))
perf1 <- performance(pred1, "tpr", "fpr")
plot(perf1)

Esto mejora los valores obtenidos en el caso del clasificador k-NN.

Clasificador Bayesiano Ingenuo (Naive Bayes Classifier)

Este modelo es un clasificador fundamentalmente probabilístico y basado en el Teorema de Bayes. Se le dice ingenuo porque parte de la presunción de que todas las variables predictoras del modelo tienen total independencia lineal, cosa que de entrada puede no ser siempre cierto. Para más detalles del modelo, se recomienda este link.

Para nuestra práctica, implementaremos el Clasificador Bayesiano haciendo uso de la función naiveBayes del paquete e1071:

library(e1071)
set.seed(1234)
clasificadorBayes <- naiveBayes(TipoEstrella ~ ., data = training_set)

Con predicciones sobre el conjunto de validación:

pred_valid_bayes <- predict(clasificadorBayes, newdata = test_set)

La matriz de confusión vendrá dada por:

matrizConfusion <- table(test_set$TipoEstrella, pred_valid_bayes)
matrizConfusion
## pred_valid_bayes
## NoPulsar Pulsar
## NoPulsar 3881 184
## Pulsar 73 337

Lo que nos genera una precisión de predicción del 94.25% y un error de predicción del 5.74%

Por su parte, la curva ROC será:

pred1 <- prediction(as.numeric(pred_valid_bayes), as.numeric(test_set$TipoEstrella))
perf1 <- performance(pred1, "tpr", "fpr")
plot(perf1)

Podemos ver que, en este caso, los resultados de clasificación a nivel de precisión y error son peores que los anteriores, pero la curva ROC está más elevada hacia el caso ideal, lo que nos puede hablar de que, para este clasificador, se obtiene una mejor relación entre predicciones correctas y los Falsos Positivos y Negativos, lo que podría sugerir que este clasificador tiene mayor capacidad de generalización que los anteriores (es decir, no sufra de sobre entrenamiento o sub entrenamiento).

Clasificación con Árbol de Decisión (Decision Tree Classifier)

Los Árboles de Decisión son modelos de predicción que pueden usarse tanto para clasificación como para regresión, y cuyo funcionamiento se basa en la construcción de reglas lógicas (divisiones de los datos entre rangos o condiciones) a partir de los datos de entrada.

El entrenamiento de los árboles de decisión se centra principalmente en la maximización de la ganancia de información al momento de realizar las reglas lógicas que forman el árbol.

En nuestro ejercicio, usaremos la función rpart del paquete rpart para crear el árbol de decisión:

library(rpart)
set.seed(1234)
clasificadorDT <- rpart(TipoEstrella ~ ., data = training_set)

Lo que generará como predicciones sobre el conjunto de validación:

pred_valid_DT <- predict(clasificadorDT, newdata = test_set, type = 'class')

Con matriz de confusión:

matrizConfusion <- table(test_set$TipoEstrella, pred_valid_DT)
matrizConfusion
## pred_valid_DT
## NoPulsar Pulsar
## NoPulsar 4037 28
## Pulsar 84 326

Lográndose un 97.49% de precisión en la predicción, y 2.50% de error en la predicción.

Para la curva ROC tendremos:

pred1 <- prediction(as.numeric(pred_valid_DT), as.numeric(test_set$TipoEstrella))
perf1 <- performance(pred1, "tpr", "fpr")
plot(perf1)

Produciendo como resultado una curva ROC que, de nuevo, demuestra el buen desempeño del clasificador para este conjunto de datos.

Clasificador con Bosques Aleatorios (Random Forests Classifier)

La clasificación con Bosques Aleatorios o Random Forests, implica la construcción al azar de una gran cantidad de árboles de decisión sobre un mismo conjunto de datos, y la decisión final de la clasificación es tomada a partir de calcular el voto de la mayoría de las predicciones ofrecidas por cada uno de los árboles que conforman el bosque.

Para implementar el Random Forest sobre nuestros datos se empleará la función randomForest del paquete randomForest:

library(randomForest)
set.seed(1234)
clasificadorRF <- randomForest(TipoEstrella ~ ., data = training_set, ntree = 250)

En este caso, el parámetro ntree hace referencia a la cantidad de árboles de decisión que formarán parte del bosque.

Una vez construido el bosque, podemos realizar las predicciones sobre el conjunto de validación:

pred_valid_RF <- predict(clasificadorRF, newdata = test_set)

Con una matriz de confusión:

matrizConfusion <- table(test_set$TipoEstrella, pred_valid_RF)
matrizConfusion
## pred_valid_RF
## NoPulsar Pulsar
## NoPulsar 4046 19
## Pulsar 73 337

Obteniéndose una precisión de predicción del 97.94% y un error de predicción del 2.05%.

Como curva ROC obtenemos:

pred1 <- prediction(as.numeric(pred_valid_RF), as.numeric(test_set$TipoEstrella))
perf1 <- performance(pred1, "tpr", "fpr")
plot(perf1)

Para este clasificador, obtenemos también no solo altos valores en la precisión de la predicción, sino una curva ROC que se acerca más al caso ideal según lo conocido de las curvas ROC.

Conclusiones

Tras observar los resultados, podemos realizar una tabla que resuma las precisiones de predicción y el error para los distintos modelos:

Si consideramos solo estos valores, podríamos asegurar que el Random Forest es el modelo que mejor resultado ofrece en la clasificación de los tipos de estrellas del conjunto de datos de validación. Sin embargo, durante la práctica se observó que tanto éste como el Naive Bayes ofrecen curvas ROC que se separan más del caso aleatorio, a diferencia de los demás modelos que, si bien tienen presiciones altas, es posible que puedan sufrir de sub o sobre entrenamiento. Por supuesto, la determinación del mejor modelo debe pasar por otra serie de técnicas y métricas que, como se comentó en la introducción, no se tocarán en esta práctica, pero que deben tenerse en cuenta para mejorar el desempeño de los modelos y obtener el más adecuado.

En este sentido, es importante en cualquier estudio de modelos de clasificación el considerar tanto los valores de precisión y error sobre los datos de validación, como la relación o peso entre Falsos y Verdaderos Negativos, pues dependiendo del problema, en ocasiones será conveniente sacrificar precisión en la predicción y dar pesos a alguno de los casos de Falsos Positivos o Negativos a efectos de producir un modelo con mayor capacidad de generalización.

Así, concluimos esta práctica introductoria a los Modelos de Clasificación en R.

--

--

Ronald Delgado
Ciencia y Datos

Físico Computacional, Data Scientist, Escritor, Gamer, Geek y Papá de Aidan.