Está en la página 1de 5

Tema 3 - LAZY LEARNING.

CLASIFICACIÓN USANDO NEAREST


NEIGHBORS

Resumen
El algoritmo kNN (k nearest neighbors por sus siglas en inglés, k vecinos más cercanos)
es un clasificador basado en el algoritmo nearest neighbors. Dichos clasificadores
agrupan las observaciones según sus variables (características), del mismo modo que
una persona podría agrupar alimentos según sus características (grado dulzura, grado
picante, color, etc).
Al observar un nuevo elemento, podremos predecir si corresponde a una clase u otra
según la distancia de la nueva observación con los demás. En particular, la decisión
que adoptará el algoritmo será la de agrupar la nueva observación dentro de la clase
del elemento/s más cercano/s.
El concepto de kNN implica asignar un valor entero k al algoritmo nn. Dicho valor se
usará para valorar las k observaciones más cercanas a la nueva observación.
Una vez obtenemos todas las observaciones más cercanas, clasificaremos la nueva
observación según una votación, teniendo en cuanta la cantidad de observaciones de
una clase determinada.
Por ejemplo, en un clasificador 3-NN, si la nueva observación tiene como los 3
elementos más cercanos las clases fruta, hortaliza, fruta, el algoritmo clasificará la
nueva observación como fruta.
Las fortalezas y debilidades que tiene el algoritmo kNN se presentan resumidas en la
siguiente tabla:

Fortalezas Debilidades
Simple y efectivo No se genera ningún modelo, lo que limita la
capacidad para entender cómo están
relacionadas las características de una clase
No estable supuestos sobre la Es necesario establecer a priori un valor para k.
distribución de los datos
La fase de entrenamiento es rápida. La fase de clasificación suele ser lenta.
Las características de tipo nominal y la falta de
observaciones requieren un tratamiento
adicional.
Librerías Usadas en R
Las librerías que se usan para este clasificador son:
• caret: usado para realizar una matriz de confusión y ver los resultados de las
predicciones contra las clases reales. Puede encontrarse toda la información
sobre esta librería en la web:
https://www.rdocumentation.org/packages/caret/versions/6.0-86
• class: contiene las funciones de kNN. La documentación de esta librería está
disponible en https://www.rdocumentation.org/packages/class/versions/7.3-
17.

if (!require(class)) install.packages('class', dependencies = T)

if (!require(caret)) install.packages('caret', dependencies = T)

Ejemplo: Clasificación de Flores Iris


Para el ejemplo usaremos el dataset iris, instalado por defecto en la librería de R.
Cargaremos el dataset con la función data() y veremos un resumen de las
características del dataset con la función str():
data(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 ...

El dataset iris está compuesto por 150 observaciones y 5 variables, de las cuales 4 son
variables numéricas (Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) y 1
cualitativa (Species).
Nuestro objetivo será predecir la variante a la que pertenece una flor iris (virginica,
setosa y versicolor) según sus características.
El primer paso a realizar será hacer un estudio numérico de las variables con la
función summary():
summary(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100 setosa :50
1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300 versicolor:50
Median :5.800 Median :3.000 Median :4.350 Median :1.300 virginica :50
Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500

Como podemos observar las variables numéricas no tienen el mismo rango de valores.
Algunas variables contienen valores entre el 4.3 y el 7.9 (como es el caso del
Petal.Width) y otras entre el 0.1 y el 2.5 (como el Petal.Length).
Esta distribución de los valores de las variables podría provocar que una variable
irrelevante con un rango de valores muy elevado tuviese un impacto demasiado
elevado sobre la modelización del problema, minimizando el impacto de variables
más relevantes pero con un rango menor.
Por dicho motivo, antes de seguir debemos normalizar estos valores, de manera que
todas las variables tengan el mismo rango. Para solventarlo, crearemos una función de
normalización llamada min-max usando la siguiente función.
iris_norm <- as.data.frame(apply(iris[, 1:4], 2, function(x) (x -
min(x))/(max(x)-min(x))))

iris_norm$Species <- iris$Species

Una vez aplicada la transformación todas las variables se encontraran entre 0 y 1.


summary(iris_norm)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species

Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.00000 setosa :50
1st Qu.:0.2222 1st Qu.:0.3333 1st Qu.:0.1017 1st Qu.:0.08333 versicolor:50
Median :0.4167 Median :0.4167 Median :0.5678 Median :0.50000 virginica :50
Mean :0.4287 Mean :0.4406 Mean :0.4675 Mean :0.45806
3rd Qu.:0.5833 3rd Qu.:0.5417 3rd Qu.:0.6949 3rd Qu.:0.70833
Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.00000
Entrenamiento del modelo
Una vez tenemos los datos normalizados, los separaremos en dos datasets distintos.
Un dataset lo usaremos para entrenar el modelo de kNN y el otro para validar el
modelo mediante una predicción de la clase y compararlo con la clase real.
Para empezar, definiremos una semilla aleatoria a fin de separar al azar los datasets.
Seguidamente crearemos un conjunto de entrenamiento con el 80% de la muestra,
dejando el 20% restante para validar los resultados:
set.seed(12345)

size <- floor(0.80 * nrow(iris_norm))

idx <- sample(seq_len(nrow(iris_norm)), size = size)

iris_train <- iris_norm[idx, ]


iris_test <- iris_norm[-idx, ]

Con los datos normalizados y separados en los datasets de entrenamiento y


validación, llamaremos a la función kNN() de la librería class. Dicha función tiene como
parámetros:
• train: dataset de entreno sin la variable categórica
• test: dataset de pruebas sin la variable categórica
• cl: listado de clasificaciones de los datos de test
• k: número de vecinos a tener en cuenta

El valor de k viene determinado por 𝑘𝑘 = √𝑁𝑁º 𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂𝑂 𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸𝐸.


Calculamos el valor del parámetro mediante:
k = sqrt(nrow(iris_train))

Una vez determinado el valor de k iniciamos el entrenamiento del modelo:

iris_prediction <- knn(


train = iris_train[1:4],
test = iris_test[1:4],
cl = iris_train[,ncol(iris_train)],
k = k )
Predicción del modelo
Una vez obtenido el modelo, podemos contrastar con el dataset de validación su
porcentaje de acierto. En nuestro ejemplo, podemos ver que el modelo tiene una
buena capacidad predictiva, acertando en el 93.33% de sus predicciones.
confusionMatrix(iris_test[,ncol(iris_test)], iris_prediction)

Confusion Matrix and Statistics

Reference
Prediction setosa versicolor virginica
setosa 10 0 0
versicolor 0 10 0
virginica 0 2 8

Overall Statistics

Accuracy : 0.9333
95% CI : (0.7793, 0.9918)
No Information Rate : 0.4
P-Value [Acc > NIR] : 1.181e-09

Kappa : 0.9

Mcnemar's Test P-Value : NA

Statistics by Class:

Class: setosa Class: versicolor Class: virginica


Sensitivity 1.0000 0.8333 1.0000
Specificity 1.0000 1.0000 0.9091
Pos Pred Value 1.0000 1.0000 0.8000
Neg Pred Value 1.0000 0.9000 1.0000
Prevalence 0.3333 0.4000 0.2667
Detection Rate 0.3333 0.3333 0.2667
Detection Prevalence 0.3333 0.3333 0.3333
Balanced Accuracy 1.0000 0.9167 0.9545

También podría gustarte