Классификация k-ближайших соседей.

Выполним классификацию k-ближайших соседей с использованием функции knn() из пакета class на наборе данных iris. Проведем нормализацию данных, разделим выборку на обучающую и тестовую. Оценим построенную модель с использованием функции CrossTable() из пакета gmodels. Построим матрицу ошибок и диагональную оценку качества прогноза.

Установка и загрузка пакетов

options(repos = c(CRAN = "https://cran.rstudio.com/"))
install.packages(c("class", "gmodels"))
## Устанавливаю пакеты в 'C:/Users/Olekander/AppData/Local/R/win-library/4.5'
## (потому что 'lib' не определено)
## пакет 'class' успешно распакован, MD5-суммы проверены
## Warning: не могу удалить прежнюю установку пакета 'class'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): проблема с копированием
## C:\Users\Olekander\AppData\Local\R\win-library\4.5\00LOCK\class\libs\x64\class.dll
## в C:\Users\Olekander\AppData\Local\R\win-library\4.5\class\libs\x64\class.dll:
## Permission denied
## Warning: восстановлен 'class'
## пакет 'gmodels' успешно распакован, MD5-суммы проверены
## 
## Скачанные бинарные пакеты находятся в
##  D:\temp\RtmpCcbaEF\downloaded_packages
library(class)
## Warning: пакет 'class' был собран под R версии 4.5.3
library(gmodels)
## Warning: пакет 'gmodels' был собран под R версии 4.5.3

Загрузка данных iris

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

Нормализация числовых признаков

scale01 <- function(v) {
  rng <- range(v)
  (v - rng[1]) / (rng[2] - rng[1])
}

iris_mm <- iris
iris_mm[1:4] <- lapply(iris_mm[1:4], scale01)
head(iris_mm)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1   0.22222222   0.6250000   0.06779661  0.04166667  setosa
## 2   0.16666667   0.4166667   0.06779661  0.04166667  setosa
## 3   0.11111111   0.5000000   0.05084746  0.04166667  setosa
## 4   0.08333333   0.4583333   0.08474576  0.04166667  setosa
## 5   0.19444444   0.6666667   0.06779661  0.04166667  setosa
## 6   0.30555556   0.7916667   0.11864407  0.12500000  setosa

Формирование обучающей и тестовой выборок

set.seed(42)
train_rows <- sample(seq_len(nrow(iris_mm)), size = floor(0.7 * nrow(iris_mm)))
learn_set <- iris_mm[train_rows, ]
check_set <- iris_mm[-train_rows, ]

Подготовка признаков и классов

learn_x <- learn_set[, 1:4]
learn_y <- learn_set$Species
check_x <- check_set[, 1:4]
check_y <- check_set$Species

Построение модели k-NN

knn_result <- knn(train = learn_x, test = check_x, cl = learn_y, k = 5)

Перекрестная таблица фактических и прогнозных значений

CrossTable(x = check_y,
           y = knn_result,
           dnn = c("Факт", "Прогноз"),
           prop.chisq = FALSE,
           prop.c = FALSE,
           prop.r = FALSE,
           prop.t = FALSE)
## 
##  
##    Cell Contents
## |-------------------------|
## |                       N |
## |-------------------------|
## 
##  
## Total Observations in Table:  45 
## 
##  
##              | Прогноз 
##         Факт |     setosa | versicolor |  virginica |  Row Total | 
## -------------|------------|------------|------------|------------|
##       setosa |         12 |          0 |          0 |         12 | 
## -------------|------------|------------|------------|------------|
##   versicolor |          0 |         15 |          0 |         15 | 
## -------------|------------|------------|------------|------------|
##    virginica |          0 |          1 |         17 |         18 | 
## -------------|------------|------------|------------|------------|
## Column Total |         12 |         16 |         17 |         45 | 
## -------------|------------|------------|------------|------------|
## 
## 

Матрица ошибок

knn_table <- table(Факт = check_y, Прогноз = knn_result)
knn_table
##             Прогноз
## Факт     setosa versicolor virginica
##   setosa         12          0         0
##   versicolor      0         15         0
##   virginica       0          1        17

Диагональная оценка качества прогноза

diag_quality_knn <- sum(diag(knn_table)) / sum(knn_table)
round(diag_quality_knn * 100, 2)
## [1] 97.78

Полученная модель k-ближайших соседей показала высокое качество классификации. Наибольшее число верных ответов расположено на диагонали матрицы ошибок, что свидетельствует о корректном распознавании видов ириса.

Реализация метода опорных векторов.

Рассмотрим пример реализации метода опорных векторов с использованием функции svm() из пакета e1071. Построим линейный классификатор для прогнозирования. Для подбора параметров модели выполним перекрестную проверку с делением исходной выборки на 10 равных частей.

Установка и загрузка пакета

install.packages("e1071")
## Устанавливаю пакет в 'C:/Users/Olekander/AppData/Local/R/win-library/4.5'
## (потому что 'lib' не определено)
## пакет 'e1071' успешно распакован, MD5-суммы проверены
## Warning: не могу удалить прежнюю установку пакета 'e1071'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): проблема с копированием
## C:\Users\Olekander\AppData\Local\R\win-library\4.5\00LOCK\e1071\libs\x64\e1071.dll
## в C:\Users\Olekander\AppData\Local\R\win-library\4.5\e1071\libs\x64\e1071.dll:
## Permission denied
## Warning: восстановлен 'e1071'
## 
## Скачанные бинарные пакеты находятся в
##  D:\temp\RtmpCcbaEF\downloaded_packages
library(e1071)
## Warning: пакет 'e1071' был собран под R версии 4.5.3

Загрузка данных iris

data("iris")
summary(iris)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  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  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 

