1. Работа с пакетом CARET

library(caret)
models <- names(getModelInfo())
length(models)
## [1] 239
head(models, 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"

Команда names(getModelInfo()) выводит список доступных методов машинного обучения в пакете caret.

Графический разведочный анализ

set.seed(123)
x <- matrix(rnorm(50*5), ncol=5)
y <- factor(rep(c("A", "B"), 25))
colnames(x) <- paste0("X", 1:5)

Boxplot

jpeg("plots/caret_box.jpg", width=1600, height=1200, res=200)
featurePlot(x=x, y=y, plot="box")
dev.off()
## quartz_off_screen 
##                 2

Density

jpeg("plots/caret_density.jpg", width=1600, height=1200, res=200)
featurePlot(x=x, y=y, plot="density")
dev.off()
## quartz_off_screen 
##                 2

Pairs

jpeg("plots/caret_pairs.jpg", width=1600, height=1200, res=200)
featurePlot(x=x, y=y, plot="pairs")
dev.off()
## quartz_off_screen 
##                 2

Вывод:
Признаки были сгенерированы случайным образом с помощью функции rnorm(), поэтому распределения классов A и B существенно перекрываются. Чёткое разделение классов по отдельным признакам отсутствует, что говорит о низкой информативности данных в данном примере.


2. Определение важности признаков (FSelector)

library(FSelector)
data(iris)

ig <- information.gain(Species ~ ., iris)
ig[order(-ig$attr_importance), , drop=FALSE]
##              attr_importance
## Petal.Width        0.9554360
## Petal.Length       0.9402853
## Sepal.Length       0.4521286
## Sepal.Width        0.2672750

Вывод:
Наиболее информативными признаками для классификации вида ириса являются Petal.Length и Petal.Width. Признаки Sepal.Length и Sepal.Width обладают меньшей значимостью. Следовательно, характеристики лепестков оказывают наибольшее влияние на определение класса.


3. Дискретизация переменной (arules)

library(arules)

x_cont <- iris$Petal.Length
summary(x_cont)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   1.000   1.600   4.350   3.758   5.100   6.900

Метод interval (равная ширина)

d_interval <- discretize(x_cont, method="interval", categories=4)
table(d_interval)
## d_interval
##    [1,2.48) [2.48,3.95) [3.95,5.43)  [5.43,6.9] 
##          50          11          61          28

Метод frequency (равная частота)

d_frequency <- discretize(x_cont, method="frequency", categories=4)
table(d_frequency)
## d_frequency
##    [1,1.6) [1.6,4.35) [4.35,5.1)  [5.1,6.9] 
##         37         38         33         42

Метод cluster (кластеризация)

d_cluster <- discretize(x_cont, method="cluster", categories=4)
table(d_cluster)
## d_cluster
##    [1,2.77) [2.77,4.52) [4.52,5.45)  [5.45,6.9] 
##          50          37          35          28

Метод fixed (заданные границы)

d_fixed <- discretize(
  x_cont,
  method="fixed",
  breaks=c(-Inf, 2, 4, 5.5, Inf),
  labels=c("short","medium","long","very_long")
)
table(d_fixed)
## d_fixed
##     short    medium      long very_long 
##        50        11        61        28

Вывод:
Метод interval формирует интервалы одинаковой ширины, но количество объектов в них может различаться. Метод frequency распределяет объекты равномерно по интервалам. Метод cluster формирует интервалы на основе естественной структуры данных. Метод fixed позволяет задавать интервалы вручную и удобен при наличии экспертных порогов.


4. Отбор признаков с помощью Boruta (Ozone)

library(mlbench)
library(Boruta)

data("Ozone")
oz <- na.omit(Ozone)

target <- names(oz)[ncol(oz)]
form <- as.formula(paste(target, "~ ."))

set.seed(123)
bor <- Boruta(form, data=oz, doTrace=1)
bor
## Boruta performed 33 iterations in 3.242922 secs.
##  9 attributes confirmed important: V1, V10, V11, V12, V4 and 4 more;
##  3 attributes confirmed unimportant: V2, V3, V6;

Boxplot важности признаков

jpeg("plots/boruta_boxplot.jpg", width=1800, height=1200, res=200)
plot(bor, las=2, cex.axis=0.8)
dev.off()
## quartz_off_screen 
##                 2

Итоговые признаки

getSelectedAttributes(bor, withTentative = TRUE)
## [1] "V1"  "V4"  "V5"  "V7"  "V8"  "V9"  "V10" "V11" "V12"
bor_fixed <- TentativeRoughFix(bor)
getSelectedAttributes(bor_fixed, withTentative = FALSE)
## [1] "V1"  "V4"  "V5"  "V7"  "V8"  "V9"  "V10" "V11" "V12"

Вывод:
Алгоритм Boruta сравнивает важность реальных признаков с теневыми (shadow features). В результате признаки делятся на Confirmed, Rejected и Tentative. По графику boxplot видно, какие признаки значительно превосходят уровень случайного шума и являются наиболее информативными для модели.