Pull to refresh

Tidymodels: аккуратное машинное обучение в R

Reading time14 min
Views3.1K
Original author: Rebecca Barter

Мой канал - https://t.me/tidy_mng

Последнее время пакет tidymodels активно развивается в направлении задач машинного обучения.

Почему tidymodels? В R есть некоторая несогласованность между библиотеками, что является результатом разных подходов в их разработке.

Несколько лет назад Макс Кун разработал пакет caret, целью которого было создать единую платформу для моделей машинного обучения, существующих в R. Caret был прекрасен во многих отношениях, но далек от идеала. Но это был прекрасный старт. В связи с этим RStudio пригласила Макса Куна для разработки “аккуратной” версии данного пакета. В итоге, мы получили tidymodels.

Что такое tidymodels?

Tidymodels, как и tidyverse, состоит из нескольких библиотек. К основным можно отнести:

  • rsample — для разделения выборки;

  • recipes — для предварительной обработки;

  • parsnip — для определения модели;

  • yardstick — для оценки модели;

  • tune — для процедуры настройки параметров;

  • workflows — для объединения предварительных процедур.

Чтобы установить весь набор библиотек, которые содержатся в tidymodels — выполните команду:

install.packages("tidymodels") #устанавливаем библеотеку
library(tidymodels) #запускаем библиотеку
── Attaching packages ──────────────────────────────────────── tidymodels 1.0.0 ──
✔ broom        1.0.0     ✔ recipes      1.0.1
✔ dials        1.0.0     ✔ rsample      1.1.0
✔ dplyr        1.0.9     ✔ tibble       3.1.8
✔ ggplot2      3.3.6     ✔ tidyr        1.2.0
✔ infer        1.0.2     ✔ tune         1.0.0
✔ modeldata    1.0.0     ✔ workflows    1.0.0
✔ parsnip      1.0.0     ✔ workflowsets 1.0.0
✔ purrr        0.3.4     ✔ yardstick    1.0.0

Набор данных

Мы будем использовать набор данных, в котором содержится информация о статусе диабета женщин племени Пима.

Информация о данных:

  • pregnant — кол-во беременностей;

  • glucose — концентрация глюкозы в крови;

  • pressure — артериальное давление;

  • triceps — толщина кожной складки трицепса;

  • insulin — 2-часовой сывороточный инсулин;

  • mass — индекс массы тела;

  • pedigree — функция родословной;

  • age — возраст;

  • diabetes — переменная класса (тест на диабет)

#Загрузим набор данных из библиотеки mlbench
library(mlbench)
data(PimaIndiansDiabetes)

#Для простоты работы, переименум наш набор данных
diabetes_orig <- as_tibble(PimaIndiansDiabetes)
diabetes_orig
# A tibble: 768 × 9
   pregnant glucose pressure triceps insulin  mass pedigree   age diabetes
      <dbl>   <dbl>    <dbl>   <dbl>   <dbl> <dbl>    <dbl> <dbl> <fct>   
 1        6     148       72      35       0  33.6    0.627    50 pos     
 2        1      85       66      29       0  26.6    0.351    31 neg     
 3        8     183       64       0       0  23.3    0.672    32 pos     
 4        1      89       66      23      94  28.1    0.167    21 neg     
 5        0     137       40      35     168  43.1    2.29     33 pos     
 6        5     116       74       0       0  25.6    0.201    30 neg     
 7        3      78       50      32      88  31      0.248    26 pos     
 8       10     115        0       0       0  35.3    0.134    29 neg     
 9        2     197       70      45     543  30.5    0.158    53 pos     
10        8     125       96       0       0   0      0.232    54 pos     
# … with 758 more rows

Поверхностный анализ показывает, что в данных много нулей. Стоит отметить, что, например, индекс массы тела или толщина кожной складки трицепса не могут быть равны нулю. Это означает, что пропущенные значения в нашем наборе данных, записывались как “0”. 

Построим гистограмму по triceps, чтобы убедиться в нашем предположении:

ggplot(diabetes_orig) +
  geom_histogram(aes(x = triceps))

Эта проблема актуальная также для параметров: glucose, pressure, insulin, mass. Давайте заменим все нули в этих данных на NA. 

diabetes_clean <- diabetes_orig %>%
  mutate(across(c(glucose:mass), na_if, 0))
