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
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
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.
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.
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