Перейти к содержимому

DecisionTreeClassifier

DecisionTreeClassifier — модель классификации, которая принимает решение как последовательность простых вопросов.

Дерево решений похоже на обычную инструкцию:

  • если условие выполнено, идём по одной ветке;
  • если не выполнено, идём по другой;
  • в конце попадаем в лист дерева, где записан ответ.

Такую модель удобно объяснять: она не просто выдаёт класс, но и показывает путь рассуждения.

Дерево решений подбирает вопросы к признакам так, чтобы лучше разделить объекты разных классов.

Например, в задаче одобрения кредита модель может задавать вопросы:

  • возраст клиента меньше или равен некоторому порогу?
  • зарплата меньше или равна некоторому порогу?

Каждый вопрос делит данные на две части. После нескольких таких делений дерево приходит к одному из классов: Одобрить или Отказать.

В примере есть небольшая таблица клиентов. По возрасту и зарплате модель учится предсказывать, надо ли одобрить кредит.

uses MLABC;
begin
var df := DataFrame.FromCsvText('''
Возраст,Зарплата,Одобрить кредит
17,25,Отказать
64,80,Одобрить
18,22,Отказать
20,36,Одобрить
38,37,Отказать
49,59,Одобрить
55,74,Одобрить
25,70,Отказать
29,33,Отказать
31,102,Одобрить
33,88,Отказать
''');
var featureNames := ['Возраст', 'Зарплата'];
var X := df.ToMatrix(featureNames);
var target := df.EncodeTarget('Одобрить кредит');
var model := new DecisionTreeClassifier;
model.Fit(X, target.Labels);
var view := model.Tree(featureNames, target.ClassNames);
// Вывод дерева решений
Println(view);
// Новый клиент
var example := [20.0, 100.0];
var pred := model.PredictOne(example);
Println('Возраст:', example[0]);
Println('Зарплата:', example[1]);
Println('Одобрить кредит:', target.ClassNames[pred]);
end.
Возраст ≤ 43.5?
├── ✓ Зарплата ≤ 95?
│ ├── ✓ Возраст ≤ 22.5?
│ │ ├── ✓ Возраст ≤ 19?
│ │ │ ├── ✓ → Отказать
│ │ │ └── ✗ → Одобрить
│ │ └── ✗ → Отказать
│ └── ✗ → Одобрить
└── ✗ → Одобрить

Символ означает, что условие выполнено, а — что условие не выполнено.

Например, для нового клиента:

Возраст: 20
Зарплата: 100
Одобрить кредит: Одобрить

Дерево сначала проверяет возраст, затем зарплату и по веткам приходит к ответу Одобрить.

Первая строка — корень дерева:

Возраст ≤ 43.5?

Это первый вопрос, который модель задаёт про объект. Если ответ “да”, движение идёт по ветке ; если “нет” — по ветке .

Строки со стрелкой — листья дерева. В них находится итоговый класс.

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

В отличие от KNN, дерево не ищет соседей. В отличие от логистической регрессии, оно не строит одну прямую границу. Оно строит набор правил вида “если признак меньше порога, идти налево, иначе направо”.

В большинстве учебных примеров можно использовать настройки по умолчанию:

var model := new DecisionTreeClassifier;

Иногда полезно ограничить сложность дерева:

  • maxDepth — максимальная глубина дерева;
  • minSamplesSplit — сколько объектов должно быть в узле, чтобы его можно было делить дальше;
  • minSamplesLeaf — минимальное число объектов в листе.

Например:

var model := new DecisionTreeClassifier(maxDepth := 3);

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

Дереву решений обычно не нужен StandardScaler.

Модель сравнивает признаки с порогами: например, Возраст ≤ 43.5 или Зарплата ≤ 95. Поэтому ей не так важно, что один признак измеряется годами, а другой — тысячами рублей.

  • Легко объяснить: модель выглядит как набор правил.
  • Можно вывести дерево и посмотреть, как принимается решение.
  • Обычно не требует масштабирования признаков.
  • Может строить нелинейные границы между классами.
  • Одно дерево легко переобучается.
  • Небольшое изменение данных может изменить структуру дерева.
  • Для сложных задач часто лучше работают ансамбли деревьев: RandomForestClassifier и GradientBoostingClassifier.