# A tibble: 768 × 9
   pregnant glucose pressure triceps insulin  mass pedigree   age diabetes
      <dbl>   <dbl>    <dbl>   <dbl>   <dbl> <dbl>    <dbl> <dbl> <fct>   
 1        6     148       72      35      NA  33.6    0.627    50 pos     
 2        1      85       66      29      NA  26.6    0.351    31 neg     
 3        8     183       64      NA      NA  23.3    0.672    32 pos     
 4        1      89       66      23      94  28.1    0.167    21 neg     
 5        0     137       40      35     168  43.1    2.29     33 pos     
 6        5     116       74      NA      NA  25.6    0.201    30 neg     
 7        3      78       50      32      88  31      0.248    26 pos     
 8       10     115       NA      NA      NA  35.3    0.134    29 neg     
 9        2     197       70      45     543  30.5    0.158    53 pos     
10        8     125       96      NA      NA  NA      0.232    54 pos     
# … with 758 more rows

Разделим данные на тестовую и обучающую выборки 

Для начала, разделим наш набор данных на обучающую и тестовые выборки. Обучающая выборка будет использоваться для подгонки нашей модели и настройки ее параметров, а тестовая — для оценки производительности нашей модели.

Это разделение мы можем выполнить автоматически с помощью функции inital_split() (из пакета rsample), которая создает специальный объект “split”.

set.seed(234589)
#разделим на обучение (75%) и на тест (25%)
diabetes_split <- initial_split(diabetes_clean, 
                                prop = 3/4)
diabetes_split
<Training/Testing/Total>
<576/192/768>

Выводимый результат diabetes_split, сообщает нам, сколько наблюдений у нас есть в обучающем наборе, тестовом наборе и сколько в общем наблюдений: <train/test/total>.

Обучающие и тестовые наборы могут быть извлечены из объекта diabetes_split с помощью функций training() и testing(). Хотя, на самом деле, мы не будем использовать эти объекты в конвейере (нам понадобится сам объект diabetes_split).

#извлекам обучающие и тестовые наборы
diabetes_train <- training(diabetes_split)
diabetes_test <- testing(diabetes_split)

В дальнейшем мы захотим выполнить некоторые настройки параметров. Для этого нам понадобится метод кросс-валидации. Для создания такого набора данных мы воспользуемся функцией vfold_cv().

#создадим объект кросс-валидации из обучающего набора 
diabetes_cv <- vfold_cv(diabetes_train)
diabetes_cv
#  10-fold cross-validation 
# A tibble: 10 × 2
   splits           id    
   <list>           <chr> 
 1 <split [518/58]> Fold01
 2 <split [518/58]> Fold02
 3 <split [518/58]> Fold03
 4 <split [518/58]> Fold04
 5 <split [518/58]> Fold05
 6 <split [518/58]> Fold06
 7 <split [519/57]> Fold07
 8 <split [519/57]> Fold08
 9 <split [519/57]> Fold09
10 <split [519/57]> Fold10

Определим “рецепт”

"Рецепты" позволяют указать роль каждой переменной в качестве результата или предиктора, а также любые шаги предварительной обработки, которые мы хотим провести (например, нормализация, PCA и т. д.).

Создание “рецепта” состоит из двух частей:

  • Указать формулу (recipe()): необходимо указать переменную результата и переменные предиктора.

  • Указать шаги предварительной обработки (step_zzz()): такие как: работа с пропущенными значениями, создание фиктивных переменных, масштабирование и многое другое.

Например, мы можем сделать следующий “рецепт”:

#определяем recipe
diabetes_recipe <- 
  #который состоит из формулы (исход ~ предикторы)
  recipe(diabetes ~ pregnant + glucose + pressure + triceps + 
           insulin + mass + pedigree + age, 
         data = diabetes_clean) %>%
  #и некоторые этапы предварительной обработки
  step_normalize(all_numeric()) %>%
  step_impute_knn(all_predictors())

Иные функции пакета вы можете найти здесь.

В приведённом выше примере мы использовали функции all_numeric() и all_predictors() в качестве аргументов предварительной обработки. Такие функции называются - «ролевыми селекторами» и указывают, что мы хотим применить шаг ко "всем числовым" переменным или "всем предикторным переменным". Список всех потенциальных селекторов ролей можно найти, набрав ?selections в консоли.

