Дерево решений и случайный лес
Дерево решений — логический алгоритм классификации, решающий задачи классификации и регрессии. Представляет собой объединение логических условий в структуру дерева.
Дерево решений
Определение: |
Дерево решений (англ. decision tree, DT) — алгоритм классификации
| , задающийся деревом (связным ациклическим графом), где:
Определение: |
Бинарное дерево решений — частный случай дерева решений, для которого | .
function classify(x):if else return
Информативность ветвления
Для того, чтобы оценивать качество разбиения объектов по предикату
Сначала оценим распределение значений классов объектов внутри каждого множества из разбиения, введя понятие меры неопределенности распределения.
Определение: |
Частотная оценка вероятности класса | в вершине :
Определение: |
Мера неопределенности (англ. impurity) распределения
где убывает и , например: , , | :
Примерами мер неопределенности распределения являются:
- Энтропия: , определяется для каждого множества из разбиения, — количество возможных классов, и — вероятность объекта принадлежать -ому классу.
- Критерий Джини:
Теперь определим суммарную неопределенность распределения в разбиении.
Определение: |
Неопределенность распределения | после ветвления вершины по предикату и разбиения :
Информационный выигрыш от разбиения определяется как изменение неопределенности в системе.
Определение: |
Информационный выигрыш от разбиения по предикату |
Рекурсивный алгоритм построения бинарного дерева решений ID3
Покажем идею построения дерева решения на частном случае бинарного дерева. Алгоритм
Проще всего записать этот алгоритм в виде рекурсивной процедуры , которая строит дерево по заданной подвыборке и возвращает его корневую вершину.
1:function ID3(): 2: if : , // создать листовую вершину c меткой класса 3: v = createLeafVertex( ) 4: return v // найти предикат с максимальным информационным выигрышом Gain( , ) // разбить выборку на две части по предикату 5: 6: 7: if || // найти класс, в котором находится большинство объектов из 8: = majorClass( ) 9: v = createLeafVertex( ) else // создать внутреннюю вершину 10: v = createVertex() 11: 12: = ID3( ) 13: = ID3( ) 14: return
Редукция решающих деревьев
Суть редукции (англ. pruning) состоит в удалении поддеревьев, имеющих недостаточную статистическую надёжность. При этом дерево перестаёт безошибочно классифицировать обучающую выборку, зато качество классификации новых объектов, как правило, улучшается. Рассмотрим наиболее простые варианты редукции.
Предредукция
Предредукция (англ. pre-pruning) или критерий раннего останова досрочно прекращает дальнейшее ветвление в вершине дерева, если информативность
Для этого на шаге 8 алгоритма условие или заменяется условием . Порог является управляющим параметром метода.
Предредукция считается не самым эффективным способом избежать переобучения, так как жадное ветвление по-прежнему остаётся глобально неоптимальным. Более эффективной считается cтратегия постредукции.
Постредукция
Постредукция (англ. post-pruning) просматривает все внутренние вершины дерева и заменяет отдельные вершины либо одной из дочерних вершин (при этом вторая дочерняя удаляется), либо терминальной вершиной. Процесс замен продолжается до тех
пор, пока в дереве остаются вершины, удовлетворяющие критерию замены.
Критерием замены является сокращение числа ошибок на контрольной выборке, отобранной заранее, и не участвовавшей в обучении дерева. Стандартная рекомендация — оставлять в контроле около 30% объектов.
Для реализации постредукции контрольная выборка пропускается через
построенное дерево. При этом в каждой внутренней вершине запоминается подмножество попавших в неё контрольных объектов. Если , то вершина считается ненадёжной и заменяется терминальной по мажоритарному правилу:
в качестве берётся тот класс, объектов которого больше всего в обучающей подвыборке , пришедшей в вершину .
Затем для каждой внутренней вершины вычисляется число ошибок, полученных при классификации выборки следующими способами:
- — классификация поддеревом, растущим из вершины ;
- — классификация поддеревом левой дочерней вершины ;
- — классификация поддеревом правой дочерней вершины ;
-
Эти величины сравниваются, и, в зависимости от того, какая из них оказалась
минимальной, принимается, соответственно, одно из четырёх решений:
- сохранить поддерево вершины ;
- заменить поддерево вершины поддеревом левой дочерней вершины ;
- заменить поддерево вершины поддеревом правой дочерней вершины ;
- заменить поддерево терминальной вершиной класса .
Алгоритмы построения деревьев решения
Недостатки рассмотренного алгоритма ID3:
- Применим только для дискретных значений признаков
- Переобучение
- На каждом шаге решение принимается по одному атрибуту
Алгоритм CART (англ. Classification And Regression Trees)
- В отличие от ID3 работает и с непрерывными значениями признаков: на каждом шаге построения дерева последовательно сравнивает все возможные разбиения для всех атрибутов и выбирает наилучший атрибут и наилучшее разбиение для него. Разбивает объекты на две части.
- Использует редукцию для избежания переобучения.
- Обрабатывает пропущенные или аномальные значения признаков.
Алгоритм C4.5
- Также работает и с непрерывными значениями признаков: на каждом шаге построения дерева выбирает правило разбиения по одному из признаков. Разбивает объекты на несколько частей по этому правилу, рекурсивно запускается из полученных подмножеств.
- Использует редукцию, чтобы избежать переобучения.
- Обрабатывает пропущенные или аномальные значения признаков.
Случайный лес
Случайный лес — один из примеров объединения классификаторов в ансамбль. Алгоритм случайного леса, состоящего из деревьев на основе обучающей выборки
for (n: 1,...,N): // сгенерировать выборку бутстрэпа = bootstrap( ) // построить решающее дерево по выборке = ID3( )c помощью бутстрэпа
Итоговый классификатор —
Таким образом, случайный лес — это бэггинг над решающими деревьями, при обучении которых для каждого разбиения признаки выбираются из некоторого случайного подмножества признаков.
Примеры использования (в scikit-learn)
- Для решения задач классификации и регрессии используют DecisionTreeClassifier, DecisionTreeRegressor
- В sklearn.ensemble также представлены методы классификации, основанные на ансамблях, в том числе: бэггинг и случайный лес, которые были описаны выше.
Так, в этом примере создается бэггинг ансамбль из классификаторов KNeighborsClassifier, каждый из которых обучен на случайных подмножествах из 50% объектов из обучающей выборки, и 50% случайно выбранных признаков.
from sklearn.ensemble import BaggingClassifier from sklearn.neighbors import KNeighborsClassifier bagging = BaggingClassifier(KNeighborsClassifier(), max_samples=0.5, max_features=0.5)
Пример использования классификатора на случайном лесе:
from sklearn import RandomForestClassifier from sklearn.datasets import make_classification // сгенерируем случайную обучающую выборку с классификацией по n_classes классам X, y = make_classification(n_samples=1000, n_features=4, n_classes = 5) // создадим классификатор на случайном лесе, состоящим из n_estimators деревьев clf = RandomForestClassifier(n_estimators=100, max_depth=2) // обучим классификатор на сгенерированном обучающем множестве clf.fit(X, y) clf.predict(0, 0, 0, 0)
Пример на языке Scala
SBT зависимость:
libraryDependencies += "com.github.haifengl" %% "smile-scala" % "1.5.2"
Пример классификации датасета и вычисления F1 меры[1] используя smile.classification.cart[2]:
import smile.classification._ import smile.data._ import smile.plot._ import smile.read import smile.validation.FMeasure
val iris: AttributeDataset = read.table("iris.csv", delimiter = ",", response = Some((new NumericAttribute("class"), 2))) val x: Array[Array[Double]] = iris.x() val y: Array[Int] = iris.y().map(_.toInt) val dt: DecisionTree = cart(x, y, 1000) val predictions: Array[Int] = x.map(dt.predict) val f1Score = new FMeasure().measure(predictions, y) plot(x, y, dt)
См. также
Источники информации
- Логические алгоритмы классификации — Лекция К. В. Воронцова
- Случайный лес — статья на Medium, Yury Kashnitskiy
- Деревья решений — scikit-learn.org
- Ансамбли классификаторов — scikit-learn.org.