library(class)
library(FactoMineR)
## Warning: package 'FactoMineR' was built under R version 3.3.3
wine <- read.table( "http://gauss.inf.um.es/datos/wine.data", header = TRUE, sep = "," )
head(wine)
## cultivar alcohol malic ash alcalinity magnesium phenols flavonoids
## 1 1 14.23 1.71 2.43 15.6 127 2.80 3.06
## 2 1 13.20 1.78 2.14 11.2 100 2.65 2.76
## 3 1 13.16 2.36 2.67 18.6 101 2.80 3.24
## 4 1 14.37 1.95 2.50 16.8 113 3.85 3.49
## 5 1 13.24 2.59 2.87 21.0 118 2.80 2.69
## 6 1 14.20 1.76 2.45 15.2 112 3.27 3.39
## phenols_no_flavonoids proanthocyanins color_intensity hue OD280_OD315
## 1 0.28 2.29 5.64 1.04 3.92
## 2 0.26 1.28 4.38 1.05 3.40
## 3 0.30 2.81 5.68 1.03 3.17
## 4 0.24 2.18 7.80 0.86 3.45
## 5 0.39 1.82 4.32 1.04 2.93
## 6 0.34 1.97 6.75 1.05 2.85
## proline
## 1 1065
## 2 1050
## 3 1185
## 4 1480
## 5 735
## 6 1450
str(wine)
## 'data.frame': 178 obs. of 14 variables:
## $ cultivar : int 1 1 1 1 1 1 1 1 1 1 ...
## $ alcohol : num 14.2 13.2 13.2 14.4 13.2 ...
## $ malic : num 1.71 1.78 2.36 1.95 2.59 1.76 1.87 2.15 1.64 1.35 ...
## $ ash : num 2.43 2.14 2.67 2.5 2.87 2.45 2.45 2.61 2.17 2.27 ...
## $ alcalinity : num 15.6 11.2 18.6 16.8 21 15.2 14.6 17.6 14 16 ...
## $ magnesium : int 127 100 101 113 118 112 96 121 97 98 ...
## $ phenols : num 2.8 2.65 2.8 3.85 2.8 3.27 2.5 2.6 2.8 2.98 ...
## $ flavonoids : num 3.06 2.76 3.24 3.49 2.69 3.39 2.52 2.51 2.98 3.15 ...
## $ phenols_no_flavonoids: num 0.28 0.26 0.3 0.24 0.39 0.34 0.3 0.31 0.29 0.22 ...
## $ proanthocyanins : num 2.29 1.28 2.81 2.18 1.82 1.97 1.98 1.25 1.98 1.85 ...
## $ color_intensity : num 5.64 4.38 5.68 7.8 4.32 6.75 5.25 5.05 5.2 7.22 ...
## $ hue : num 1.04 1.05 1.03 0.86 1.04 1.05 1.02 1.06 1.08 1.01 ...
## $ OD280_OD315 : num 3.92 3.4 3.17 3.45 2.93 2.85 3.58 3.58 2.85 3.55 ...
## $ proline : int 1065 1050 1185 1480 735 1450 1290 1295 1045 1045 ...
wine$cultivar <- factor(wine$cultivar)
str(wine$cultivar)
## Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
wine.train <- wine[sample(c(1:178), 100), 1:14]
wine.test <- wine[sample(c(1:178), 50), 1:14]
wine.pred <- knn(train = wine.train[, 2:14], test = wine.test[ ,2:14], cl = wine.train[, 1], k = 3 )
prediction <- table(Predic = wine.pred, Test = wine.test[, 1])
prediction
## Test
## Predic 1 2 3
## 1 14 0 0
## 2 0 17 8
## 3 2 4 5
percentage_of_error <- function(numeric_matrix){
all_tested <- sum(numeric_matrix)
right_ones <- sum(diag(numeric_matrix))
return ((all_tested - right_ones) * 100 / all_tested)
}
percentage_of_error(prediction)
## [1] 28
wine_pca <- PCA(wine[, 2:14])
wine_dim <- wine_pca$ind$coord
wine_dim <- cbind(wine[, 1], wine_dim)
wine_dim.train <- wine_dim[sample(c(1:178), 100), 1:6]
wine_dim.test <- wine_dim[sample(c(1:178), 50), 1:6]
wine_dim.pred <- knn(train = wine_dim.train[, 2:6], test = wine_dim.test[, 2:6], cl = wine_dim.train[, 1], k = 3 )
prediction_pca <- table(Predic = wine_dim.pred, Test = wine_dim.test[, 1])
prediction_pca
## Test
## Predic 1 2 3
## 1 20 0 0
## 2 0 19 0
## 3 0 1 10
percentage_of_error(prediction_pca)
## [1] 2
El modelo KNN generado a partir de las componentes obtenidas del PCA es mucho mejor, apenas comete fallos.
Son necesarios 4 componentes para explicar en conjunto un 73.599 % de la varianza:
wine_pca$eig$`cumulative percentage of variance`
## [1] 36.19885 55.40634 66.52997 73.59900 80.16229 85.09812 89.33680
## [8] 92.01754 94.23970 96.16972 97.90655 99.20479 100.00000
“flavonoids”
wine_pca$var$contrib[, 1]
## alcohol malic ash
## 2.083097e+00 6.011695e+00 4.206853e-04
## alcalinity magnesium phenols
## 5.727426e+00 2.016174e+00 1.557572e+01
## flavonoids phenols_no_flavonoids proanthocyanins
## 1.788734e+01 8.912201e+00 9.823804e+00
## color_intensity hue OD280_OD315
## 7.852920e-01 8.803953e+00 1.415019e+01
## proline
## 8.222684e+00
max(wine_pca$var$contrib[, 1])
## [1] 17.88734
Tendrá un alto contenido en flavonoides, como puede verse en el mapa de variables factores o bien consultando las correlaciones para la dimensión 1, siendo en el caso de “flavonoids” de 0.917, muy cercana a 1.
PCA(wine[, 2:14])
## **Results for the Principal Component Analysis (PCA)**
## The analysis was performed on 178 individuals, described by 13 variables
## *The results are available in the following objects:
##
## name description
## 1 "$eig" "eigenvalues"
## 2 "$var" "results for the variables"
## 3 "$var$coord" "coord. for the variables"
## 4 "$var$cor" "correlations variables - dimensions"
## 5 "$var$cos2" "cos2 for the variables"
## 6 "$var$contrib" "contributions of the variables"
## 7 "$ind" "results for the individuals"
## 8 "$ind$coord" "coord. for the individuals"
## 9 "$ind$cos2" "cos2 for the individuals"
## 10 "$ind$contrib" "contributions of the individuals"
## 11 "$call" "summary statistics"
## 12 "$call$centre" "mean of the variables"
## 13 "$call$ecart.type" "standard error of the variables"
## 14 "$call$row.w" "weights for the individuals"
## 15 "$call$col.w" "weights for the variables"
wine_pca$var$cor[, 1]
## alcohol malic ash
## 0.313093350 -0.531884726 -0.004449362
## alcalinity magnesium phenols
## -0.519157081 0.308022936 0.856136658
## flavonoids phenols_no_flavonoids proanthocyanins
## 0.917470177 -0.647607018 0.679921705
## color_intensity hue OD280_OD315
## -0.192235968 0.643662066 0.816018903
## proline
## 0.622050797
Su alcalinidad será más baja que la media, puede visualizarse de forma análoga al apartado 4.
simulation_errors <- matrix(ncol=2, nrow = 20)
colnames(simulation_errors) <- c("Raw", "After PCA")
for(n in 1:20){
# Con los datos crudos
wine.train <- wine[sample(c(1:178), 100), 1:14]
wine.test <- wine[sample(c(1:178), 50), 1:14]
wine.pred <- knn(train = wine.train[, 2:14], test = wine.test[ ,2:14], cl = wine.train[, 1], k = 3 )
prediction <- table(Predic = wine.pred, Test = wine.test[, 1])
error_raw <- percentage_of_error(prediction)
# Con la matriz de datos de PCA
wine_dim.train <- wine_dim[sample(c(1:178), 100), 1:6]
wine_dim.test <- wine_dim[sample(c(1:178), 50), 1:6]
wine_dim.pred <- knn(train = wine_dim.train[, 2:6], test = wine_dim.test[, 2:6], cl = wine_dim.train[, 1], k = 3 )
prediction_pca <- table(Predic = wine_dim.pred, Test = wine_dim.test[, 1])
error_pca <- percentage_of_error(prediction_pca)
# Guardado de los porcentajes de error
simulation_errors[n, ] <- c(error_raw, error_pca)
}
simulation_errors
## Raw After PCA
## [1,] 12 4
## [2,] 28 4
## [3,] 20 0
## [4,] 28 2
## [5,] 18 10
## [6,] 30 2
## [7,] 24 2
## [8,] 20 6
## [9,] 24 6
## [10,] 22 2
## [11,] 22 6
## [12,] 18 6
## [13,] 16 0
## [14,] 28 6
## [15,] 22 2
## [16,] 12 4
## [17,] 24 2
## [18,] 28 4
## [19,] 20 0
## [20,] 12 4
summary(simulation_errors)
## Raw After PCA
## Min. :12.0 Min. : 0.0
## 1st Qu.:18.0 1st Qu.: 2.0
## Median :22.0 Median : 4.0
## Mean :21.4 Mean : 3.6
## 3rd Qu.:25.0 3rd Qu.: 6.0
## Max. :30.0 Max. :10.0
Creo que la simulación deja clara la supremacía del modelo KNN aplicado sobre la matriz de datos obtenida por PCA respecto al KNN aplicado sobre los datos crudos:
La mediana de fallos del modelo con datos crudos es del 21% (tiende a fallar 1 de cada 5 cultivares), mientras que la del generado a partir de la matriz de PCA es del 4% (tiende a fallar 1 de cada 25 cultivares, podría estimarse que es “5 veces mejor”).
El mínimo porcentaje de fallos cometido por el modelo de datos crudos y observado en la simulación es de un 10%, es decir, fallaría como mínimo en 5 cultivares de los 50 que le damos para testear.
El máximo porcentaje de fallos cometido por el modelo generado a partir de la matriz de datos de PCA es del 8%, inferior al mínimo observado para los datos crudos. Mientras que en ocasiones, el modelo generado a partir de PCA acierta todos los cultivares del test.