Обратите внимание, что мы работаем с исходным объектом данных diabetes_clean, а не diabetes_train или diabetes_split. В целом, мы могли бы использовать любой из них, так как все, что "рецепт" "берет" - это имена и роли переменных результата и предиктора. Позже мы применим этот рецепт к конкретным наборам данных.

Если мы распечатаем сводку по объекту diabetes_recipe, то убедимся в выше сказанном:

diabetes_recipe
Recipe

Inputs:

      role #variables
   outcome          1
 predictor          8

Operations:

Centering and scaling for all_numeric()
K-nearest neighbor imputation for all_predictors()

Если вы хотите извлечь предварительно обработанный набор данных, то вы можете сначала использовать prep(), а на следующем шаге, при помощи функции juice(), извлечь результат. На самом деле данный шаг не обязателен, так как он будет выполнен "под капотом" при подгонке модели.

diabetes_train_preprocessed <- diabetes_recipe %>%
  # применяем рецепт к обучающим данным
  prep(diabetes_train) %>%
  # извлекаем предварительно обработанный набор данных
  juice()
diabetes_train_preprocessed
A tibble: 576 × 9
   pregnant glucose pressure triceps insulin     mass pedigree     age diabetes
      <dbl>   <dbl>    <dbl>   <dbl>   <dbl>    <dbl>    <dbl>   <dbl> <fct>   
 1   1.23   -0.390    0.262   0.892   -0.317 -0.656      0.502 -0.201  pos     
 2   0.0447  1.09    -0.0616 -0.0348  -0.219 -0.168     -0.400  0.301  neg     
 3   1.82    1.91    -0.224   0.595    0.146  0.379     -0.813  0.301  neg     
 4  -1.14   -0.0948  -0.710  -0.591   -0.522 -0.311      3.76  -1.04   neg     
 5  -0.548   0.233    0.424   0.706    0.239  1.56       2.25  -0.201  pos     
 6   0.637  -0.0620  -1.84   -0.683    0.190 -0.771      2.53  -0.0335 pos     
 7  -0.844  -1.64    -2.01   -1.05    -0.629 -1.73      -0.445 -0.953  neg     
 8  -0.548  -0.423   -1.68   -0.313   -0.735  0.00505   -0.460 -0.953  neg     
 9  -1.14    0.463   -0.386   1.17     0.796  1.41      -0.320 -0.786  pos     
10   1.53    1.41     0.424   0.150    0.877  0.0482    -0.968  0.969  pos     
# … with 566 more rows

Укажем модель

Пока, мы только разделили наши данные на тестовую и обучающую выборки и указали шаги предварительной обработки данных при помощи пакета recipe. Следующее, что мы хотим сделать — нашу модель. Для этого мы воспользуемся пакетом parsnip.

Parsnip предлагает унифицированный интерфейс для огромного количества моделей, существующих в R. Это значит, что мы сможем при помощи одной строки кода строить различные модели, придерживаясь одной логики. 

Есть несколько основных компонентов, которые нам понадобятся для построения модели: 

  1. Тип модели: какую модель мы хотим. Для этого необходимо выбрать одну из нескольких функций, например: rand_forest() для случайного леса, logistic_reg() для логистической регрессии, svm_poly()для сингулярное разложения. С полным перечнем функций можно ознакомиться здесь.

  2. Аргументы: значения параметров модели (указывааются последовательно в разных моделях), задаем с помощью set_args().

  3. Движок: базовый пакет, из которого должна быть получена модель (например, ranger для реализации случайного леса), задаем с помощью set_engine().

  4. Режим: тип прогнозирования, так как различные пакеты могут выполнять как классификацию, так и регрессию. Задаем с помощью set_mode().

Например, если мы хотим подогнать модель случайного леса, реализованную пакетом ranger, для целей классификации, и хотим указать параметр mtry (количество случайно выбранных переменных, которые будут учитываться при каждом разбиении деревьев), то нам нужно задать следующую спецификацию модели:

rf_model <- 
  # указываем, что модель представляет собой случайный лес
  rand_forest() %>%
  # указываем `mtry` 
  set_args(mtry = tune()) %>%
  # выберите движок/пакет, лежащий в основе модели
  set_engine("ranger", importance = "impurity") %>%
  # выбрать режим регрессии или классификации
  set_mode("classification") 

Если вы хотите в дальнейшем посмотреть на оценки важности переменных в вашей модели, необходимо будет воспользоваться аргументом importance в set_engine. Для пакета ranger важными вариантами являются impurity или permutation.

