1. Introducción

En este proyecto vamos a trabajar con el conocido dataset de iris para clasificar la variación morfológica de la flor Iris de tres especies relacionadas. Más información

2. Lectura del dataset.

library(ISLR)
library(ggplot2)
## Registered S3 methods overwritten by 'ggplot2':
##   method         from 
##   [.quosures     rlang
##   c.quosures     rlang
##   print.quosures rlang
library(caTools)
library(class)
df <- iris
str(df)
## '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 ...

Las columnas tienen asignada perfectamente su clase. Comprobamos si hay algún NA.

any(is.na(df))
## [1] FALSE

3. Visualización del dataset

Vamos a generar algunas gráficas para introducir más fácilmente el problema.

ggplot(df, aes(Sepal.Width, Sepal.Length)) + geom_point(aes(col=Species))

ggplot(df, aes(Petal.Width, Petal.Length)) + geom_point(aes(col=Species))

ggplot(df, aes(y=Petal.Width)) + geom_boxplot(aes(col=Species))

ggplot(df, aes(y=Petal.Length)) + geom_boxplot(aes(col=Species))

ggplot(df, aes(y=Sepal.Width)) + geom_boxplot(aes(col=Species))

ggplot(df, aes(y=Sepal.Length)) + geom_boxplot(aes(col=Species))

Podemos observar en estas últimas 3 gráficas la existencia de outliers.

3. Escalado de los datos

Vamos a tomar las columnas numéricas y vamos a escalar los datos para poder aplicar posteriormente el método de los K Nearest Neighbors.

df.numeric <- df[,1:4]
specie <- df[,5]
df.scaled <- data.frame(scale(df.numeric))
sapply(df.scaled, var)
## Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
##            1            1            1            1
sapply(df.scaled, mean)
##  Sepal.Length   Sepal.Width  Petal.Length   Petal.Width 
## -4.484318e-16  2.034094e-16 -2.895326e-17 -3.663049e-17

Efectivamente, el dataset ya está escalado.

4. Creación del train y test dataset y modelización.

Tomamos el 70% del dataset para entrenar y el 30% restante para testear.

df.final <-  cbind(df.scaled, specie)
sample <- sample.split(df.final$specie, SplitRatio = .70)
train.data <- subset(df.final, sample==TRUE) 
test.data <- subset(df.final, sample==FALSE)

Aplicamos el método de K Nearest Neighbors.

predicted.species <- knn(train.data[1:4], test.data[1:4], train.data[,5], k=1)
head(predicted.species)
## [1] setosa setosa setosa setosa setosa setosa
## Levels: setosa versicolor virginica

Calculamos el error del modelo sobre el test data.

error <- mean(test.data$specie!=predicted.species)
error
## [1] 0.08888889

Veamos cómo evoluciona el error con el aumento de k

k <- 1:10
error <- NULL
predicted.species <- NULL
for (i in k){
  predicted.species <- knn(train.data[1:4], test.data[1:4], train.data[,5], k=i)
  error[i] <- mean(test.data$specie!=predicted.species)
}
error
##  [1] 0.08888889 0.08888889 0.08888889 0.11111111 0.08888889 0.11111111
##  [7] 0.11111111 0.08888889 0.08888889 0.08888889
data.error <- data.frame(k, error)
ggplot(data.error, aes(k, error)) + geom_point() + geom_line(lty='dotted',col='red') + scale_x_continuous(breaks=seq(0,10, by=1)) + theme_bw()

Como podemos observar, no obtenemos una función decreciente como veíamos en el ejemplo de las Caravanas. Esto es debido a que el dataset es muy pequeño y puede llegar a variar bastante. En este caso, para k=4 observarmos que el error es el mínimo para llevar a cabo la clasificación.

