Цель работы:
Изучить методы классификации и анализа данных на примере набора данных
iris. В работе рассматриваются:
1. K-ближайших соседей (k-NN)
2. Метод опорных векторов (SVM)
3. Метод главных компонент (PCA) через vegan::rda()
В качестве исходных данных используется стандартный набор
iris. Для корректной работы алгоритмов классификации
проведена нормализация числовых признаков.
# Указываем зеркало CRAN для установки пакетов
options(repos = c(CRAN = "https://cloud.r-project.org"))
# Если нужно — автоматически устанавливаем пакеты
packages <- c("class", "gmodels", "e1071", "vegan")
for (pkg in packages) {
if (!require(pkg, character.only = TRUE)) install.packages(pkg)
}
library(class)
library(gmodels)
library(e1071)
library(vegan)
# Загрузка данных
data(iris)
# Нормализация числовых признаков
normalize <- function(x) (x - min(x)) / (max(x) - min(x))
iris_norm <- as.data.frame(lapply(iris[,1:4], normalize))
iris_norm$Species <- iris$Species
# Разделение выборки на обучающую (70%) и тестовую (30%)
set.seed(123)
train_idx <- sample(1:nrow(iris_norm), 0.7 * nrow(iris_norm))
train_data <- iris_norm[train_idx, ]
test_data <- iris_norm[-train_idx, ]
train_X <- train_data[,1:4]
train_y <- train_data$Species
test_X <- test_data[,1:4]
test_y <- test_data$Species
# Нормализация нужна для k-NN, чтобы признаки с разной шкалой
# не смещали расстояния между объектами
Используется алгоритм knn() из пакета
class. Для оценки точности классификации применяется
CrossTable() из gmodels и построение матрицы
ошибок.
# k-NN классификация с k = 3
knn_pred <- knn(train = train_X, test = test_X, cl = train_y, k = 3)
# Матрица ошибок и CrossTable
CrossTable(test_y, knn_pred, prop.chisq = FALSE)
##
##
## Cell Contents
## |-------------------------|
## | N |
## | N / Row Total |
## | N / Col Total |
## | N / Table Total |
## |-------------------------|
##
##
## Total Observations in Table: 45
##
##
## | knn_pred
## test_y | setosa | versicolor | virginica | Row Total |
## -------------|------------|------------|------------|------------|
## setosa | 14 | 0 | 0 | 14 |
## | 1.000 | 0.000 | 0.000 | 0.311 |
## | 1.000 | 0.000 | 0.000 | |
## | 0.311 | 0.000 | 0.000 | |
## -------------|------------|------------|------------|------------|
## versicolor | 0 | 17 | 1 | 18 |
## | 0.000 | 0.944 | 0.056 | 0.400 |
## | 0.000 | 0.944 | 0.077 | |
## | 0.000 | 0.378 | 0.022 | |
## -------------|------------|------------|------------|------------|
## virginica | 0 | 1 | 12 | 13 |
## | 0.000 | 0.077 | 0.923 | 0.289 |
## | 0.000 | 0.056 | 0.923 | |
## | 0.000 | 0.022 | 0.267 | |
## -------------|------------|------------|------------|------------|
## Column Total | 14 | 18 | 13 | 45 |
## | 0.311 | 0.400 | 0.289 | |
## -------------|------------|------------|------------|------------|
##
##
# Классическая матрица ошибок
conf_matrix <- table(test_y, knn_pred)
conf_matrix
## knn_pred
## test_y setosa versicolor virginica
## setosa 14 0 0
## versicolor 0 17 1
## virginica 0 1 12
# Диагональная оценка качества (accuracy)
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)
round(accuracy * 100, 2)
## [1] 95.56
Диагональная оценка качества (accuracy) показывает долю правильно классифицированных объектов по сравнению с общим числом наблюдений.
Вывод:
Алгоритм k-NN показал высокую точность **95.56%**, ошибки встречаются
редко между versicolor и virginica.
Для демонстрации строится линейный SVM на двухклассовом подмножестве
(setosa и versicolor). Используется 10-кратная
перекрестная проверка.
# Двухклассовый набор данных
iris_binary <- iris[iris$Species != "virginica", ]
iris_binary$Species <- factor(iris_binary$Species)
X <- iris_binary[,1:4]
y <- iris_binary$Species
# SVM с линейным ядром и 10-кратной перекрестной проверкой
svm_model <- svm(Species ~ ., data = iris_binary, kernel = "linear", cost = 1, cross = 10)
summary(svm_model)
##
## Call:
## svm(formula = Species ~ ., data = iris_binary, kernel = "linear",
## cost = 1, cross = 10)
##
##
## Parameters:
## SVM-Type: C-classification
## SVM-Kernel: linear
## cost: 1
##
## Number of Support Vectors: 4
##
## ( 2 2 )
##
##
## Number of Classes: 2
##
## Levels:
## setosa versicolor
##
## 10-fold cross-validation on training data:
##
## Total Accuracy: 100
## Single Accuracies:
## 100 100 100 100 100 100 100 100 100 100
# Предсказание и точность
svm_pred <- predict(svm_model, X)
conf_matrix_svm <- table(True = y, Predicted = svm_pred)
conf_matrix_svm
## Predicted
## True setosa versicolor
## setosa 50 0
## versicolor 0 50
accuracy_svm <- sum(diag(conf_matrix_svm)) / sum(conf_matrix_svm)
round(accuracy_svm * 100, 2)
## [1] 100
Перекрестная проверка (cross=10) оценивает устойчивость модели и помогает избежать переобучения. Для учебного примера использован линейный SVM для двух классов.
Вывод:
Линейный SVM идеально классифицирует два класса: точность 100%.
Для анализа структуры данных выполняется PCA с помощью функции
rda() из пакета vegan.
iris_features <- iris[,1:4]
# PCA
pca_result <- rda(iris_features, scale = TRUE)
summary(pca_result)
##
## Call:
## rda(X = iris_features, 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
# Biplot
biplot(pca_result, scaling = "species", main = "PCA для Iris")
# Доля объясненной дисперсии
prop_var <- pca_result$CA$eig / sum(pca_result$CA$eig)
round(prop_var * 100, 2)
## PC1 PC2 PC3 PC4
## 72.96 22.85 3.67 0.52
Две первые главные компоненты покрывают 95.81% дисперсии, что позволяет визуально отделить виды iris на плоскости PC1–PC2. Biplot можно раскрасить по видам для лучшей наглядности.
Вывод:
- PC1 объясняет 72.96% дисперсии
- PC2 объясняет 22.85%
- Две первые компоненты покрывают почти всю информацию (95.81%)
- Biplot наглядно показывает группировку видов iris