В качестве другого примера воспользуемся пакетом glm для логистической регрессии:

lr_model <- 
  # указать, что что модель - логистическая регрессия
  logistic_reg() %>%
  # выбрать пакет, который лежит в основе модели
  set_engine("glm") %>%
  # выбрать режим регрессии или классификации
  set_mode("classification") 

Обратите внимание, что данный код плохо подходит для конечной модели. Во-первых, как и recipe, он просто описывает модель. Во-вторых, в этой спецификации модели ничего не относится к набору данных о диабете.

Кроме того, установка параметра tune() означает, что этот параметр будет настроен позже на этапе настройки конвейера (то есть, будет выбрано значение параметров, обеспечивающих наилучшую производительность). Но вы можете настроить этот параметр сами, если хотите контролировать модель, например, сделав это так: set_args(mtry = 4).

Соберем все в один рабочий процесс

Теперь мы готовы объединить модель и “рецепты” в один рабочий процесс. Это вы можете сделать при помощи workflow() из пакета workflows , куда передадите данные о модели и “рецепте”.

# установливаем рабочий процесс
rf_workflow <- workflow() %>%
  # добавляем "рецепт"
  add_recipe(diabetes_recipe) %>%
  # добавляем модель
  add_model(rf_model)

Обратите внимание, что мы еще не реализовали этапы предварительной обработки в “рецепте” и не подогнали модель. Мы написали основу. Только после того, как мы настроим параметры или подгоним модель, мы сможем получить результаты.

Настройка параметров

Поскольку у нас есть параметр mtry, нам необходимо настроить его (т. е. выбрать значение, обеспечивающее наилучшую производительность). Если у вас нет параметров для настройки, вы можете пропустить этот шаг.

Обратите внимание, что для настройки мы будем использовать объект кросс-валидации diabetes_cv. Для этого мы указываем диапазон значений mtry, которые мы хотим попробовать, а затем добавляем параметр tune_grid() в наш рабочий процесс, используя пакет tune. Нас интересует два показателя: accuracy и roc_auc (пакет yardstick). 

# укажите, какие значения вы хотите попробовать
rf_grid <- expand.grid(mtry = c(3, 4, 5))

# извлекаем результаты
rf_tune_results <- rf_workflow %>%
  tune_grid(resamples = diabetes_cv, # объект кросс-валидации
            grid = rf_grid, # сетка значений, котрую мы пробуем
            metrics = metric_set(accuracy, roc_auc) # показатели, которые нас интересуют
  )

Вы можете настроить несколько параметров одновременно, использовав функцию expand.grid(). Например, expand.grid(mtry = c(3, 4, 5), trees = c(100, 500))

Всегда интересно посмотреть на результаты кросс-валидации. collect_metrics() — удобная функция, которую можно использовать для извлечения метрик, рассчитанных для объекта.

# посмотрим на результат
rf_tune_results %>%
  collect_metrics()
# A tibble: 6 × 7
   mtry .metric  .estimator  mean     n std_err .config             
  <dbl> <chr>    <chr>      <dbl> <int>   <dbl> <chr>               
1     3 accuracy binary     0.762    10  0.0108 Preprocessor1_Model1
2     3 roc_auc  binary     0.840    10  0.0116 Preprocessor1_Model1
3     4 accuracy binary     0.767    10  0.0130 Preprocessor1_Model2
4     4 roc_auc  binary     0.840    10  0.0128 Preprocessor1_Model2
5     5 accuracy binary     0.766    10  0.0108 Preprocessor1_Model3
6     5 roc_auc  binary     0.837    10  0.0118 Preprocessor1_Model3

И accuracy, и roc_auc, при mtry = 4 дают наилучшие результаты.

Завершение рабочего процесса

Мы хотим добавить в наш рабочий процесс слой, который соответствует настроенному параметру, т.е. установить такой mtry , который дал наилучшие результаты. Если вы не настроили никаких параметров, вы можете пропустить этот шаг.

Мы можем извлечь наилучшее значение для метрик точности, применив функцию select_best() к объекту tune.

param_final <- rf_tune_results %>%
  select_best(metric = "accuracy")
param_final
# A tibble: 1 × 2
   mtry .config             
  <dbl> <chr>               
1     4 Preprocessor1_Model2

Затем мы можем добавить этот параметр в рабочий процесс с помощью функции finalize_workflow().

