K vecinos más próximos (K-nearest neighbors algorithm)

Contexto

.Pagina de Descarga1

K-nearest neighbors algorithm (1)

Los algoritmos de clasificacion: Son unas de las tares que más frecuentemente son llevadas a cabo por los denominados Sistemas Inteligentes.

Es un método no paramétrico usado para clasificación y regresión, la idea básica es que un nuevo caso se va a clasificar según la clase que tengan sus K - Vecinos más cercanos. Es un concepto simple , intuitivo y fácil de implementar por eso es un método de uso común.

K-nearest neighbors algorithm (2)

El algoritmo KNN predice las etiquetas del conjunto de datos de prueba observando las etiquetas de sus vecinos más cercanos en el espacio de características del conjunto de datos de entrenamiento. La “K” es el hiperparámetro más importante que se puede ajustar para optimizar el rendimiento del modelo.

Primer Ejemplo (1)

Para ejemplificar su uso vamos a usar un data set que se encuentra en R y que resulta muy apropiado para ver el funcionamiento de modelos de clasificación en general, el dataset Iris

Explorar en que consiste este Data Set

Primer Ejemplo (2)

Cargamos el DataSet

datos<-iris
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

Primer Ejemplo (3)

Mediante un muestreo aleatorio definimos una tabla de aprendizaje para el modelo y una tabla de pruebas para verificar su calidad predictiva

#install.packages('caTools')
library(caTools)
set.seed(123)
split = sample.split(datos$Species, SplitRatio = 0.7)
train = subset(datos, split == TRUE)
test = subset(datos, split == FALSE)
str(train)
## 'data.frame':    105 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.7 5.4 4.6 4.4 4.9 4.8 4.8 4.3 5.8 ...
##  $ Sepal.Width : num  3.5 3.2 3.9 3.4 2.9 3.1 3.4 3 3 4 ...
##  $ Petal.Length: num  1.4 1.3 1.7 1.4 1.4 1.5 1.6 1.4 1.1 1.2 ...
##  $ Petal.Width : num  0.2 0.2 0.4 0.3 0.2 0.1 0.2 0.1 0.1 0.2 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
str(test)
## 'data.frame':    45 obs. of  5 variables:
##  $ Sepal.Length: num  4.9 4.6 5 5 5.4 5.7 5.1 5.4 5.1 5 ...
##  $ Sepal.Width : num  3 3.1 3.6 3.4 3.7 4.4 3.8 3.4 3.3 3 ...
##  $ Petal.Length: num  1.4 1.5 1.4 1.5 1.5 1.5 1.5 1.7 1.7 1.6 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.5 0.2 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

Primer Ejemplo (4)

Escalado de características Ahora escalaremos tanto el conjunto de entrenamiento como el de prueba. En la parte posterior, la función usa (x - mean(x)) / sd(x). Solo estamos escalando funciones y eliminando etiquetas de destino tanto de los conjuntos de prueba como de entrenamiento.

train_scaled = scale(train [-5])
test_scaled = scale(test[-5])

Primer Ejemplo (5)

Entrenamiento del clasificador KNN y predicción

library(class)
test_pred <- knn(
                 train  = train_scaled, 
                 test = test_scaled,
                 cl = train$Species, 
                 k=10
                 )

Primer Ejemplo (6)

Evaluación del Modelo

actual <- test$Species
cm <- table(actual,test_pred)
cm
##             test_pred
## actual       setosa versicolor virginica
##   setosa         15          0         0
##   versicolor      0         13         2
##   virginica       0          2        13

Primer Ejemplo (7)

Calculemos por ejemplo un indicador de “accuracy”

accuracy <- sum(diag(cm))/length(actual)
sprintf("Accuracy: %.2f%%", accuracy*100)
## [1] "Accuracy: 91.11%"

Primer Ejemplo (8)

Ahora mismo ejemplo, con una libreria conocidad como CARET

División de entrenamiento y prueba

library(caret)
## Loading required package: ggplot2
## Loading required package: lattice
set.seed(123)
trainIndex <- createDataPartition(datos$Specie, 
                                  times=1, 
                                  p = .7, 
                                  list = FALSE)
trainX <- datos[trainIndex, ]
testX <- datos[-trainIndex, ]

Primer Ejemplo (9)

Procesamiento de los datos (escalar los datos)

preProcValues <- preProcess(trainX, method = c("center", "scale"))
trainTransformed <- predict(preProcValues, trainX)
testTransformed <- predict(preProcValues, testX)

Primer Ejemplo (10)

Ajuste del Modelo

knnModel <- train(
             Species ~ ., 
             data = trainTransformed, 
           method = "knn", 
             trControl = trainControl(method = "cv"), 
             tuneGrid = data.frame(k = c(3,5,7))
            )

Primer Ejemplo (11)

Entrenar el mejor modelo

best_model<- knn3(
                  Species ~ .,
                  data = trainTransformed,
                  k = knnModel$bestTune$k
                 )

Primer Ejemplo (12)

Evaluar el modelo

predictions <- predict(best_model, testTransformed,type = "class")
# Calculate confusion matrix
cm <- confusionMatrix(predictions, testTransformed$Species)
cm
## Confusion Matrix and Statistics
## 
##             Reference
## Prediction   setosa versicolor virginica
##   setosa         15          0         0
##   versicolor      0         14         3
##   virginica       0          1        12
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9111          
##                  95% CI : (0.7878, 0.9752)
##     No Information Rate : 0.3333          
##     P-Value [Acc > NIR] : 8.467e-16       
##                                           
##                   Kappa : 0.8667          
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: setosa Class: versicolor Class: virginica
## Sensitivity                 1.0000            0.9333           0.8000
## Specificity                 1.0000            0.9000           0.9667
## Pos Pred Value              1.0000            0.8235           0.9231
## Neg Pred Value              1.0000            0.9643           0.9062
## Prevalence                  0.3333            0.3333           0.3333
## Detection Rate              0.3333            0.3111           0.2667
## Detection Prevalence        0.3333            0.3778           0.2889
## Balanced Accuracy           1.0000            0.9167           0.8833

