Данная лабораторная работа посвящена изучению базовых инструментов анализа данных в языке 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.019441 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: важность признаков"
)
В четвертом задании был использован пакет Boruta.
Алгоритм Boruta предназначен для выбора важных
признаков. Он помогает определить, какие переменные действительно
полезны для объяснения целевой переменной.
Перед запуском алгоритма были удалены строки с пропущенными
значениями, потому что Boruta не работает с
NA.
В результате были получены признаки, которые алгоритм считает важными или неважными. График Boruta показывает распределение важности признаков.
Всю представленную работу собрать в единый файл RMarkdown. Опубликовать его на RPubs. В качестве отчета о лабораторной работе представить ссылку на полученный файл.
Данная работа оформлена в виде единого файла RMarkdown.
После нажатия кнопки Knit формируется HTML-документ,
содержащий:
Для публикации на RPubs необходимо:
Knit или Knit to HTML.Publish.RPubs.Формат RMarkdown удобен для оформления лабораторных работ, так как позволяет объединить теоретическое описание, код, результаты вычислений и графики в одном документе.
В ходе лабораторной работы были изучены основные способы анализа и выбора признаков в языке R.
С помощью пакета caret был выполнен графический
разведочный анализ данных.
С помощью пакета FSelector была определена важность
признаков для набора данных iris.
С помощью пакета arules была выполнена дискретизация
числовой переменной Sepal.Length.
С помощью пакета Boruta был проведен отбор признаков для
набора данных Ozone.
По результатам работы можно сделать вывод, что выбор и анализ признаков являются важными этапами подготовки данных. Они позволяют лучше понять структуру данных и определить, какие переменные наиболее полезны для дальнейшего анализа или построения моделей.