.
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.
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.
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
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 ...
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 ...
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])
Entrenamiento del clasificador KNN y predicción
library(class)
test_pred <- knn(
train = train_scaled,
test = test_scaled,
cl = train$Species,
k=10
)
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
Calculemos por ejemplo un indicador de “accuracy”
accuracy <- sum(diag(cm))/length(actual)
sprintf("Accuracy: %.2f%%", accuracy*100)
## [1] "Accuracy: 91.11%"
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, ]
Procesamiento de los datos (escalar los datos)
preProcValues <- preProcess(trainX, method = c("center", "scale"))
trainTransformed <- predict(preProcValues, trainX)
testTransformed <- predict(preProcValues, testX)
Ajuste del Modelo
knnModel <- train(
Species ~ .,
data = trainTransformed,
method = "knn",
trControl = trainControl(method = "cv"),
tuneGrid = data.frame(k = c(3,5,7))
)
Entrenar el mejor modelo
best_model<- knn3(
Species ~ .,
data = trainTransformed,
k = knnModel$bestTune$k
)
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
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.
Aquí tienes un resumen de las desventajas del algoritmo KNN en 7 ítems:
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 ...
library(caret)
set.seed(123)
trainIndexAID <- createDataPartition(Aids2$status,
times=1,
p = .7,
list = FALSE)
trainS <- Aids2[trainIndexAID, ]
testS <- Aids2[-trainIndexAID, ]
preProcValues <- preProcess(trainS, method = c("center", "scale"))
trainTransformed <- predict(preProcValues, trainS)
testTransformed <- predict(preProcValues, testS)
Ajuste del Modelo
knnModel <- train(
status ~ diag + age,
data = trainTransformed,
method = "knn",
trControl = trainControl(method = "cv"),
tuneGrid = data.frame(k = c(3,5,7))
)
Entrenar el mejor modelo
best_modelS<- knn3(
status ~ diag + age,
data = trainTransformed,
k = knnModel$bestTune$k
)
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
##
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)