Ventajas de Modelo KNN

Simplicidad: Es un algoritmo fácil de entender e implementar.

Versatilidad: Puede ser utilizado tanto para tareas de regresión como de clasificación.

Interpretabilidad: Proporciona resultados que pueden ser visualizados e interpretados, ya que la clase predicha se basa en las etiquetas de los vecinos más cercanos en los datos de entrenamiento.

Flexibilidad: No hace suposiciones sobre el límite de decisión entre las clases, lo que le permite capturar relaciones no lineales entre características.

Amplitud: No hace suposiciones sobre la distribución de los datos, lo que lo hace adecuado para una amplia gama de problemas.

Almacenamiento: No construye el modelo. Almacena los datos de entrenamiento y los utiliza para la predicción.

Desventajas de Modelo KNN

Aquí tienes un resumen de las desventajas del algoritmo KNN en 7 ítems:

  1. Costoso: Es computacionalmente costoso y requiere mucha memoria para conjuntos de datos grandes y complejos.
  2. Desbalance: Su rendimiento disminuye con datos desbalanceados. Muestra sesgos hacia la clase mayoritaria, lo que puede resultar en un rendimiento deficiente para las clases minoritarias.
  3. Ruido: No es adecuado para datos ruidosos. Los vecinos más cercanos de un punto de datos pueden no ser representativos de la verdadera etiqueta de clase.
  4. Alta dimensionalidad: No es adecuado para datos de alta dimensionalidad, ya que la alta dimensionalidad puede hacer que la distancia entre todos los puntos de datos se vuelva similar.
  5. Optimización: Encontrar el número óptimo de vecinos K puede ser un proceso que consume mucho tiempo.
  6. Sensibilidad a outliers: Es sensible a los valores atípicos, ya que elige vecinos basándose en la métrica de evidencia.
  7. Valores faltantes: No es bueno manejando valores faltantes en el conjunto de datos de entrenamiento.

Segundo Ejemplo (1)

Vamos a usar una nueva base de datos (AID) (Saben en que consiste?)

library(MASS)
data("Aids2")
str(Aids2)
## 'data.frame':    2843 obs. of  7 variables:
##  $ state  : Factor w/ 4 levels "NSW","Other",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ sex    : Factor w/ 2 levels "F","M": 2 2 2 2 2 2 2 2 2 2 ...
##  $ diag   : int  10905 11029 9551 9577 10015 9971 10746 10042 10464 10439 ...
##  $ death  : int  11081 11096 9983 9654 10290 10344 11135 11069 10956 10873 ...
##  $ status : Factor w/ 2 levels "A","D": 2 2 2 2 2 2 2 2 2 2 ...
##  $ T.categ: Factor w/ 8 levels "hs","hsid","id",..: 1 1 1 5 1 1 8 1 1 2 ...
##  $ age    : int  35 53 42 44 39 36 36 31 26 27 ...

Segundo Ejemplo (2)

library(caret)
set.seed(123)
trainIndexAID <- createDataPartition(Aids2$status, 
                                  times=1, 
                                  p = .7, 
                                  list = FALSE)
trainS <- Aids2[trainIndexAID, ]
testS <- Aids2[-trainIndexAID, ]

Segundo Ejemplo (3)

preProcValues <- preProcess(trainS, method = c("center", "scale"))
trainTransformed <- predict(preProcValues, trainS)
testTransformed <- predict(preProcValues, testS)

Segundo Ejemplo (4)

Ajuste del Modelo

knnModel <- train(
             status ~ diag + age, 
             data = trainTransformed, 
           method = "knn", 
             trControl = trainControl(method = "cv"), 
             tuneGrid = data.frame(k = c(3,5,7))
            )

Segundo Ejemplo (5)

Entrenar el mejor modelo

best_modelS<- knn3(
                  status ~ diag + age,
                  data = trainTransformed,
                  k = knnModel$bestTune$k
                 )

Segundo Ejemplo (6)

Evaluar el modelo

predictions <- predict(best_modelS, testTransformed,type = "class")
# Calculate confusion matrix
cm <- confusionMatrix(predictions, testTransformed$status)
cm
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction   A   D
##          A 206  67
##          D 118 461
##                                           
##                Accuracy : 0.7829          
##                  95% CI : (0.7536, 0.8101)
##     No Information Rate : 0.6197          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.5249          
##                                           
##  Mcnemar's Test P-Value : 0.0002369       
##                                           
##             Sensitivity : 0.6358          
##             Specificity : 0.8731          
##          Pos Pred Value : 0.7546          
##          Neg Pred Value : 0.7962          
##              Prevalence : 0.3803          
##          Detection Rate : 0.2418          
##    Detection Prevalence : 0.3204          
##       Balanced Accuracy : 0.7545          
##                                           
##        'Positive' Class : A               
## 

Segundo Ejemplo (7)

Curva Roc y AUC

library(pROC)
## Type 'citation("pROC")' for a citation.
## 
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
prob_pred <- predict(best_modelS, newdata = testTransformed, type = "prob")
roc_obj <- roc(testTransformed$status, prob_pred[,2])
## Setting levels: control = A, case = D
## Setting direction: controls < cases
auc(roc_obj)
## Area under the curve: 0.8151
plot(roc_obj, print.auc=TRUE)