predicted.species <- knn(train.data[1:4], test.data[1:4], train.data[,5], k=4)
cbind(test.data, predicted.species)
##     Sepal.Length Sepal.Width Petal.Length   Petal.Width     specie
## 12   -1.25996379  0.78617383  -1.22245633 -1.3110521482     setosa
## 17   -0.53538397  1.93331463  -1.39239929 -1.0486667950     setosa
## 20   -0.89767388  1.70388647  -1.27910398 -1.1798594716     setosa
## 22   -0.89767388  1.47445831  -1.27910398 -1.0486667950     setosa
## 23   -1.50149039  1.24503015  -1.56234224 -1.3110521482     setosa
## 28   -0.77691058  1.01560199  -1.27910398 -1.3110521482     setosa
## 30   -1.38072709  0.32731751  -1.22245633 -1.3110521482     setosa
## 31   -1.25996379  0.09788935  -1.22245633 -1.3110521482     setosa
## 32   -0.53538397  0.78617383  -1.27910398 -1.0486667950     setosa
## 34   -0.41462067  2.62159911  -1.33575163 -1.3110521482     setosa
## 36   -1.01843718  0.32731751  -1.44904694 -1.3110521482     setosa
## 38   -1.13920048  1.24503015  -1.33575163 -1.4422448248     setosa
## 41   -1.01843718  1.01560199  -1.39239929 -1.1798594716     setosa
## 44   -1.01843718  1.01560199  -1.22245633 -0.7862814418     setosa
## 47   -0.89767388  1.70388647  -1.22245633 -1.3110521482     setosa
## 58   -1.13920048 -1.50810778  -0.25944625 -0.2615107354 versicolor
## 61   -1.01843718 -2.42582042  -0.14615094 -0.2615107354 versicolor
## 63    0.18919584 -1.96696410   0.13708732 -0.2615107354 versicolor
## 64    0.30995914 -0.36096697   0.53362088  0.2632599711 versicolor
## 65   -0.29385737 -0.36096697  -0.08950329  0.1320672944 versicolor
## 67   -0.29385737 -0.13153881   0.42032558  0.3944526477 versicolor
## 73    0.55148575 -1.27867961   0.64691619  0.3944526477 versicolor
## 78    1.03453895 -0.13153881   0.70356384  0.6568380009 versicolor
## 83   -0.05233076 -0.81982329   0.08043967  0.0008746178 versicolor
## 84    0.18919584 -0.81982329   0.76021149  0.5256453243 versicolor
## 90   -0.41462067 -1.27867961   0.13708732  0.1320672944 versicolor
## 91   -0.41462067 -1.04925145   0.36367793  0.0008746178 versicolor
## 94   -1.01843718 -1.73753594  -0.25944625 -0.2615107354 versicolor
## 96   -0.17309407 -0.13153881   0.25038262  0.0008746178 versicolor
## 100  -0.17309407 -0.59039513   0.19373497  0.1320672944 versicolor
## 104   0.55148575 -0.36096697   1.04344975  0.7880306775  virginica
## 105   0.79301235 -0.13153881   1.15674505  1.3128013839  virginica
## 107  -1.13920048 -1.27867961   0.42032558  0.6568380009  virginica
## 114  -0.17309407 -1.27867961   0.70356384  1.0504160307  virginica
## 117   0.79301235 -0.13153881   0.98680210  0.7880306775  virginica
## 118   2.24217198  1.70388647   1.66657392  1.3128013839  virginica
## 120   0.18919584 -1.96696410   0.70356384  0.3944526477  virginica
## 122  -0.29385737 -0.59039513   0.64691619  1.0504160307  virginica
## 123   2.24217198 -0.59039513   1.66657392  1.0504160307  virginica
## 125   1.03453895  0.55674567   1.10009740  1.1816087073  virginica
## 129   0.67224905 -0.59039513   1.04344975  1.1816087073  virginica
## 130   1.63835547 -0.13153881   1.15674505  0.5256453243  virginica
## 139   0.18919584 -0.13153881   0.59026853  0.7880306775  virginica
## 145   1.03453895  0.55674567   1.10009740  1.7063794137  virginica
## 146   1.03453895 -0.13153881   0.81685914  1.4439940605  virginica
##     predicted.species
## 12             setosa
## 17             setosa
## 20             setosa
## 22             setosa
## 23             setosa
## 28             setosa
## 30             setosa
## 31             setosa
## 32             setosa
## 34             setosa
## 36             setosa
## 38             setosa
## 41             setosa
## 44             setosa
## 47             setosa
## 58         versicolor
## 61         versicolor
## 63         versicolor
## 64         versicolor
## 65         versicolor
## 67         versicolor
## 73          virginica
## 78          virginica
## 83         versicolor
## 84          virginica
## 90         versicolor
## 91         versicolor
## 94         versicolor
## 96         versicolor
## 100        versicolor
## 104         virginica
## 105         virginica
## 107        versicolor
## 114         virginica
## 117         virginica
## 118         virginica
## 120        versicolor
## 122         virginica
## 123         virginica
## 125         virginica
## 129         virginica
## 130         virginica
## 139         virginica
## 145         virginica
## 146         virginica