Изучить методы разведочного анализа данных, определения важности
признаков, дискретизации непрерывных переменных и отбора признаков с
использованием пакетов caret, FSelector,
arules и Boruta.
Пакет caret предназначен для построения моделей
машинного обучения, предварительной обработки данных и анализа
признаков.
Для просмотра доступных моделей используется функция
getModelInfo().
library(caret)
library(FSelector)
library(arules)
library(Boruta)
set.seed(123)
Получим список доступных моделей:
model_list <- names(getModelInfo())
head(model_list, 30)
## [1] "ada" "AdaBag" "AdaBoost.M1" "adaboost"
## [5] "amdai" "ANFIS" "avNNet" "awnb"
## [9] "awtan" "bag" "bagEarth" "bagEarthGCV"
## [13] "bagFDA" "bagFDAGCV" "bam" "bartMachine"
## [17] "bayesglm" "binda" "blackboost" "blasso"
## [21] "blassoAveraged" "bridge" "brnn" "BstLm"
## [25] "bstSm" "bstTree" "C5.0" "C5.0Cost"
## [29] "C5.0Rules" "C5.0Tree"
Количество доступных моделей:
length(model_list)
## [1] 239
В соответствии с условием задания создадим матрицу из 50 наблюдений и 5 признаков.
x <- matrix(rnorm(50 * 5), ncol = 5)
y <- factor(rep(c("A", "B"), 25))
colnames(x) <- paste0("X", 1:5)
head(x)
## X1 X2 X3 X4 X5
## [1,] -0.56047565 0.25331851 -0.71040656 0.7877388 2.1988103
## [2,] -0.23017749 -0.02854676 0.25688371 0.7690422 1.3124130
## [3,] 1.55870831 -0.04287046 -0.24669188 0.3322026 -0.2651451
## [4,] 0.07050839 1.36860228 -0.34754260 -1.0083766 0.5431941
## [5,] 0.12928774 -0.22577099 -0.95161857 -0.1194526 -0.4143399
## [6,] 1.71506499 1.51647060 -0.04502772 -0.2803953 -0.4762469
Количество объектов каждого класса:
table(y)
## y
## A B
## 25 25
С помощью функции featurePlot() построим попарные
диаграммы рассеяния признаков.
Сначала сохраним график в JPG-файл.
jpeg(
filename = "featurePlot_pairs.jpg",
width = 1800,
height = 1800,
res = 200
)
featurePlot(
x = x,
y = y,
plot = "pairs"
)
dev.off()
## png
## 2
Отобразим график в отчёте:
featurePlot(
x = x,
y = y,
plot = "pairs"
)
Также построим графики плотности распределения признаков и сохраним их в JPG-файл.
jpeg(
filename = "featurePlot_density.jpg",
width = 1800,
height = 1400,
res = 200
)
featurePlot(
x = x,
y = y,
plot = "density",
scales = list(
x = list(relation = "free")
)
)
dev.off()
## png
## 2
Отобразим графики плотности в отчёте:
featurePlot(
x = x,
y = y,
plot = "density",
scales = list(
x = list(relation = "free")
)
)
В ходе первого задания был выполнен графический разведочный анализ набора данных из 50 наблюдений и 5 признаков.
С помощью функции featurePlot() были построены попарные
диаграммы рассеяния и графики плотности распределения признаков.
Полученные графики сохранены в JPG-файлы.
Так как исходные значения были случайно сгенерированы из нормального распределения, выраженного разделения классов A и B на графиках не наблюдается.
Для определения важности признаков используется стандартный набор
данных 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
Общая статистическая информация:
summary(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species
## setosa :50
## versicolor:50
## virginica :50
##
##
##
Названия переменных:
names(iris)
## [1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Species"
Набор данных iris содержит четыре числовых признака:
Sepal.Length, Sepal.Width,
Petal.Length и Petal.Width. Целевой переменной
является Species.
Для оценки важности признаков используется метод Information Gain.
ig <- information.gain(
Species ~ .,
data = iris
)
ig
## attr_importance
## Sepal.Length 0.4521286
## Sepal.Width 0.2672750
## Petal.Length 0.9402853
## Petal.Width 0.9554360
Отсортируем признаки по убыванию важности:
ig_sorted <- ig[order(-ig[[1]]), , drop = FALSE]
ig_sorted
## attr_importance
## Petal.Width 0.9554360
## Petal.Length 0.9402853
## Sepal.Length 0.4521286
## Sepal.Width 0.2672750
barplot(
ig_sorted[[1]],
names.arg = rownames(ig_sorted),
main = "Важность признаков по Information Gain",
xlab = "Признак",
ylab = "Важность",
las = 2
)
Метод Information Gain позволяет определить, насколько каждый признак информативен для определения класса объекта.
Полученное ранжирование показывает, какие признаки наиболее полезны
для классификации объектов набора iris. Наиболее
информативными обычно являются признаки, характеризующие размеры
лепестков.
Для дискретизации используется непрерывная переменная
Sepal.Length из набора данных iris.
x_iris <- iris$Sepal.Length
summary(x_iris)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.300 5.100 5.800 5.843 6.400 7.900
Метод interval разбивает диапазон значений на интервалы
одинаковой ширины.
iris_interval <- discretize(
x_iris,
method = "interval",
categories = 3
)
## Warning in discretize(x_iris, method = "interval", categories = 3): Parameter
## categories is deprecated. Use breaks instead! Also, the default method is now
## frequency!
table(iris_interval)
## iris_interval
## [4.3,5.5) [5.5,6.7) [6.7,7.9]
## 52 70 28
Метод frequency формирует категории с приблизительно
одинаковым количеством наблюдений.
iris_frequency <- discretize(
x_iris,
method = "frequency",
categories = 3
)
## Warning in discretize(x_iris, method = "frequency", categories = 3): Parameter
## categories is deprecated. Use breaks instead! Also, the default method is now
## frequency!
table(iris_frequency)
## iris_frequency
## [4.3,5.4) [5.4,6.3) [6.3,7.9]
## 46 53 51
Метод cluster выполняет дискретизацию на основе
кластеризации значений.
iris_cluster <- discretize(
x_iris,
method = "cluster",
categories = 3
)
## Warning in discretize(x_iris, method = "cluster", categories = 3): Parameter
## categories is deprecated. Use breaks instead! Also, the default method is now
## frequency!
table(iris_cluster)
## iris_cluster
## [4.3,5.33) [5.33,6.27) [6.27,7.9]
## 46 53 51
При использовании метода fixed границы интервалов
задаются пользователем.
iris_fixed <- discretize(
x_iris,
method = "fixed",
breaks = c(4.3, 5.4, 6.5, 7.9)
)
table(iris_fixed)
## iris_fixed
## [4.3,5.4) [5.4,6.5) [6.5,7.9]
## 46 69 35
discretization_result <- data.frame(
Original = x_iris,
Interval = iris_interval,
Frequency = iris_frequency,
Cluster = iris_cluster,
Fixed = iris_fixed
)
head(discretization_result, 15)
## Original Interval Frequency Cluster Fixed
## 1 5.1 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 2 4.9 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 3 4.7 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 4 4.6 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 5 5.0 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 6 5.4 [4.3,5.5) [5.4,6.3) [5.33,6.27) [5.4,6.5)
## 7 4.6 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 8 5.0 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 9 4.4 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 10 4.9 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 11 5.4 [4.3,5.5) [5.4,6.3) [5.33,6.27) [5.4,6.5)
## 12 4.8 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 13 4.8 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 14 4.3 [4.3,5.5) [4.3,5.4) [4.3,5.33) [4.3,5.4)
## 15 5.8 [5.5,6.7) [5.4,6.3) [5.33,6.27) [5.4,6.5)
В ходе третьего задания непрерывная переменная
Sepal.Length была преобразована в категориальную четырьмя
способами.
Метод interval создаёт интервалы одинаковой ширины.
Метод frequency стремится распределить наблюдения между
категориями равномерно. Метод cluster формирует категории
на основе кластеризации значений. Метод fixed позволяет
самостоятельно задавать границы интервалов.
Таким образом, выбор метода дискретизации зависит от особенностей исходных данных и целей дальнейшего анализа.
Для выполнения задания используется набор данных
Ozone.
if (!requireNamespace("mlbench", quietly = TRUE)) {
stop(
"Для выполнения задания 4 необходимо установить пакет mlbench. ",
"Выполните в консоли R: install.packages('mlbench')"
)
}
data("Ozone", package = "mlbench")
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 ...
Основные статистические характеристики:
summary(Ozone)
## V1 V2 V3 V4 V5
## 1 : 31 1 : 12 1:52 Min. : 1.00 Min. :5320
## 3 : 31 2 : 12 2:52 1st Qu.: 5.00 1st Qu.:5700
## 5 : 31 3 : 12 3:52 Median : 9.00 Median :5770
## 7 : 31 4 : 12 4:53 Mean :11.53 Mean :5753
## 8 : 31 5 : 12 5:53 3rd Qu.:16.00 3rd Qu.:5830
## 10 : 31 6 : 12 6:52 Max. :38.00 Max. :5950
## (Other):180 (Other):294 7:52 NAs :5 NAs :12
## V6 V7 V8 V9
## Min. : 0.000 Min. :19.00 Min. :25.00 Min. :27.68
## 1st Qu.: 3.000 1st Qu.:49.00 1st Qu.:51.00 1st Qu.:49.73
## Median : 5.000 Median :65.00 Median :62.00 Median :57.02
## Mean : 4.869 Mean :58.48 Mean :61.91 Mean :56.85
## 3rd Qu.: 6.000 3rd Qu.:73.00 3rd Qu.:72.00 3rd Qu.:66.11
## Max. :11.000 Max. :93.00 Max. :93.00 Max. :82.58
## NAs :15 NAs :2 NAs :139
## V10 V11 V12 V13
## Min. : 111 Min. :-69.0 Min. :27.50 Min. : 0.0
## 1st Qu.: 890 1st Qu.:-10.0 1st Qu.:51.26 1st Qu.: 70.0
## Median :2125 Median : 24.0 Median :62.24 Median :110.0
## Mean :2591 Mean : 17.8 Mean :60.93 Mean :123.3
## 3rd Qu.:5000 3rd Qu.: 45.0 3rd Qu.:70.52 3rd Qu.:150.0
## Max. :5000 Max. :107.0 Max. :91.76 Max. :500.0
## NAs :15 NAs :1 NAs :14
Удалим строки, содержащие пропущенные значения:
Ozone_clean <- na.omit(Ozone)
dim(Ozone_clean)
## [1] 203 13
Для применения Boruta в задаче классификации сформируем категориальную переменную на основе медианного значения концентрации озона.
ozone_median <- median(Ozone_clean$V4)
Ozone_clean$ozone_class <- factor(
ifelse(
Ozone_clean$V4 >= ozone_median,
"High",
"Low"
)
)
table(Ozone_clean$ozone_class)
##
## High Low
## 108 95
Исходную переменную ozone исключим из списка
признаков.
ozone_data <- Ozone_clean[
,
setdiff(names(Ozone_clean), "V4")
]
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 ...
## $ 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 ...
## $ ozone_class: Factor w/ 2 levels "High","Low": 2 2 2 2 2 2 2 2 2 2 ...
set.seed(123)
boruta_model <- Boruta(
ozone_class ~ .,
data = ozone_data,
doTrace = 0
)
boruta_model
## Boruta performed 99 iterations in 2.517292 secs.
## 9 attributes confirmed important: V1, V10, V11, V12, V13 and 4 more;
## 2 attributes confirmed unimportant: V3, V6;
## 1 tentative attributes left: V2;
boruta_stats <- attStats(boruta_model)
boruta_stats
## meanImp medianImp minImp maxImp normHits decision
## V1 0.527820582 0.52673908 0.464166850 0.58819891 1.0000000 Confirmed
## V2 0.108899476 0.11140582 -0.002062672 0.24203424 0.4141414 Tentative
## V3 -0.002365002 0.01146640 -0.065534702 0.03673776 0.0000000 Rejected
## V5 0.496486423 0.49474689 0.436704013 0.58892617 1.0000000 Confirmed
## V6 0.033439729 0.03094937 -0.061311663 0.13041460 0.0000000 Rejected
## V7 0.583246145 0.58147708 0.496733201 0.68851283 1.0000000 Confirmed
## V8 0.920008697 0.92353584 0.807444434 1.04277559 1.0000000 Confirmed
## V9 0.746108167 0.74904350 0.668899070 0.81078945 1.0000000 Confirmed
## V10 0.428106615 0.42910216 0.315777636 0.49989416 1.0000000 Confirmed
## V11 0.610045934 0.61291192 0.506182653 0.70091731 1.0000000 Confirmed
## V12 0.703997619 0.70495727 0.633350834 0.78104290 1.0000000 Confirmed
## V13 0.382070133 0.38501117 0.299333053 0.46957763 1.0000000 Confirmed
Подтверждённые признаки:
boruta_stats[
boruta_stats$decision == "Confirmed",
,
drop = FALSE
]
## meanImp medianImp minImp maxImp normHits decision
## V1 0.5278206 0.5267391 0.4641668 0.5881989 1 Confirmed
## V5 0.4964864 0.4947469 0.4367040 0.5889262 1 Confirmed
## V7 0.5832461 0.5814771 0.4967332 0.6885128 1 Confirmed
## V8 0.9200087 0.9235358 0.8074444 1.0427756 1 Confirmed
## V9 0.7461082 0.7490435 0.6688991 0.8107894 1 Confirmed
## V10 0.4281066 0.4291022 0.3157776 0.4998942 1 Confirmed
## V11 0.6100459 0.6129119 0.5061827 0.7009173 1 Confirmed
## V12 0.7039976 0.7049573 0.6333508 0.7810429 1 Confirmed
## V13 0.3820701 0.3850112 0.2993331 0.4695776 1 Confirmed
plot(
boruta_model,
las = 2
)
Построим boxplot распределения концентрации озона для двух сформированных классов.
boxplot(
V4 ~ ozone_class,
data = Ozone_clean,
main = "Распределение концентрации озона по классам",
xlab = "Класс",
ylab = "Концентрация озона"
)
Алгоритм Boruta используется для определения информативности признаков относительно целевой переменной.
В результате работы алгоритма признаки получают один из статусов:
Confirmed, Rejected или
Tentative.
График Boruta позволяет визуально сравнить важность признаков и выделить наиболее информативные характеристики.
Boxplot показывает распределение концентрации озона для двух сформированных групп и позволяет визуально оценить различия между ними.
В ходе лабораторной работы были изучены различные методы разведочного анализа, дискретизации и отбора признаков.
С помощью пакета caret был выполнен графический
разведочный анализ с использованием функции
featurePlot().
С помощью пакета FSelector была определена важность
признаков набора данных iris методом Information Gain.
С использованием функции discretize() пакета
arules выполнена дискретизация непрерывной переменной
четырьмя методами: interval, frequency,
cluster и fixed.
Для набора данных Ozone был применён алгоритм Boruta для
определения информативности признаков. Дополнительно был построен
boxplot для анализа распределения концентрации озона по сформированным
классам.
Полученные результаты показывают, что разведочный анализ, дискретизация и отбор признаков являются важными этапами предварительной обработки данных перед построением моделей машинного обучения.