Данная лабораторная работа посвящена изучению базовых инструментов анализа данных в языке R.
В работе используются пакеты caret,
FSelector, arules, Boruta и
mlbench.
Основные задачи работы:
caret и доступными в нем
методами;Boruta;Перед выполнением отчета необходимые пакеты нужно один раз установить в консоли RStudio:
install.packages("recipes")
install.packages("caret", dependencies = TRUE)
install.packages("FSelector")
install.packages("arules")
install.packages("Boruta")
install.packages("mlbench")
Установить пакет caret, выполнить команду
names(getModelInfo()), ознакомиться со списком доступных
методов выбора признаков.
Выполнить графический разведочный анализ данных с использованием
функции featurePlot() для набора данных:
x <- matrix(rnorm(50 * 5), ncol = 5)
y <- factor(rep(c("A", "B"), 25))
Сохранить полученные графики в формате .jpg.
library(caret)
Пакет caret содержит большое количество методов
машинного обучения.
Команда getModelInfo() возвращает информацию о доступных
моделях, а names() выводит их названия.
models <- names(getModelInfo())
head(models, 20)
## [1] "ada" "AdaBag" "AdaBoost.M1" "adaboost" "amdai"
## [6] "ANFIS" "avNNet" "awnb" "awtan" "bag"
## [11] "bagEarth" "bagEarthGCV" "bagFDA" "bagFDAGCV" "bam"
## [16] "bartMachine" "bayesglm" "binda" "blackboost" "blasso"
Создадим исходные данные для анализа.
set.seed(123)
x <- matrix(rnorm(50 * 5), ncol = 5)
y <- factor(rep(c("A", "B"), 25))
dim(x)
## [1] 50 5
head(y)
## [1] A B A B A B
## Levels: A B
Матрица x содержит 50 наблюдений и 5 признаков.
Переменная y содержит два класса: A и
B.
График box показывает распределение значений признаков
по классам.
С его помощью можно увидеть медиану, разброс значений и возможные
выбросы.
featurePlot(
x = x,
y = y,
plot = "box",
main = "Box plot: распределение признаков по классам"
)
Сохраним график в файл .jpg.
jpeg("featurePlot_box.jpg", width = 1200, height = 900)
featurePlot(
x = x,
y = y,
plot = "box",
main = "Box plot: распределение признаков по классам"
)
dev.off()
## png
## 2
График density показывает плотность распределения
признаков для разных классов.
Если кривые классов сильно отличаются, значит признак может быть полезен
для классификации.
featurePlot(
x = x,
y = y,
plot = "density",
main = "Density plot: распределение признаков по классам",
auto.key = list(columns = 2)
)
Сохраним график в файл .jpg.
jpeg("featurePlot_density.jpg", width = 1200, height = 900)
featurePlot(
x = x,
y = y,
plot = "density",
main = "Density plot: распределение признаков по классам",
auto.key = list(columns = 2)
)
dev.off()
## png
## 2
График pairs показывает попарные зависимости между
признаками.
Он помогает увидеть возможные связи между переменными и визуальное
разделение классов.
featurePlot(
x = x,
y = y,
plot = "pairs",
main = "Pairs plot: попарные зависимости признаков",
auto.key = list(columns = 2)
)
Сохраним график в файл .jpg.
jpeg("featurePlot_pairs.jpg", width = 1200, height = 900)
featurePlot(
x = x,
y = y,
plot = "pairs",
main = "Pairs plot: попарные зависимости признаков",
auto.key = list(columns = 2)
)
dev.off()
## png
## 2
В первом задании был использован пакет caret. С помощью
команды names(getModelInfo()) был получен список доступных
методов машинного обучения.
Функция featurePlot() позволила построить три вида
графиков:
box;density;pairs.Так как данные были сгенерированы случайно, четкого разделения между
классами A и B не наблюдается. На графиках
видно, что распределения классов в основном перекрываются. Это означает,
что случайные признаки плохо подходят для разделения классов.
С использованием функций из пакета FSelector определить
важность признаков для решения задачи классификации.
Использовать набор данных iris.
library(FSelector)
Загрузим встроенный набор данных 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
Набор данных iris содержит измерения цветков ириса:
Sepal.Length — длина чашелистика;Sepal.Width — ширина чашелистика;Petal.Length — длина лепестка;Petal.Width — ширина лепестка;Species — вид ириса.Целевая переменная — Species.
Для оценки важности признаков используем функцию
information.gain().
weights <- information.gain(Species ~ ., data = iris)
weights
## attr_importance
## Sepal.Length 0.4521286
## Sepal.Width 0.2672750
## Petal.Length 0.9402853
## Petal.Width 0.9554360
Отсортируем признаки по убыванию важности.
weights_sorted <- weights[
order(-weights$attr_importance),
,
drop = FALSE
]
weights_sorted
## attr_importance
## Petal.Width 0.9554360
## Petal.Length 0.9402853
## Sepal.Length 0.4521286
## Sepal.Width 0.2672750
Функция information.gain() показывает, насколько каждый
признак полезен для определения класса.
По результатам видно, что самыми важными признаками являются:
Petal.Width;Petal.Length.Эти признаки имеют наибольшие значения важности. Это означает, что ширина и длина лепестка лучше всего помогают определить вид ириса.
Наименьшую важность имеет признак Sepal.Width.
Следовательно, ширина чашелистика хуже всего помогает при
классификации.
С использованием функции discretize() из пакета
arules выполнить преобразование непрерывной переменной в
категориальную различными методами:
interval — равная ширина интервала;frequency — равная частота;cluster — кластеризация;fixed — категории задают границы интервалов.Использовать набор данных iris.
library(arules)
В качестве переменной для дискретизации возьмем
Sepal.Length.
summary(iris$Sepal.Length)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.300 5.100 5.800 5.843 6.400 7.900
Переменная Sepal.Length является числовой.
Задача дискретизации состоит в том, чтобы преобразовать числовые
значения в интервальные категории.
Метод interval делит весь диапазон значений на интервалы
одинаковой ширины.
disc_interval <- discretize(
iris$Sepal.Length,
method = "interval",
breaks = 4
)
table(disc_interval)
## disc_interval
## [4.3,5.2) [5.2,6.1) [6.1,7) [7,7.9]
## 41 48 48 13
Метод frequency делит данные так, чтобы в каждом
интервале было примерно одинаковое количество объектов.
disc_frequency <- discretize(
iris$Sepal.Length,
method = "frequency",
breaks = 4
)
table(disc_frequency)
## disc_frequency
## [4.3,5.1) [5.1,5.8) [5.8,6.4) [6.4,7.9]
## 32 41 35 42
Метод cluster выполняет разбиение с учетом структуры
данных.
Интервалы формируются на основе группировки близких значений.
disc_cluster <- discretize(
iris$Sepal.Length,
method = "cluster",
breaks = 4
)
table(disc_cluster)
## disc_cluster
## [4.3,4.89) [4.89,5.59) [5.59,6.49) [6.49,7.9]
## 16 43 56 35
Метод fixed использует границы, которые задаются
вручную.
disc_fixed <- discretize(
iris$Sepal.Length,
method = "fixed",
breaks = c(-Inf, 5, 6, 7, Inf)
)
table(disc_fixed)
## disc_fixed
## [-Inf,5) [5,6) [6,7) [7, Inf]
## 22 61 54 13
Соберем результаты дискретизации в одну таблицу.
discretization_result <- data.frame(
Sepal.Length = iris$Sepal.Length,
interval = disc_interval,
frequency = disc_frequency,
cluster = disc_cluster,
fixed = disc_fixed
)
head(discretization_result, 10)
## Sepal.Length interval frequency cluster fixed
## 1 5.1 [4.3,5.2) [5.1,5.8) [4.89,5.59) [5,6)
## 2 4.9 [4.3,5.2) [4.3,5.1) [4.89,5.59) [-Inf,5)
## 3 4.7 [4.3,5.2) [4.3,5.1) [4.3,4.89) [-Inf,5)
## 4 4.6 [4.3,5.2) [4.3,5.1) [4.3,4.89) [-Inf,5)
## 5 5.0 [4.3,5.2) [4.3,5.1) [4.89,5.59) [5,6)
## 6 5.4 [5.2,6.1) [5.1,5.8) [4.89,5.59) [5,6)
## 7 4.6 [4.3,5.2) [4.3,5.1) [4.3,4.89) [-Inf,5)
## 8 5.0 [4.3,5.2) [4.3,5.1) [4.89,5.59) [5,6)
## 9 4.4 [4.3,5.2) [4.3,5.1) [4.3,4.89) [-Inf,5)
## 10 4.9 [4.3,5.2) [4.3,5.1) [4.89,5.59) [-Inf,5)
В третьем задании была выполнена дискретизация переменной
Sepal.Length.
Метод interval делит диапазон значений на равные по
ширине интервалы. Этот метод простой, но количество объектов в группах
может быть разным.
Метод frequency формирует интервалы так, чтобы
количество объектов в группах было примерно одинаковым.
Метод cluster учитывает распределение данных и
группирует близкие значения.
Метод fixed позволяет самостоятельно задать границы
интервалов. Такой способ удобен, если заранее известно, какие диапазоны
нужно выделить.
Таким образом, одна и та же числовая переменная может быть преобразована в категориальную разными способами.
Установить пакет Boruta и провести выбор признаков для
набора данных Ozone.
Построить график boxplot и сделать выводы.
library(Boruta)
library(mlbench)
Загрузим набор данных Ozone.
data("Ozone")
str(Ozone)
## 'data.frame': 366 obs. of 13 variables:
## $ V1 : Factor w/ 12 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ V2 : Factor w/ 31 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
## $ V3 : Factor w/ 7 levels "1","2","3","4",..: 4 5 6 7 1 2 3 4 5 6 ...
## $ V4 : num 3 3 3 5 5 6 4 4 6 7 ...
## $ V5 : num 5480 5660 5710 5700 5760 5720 5790 5790 5700 5700 ...
## $ V6 : num 8 6 4 3 3 4 6 3 3 3 ...
## $ V7 : num 20 NA 28 37 51 69 19 25 73 59 ...
## $ V8 : num NA 38 40 45 54 35 45 55 41 44 ...
## $ V9 : num NA NA NA NA 45.3 ...
## $ V10: num 5000 NA 2693 590 1450 ...
## $ V11: num -15 -14 -25 -24 25 15 -33 -28 23 -2 ...
## $ V12: num 30.6 NA 47.7 55 57 ...
## $ V13: num 200 300 250 100 60 60 100 250 120 120 ...
В наборе данных есть пропущенные значения.
Для корректной работы алгоритма Boruta удалим строки с
NA.
Ozone_clean <- na.omit(Ozone)
cat("Количество строк до очистки:", nrow(Ozone), "\n")
## Количество строк до очистки: 366
cat("Количество строк после очистки:", nrow(Ozone_clean), "\n")
## Количество строк после очистки: 203
Запустим алгоритм Boruta.
set.seed(123)
boruta_output <- Boruta(
V4 ~ .,
data = Ozone_clean,
doTrace = 0
)
boruta_output
## Boruta performed 18 iterations in 1.016538 secs.
## 9 attributes confirmed important: V1, V10, V11, V12, V13 and 4 more;
## 3 attributes confirmed unimportant: V2, V3, V6;
В данном случае V4 используется как целевая переменная,
а остальные столбцы используются как признаки.
Построим график важности признаков.
plot(
boruta_output,
las = 2,
cex.axis = 0.7,
main = "Boruta: важность признаков"
)
Построим дополнительный график boxplot, чтобы посмотреть
распределение V4 по значениям признака V1.
boxplot(
Ozone_clean$V4 ~ Ozone_clean$V1,
main = "Boxplot V4 по значениям V1",
xlab = "V1",
ylab = "V4"
)
В четвертом задании был использован пакет Boruta.
Алгоритм Boruta предназначен для выбора важных
признаков. Он помогает определить, какие переменные действительно
полезны для объяснения целевой переменной.
Перед запуском алгоритма были удалены строки с пропущенными
значениями, потому что Boruta не работает с
NA.
В результате были получены признаки, которые алгоритм считает важными
или неважными. График Boruta показывает распределение важности
признаков. Дополнительный boxplot показывает, как целевая
переменная V4 распределяется по группам признака
V1.
Всю представленную работу собрать в единый файл RMarkdown. Опубликовать его на RPubs. В качестве отчета о лабораторной работе представить ссылку на полученный файл.
Данная работа оформлена в виде единого файла RMarkdown.
После нажатия кнопки Knit формируется HTML-документ,
содержащий:
Для публикации на RPubs необходимо:
Knit или Knit to HTML.Publish.RPubs.Формат RMarkdown удобен для оформления лабораторных работ, так как позволяет объединить теоретическое описание, код, результаты вычислений и графики в одном документе.
В ходе лабораторной работы были изучены основные способы анализа и выбора признаков в языке R.
С помощью пакета caret был выполнен графический
разведочный анализ данных.
С помощью пакета FSelector была определена важность
признаков для набора данных iris.
С помощью пакета arules была выполнена дискретизация
числовой переменной Sepal.Length.
С помощью пакета Boruta был проведен отбор признаков для
набора данных Ozone.
По результатам работы можно сделать вывод, что выбор и анализ признаков являются важными этапами подготовки данных. Они позволяют лучше понять структуру данных и определить, какие переменные наиболее полезны для дальнейшего анализа или построения моделей.