rf_workflow <- rf_workflow %>%
  finalize_workflow(param_final)

Оценим модель на тестовом наборе

Теперь, когда мы определили наш рецепт, нашу модель и настроили параметры модели, мы готовы приступить к подгонке окончательной модели.

Поскольку вся информация содержится в объекте рабочего процесса (rf_workflow), мы применим функцию last_fit() к  rf_workflow в рамках разделенного объекта diabetes_split. Это позволит автоматически обучить модель, указанную в рабочем процессе, используя данные для обучения и произвести оценку на основе тестового набора.

rf_fit <- rf_workflow %>%
  last_fit(diabetes_split)

rf_fit
# Resampling results
# Manual resampling 
# A tibble: 1 × 6
  splits            id               .metrics .notes   .predictions .workflow 
  <list>            <chr>            <list>   <list>   <list>       <list>    
1 <split [576/192]> train/test split <tibble> <tibble> <tibble>     <workflow>

Обратите внимание, что создаваемый объект fit является объектом tibble со списком столбцов.

Эта замечательная особенность tidymodels упрощает взаимодействие с tidyverse. Хотя для реального использования этой связи требуется умение работать с purrr. Если вы хотите избежать пакета purrr, то существуют функции, которые позволяют достаточно легко извлекать необходимую нам информацию.

Так как мы используем объект diabetes_split, то метрики оцениваются только в тестовом наборе. Теперь, когда мы применим функцию collect_metrics() (напомним, что мы использовали ее при настройке параметров), она извлечет производительность конечной модели (поскольку rf_fit теперь состоит из одной конечной модели), примененной к тестовому набору.

test_performance <- rf_fit %>% collect_metrics()
test_performance
# A tibble: 2 × 4
  .metric  .estimator .estimate .config             
  <chr>    <chr>          <dbl> <chr>               
1 accuracy binary         0.792 Preprocessor1_Model1
2 roc_auc  binary         0.853 Preprocessor1_Model1

В целом производительность очень хорошая: accuracy 0.79 и AUC 0.85.

Вы также можете извлечь прогнозы тестового набора с помощью функции collect_predictions(). Обратите внимание, что в объекте прогнозов — 192 строки, которые соответствуют количеству наблюдений в тестовом наборе (это некоторое доказательство того, что они основаны на тестовом наборе, а не на тренировочном).

test_predictions <- rf_fit %>% collect_predictions()
test_predictions
# A tibble: 192 × 7
   id               .pred_neg .pred_pos  .row .pred_class diabetes .config        
   <chr>                <dbl>     <dbl> <int> <fct>       <fct>    <chr>          
 1 train/test split     0.365    0.635      3 pos         pos      Preprocessor1_…
 2 train/test split     0.213    0.787      9 pos         pos      Preprocessor1_…
 3 train/test split     0.765    0.235     11 neg         neg      Preprocessor1_…
 4 train/test split     0.511    0.489     13 neg         neg      Preprocessor1_…
 5 train/test split     0.594    0.406     18 neg         pos      Preprocessor1_…
 6 train/test split     0.356    0.644     26 pos         pos      Preprocessor1_…
 7 train/test split     0.209    0.791     32 pos         pos      Preprocessor1_…
 8 train/test split     0.751    0.249     50 neg         neg      Preprocessor1_…
 9 train/test split     0.961    0.0385    53 neg         neg      Preprocessor1_…
10 train/test split     0.189    0.811     55 pos         neg      Preprocessor1_…
# … with 182 more rows

Поскольку это всего лишь обычный tibble, мы можем сгенерировать матрицу ошибок.

test_predictions %>%
  conf_mat(truth = diabetes, estimate = .pred_class)
          Truth
Prediction neg pos
       neg 107  17
       pos  23  45

Мы также можем построить график распределения предсказанных вероятностей для каждого класса.

test_predictions %>%
  ggplot() +
  geom_density(aes(x = .pred_pos, fill = diabetes), 
               alpha = 0.5)

Вы можете использовать пакет purrr для извлечения прогнозов с помощью функции pull(). Следующий код делает почти то же самое, что и collect_predictions()

