English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
С этого раздела начинается正式的 изучение алгоритмов.
Сначала мы изучим классический и эффективный классификационный алгоритм: алгоритм классификации решающего дерева.
1. Алгоритм решающего дерева
Решающее дерево использует древовидную структуру для классификации свойств образца, это наиболее интуитивный алгоритм классификации, и его также можно использовать для регрессии. Однако у него могут быть трудности при некоторых специальных логических классификациях. Типичными являются логические операции ИЛИ (XOR), решающее дерево не очень擅长 решать такие проблемы.
Строительство решающего дерева не является уникальным, к сожалению, строительство оптимального решающего дерева относится к NP-проблеме. Таким образом, как построить хорошее решающее дерево является важной задачей.
J. Ross Quinlan в 1975 году предложил引入 концепцию энтропии в строительство решающего дерева, это знаменитый алгоритм ID3. Следующие C4.5, C5.0, CART и т.д. являются улучшениями этого метода.
Энтропия - это уровень «беспорядка» и «хаоса». При первом знакомстве с этой концепцией может возникнуть некоторое замешательство. Чтобы быстро понять, как использовать增益 энтропии для разделения свойств, можно обратиться к статье этого兄弟а: Python Machine Learning Decision Tree Algorithm
Если вы все еще не понимаете, посмотрите на следующий пример.
Предположим, что нужно создать такое автоматическое решение для выбора хороших яблок, для простоты я позволю ему изучить только следующие 4 образца:
Образец Красный Большой Хороший яблоко
0 1 1 1
1 1 0 1
2 0 1 0
3 0 0 0
В этом образце есть 2 свойства, A0 означает, является ли яблоко красным. A1 означает, является ли яблоко большим.
Таким образом, информация энтропии этого образца перед классификацией составляет S = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1.
Информация энтропии 1 означает, что текущее состояние является наиболее хаотичным и хаотичным.
В этом примере всего 2 свойства. Таким образом, естественно, что всего может быть только 2 решающих дерева, как показано на рисунке ниже:
Конечно, решающее дерево слева, использующее A0 (красный) в качестве основания для разделения, превосходит решающее дерево справа, использующее A1 (размер) в качестве основания для разделения.
Конечно, это интуитивное понимание. Квантitative оценка требует вычисления增益 энтропии для каждого случая разделения.
Сначала выберем A0 для разделения, расчет информации энтропии для каждого подузла будет следующим:
У листовых узлов 0 и 1 есть 2 положительных примера, нет отрицательных примеров. Информация энтропии: e1 = -(2/2 * log(2/2) + 0/2 * log(0/2)) = 0.
У листовых узлов 2 и 3 нет положительных примеров, есть 2 отрицательных примера. Информация энтропии: e2 = -(0/2 * log(0/2) + 2/2 * log(2/2)) = 0.
Таким образом, выбор информации энтропии для каждого подузла после разделения A0 является весовой суммой доли информации энтропии каждого подузла: E = e1 * 2/4 + e2 * 2/4 = 0.
Выбор A0 для разделения增益 энтропии G(S, A0) = S - E = 1 - 0 = 1.
На самом деле, листья дерева решений представляют собой категории, которые уже都属于 один и тот же класс, поэтому энтропия всегда равна 0.
Таким же образом, если сначала выбрать A1 для разделения, энтропия каждого подузла будет рассчитываться следующим образом:
Подузел 0,2 содержит 1 положительный пример и 1 отрицательный пример. Энтропия: e1 = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1.
Подузел 1,3 содержит 1 положительный пример и 1 отрицательный пример. Энтропия: e2 = -(1/2 * log(1/2) + 1/2 * log(1/2)) = 1.
Таким образом, энтропия после разделения A1 равна весу каждого подузла энтропии умноженному на его долю: E = e1*2/4 + e2*2/4 = 1. То есть, это как если бы не разделяли!
Выбор A1 для разделения增益 энтропии G(S, A1) = S - E = 1 - 1 = 0.
Таким образом, перед каждым разделением нам нужно только вычислить разделение, которое дает наибольшую增益 энтропии.
2. Набор данных
Для удобства explanations и понимания мы используем следующий极为 простой тестовый набор данных:
1.5 50 thin
1.5 60 fat
1.6 40 thin
1.6 60 fat
1.7 60 thin
1.7 80 fat
1.8 60 thin
1.8 90 fat
1.9 70 thin
1.9 80 fat
Этот набор данных содержит 10 примеров, каждый из которых имеет два свойства: рост и вес, третий столбец - метка класса, которая показывает «полный» или «худой». Данные сохранены в файле 1.txt.
Наша задача - обучить классификатор решений, который на основе роста и веса человека сможет определить, является ли он полным или худым.
(Данные являются субъективными предположениями автора, имеют определенную логику, но игнорируйте их обоснованность)
Дерево решений очень естественно для двоичной логики «да» и «нет». А что делать, если в этой выборке рост и вес - непрерывные значения?
Хотя это и немного неудобно, но это не проблема, нужно только найти середину, которая разделяет эти непрерывные значения на разные интервалы, и это становится двоичной логической проблемой.
Задача этого примера классификации решений - найти некоторые критические значения роста и веса, классифицировать примеры параллельно по логике больше или меньше этих критических значений, строить дерево решений сверху вниз.
Использование библиотеки машинного обучения Python очень просто и элегантно.
3. Реализация на Python
Python код выполнения таков:
# -*- coding: utf-8 -*- import numpy as np import scipy as sp from sklearn import tree from sklearn.metrics import precision_recall_curve from sklearn.metrics import classification_report from sklearn.cross_validation import train_test_split '''Чтение данных''' data = [] labels = [] with open("data\\1.txt") as ifile: for line in ifile: tokens = line.strip().split(' ') data.append([float(tk) for tk in tokens[:-1]]) labels.append(tokens[-1]) x = np.array(data) labels = np.array(labels) y = np.zeros(labels.shape) '''Преобразование меток в 0/1''' y[labels=='fat']=1 '''Разделение обучающих и тестовых данных''' x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2) '''Использование энтропии в качестве критерия разделения для обучения決ьескового дерева''' clf = tree.DecisionTreeClassifier(criterion='entropy') print(clf) clf.fit(x_train, y_train) '''Запись структуры決策ового дерева в файл''' with open("tree.dot", 'w') as f: f = tree.export_graphviz(clf, out_file=f) '''Коэффициенты отражают влияние каждого признака. Больше означает, что признак играет более важную роль в классификации''' print(clf.feature_importances_) '''Вывод результатов тестирования''' answer = clf.predict(x_train) print(x_train) print(answer) print(y_train) print(np.mean( answer == y_train)) '''''Точность и召回''' precision, recall, thresholds = precision_recall_curve(y_train, clf.predict(x_train)) answer = clf.predict_proba(x)[:,1] print(classification_report(y, answer, target_names = ['thin', 'fat']))
Результаты выводятся примерно так:
[ 0.2488562 0.7511438]
array([[ 1.6, 60. ]],
[ 1.7, 60. ],
[ 1.9, 80. ],
[ 1.5, 50. ],
[ 1.6, 40. ],
[ 1.7, 80. ],
[ 1.8, 90. ],
[ 1.5, 60. ]])
array([ 1., 0., 1., 0., 0., 1., 1., 1.])
array([ 1., 0., 1., 0., 0., 1., 1., 1.])
1.0
precision recall f1-score support
thin 0.83 1.00 0.91 5
fat 1.00 0.80 0.89 5
avg / total 1.00 1.00 1.00 8
array([ 0., 1., 0., 1., 0., 1., 0., 1., 0., 0.])
array([ 0., 1., 0., 1., 0., 1., 0., 1., 0., 1.])
可以看出,при тестировании обученных данных точность составляет 100%. Однако при тестировании всех данных会出现一个分类错误的测试样本.
Извещается, что в данном примере правилам, поглощенным решающим деревом, соответствует хорошо, но прогнозируемость несколько хуже.
Здесь есть три момента, которые необходимо пояснить, и они будут использоваться в以后的 машинном обучении.
1. Разделите данные для обучения и тестирования.
Такое действие предназначено для удобства выполнения перекрестной проверки. Перекрестная проверка предназначена для полного тестирования стабильности классификатора.
0.2 в коде означает случайное выборку 20% данных для тестирования. Оставшиеся 80% используются для обучения決策ковой системы.
也就是说,从10个样本中随机选取8个进行训练。由于本文数据集较小,这里的目的是可以看到由于取的训练数据随机,每次构建的决策树都不一样。
2、特征的不同影响因子。
样本的不同特征对分类的影响权重差异很大。分类结束后,看看每个样本对分类的影响度也是很重要的。
在本例中,身高的权重为0.25,体重为0.75,可以看到重量的重要性远远高于身高。对于胖瘦的判断而言,这也是相当符合逻辑的。
3、准确率与召回率。
这两个值是评估分类准确率的一个重要标准。例如,代码的最后将所有10个样本输入分类器进行测试的结果:
测试结果:array([ 0., 1., 0., 1., 0., 1., 0., 1., 0., 0.])
真实结果:array([ 0., 1., 0., 1., 0., 1., 0., 1., 0., 1.])
将thin的准确率为0.83。因为分类器分出了6个thin,其中正确的有5个,因此将thin的准确率为5/6=0.83。
将thin的召回率为1.00。因为数据集中共有5个thin,而分类器将它们都分对了(尽管将一个fat分成了thin!),召回率5/5=1。
将fat的准确率为1.00。不再赘述。
将fat的召回率为0.80。因为数据集中共有5个fat,而分类器只分出了4个(将一个fat分成了thin!),召回率4/5=0.80。
在许多情况下,尤其是在数据分类难度较大的情况下,准确率与召回率往往是矛盾的。你可能需要根据你的需求找到最佳的一个平衡点。
例如,在本例中,你的目标是尽可能保证找到的胖子是真胖子(准确率),还是尽可能找到更多的胖子(召回率)。
代码还将决策树的结构写入到tree.dot中。打开该文件,可以轻松地绘制出决策树,还可以看到决策树的更多分类信息。
本文的tree.dot如下所示:
digraph Tree { 0 [label="X[1] <= 55.0000\n熵 = 0.954434002925\nsamples = 8", shape="box"] ; 1 [label="熵 = 0.0000\nsamples = 2\nvalue = [ 2. 0.]", shape="box"] ; 0 -> 1 ; 2 [label="X[1] <= 70.0000\nentropy = 0.650022421648\nsamples = 6", shape="box"] ; 0 -> 2 ; 3 [label="X[0] <= 1.6500\nentropy = 0.918295834054\nsamples = 3", shape="box"] ; 2 -> 3 ; 4 [label="entropy = 0.0000\nsamples = 2\nvalue = [ 0. 2.]", shape="box"] ; 3 -> 4 ; 5 [label="entropy = 0.0000\nsamples = 1\nvalue = [ 1. 0.]", shape="box"] ; 3 -> 5 ; 6 [label="entropy = 0.0000\nsamples = 3\nvalue = [ 0. 3.]", shape="box"] ; 2 -> 6 ; }
На основе этой информации, décision-tree должен быть следующим образом:
Вот весь контент этой статьи, надеюсь, он поможет вам в изучении, также希望大家多多支持呐喊教程。
Заявление: содержимое этой статьи взято из Интернета, авторские права принадлежат соответствующему автору. Контент предоставлен пользователями Интернета, автоматически загружен, сайт не имеет права собственности, не был отредактирован вручную и не несет ответственности за это. Если вы обнаружите содержимое,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма, пожалуйста, замените # на @) для отчета и предоставьте соответствующие доказательства. Если证实侵权, сайт немедленно удалил涉嫌侵权的内容。