В данной лабораторной работе рассматриваются инструменты языка R, которые используются для первичного анализа данных, оценки значимости признаков и преобразования числовых переменных.
В ходе работы применяются следующие пакеты:
caret — для построения графиков и работы с
моделями;FSelector — для оценки информативности признаков;arules — для дискретизации числовых переменных;Boruta — для отбора важных признаков;mlbench — для загрузки набора данных
Ozone.Основная цель работы — познакомиться с базовыми методами анализа признаков и научиться оформлять результаты в виде RMarkdown-отчета.
Необходимо установить и подключить пакет caret,
выполнить команду names(getModelInfo()), а затем провести
графический анализ искусственно созданного набора данных.
Для анализа используются данные:
sample_x <- matrix(rnorm(50 * 5), ncol = 5)
sample_y <- factor(rep(c("A", "B"), 25))
Также требуется сохранить построенные графики в формате
.jpg.
# Проверка и установка пакета при необходимости
if (!require(caret, quietly = TRUE)) {
install.packages("caret")
}
library(caret)
Выведем несколько первых названий моделей, доступных в пакете
caret:
available_models <- names(getModelInfo())
head(available_models, 10)
## [1] "ada" "AdaBag" "AdaBoost.M1" "adaboost" "amdai"
## [6] "ANFIS" "avNNet" "awnb" "awtan" "bag"
Сформируем данные для анализа:
set.seed(321)
sample_x <- matrix(rnorm(50 * 5), ncol = 5)
sample_y <- factor(rep(c("A", "B"), 25))
Построим график попарных зависимостей:
featurePlot(
x = sample_x,
y = sample_y,
plot = "pairs"
)
Сохраним его в файл:
jpeg("caret_pairs_plot.jpg")
featurePlot(x = sample_x, y = sample_y, plot = "pairs")
dev.off()
## png
## 2
Построим график плотности распределения:
featurePlot(
x = sample_x,
y = sample_y,
plot = "density"
)
Сохраним график плотности:
jpeg("caret_density_plot.jpg")
featurePlot(x = sample_x, y = sample_y, plot = "density")
dev.off()
## png
## 2
Построим boxplot-график:
featurePlot(
x = sample_x,
y = sample_y,
plot = "box"
)
Сохраним boxplot:
jpeg("caret_box_plot.jpg")
featurePlot(x = sample_x, y = sample_y, plot = "box")
dev.off()
## png
## 2
В результате выполнения первого задания был подключен пакет
caret и получен список моделей, доступных через функцию
getModelInfo().
Функция featurePlot() позволила построить несколько
типов графиков:
pairs показывает взаимосвязи между признаками;density отображает распределение значений по
классам;box позволяет сравнить разброс значений внутри
групп.Поскольку исходные данные были созданы случайным образом, выраженного
разделения между классами A и B не видно. Это
означает, что признаки в данном примере не позволяют надежно отличить
один класс от другого.
Необходимо использовать пакет FSelector и определить
важность признаков для задачи классификации на наборе данных
iris.
if (!require(FSelector, quietly = TRUE)) {
install.packages("FSelector")
}
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_importance <- information.gain(Species ~ ., data = iris)
iris_importance
## attr_importance
## Sepal.Length 0.4521286
## Sepal.Width 0.2672750
## Petal.Length 0.9402853
## Petal.Width 0.9554360
Отсортируем признаки по убыванию важности:
iris_importance_sorted <- iris_importance[order(-iris_importance$attr_importance), , drop = FALSE]
iris_importance_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.
if (!require(arules, quietly = TRUE)) {
install.packages("arules")
}
library(arules)
Создадим копию набора данных:
data(iris)
iris_data <- iris
Выполним дискретизацию переменной Sepal.Length
различными методами:
iris_data$Sepal_interval <- discretize(
iris_data$Sepal.Length,
method = "interval",
breaks = 3
)
iris_data$Sepal_frequency <- discretize(
iris_data$Sepal.Length,
method = "frequency",
breaks = 3
)
iris_data$Sepal_cluster <- discretize(
iris_data$Sepal.Length,
method = "cluster",
breaks = 3
)
iris_data$Sepal_fixed <- discretize(
iris_data$Sepal.Length,
method = "fixed",
breaks = c(-Inf, 5, 6, Inf)
)
Посмотрим первые строки полученного набора данных:
head(iris_data)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal_interval
## 1 5.1 3.5 1.4 0.2 setosa [4.3,5.5)
## 2 4.9 3.0 1.4 0.2 setosa [4.3,5.5)
## 3 4.7 3.2 1.3 0.2 setosa [4.3,5.5)
## 4 4.6 3.1 1.5 0.2 setosa [4.3,5.5)
## 5 5.0 3.6 1.4 0.2 setosa [4.3,5.5)
## 6 5.4 3.9 1.7 0.4 setosa [4.3,5.5)
## Sepal_frequency Sepal_cluster Sepal_fixed
## 1 [4.3,5.4) [4.3,5.33) [5,6)
## 2 [4.3,5.4) [4.3,5.33) [-Inf,5)
## 3 [4.3,5.4) [4.3,5.33) [-Inf,5)
## 4 [4.3,5.4) [4.3,5.33) [-Inf,5)
## 5 [4.3,5.4) [4.3,5.33) [5,6)
## 6 [5.4,6.3) [5.33,6.27) [5,6)
Сравним распределение значений по группам:
table(iris_data$Sepal_interval)
##
## [4.3,5.5) [5.5,6.7) [6.7,7.9]
## 52 70 28
table(iris_data$Sepal_frequency)
##
## [4.3,5.4) [5.4,6.3) [6.3,7.9]
## 46 53 51
table(iris_data$Sepal_cluster)
##
## [4.3,5.33) [5.33,6.27) [6.27,7.9]
## 46 53 51
table(iris_data$Sepal_fixed)
##
## [-Inf,5) [5,6) [6, Inf]
## 22 61 67
В данном задании была выполнена дискретизация переменной
Sepal.Length, то есть числовые значения были преобразованы
в интервальные категории.
Метод interval разбивает диапазон значений на интервалы
одинаковой ширины. Он удобен своей простотой, но не учитывает, сколько
объектов попадает в каждый интервал.
Метод frequency старается распределить наблюдения по
группам более равномерно. Поэтому он полезен, если важно получить
интервалы примерно с одинаковым количеством объектов.
Метод cluster использует структуру данных и формирует
интервалы на основе близости значений. Такой подход может быть более
гибким.
Метод fixed позволяет самостоятельно задать границы
интервалов. Он удобен в случаях, когда заранее известны нужные диапазоны
значений.
Необходимо установить пакет Boruta, выполнить отбор
признаков для набора данных Ozone, построить график и
сделать выводы.
if (!require(Boruta, quietly = TRUE)) {
install.packages("Boruta")
}
if (!require(mlbench, quietly = TRUE)) {
install.packages("mlbench")
}
library(Boruta)
library(mlbench)
Загрузим набор данных Ozone и удалим пропущенные
значения:
data("Ozone")
ozone_data <- na.omit(Ozone)
str(ozone_data)
## 'data.frame': 203 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",..: 5 6 7 8 9 12 13 14 15 16 ...
## $ V3 : Factor w/ 7 levels "1","2","3","4",..: 1 2 3 4 5 1 2 3 4 5 ...
## $ V4 : num 5 6 4 4 6 6 5 4 4 7 ...
## $ V5 : num 5760 5720 5790 5790 5700 5720 5760 5780 5830 5870 ...
## $ V6 : num 3 4 6 3 3 3 6 6 3 2 ...
## $ V7 : num 51 69 19 25 73 44 33 19 19 19 ...
## $ V8 : num 54 35 45 55 41 51 51 54 58 61 ...
## $ V9 : num 45.3 49.6 46.4 52.7 48 ...
## $ V10: num 1450 1568 2631 554 2083 ...
## $ V11: num 25 15 -33 -28 23 9 -44 -44 -53 -67 ...
## $ V12: num 57 53.8 54.1 64.8 52.5 ...
## $ V13: num 60 60 100 250 120 150 40 200 250 200 ...
## - attr(*, "na.action")= 'omit' Named int [1:163] 1 2 3 4 10 11 17 18 20 24 ...
## ..- attr(*, "names")= chr [1:163] "1" "2" "3" "4" ...
Выполним отбор признаков. В качестве целевой переменной используем
V4:
set.seed(321)
boruta_result <- Boruta(V4 ~ ., data = ozone_data, doTrace = 0)
boruta_result
## Boruta performed 18 iterations in 0.3317089 secs.
## 9 attributes confirmed important: V1, V10, V11, V12, V13 and 4 more;
## 3 attributes confirmed unimportant: V2, V3, V6;
Построим график важности признаков:
plot(
boruta_result,
las = 2,
cex.axis = 0.7,
main = "Оценка важности признаков методом Boruta"
)
Посмотрим итоговое решение Boruta по признакам:
final_boruta <- attStats(boruta_result)
final_boruta
## meanImp medianImp minImp maxImp normHits decision
## V1 0.41096250 0.40960986 0.35760943 0.46785640 1.0000000 Confirmed
## V2 0.02918872 0.03406152 -0.03369836 0.10424128 0.0000000 Rejected
## V3 -0.05306116 -0.04258777 -0.11079874 0.01874702 0.0000000 Rejected
## V5 0.39323788 0.39677892 0.32238272 0.45811450 1.0000000 Confirmed
## V6 0.03167463 0.02244017 -0.03666906 0.15064050 0.1111111 Rejected
## V7 0.51623762 0.51936006 0.44466627 0.60793755 1.0000000 Confirmed
## V8 0.77232372 0.77006262 0.74191138 0.82035114 1.0000000 Confirmed
## V9 0.89607361 0.89698711 0.82591468 0.95376503 1.0000000 Confirmed
## V10 0.44715079 0.43596601 0.40288784 0.54094438 1.0000000 Confirmed
## V11 0.55336146 0.56235143 0.46693799 0.60844589 1.0000000 Confirmed
## V12 0.64190812 0.65311896 0.57822867 0.69316528 1.0000000 Confirmed
## V13 0.42188532 0.41730054 0.36515241 0.47906714 1.0000000 Confirmed
В четвертом задании был применен алгоритм Boruta,
который используется для отбора значимых признаков.
Алгоритм сравнивает реальные признаки с искусственно созданными теневыми признаками и определяет, какие переменные действительно важны для целевой переменной.
По результатам работы часть признаков была признана важной, а часть — неважной. Это позволяет уменьшить количество переменных и оставить только наиболее полезные признаки для дальнейшего анализа.
График Boruta показывает распределение важности признаков. Чем выше значения на графике, тем больше вклад признака в объяснение целевой переменной.
Необходимо собрать все выполненные задания в единый файл RMarkdown и опубликовать результат на RPubs.
Данный отчет оформлен в формате RMarkdown. После нажатия кнопки
Knit создается HTML-файл с результатами выполнения кода,
графиками и текстовыми выводами.
Для публикации на RPubs необходимо:
Knit to HTML.Publish.RPubs.Формат RMarkdown удобен для оформления лабораторных работ, так как в одном документе можно совместить текст задания, программный код, результаты выполнения и графики.
В ходе лабораторной работы были рассмотрены основные инструменты анализа признаков в языке R.
С помощью пакета caret был выполнен графический
разведочный анализ данных. Пакет FSelector позволил
определить наиболее важные признаки в наборе данных iris.
Пакет arules был использован для преобразования числовой
переменной в категориальную. С помощью пакета Boruta был
проведен отбор значимых признаков на наборе данных
Ozone.
В результате работы были закреплены навыки использования RMarkdown, построения графиков, оценки важности признаков и подготовки отчета для публикации на RPubs. ```
toc: false в
YAML-заголовке (вместо toc: true)Если вам также нужно убрать нумерацию разделов или изменить оформление, дайте знать.