test_predictions <- rf_fit %>% pull(.predictions)
test_predictions
# A tibble: 192 × 6
   .pred_neg .pred_pos  .row .pred_class diabetes .config             
       <dbl>     <dbl> <int> <fct>       <fct>    <chr>               
 1     0.365    0.635      3 pos         pos      Preprocessor1_Model1
 2     0.213    0.787      9 pos         pos      Preprocessor1_Model1
 3     0.765    0.235     11 neg         neg      Preprocessor1_Model1
 4     0.511    0.489     13 neg         neg      Preprocessor1_Model1
 5     0.594    0.406     18 neg         pos      Preprocessor1_Model1
 6     0.356    0.644     26 pos         pos      Preprocessor1_Model1
 7     0.209    0.791     32 pos         pos      Preprocessor1_Model1
 8     0.751    0.249     50 neg         neg      Preprocessor1_Model1
 9     0.961    0.0385    53 neg         neg      Preprocessor1_Model1
10     0.189    0.811     55 pos         neg      Preprocessor1_Model1
# … with 182 more rows

Установка и использование окончательной модели

В предыдущем разделе оценивалась модель, обученная на тренировочных данных. Но как только вы определили свою окончательную модель, вы хотите обучить ее на своем полном наборе данных, а затем использовать ее для прогнозирования. Для этого вам нужно применить функцию fit() в вашем рабочем процессе.

final_model <- fit(rf_workflow, diabetes_clean)

Объект final_model содержит несколько вещей, включая объект ranger, обученный с параметрами, установленными с помощью рабочего процесса, содержащегося в rf_workflow, на основе данных в diabetes_clean

final_model
══ Workflow [trained] ════════════════════════════════════════════════════════════
Preprocessor: Recipe
Model: rand_forest()

── Preprocessor ──────────────────────────────────────────────────────────────────
2 Recipe Steps

• step_normalize()
• step_impute_knn()

── Model ─────────────────────────────────────────────────────────────────────────
Ranger result

Call:
 ranger::ranger(x = maybe_data_frame(x), y = y, mtry = min_cols(~4,      x), importance = ~"impurity", num.threads = 1, verbose = FALSE,      seed = sample.int(10^5, 1), probability = TRUE) 

Type:                             Probability estimation 
Number of trees:                  500 
Sample size:                      768 
Number of independent variables:  8 
Mtry:                             4 
Target node size:                 10 
Variable importance mode:         impurity 
Splitrule:                        gini 
OOB prediction error (Brier s.):  0.1583874 

Если бы мы хотели предсказать статус диабета для новой женщины из племени Пима, мы бы обратились к функции predict().

Создадим пример, для новой женщины.

new_woman <- tribble(~pregnant, ~glucose, ~pressure, ~triceps, ~insulin, ~mass, ~pedigree, ~age,
                     2, 95, 70, 31, 102, 28.2, 0.67, 47)
new_woman
# A tibble: 1 × 8
  pregnant glucose pressure triceps insulin  mass pedigree   age
     <dbl>   <dbl>    <dbl>   <dbl>   <dbl> <dbl>    <dbl> <dbl>
1        2      95       70      31     102  28.2     0.67    47

Прогнозируемый диабетический статус для новой женщины - “отрицательный”.

predict(final_model, new_data = new_woman)
# A tibble: 1 × 1
  .pred_class
  <fct>      
1 neg        

Оценка важности переменных

Если вы хотите извлечь оценки важности из своей модели, вам нужно применить функцию extract_fit_parsnip(), а затем извлечь объект fit, который содержится в выводе:

ranger_obj <- extract_fit_parsnip(final_model)$fit
ranger_obj
Ranger result

Call:
 ranger::ranger(x = maybe_data_frame(x), y = y, mtry = min_cols(~4,      x), importance = ~"impurity", num.threads = 1, verbose = FALSE,      seed = sample.int(10^5, 1), probability = TRUE) 

Type:                             Probability estimation 
Number of trees:                  500 
Sample size:                      768 
Number of independent variables:  8 
Mtry:                             4 
Target node size:                 10 
Variable importance mode:         impurity 
Splitrule:                        gini 
OOB prediction error (Brier s.):  0.1583874 

Затем вы можете извлечь оценки важности при помощи объекта $variable.importance

ranger_obj$variable.importance
pregnant  glucose pressure  triceps  insulin     mass pedigree      age 
16.40687 79.68408 17.08361 22.10685 52.27195 42.60717 30.12246 33.19040 

Tags:
Hubs:
Total votes 5: ↑5 and ↓0+5
Comments2

Articles