Разделение выборки на обучающую и контрольную части

set.seed(101)
svm_rows <- sample(seq_len(nrow(iris)), size = floor(0.7 * nrow(iris)))
svm_train <- iris[svm_rows, ]
svm_test <- iris[-svm_rows, ]

Подбор параметра cost методом перекрестной проверки

svm_tune <- tune.svm(
  Species ~ .,
  data = svm_train,
  kernel = "linear",
  cost = c(0.25, 0.5, 1, 2, 4, 8),
  tunecontrol = tune.control(cross = 10)
)

summary(svm_tune)
## 
## Parameter tuning of 'svm':
## 
## - sampling method: 10-fold cross validation 
## 
## - best parameters:
##  cost
##     1
## 
## - best performance: 0.01 
## 
## - Detailed performance results:
##   cost      error dispersion
## 1 0.25 0.03727273 0.06448923
## 2 0.50 0.02818182 0.04544444
## 3 1.00 0.01000000 0.03162278
## 4 2.00 0.01909091 0.04030417
## 5 4.00 0.01909091 0.04030417
## 6 8.00 0.01909091 0.04030417

Лучшая линейная модель

svm_best <- svm_tune$best.model
svm_best
## 
## Call:
## best.svm(x = Species ~ ., data = svm_train, cost = c(0.25, 0.5, 1, 
##     2, 4, 8), kernel = "linear", tunecontrol = tune.control(cross = 10))
## 
## 
## Parameters:
##    SVM-Type:  C-classification 
##  SVM-Kernel:  linear 
##        cost:  1 
## 
## Number of Support Vectors:  24

Прогноз на контрольной выборке

svm_forecast <- predict(svm_best, newdata = svm_test)

Матрица ошибок

svm_table <- table(Факт = svm_test$Species, Прогноз = svm_forecast)
svm_table
##             Прогноз
## Факт     setosa versicolor virginica
##   setosa         17          0         0
##   versicolor      0         13         2
##   virginica       0          2        11

Точность линейного классификатора

svm_accuracy <- mean(svm_forecast == svm_test$Species)
round(svm_accuracy * 100, 2)
## [1] 91.11

Линейный классификатор SVM после подбора параметра cost с помощью 10-кратной перекрестной проверки показал высокую точность на контрольной выборке. Это подтверждает пригодность метода для распознавания объектов набора iris.

Расчет главных компонент.

Выполним расчет главных компонент с использованием пакета vegan() и его функции rda(). Построим ординационную диаграмму методом PCA и сделаем выводы.

Установка и загрузка пакета

install.packages("vegan")
## Устанавливаю пакет в 'C:/Users/Olekander/AppData/Local/R/win-library/4.5'
## (потому что 'lib' не определено)
## пакет 'vegan' успешно распакован, MD5-суммы проверены
## Warning: не могу удалить прежнюю установку пакета 'vegan'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): проблема с копированием
## C:\Users\Olekander\AppData\Local\R\win-library\4.5\00LOCK\vegan\libs\x64\vegan.dll
## в C:\Users\Olekander\AppData\Local\R\win-library\4.5\vegan\libs\x64\vegan.dll:
## Permission denied
## Warning: восстановлен 'vegan'
## 
## Скачанные бинарные пакеты находятся в
##  D:\temp\RtmpCcbaEF\downloaded_packages
library(vegan)
## Warning: пакет 'vegan' был собран под R версии 4.5.3
## Загрузка требуемого пакета: permute
## Warning: пакет 'permute' был собран под R версии 4.5.3

Загрузка данных iris

data("iris")
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa

Подготовка числовых признаков для PCA

iris_num <- subset(iris, select = -Species)

Выполнение анализа главных компонент

iris_pca <- rda(iris_num, scale = TRUE)
iris_pca
## 
## Call: rda(X = iris_num, scale = TRUE)
## 
##               Inertia Rank
## Total               4     
## Unconstrained       4    4
## 
## Inertia is correlations
## 
## Eigenvalues for unconstrained axes:
##    PC1    PC2    PC3    PC4 
## 2.9185 0.9140 0.1468 0.0207

Сводка по главным компонентам

summary(iris_pca)
## 
## Call:
## rda(X = iris_num, scale = TRUE) 
## 
## Partitioning of correlations:
##               Inertia Proportion
## Total               4          1
## Unconstrained       4          1
## 
## Eigenvalues, and their contribution to the correlations 
## 
## Importance of components:
##                          PC1    PC2     PC3      PC4
## Eigenvalue            2.9185 0.9140 0.14676 0.020715
## Proportion Explained  0.7296 0.2285 0.03669 0.005179
## Cumulative Proportion 0.7296 0.9581 0.99482 1.000000

Построение ординационной диаграммы

plot(iris_pca, type = "n", scaling = 2, main = "PCA для набора iris")
points(iris_pca, display = "sites", scaling = 2, col = as.numeric(iris$Species), pch = 19)
text(iris_pca, display = "species", scaling = 2, col = 1:4)
legend("topright", legend = levels(iris$Species), col = 1:3, pch = 19, cex = 0.8)

Доли объясненной дисперсии

pca_share <- eigenvals(iris_pca)
round(100 * pca_share / sum(pca_share), 2)
##   PC1   PC2   PC3   PC4 
## 72.96 22.85  3.67  0.52

По результатам анализа главных компонент основная доля изменчивости описывается первыми двумя компонентами, что позволяет использовать их для наглядного представления структуры данных. На ординационной диаграмме видно четкое отделение вида setosa, тогда как versicolor и virginica находятся ближе друг к другу. Наибольшее влияние на разделение объектов оказывают признаки, связанные с длиной и шириной лепестка.