В данной лабораторной работе рассматриваются методы выбора признаков и дискретизации данных с использованием различных пакетов R:
Функция getModelInfo() возвращает информацию о всех
доступных моделях в пакете caret:
# Получить список всех доступных методов
available_methods <- names(getModelInfo())
cat("Количество доступных методов:", length(available_methods), "\n\n")## Количество доступных методов: 239
## Первые 50 методов:
## [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" "cforest" "chaid"
## [33] "CSimca" "ctree" "ctree2" "cubist"
## [37] "dda" "deepboost" "DENFIS" "dnn"
## [41] "dwdLinear" "dwdPoly" "dwdRadial" "earth"
## [45] "elm" "enet" "evtree" "extraTrees"
## [49] "fda" "FH.GBML"
# Установка seed для воспроизводимости
set.seed(42)
# Создание матрицы признаков
x <- matrix(rnorm(50 * 5), ncol = 5)
colnames(x) <- paste0("Feature_", 1:5)
# Создание целевой переменной
y <- factor(rep(c("A", "B"), 25))
# Преобразование в data.frame для удобства
data_df <- data.frame(x, Class = y)
# Просмотр структуры данных
str(data_df)## 'data.frame': 50 obs. of 6 variables:
## $ Feature_1: num 1.371 -0.565 0.363 0.633 0.404 ...
## $ Feature_2: num 0.3219 -0.7838 1.5757 0.6429 0.0898 ...
## $ Feature_3: num 1.201 1.045 -1.003 1.848 -0.667 ...
## $ Feature_4: num -0.0407 -1.5515 1.1672 -0.2736 -0.4678 ...
## $ Feature_5: num -2.001 0.334 1.171 2.06 -1.377 ...
## $ Class : Factor w/ 2 levels "A","B": 1 2 1 2 1 2 1 2 1 2 ...
## Feature_1 Feature_2 Feature_3 Feature_4
## Min. :-2.65646 Min. :-2.9931 Min. :-2.0247 Min. :-1.74506
## 1st Qu.:-0.63223 1st Qu.:-0.5262 1st Qu.:-0.5884 1st Qu.:-0.57145
## Median :-0.10039 Median : 0.2672 Median :-0.2523 Median : 0.03927
## Mean :-0.03567 Mean : 0.1007 Mean :-0.1513 Mean :-0.02372
## 3rd Qu.: 0.65072 3rd Qu.: 0.6728 3rd Qu.: 0.1341 3rd Qu.: 0.57841
## Max. : 2.28665 Max. : 1.5757 Max. : 2.7019 Max. : 1.81523
## Feature_5 Class
## Min. :-2.00093 A:25
## 1st Qu.:-0.69399 B:25
## Median :-0.15305
## Mean : 0.00794
## 3rd Qu.: 0.65662
## Max. : 2.05954
# Сохранение графика в JPG
jpeg("plots/featureplot_scatter.jpg", width = 800, height = 600, quality = 100)
featurePlot(x = x,
y = y,
plot = "pairs",
auto.key = list(columns = 2))
dev.off()## png
## 2
# Box plots для каждого признака по классам
featurePlot(x = x,
y = y,
plot = "box",
scales = list(x = list(relation = "free"),
y = list(relation = "free")),
auto.key = list(columns = 2))# Сохранение графика в JPG
jpeg("plots/featureplot_box.jpg", width = 800, height = 600, quality = 100)
featurePlot(x = x,
y = y,
plot = "box",
scales = list(x = list(relation = "free"),
y = list(relation = "free")),
auto.key = list(columns = 2))
dev.off()## png
## 2
# Графики плотности распределения
featurePlot(x = x,
y = y,
plot = "density",
scales = list(x = list(relation = "free"),
y = list(relation = "free")),
auto.key = list(columns = 2),
layout = c(3, 2))# Сохранение графика в JPG
jpeg("plots/featureplot_density.jpg", width = 800, height = 600, quality = 100)
featurePlot(x = x,
y = y,
plot = "density",
scales = list(x = list(relation = "free"),
y = list(relation = "free")),
auto.key = list(columns = 2),
layout = c(3, 2))
dev.off()## png
## 2
# Strip plots для каждого признака по классам
featurePlot(x = x,
y = y,
plot = "strip",
jitter = TRUE,
scales = list(x = list(relation = "free"),
y = list(relation = "free")),
auto.key = list(columns = 2))# Сохранение графика в JPG
jpeg("plots/featureplot_strip.jpg", width = 800, height = 600, quality = 100)
featurePlot(x = x,
y = y,
plot = "strip",
jitter = TRUE,
scales = list(x = list(relation = "free"),
y = list(relation = "free")),
auto.key = list(columns = 2))
dev.off()## png
## 2
Выводы:
Пакет caret предоставляет более 230 методов машинного обучения для решения задач классификации и регрессии.
Функция featurePlot() позволяет быстро провести
графический разведочный анализ данных:
Поскольку данные сгенерированы случайным образом
(rnorm), признаки не показывают значимого разделения между
классами A и B - распределения почти идентичны.
## 'data.frame': 150 obs. of 5 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
## 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
##
##
##
# Вычисление информационного прироста
info_gain <- information.gain(Species ~ ., data = iris)
print("Information Gain:")## [1] "Information Gain:"
## attr_importance
## Sepal.Length 0.4521286
## Sepal.Width 0.2672750
## Petal.Length 0.9402853
## Petal.Width 0.9554360
# Вычисление коэффициента прироста
gain_rat <- gain.ratio(Species ~ ., data = iris)
print("Gain Ratio:")## [1] "Gain Ratio:"
## attr_importance
## Sepal.Length 0.4196464
## Sepal.Width 0.2472972
## Petal.Length 0.8584937
## Petal.Width 0.8713692
# Вычисление симметричной неопределенности
sym_uncert <- symmetrical.uncertainty(Species ~ ., data = iris)
print("Symmetrical Uncertainty:")## [1] "Symmetrical Uncertainty:"
## attr_importance
## Sepal.Length 0.4155563
## Sepal.Width 0.2452743
## Petal.Length 0.8571872
## Petal.Width 0.8705214
# Объединение результатов
importance_df <- data.frame(
Feature = rownames(info_gain),
Information_Gain = info_gain$attr_importance,
Gain_Ratio = gain_rat$attr_importance,
Symmetrical_Uncertainty = sym_uncert$attr_importance,
Chi_Squared = chi_sq$attr_importance
)
# Сортировка по Information Gain
importance_df <- importance_df[order(-importance_df$Information_Gain), ]
print(importance_df)## Feature Information_Gain Gain_Ratio Symmetrical_Uncertainty Chi_Squared
## 4 Petal.Width 0.9554360 0.8713692 0.8705214 0.9432359
## 3 Petal.Length 0.9402853 0.8584937 0.8571872 0.9346311
## 1 Sepal.Length 0.4521286 0.4196464 0.4155563 0.6288067
## 2 Sepal.Width 0.2672750 0.2472972 0.2452743 0.4922162
# Визуализация важности признаков
par(mfrow = c(2, 2), mar = c(5, 8, 4, 2))
barplot(info_gain$attr_importance[order(info_gain$attr_importance)],
names.arg = rownames(info_gain)[order(info_gain$attr_importance)],
horiz = TRUE, las = 1, col = "steelblue",
main = "Information Gain", xlab = "Importance")
barplot(gain_rat$attr_importance[order(gain_rat$attr_importance)],
names.arg = rownames(gain_rat)[order(gain_rat$attr_importance)],
horiz = TRUE, las = 1, col = "darkgreen",
main = "Gain Ratio", xlab = "Importance")
barplot(sym_uncert$attr_importance[order(sym_uncert$attr_importance)],
names.arg = rownames(sym_uncert)[order(sym_uncert$attr_importance)],
horiz = TRUE, las = 1, col = "darkorange",
main = "Symmetrical Uncertainty", xlab = "Importance")
barplot(chi_sq$attr_importance[order(chi_sq$attr_importance)],
names.arg = rownames(chi_sq)[order(chi_sq$attr_importance)],
horiz = TRUE, las = 1, col = "darkred",
main = "Chi-Squared", xlab = "Importance")# Сохранение графика
jpeg("plots/fselector_importance.jpg", width = 800, height = 600, quality = 100)
par(mfrow = c(2, 2), mar = c(5, 8, 4, 2))
barplot(info_gain$attr_importance[order(info_gain$attr_importance)],
names.arg = rownames(info_gain)[order(info_gain$attr_importance)],
horiz = TRUE, las = 1, col = "steelblue",
main = "Information Gain", xlab = "Importance")
barplot(gain_rat$attr_importance[order(gain_rat$attr_importance)],
names.arg = rownames(gain_rat)[order(gain_rat$attr_importance)],
horiz = TRUE, las = 1, col = "darkgreen",
main = "Gain Ratio", xlab = "Importance")
barplot(sym_uncert$attr_importance[order(sym_uncert$attr_importance)],
names.arg = rownames(sym_uncert)[order(sym_uncert$attr_importance)],
horiz = TRUE, las = 1, col = "darkorange",
main = "Symmetrical Uncertainty", xlab = "Importance")
barplot(chi_sq$attr_importance[order(chi_sq$attr_importance)],
names.arg = rownames(chi_sq)[order(chi_sq$attr_importance)],
horiz = TRUE, las = 1, col = "darkred",
main = "Chi-Squared", xlab = "Importance")
dev.off()## png
## 2
# Выбор подмножества признаков с помощью cutoff
cutoff_features <- cutoff.k(info_gain, k = 2)
cat("Лучшие 2 признака (Information Gain):", cutoff_features, "\n")## Лучшие 2 признака (Information Gain): Petal.Width Petal.Length
# Автоматический выбор на основе порога
cutoff_biggest <- cutoff.biggest.diff(info_gain)
cat("Признаки (biggest diff):", cutoff_biggest, "\n")## Признаки (biggest diff): Petal.Width Petal.Length
Выводы:
Все методы (Information Gain, Gain Ratio, Symmetrical Uncertainty, Chi-Squared) согласованно определяют порядок важности признаков для набора данных iris:
Признаки лепестка (Petal) значительно более информативны для определения вида ириса, чем признаки чашелистика (Sepal).
Пакет FSelector предоставляет удобные функции
cutoff.k() и cutoff.biggest.diff() для
автоматического выбора наиболее значимых признаков.
# Используем переменную Sepal.Length из iris
data(iris)
sepal_length <- iris$Sepal.Length
cat("Статистика Sepal.Length:\n")## Статистика Sepal.Length:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.300 5.100 5.800 5.843 6.400 7.900
##
## Количество наблюдений: 150
# Дискретизация с равной шириной интервалов
disc_interval <- discretize(sepal_length, method = "interval", breaks = 4)
cat("\nМетод 'interval' (равная ширина интервалов):\n")##
## Метод 'interval' (равная ширина интервалов):
## disc_interval
## [4.3,5.2) [5.2,6.1) [6.1,7) [7,7.9]
## 41 48 48 13
## [1] "[4.3,5.2)" "[5.2,6.1)" "[6.1,7)" "[7,7.9]"
# Дискретизация с равной частотой (квантили)
disc_frequency <- discretize(sepal_length, method = "frequency", breaks = 4)
cat("\nМетод 'frequency' (равная частота):\n")##
## Метод 'frequency' (равная частота):
## disc_frequency
## [4.3,5.1) [5.1,5.8) [5.8,6.4) [6.4,7.9]
## 32 41 35 42
## [1] "[4.3,5.1)" "[5.1,5.8)" "[5.8,6.4)" "[6.4,7.9]"
# Дискретизация методом кластеризации
disc_cluster <- discretize(sepal_length, method = "cluster", breaks = 4)
cat("\nМетод 'cluster' (k-means кластеризация):\n")##
## Метод 'cluster' (k-means кластеризация):
## disc_cluster
## [4.3,5.32) [5.32,6.12) [6.12,6.98) [6.98,7.9]
## 46 49 42 13
## [1] "[4.3,5.32)" "[5.32,6.12)" "[6.12,6.98)" "[6.98,7.9]"
# Дискретизация с фиксированными границами
disc_fixed <- discretize(sepal_length, method = "fixed",
breaks = c(-Inf, 5.0, 6.0, 7.0, Inf),
labels = c("Маленький", "Средний", "Большой", "Очень большой"))
cat("\nМетод 'fixed' (фиксированные границы: 5.0, 6.0, 7.0):\n")##
## Метод 'fixed' (фиксированные границы: 5.0, 6.0, 7.0):
## disc_fixed
## Маленький Средний Большой Очень большой
## 22 61 54 13
## [1] "Маленький" "Средний" "Большой" "Очень большой"
# Визуализация всех методов дискретизации
par(mfrow = c(3, 2), mar = c(4, 4, 3, 1))
# Оригинальные данные
hist(sepal_length, breaks = 20, col = "lightgray",
main = "Оригинальные данные", xlab = "Sepal.Length", border = "white")
# Interval
barplot(table(disc_interval), col = "steelblue",
main = "Interval (равная ширина)", las = 2, cex.names = 0.7)
# Frequency
barplot(table(disc_frequency), col = "darkgreen",
main = "Frequency (равная частота)", las = 2, cex.names = 0.7)
# Cluster
barplot(table(disc_cluster), col = "darkorange",
main = "Cluster (k-means)", las = 2, cex.names = 0.7)
# Fixed
barplot(table(disc_fixed), col = "darkred",
main = "Fixed (заданные границы)", las = 2, cex.names = 0.7)# Сохранение графика
jpeg("plots/discretization_comparison.jpg", width = 800, height = 800, quality = 100)
par(mfrow = c(3, 2), mar = c(4, 4, 3, 1))
hist(sepal_length, breaks = 20, col = "lightgray",
main = "Оригинальные данные", xlab = "Sepal.Length", border = "white")
barplot(table(disc_interval), col = "steelblue",
main = "Interval (равная ширина)", las = 2, cex.names = 0.7)
barplot(table(disc_frequency), col = "darkgreen",
main = "Frequency (равная частота)", las = 2, cex.names = 0.7)
barplot(table(disc_cluster), col = "darkorange",
main = "Cluster (k-means)", las = 2, cex.names = 0.7)
barplot(table(disc_fixed), col = "darkred",
main = "Fixed (заданные границы)", las = 2, cex.names = 0.7)
dev.off()## png
## 2
# Дискретизация всех числовых столбцов iris
iris_numeric <- iris[, 1:4]
# Применение метода frequency ко всем столбцам
iris_disc <- as.data.frame(lapply(iris_numeric, function(x) {
discretize(x, method = "frequency", breaks = 3)
}))
# Добавление целевой переменной
iris_disc$Species <- iris$Species
cat("\nДискретизированный набор данных iris (первые 10 строк):\n")##
## Дискретизированный набор данных iris (первые 10 строк):
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 [4.3,5.4) [3.2,4.4] [1,2.63) [0.1,0.867) setosa
## 2 [4.3,5.4) [2.9,3.2) [1,2.63) [0.1,0.867) setosa
## 3 [4.3,5.4) [3.2,4.4] [1,2.63) [0.1,0.867) setosa
## 4 [4.3,5.4) [2.9,3.2) [1,2.63) [0.1,0.867) setosa
## 5 [4.3,5.4) [3.2,4.4] [1,2.63) [0.1,0.867) setosa
## 6 [5.4,6.3) [3.2,4.4] [1,2.63) [0.1,0.867) setosa
## 7 [4.3,5.4) [3.2,4.4] [1,2.63) [0.1,0.867) setosa
## 8 [4.3,5.4) [3.2,4.4] [1,2.63) [0.1,0.867) setosa
## 9 [4.3,5.4) [2.9,3.2) [1,2.63) [0.1,0.867) setosa
## 10 [4.3,5.4) [2.9,3.2) [1,2.63) [0.1,0.867) setosa
Выводы:
Метод “interval” (равная ширина) делит диапазон данных на равные интервалы. Подходит, когда данные распределены равномерно.
Метод “frequency” (равная частота) создает интервалы с примерно одинаковым количеством наблюдений. Лучше подходит для асимметричных распределений.
Метод “cluster” (k-means) определяет границы на основе кластеризации данных. Эффективен для данных с естественными группами.
Метод “fixed” позволяет задать экспертные границы категорий. Полезен, когда есть предметные знания о данных.
Выбор метода дискретизации зависит от:
# Установка необходимых пакетов
if (!requireNamespace("Boruta", quietly = TRUE)) {
install.packages("Boruta", repos = "https://cloud.r-project.org/")
}
if (!requireNamespace("mlbench", quietly = TRUE)) {
install.packages("mlbench", repos = "https://cloud.r-project.org/")
}
library(Boruta)
library(mlbench)## '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 ...
##
## Размер данных: 366 x 13
## Количество пропущенных значений по столбцам:
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13
## 0 0 0 5 12 0 15 2 139 15 1 14 0
# Удаление строк с пропущенными значениями для Boruta
ozone_clean <- na.omit(Ozone)
cat("\nРазмер данных после удаления NA:", nrow(ozone_clean), "x", ncol(ozone_clean), "\n")##
## Размер данных после удаления NA: 203 x 13
# Установка seed для воспроизводимости
set.seed(123)
# Выполнение Boruta (V4 - целевая переменная - уровень озона)
# V4 - Daily maximum one-hour-average ozone reading
boruta_result <- Boruta(V4 ~ ., data = ozone_clean, doTrace = 0)
print(boruta_result)## Boruta performed 24 iterations in 1.718744 secs.
## 9 attributes confirmed important: V1, V10, V11, V12, V13 and 4 more;
## 3 attributes confirmed unimportant: V2, V3, V6;
##
## Подтвержденные (Confirmed) признаки:
## [1] "V1" "V5" "V7" "V8" "V9" "V10" "V11" "V12" "V13"
##
## Все важные признаки (включая Tentative):
## [1] "V1" "V5" "V7" "V8" "V9" "V10" "V11" "V12" "V13"
# Подробная таблица результатов
boruta_df <- attStats(boruta_result)
boruta_df <- boruta_df[order(-boruta_df$meanImp), ]
print(boruta_df)## meanImp medianImp minImp maxImp normHits decision
## V9 19.2281405 19.0627349 17.5889826 20.9190449 1.0000000 Confirmed
## V8 17.1647491 17.2255744 16.0336735 18.5525852 1.0000000 Confirmed
## V12 14.6326841 14.6095338 13.5595253 16.0775580 1.0000000 Confirmed
## V11 11.8977619 11.8484607 10.9347533 13.6520570 1.0000000 Confirmed
## V7 11.7026875 11.5169965 10.5127703 13.4896943 1.0000000 Confirmed
## V10 9.8662368 9.7266893 8.6477478 11.3131795 1.0000000 Confirmed
## V1 9.5563296 9.7071000 8.4255686 10.7247899 1.0000000 Confirmed
## V13 9.4438214 9.5489762 8.1005306 10.7881019 1.0000000 Confirmed
## V5 9.2426781 9.2313179 8.1108460 10.5140883 1.0000000 Confirmed
## V2 1.1557680 1.1576551 -0.2474598 2.7423660 0.1666667 Rejected
## V6 0.9886679 1.3615721 -1.1013954 1.9852132 0.0000000 Rejected
## V3 -0.9877372 -0.7333367 -3.4162909 0.3794342 0.0000000 Rejected
# Построение boxplot
plot(boruta_result, las = 2, cex.axis = 0.7,
xlab = "", main = "Boruta Feature Importance - Ozone Dataset")# Сохранение графика
jpeg("plots/boruta_boxplot.jpg", width = 1000, height = 600, quality = 100)
plot(boruta_result, las = 2, cex.axis = 0.7,
xlab = "", main = "Boruta Feature Importance - Ozone Dataset")
dev.off()## png
## 2
# Попытка определить статус Tentative признаков
boruta_final <- TentativeRoughFix(boruta_result)
print(boruta_final)## Boruta performed 24 iterations in 1.718744 secs.
## 9 attributes confirmed important: V1, V10, V11, V12, V13 and 4 more;
## 3 attributes confirmed unimportant: V2, V3, V6;
##
## Финальный список подтвержденных признаков:
## [1] "V1" "V5" "V7" "V8" "V9" "V10" "V11" "V12" "V13"
Выводы:
Алгоритм Boruta использует метод случайного леса для определения важности признаков, сравнивая их с “теневыми” (shadow) признаками.
Признаки классифицируются на три категории:
Для набора данных Ozone наиболее важными признаками оказались метеорологические параметры (температура, влажность, давление), что соответствует научным представлениям о факторах, влияющих на концентрацию озона.
Box plot наглядно показывает распределение важности каждого признака по итерациям алгоритма, а также сравнение с теневыми признаками (shadowMin, shadowMean, shadowMax).
В данной лабораторной работе были изучены различные методы выбора признаков и дискретизации данных:
Пакет caret предоставляет широкий набор методов машинного обучения и удобные средства визуализации для разведочного анализа данных.
Пакет FSelector позволяет оценить важность признаков различными методами на основе теории информации и статистических тестов.
Пакет arules предлагает гибкие методы дискретизации непрерывных переменных с различными стратегиями определения границ интервалов.
Пакет Boruta реализует надежный алгоритм выбора признаков на основе случайного леса с использованием теневых атрибутов.
## R version 4.5.2 (2025-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: CachyOS
##
## Matrix products: default
## BLAS: /usr/lib/libblas.so.3.12.0
## LAPACK: /usr/lib/liblapack.so.3.12.0 LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=en_US.UTF-8
## [9] LC_ADDRESS=en_US.UTF-8 LC_TELEPHONE=en_US.UTF-8
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=en_US.UTF-8
##
## time zone: Europe/Samara
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] mlbench_2.1-6 Boruta_9.0.0 arules_1.7.13 Matrix_1.7-4 FSelector_0.34
## [6] caret_7.0-1 lattice_0.22-7 ggplot2_4.0.2
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 xfun_0.56 bslib_0.10.0
## [4] recipes_1.3.1 rJava_1.0-14 vctrs_0.7.1
## [7] tools_4.5.2 generics_0.1.4 stats4_4.5.2
## [10] parallel_4.5.2 tibble_3.3.1 pkgconfig_2.0.3
## [13] ModelMetrics_1.2.2.2 data.table_1.18.2.1 RColorBrewer_1.1-3
## [16] S7_0.2.1 lifecycle_1.0.5 compiler_4.5.2
## [19] farver_2.1.2 stringr_1.6.0 codetools_0.2-20
## [22] htmltools_0.5.9 class_7.3-23 sass_0.4.10
## [25] yaml_2.3.12 prodlim_2025.04.28 pillar_1.11.1
## [28] jquerylib_0.1.4 MASS_7.3-65 entropy_1.3.2
## [31] cachem_1.1.0 gower_1.0.2 iterators_1.0.14
## [34] rpart_4.1.24 foreach_1.5.2 nlme_3.1-168
## [37] parallelly_1.46.1 lava_1.8.2 tidyselect_1.2.1
## [40] digest_0.6.39 stringi_1.8.7 future_1.69.0
## [43] dplyr_1.2.0 reshape2_1.4.5 purrr_1.2.1
## [46] listenv_0.10.0 RWekajars_3.9.3-2 splines_4.5.2
## [49] fastmap_1.2.0 grid_4.5.2 cli_3.6.5
## [52] magrittr_2.0.4 randomForest_4.7-1.2 survival_3.8-3
## [55] future.apply_1.20.1 withr_3.0.2 scales_1.4.0
## [58] lubridate_1.9.5 timechange_0.4.0 rmarkdown_2.30
## [61] globals_0.19.0 nnet_7.3-20 RWeka_0.4-46
## [64] timeDate_4052.112 ranger_0.18.0 evaluate_1.0.5
## [67] knitr_1.51 hardhat_1.4.2 rlang_1.1.7
## [70] Rcpp_1.1.1 glue_1.8.0 pROC_1.19.0.1
## [73] ipred_0.9-15 jsonlite_2.0.0 R6_2.6.1
## [76] plyr_1.8.9