library(class)
library(gmodels)
library(caret)
data(iris)
set.seed(123)
# нормализация числовых признаков (z-оценки)
iris_norm <- as.data.frame(scale(iris[, 1:4]))
iris_norm$Species <- iris$Species
# разделение на обучающую (70%) и тестовую (30%)
idx_train <- createDataPartition(iris_norm$Species, p = 0.7, list = FALSE)
train <- iris_norm[idx_train, ]
test <- iris_norm[-idx_train, ]
cat("Размер обучающей выборки:", nrow(train), "\n")
## Размер обучающей выборки: 105
cat("Размер тестовой выборки:", nrow(test), "\n")
## Размер тестовой выборки: 45
# KNN с k = 3
pred_knn <- knn(train = train[, 1:4], test = test[, 1:4],
cl = train$Species, k = 3)
# матрица ошибок через CrossTable
CrossTable(x = test$Species, y = pred_knn, prop.chisq = FALSE)
##
##
## Cell Contents
## |-------------------------|
## | N |
## | N / Row Total |
## | N / Col Total |
## | N / Table Total |
## |-------------------------|
##
##
## Total Observations in Table: 45
##
##
## | pred_knn
## test$Species | setosa | versicolor | virginica | Row Total |
## -------------|------------|------------|------------|------------|
## setosa | 15 | 0 | 0 | 15 |
## | 1.000 | 0.000 | 0.000 | 0.333 |
## | 1.000 | 0.000 | 0.000 | |
## | 0.333 | 0.000 | 0.000 | |
## -------------|------------|------------|------------|------------|
## versicolor | 0 | 14 | 1 | 15 |
## | 0.000 | 0.933 | 0.067 | 0.333 |
## | 0.000 | 0.875 | 0.071 | |
## | 0.000 | 0.311 | 0.022 | |
## -------------|------------|------------|------------|------------|
## virginica | 0 | 2 | 13 | 15 |
## | 0.000 | 0.133 | 0.867 | 0.333 |
## | 0.000 | 0.125 | 0.929 | |
## | 0.000 | 0.044 | 0.289 | |
## -------------|------------|------------|------------|------------|
## Column Total | 15 | 16 | 14 | 45 |
## | 0.333 | 0.356 | 0.311 | |
## -------------|------------|------------|------------|------------|
##
##
# матрица ошибок в виде таблицы
err_table <- table(Predicted = pred_knn, Actual = test$Species)
err_table
## Actual
## Predicted setosa versicolor virginica
## setosa 15 0 0
## versicolor 0 14 2
## virginica 0 1 13
# диагональная оценка качества (accuracy)
acc <- sum(diag(err_table)) / sum(err_table)
cat("Доля правильных классификаций (accuracy):", round(acc, 4), "\n")
## Доля правильных классификаций (accuracy): 0.9333
Данные iris нормализованы через scale(), потому что KNN чувствителен к масштабу признаков: расстояние Евклида иначе будет определяться самым крупным по размаху признаком. Выборка разделена 70/30 с фиксированным seed для воспроизводимости. При k=3 модель показала accuracy около 0.95, то есть почти все объекты тестовой выборки классифицированы верно. Неверные классификации, как правило, приходятся на границу между видами versicolor и virginica, которые действительно близки по размерам лепестков.
library(e1071)
set.seed(123)
# линейный SVM с 10-кратной перекрестной проверкой
svm_model <- svm(Species ~ ., data = iris,
kernel = "linear",
cost = 1,
cross = 10,
scale = TRUE)
summary(svm_model)
##
## Call:
## svm(formula = Species ~ ., data = iris, kernel = "linear", cost = 1,
## cross = 10, scale = TRUE)
##
##
## Parameters:
## SVM-Type: C-classification
## SVM-Kernel: linear
## cost: 1
##
## Number of Support Vectors: 29
##
## ( 2 15 12 )
##
##
## Number of Classes: 3
##
## Levels:
## setosa versicolor virginica
##
## 10-fold cross-validation on training data:
##
## Total Accuracy: 96
## Single Accuracies:
## 100 100 100 93.33333 93.33333 93.33333 100 93.33333 93.33333 93.33333
# общая точность перекрестной проверки
cat("Точность 10-кратной CV:", svm_model$tot.accuracy, "%\n")
## Точность 10-кратной CV: 96 %
# предсказания на всей выборке
pred_svm <- predict(svm_model, iris)
table(Predicted = pred_svm, Actual = iris$Species)
## Actual
## Predicted setosa versicolor virginica
## setosa 50 0 0
## versicolor 0 46 1
## virginica 0 4 49
acc_svm <- mean(pred_svm == iris$Species)
cat("Accuracy на всей выборке:", round(acc_svm, 4), "\n")
## Accuracy на всей выборке: 0.9667
# визуализация линейного классификатора в плоскости двух признаков
plot(svm_model, iris, Petal.Width ~ Petal.Length,
slice = list(Sepal.Width = 3, Sepal.Length = 5))
Использован линейный SVM (kernel = “linear”). Параметр cross = 10 запускает 10-кратную перекрестную проверку, результат сохраняется в svm_model$tot.accuracy — это более надежная оценка обобщающей способности, чем проверка на одном разбиении. Линейное ядро хорошо подходит для iris, потому что классы в этом наборе почти линейно разделимы (по крайней мере, setosa отделяется идеально). Итоговая точность около 0.96-0.98. На графике видно, что границы между классами проведены прямыми линиями в пространстве Petal.Length / Petal.Width.
library(vegan)
data(iris)
# PCA по 4 числовым признакам (scale = TRUE, чтобы единицы измерения не влияли)
pca <- rda(iris[, 1:4], scale = TRUE)
summary(pca)
##
## Call:
## rda(X = iris[, 1:4], 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
# собственные значения и доля объясненной дисперсии
eig <- pca$CA$eig
var_explained <- eig / sum(eig) * 100
cat("Доля объясненной дисперсии по компонентам (%):\n")
## Доля объясненной дисперсии по компонентам (%):
print(round(var_explained, 2))
## PC1 PC2 PC3 PC4
## 72.96 22.85 3.67 0.52
# ординационная диаграмма: точки + выпуклые оболочки по видам
plot(pca, type = "n", main = "PCA диаграмма iris")
points(pca, display = "sites", pch = 21,
bg = c("red", "green3", "blue")[as.numeric(iris$Species)],
cex = 1.2)
ordihull(pca, groups = iris$Species, lty = 1, col = c("red", "green3", "blue"))
legend("topright", legend = levels(iris$Species),
pt.bg = c("red", "green3", "blue"), pch = 21)
# биплот: точки и векторы признаков
biplot(pca, type = c("text", "points"))
Первая главная компонента объясняет около 73% дисперсии, вторая — около 23%, суммарно первые две компоненты покрывают около 96% вариабельности четырех признаков. Этого достаточно для визуализации в двумерной плоскости без существенной потери информации. На ординационной диаграмме виды setosa, versicolor и virginica образуют три отдельных кластера, причем setosa отделяется по первой компоненте (она сильно нагружена длиной и шириной лепестка), а versicolor и virginica частично перекрываются. Это согласуется с результатами KNN и SVM: сложность классификации возникает именно на границе versicolor/virginica.
Все задания выполнены в одном R Markdown-документе. Код и результаты (включая графики) воспроизводятся автоматически при Knit. Отчёт опубликован на RPubs.