Давайте временно обновим эту серию статей о машинном обучении вручную. В настоящее время завершена поддержка векторной машины SVM, дерева решений, KNN, байесовской, линейной регрессии и логистической регрессии. Для других алгоритмов, пожалуйста, позвольте Taoye отдать должное здесь сначала Позже будет время наверстать упущенное.
Это обновление также получило положительные отзывы от некоторых читателей. Хотя это не так много, я очень благодарен за вашу поддержку, и я надеюсь, что каждый читатель, прочитавший его, сможет что-то почерпнуть.
Все содержание этой серии статей написано Таойе исключительно от руки.Также есть отсылки ко многим книгам и общедоступным ресурсам.Общее количество слов в серии около 15W (включая исходный код), которые будут заполнены позже.Подробнее технические статьи могут посетить общественность Taoye.Циничный кодер. Документ можно распространять свободно, но будьте осторожны, не изменяйте его содержание.
Если в статье есть какие-либо вопросы, которые вы не понимаете, вы можете задать их напрямую, и Taoye ответит, как только они ее увидят.В то же время каждый может прийти сюда, чтобы напомнить Taoye в частном порядке:Циничный кодер, в официальном аккаунте также есть личная контактная информация Таое. Несколько слов, Таойе может говорить с тобой тайно только там (#`О')
Чтобы улучшить опыт чтения для всех, серия статей Taoye по машинному обучению была организована в видеPDF и HTML, эффект чтения очень хороший,Ответьте на [666] под официальным аккаунтом [Cynical Coder], чтобы получить его бесплатно.
В предыдущей статье,«Машинное обучение в действии» — Taoye рассказывает, что за «призрак» представляет собой дерево решенийОн в основном описывает теоретическое содержание деревьев решений, какие деревья решений вводятся, а также три критерия принятия решений, которые необходимо предпочтительно выбирать при создании деревьев решений. Если вы изучали SVM или читали несколько статей по SVM, написанных Taoye ранее, вы можете обнаружить, что дерево решений намного проще, чем SVM, и не так много сложных выводов формулы.
Давайте немного рассмотрим предыдущий контент:
- Чем выше информационный прирост признака атрибута, тем он должен быть предпочтительно выбран логически.Он часто используется валгоритм
- Чем выше коэффициент усиления атрибутивной функции, тем логически предпочтительнее выбирать ее.алгоритм
- Индекс признаков атрибутов Никки низкий, и его следует выбирать в первую очередь в соответствии с разумом.Он часто используется валгоритм
С предыдущим содержанием в качестве основы чтение этой статьи будет очень легким. В этой статье в основном описываются следующие части:
- Вручную постройте дерево решений на основе алгоритма ID3 и визуализируйте его с помощью Matplotlib.
- Предсказание классификации на основе уже построенного дерева решений
- Как сохранить и прочитать построенную модель дерева решений?
- Через набор данных Iris используйте Sklearn для построения дерева решений,
1. Вручную построить дерево решений на основе алгоритма ID3 и визуализировать его через Matplotlib
Существует несколько алгоритмов построения деревьев решений, таких как ID3, C4.5, CART и т. д. Из-за ограниченности места, времени и энергии в этой статье для построения в основном используется алгоритм ID3, а используемые критерии принятия решений (индикаторы) ) — прирост информации, упомянутый в предыдущей статье. Что касается алгоритмов C4.5 и CART для построения деревьев решений, заинтересованные читатели могут обратиться к содержанию коэффициента усиления и индекса Никки в предыдущем выпуске.
Набор данных, необходимый для построения дерева решений, на этот раз по-прежнему представляет собой данные о кредите в Ли Ханге - «Статистические методы обучения», вот снова набор данных для просмотра:
Как упоминалось ранее, алгоритм ID3 в основном основан на приросте информации в качестве критерия для выбора признаков атрибута.В последнем выпуске мы также рассчитали значение прироста информации, соответствующее каждому признаку атрибута, следующим образом:
В соответствии с процессом алгоритма ID3 мы можем знать, что атрибут с наибольшим информационным приростом должен быть выбран первым для принятия решения, то есть дом, то есть дом используется в качестве корневого узла решения. дерево. Поскольку признак свойства дома имеет два значения, получаются два подузла, один соответствует «иметь дом», а другой соответствует «отсутствию дома», а категории шести выборок «иметь дом» являются все разрешено давать взаймы.То есть есть однотипные точки выборки, значит должно бытьлистовой узел, а класс узла может быть помечен как "разрешенный".
Таким образом определяется наш корневой узел и один из конечных узлов. Затем нам нужно снова выбрать новый признак атрибута для набора образцов, соответствующий «нет дома», для принятия решения. Уведомление:Общая выборка данных для этого принятия решения – это уже не исходные данные, а все выборки, соответствующие «нет дома», что требует особого внимания.
Снова вычисляем информационный прирост, соответствующий другим признакам, в «бездомной» выборке данных. Допустим, что эта выборка данных записана как, результаты расчета следующие:
В том же анализе, что и выше, можно обнаружить, что значение прироста информации, соответствующее работе в это время, является самым высоким, то есть выбранным атрибутом второго приоритета является «работа». Кроме того, мы можем найти, что в выборке данныхСреди них всего 9, из которых 3 разрешено давать в долг, а 6 - отклонено, а метка результата и стоимость работы точно соответствуют друг другу, то есть тем, у кого есть работа, разрешено давать взаймы. , а тем, у кого нет работы, отказывают. . Таким образом, после завершения второго выбора атрибутивных признаков в это время генерируются два листовых узла, и результаты узлов соответствуют тому, есть ли работа.
Благодаря приведенному выше анализу мы получили дерево решений, построенное на основе алгоритма ID3, Дерево решений выглядит следующим образом:
Затем мы генерируем это дерево решений с помощью кода.Для данных с древовидной структурой мы можем сохранить его с помощью словаря или типа json. Например, дерево решений на рисунке выше, мы можем представить его следующими результатами:
{"房子": {
"1": "Y",
"0":{"工作": {
"1": "Y",
"0": "N"
}}
}}
Формат данных, представленный выше, обычно называется Json, который широко используется во внешнем и внутреннем интерфейсе, поисковых роботах или в различных других областях. Кроме того, мы можем обнаружить, что в процессе генерации дерева решений, после завершения выбора атрибутивного признака, атрибутивный признак необходимо выбрать снова с помощью той же операции, что фактически эквивалентно циклу, другими словами, он просто удовлетворяет рекурсивным характеристикам, просто наши данные в целом изменились. Теперь, когда мы выяснили тип, необходимый для сохранения древовидных данных, давайте реализуем его через код:
По сравнению с предыдущей статьей в коде есть три основных изменения для расчета прироста информации:
- Поскольку нам, наконец, нужно сгенерировать конкретное содержимое атрибута, а не только индекс, при создании данных, в дополнение к возврату самих данных, нам также необходимо вернуть соответствующий атрибут, изменить
establish_data
Метод выглядит следующим образом:
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建训数据集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 样本数据集相关信息,前面几项代表属性特征,最后一项表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
labels = ["年纪", "工作", "房子", "信用"]
return np.array(data), labels
- В предыдущей статье наш
handle_data
Метод заключается в том, чтобы просто найти образцы соответствующих значений признаков атрибута, например, найти все выборочные наборы данных молодых людей. Чтобы построить дерево решений, после первого выбора атрибута этот атрибут следует удалить из набора данных, поэтому изменитеhandle_data
следующее:
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:找出对应属性特征值的样本,比如找出所有年纪为青年的样本数据集
"""
def handle_data(data, axis, value):
result_data = list()
for item in data:
if item[axis] == value:
reduced_data = item[: axis].tolist()
reduced_data.extend(item[axis + 1:])
result_data.append(reduced_data)
return result_data
- В-третьих, необходимость в способе создания дерева решений.
establish_decision_tree
, конкретный код такой, где после выбора атрибута необходимо рекурсивно вызывать себя для выбора второго атрибута
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建决策树
"""
def establish_decision_tree(data, labels, feat_labels):
cat_list = [item[-1] for item in data]
if (cat_list.count(cat_list[0]) == len(cat_list)): return cat_list[0] # 数据集中的类别只有一种
best_feature_index = calc_information_gain(data) # 通过信息增益优先选取最好的属性特征
best_label = labels[best_feature_index] # 属性特征对应的标签内容
# feat_labels表示已选取的属性;新建一个决策树节点;将属性标签列表中删除已选取的属性
feat_labels.append(best_label); decision_tree = {best_label: dict()}; del(labels[best_feature_index])
feature_values = [item[best_feature_index] for item in data]
unique_values = set(feature_values) # 获取最优属性对应值的set集合
for value in unique_values:
sub_label = labels[:]
decision_tree[best_label][value] = establish_decision_tree(np.array(handle_data(data, best_feature_index, value)), sub_label, feat_labels)
return decision_tree
Полный код этого раздела выглядит так:
import numpy as np
import pandas as pd
np.__version__
pd.__version__
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建训数据集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 样本数据集相关信息,前面几项代表属性特征,最后一项表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
labels = ["年纪", "工作", "房子", "信用"]
return np.array(data), labels
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:找出对应属性特征值的样本,比如找出所有年纪为青年的样本数据集
"""
def handle_data(data, axis, value):
result_data = list()
for item in data:
if item[axis] == value:
reduced_data = item[: axis].tolist()
reduced_data.extend(item[axis + 1:])
result_data.append(reduced_data)
return result_data
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算最大的信息增益,并输出其所对应的特征索引
"""
def calc_information_gain(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
max_information_gain, best_feature = 0.0, -1 # 初始化最大信息增益和对应的特征索引
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy = 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
temp_information_gain = base_entropy - new_entropy # 计算信息增益
print("第%d个属性特征所对应的的增益为%.3f" % (index + 1, temp_information_gain)) # 输出每个特征的信息增益
if (temp_information_gain > max_information_gain):
max_information_gain, best_feature = temp_information_gain, index # 更新信息增益,确定的最大的信息增益对应的索引
return best_feature
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建决策树
"""
def establish_decision_tree(data, labels, feat_labels):
cat_list = [item[-1] for item in data]
if (cat_list.count(cat_list[0]) == len(cat_list)): return cat_list[0] # 数据集中的类别只有一种
best_feature_index = calc_information_gain(data) # 通过信息增益优先选取最好的属性特征
best_label = labels[best_feature_index] # 属性特征对应的标签内容
# feat_labels表示已选取的属性;新建一个决策树节点;将属性标签列表中删除已选取的属性
feat_labels.append(best_label); decision_tree = {best_label: dict()}; del(labels[best_feature_index])
feature_values = [item[best_feature_index] for item in data]
unique_values = set(feature_values) # 获取最优属性对应值的set集合
for value in unique_values:
sub_label = labels[:]
decision_tree[best_label][value] = establish_decision_tree(np.array(handle_data(data, best_feature_index, value)), sub_label, feat_labels)
return decision_tree
if __name__ == "__main__":
data, labels = establish_data()
print(establish_decision_tree(data, labels, list()))
результат операции:
{'房子': {'1': 'Y', '0': {'工作': {'1': 'Y', '0': 'N'}}}}
Видно, что результат выполнения кода точно такой же, как дерево решений, которое мы создали вручную, отлично, хахаха~~~
Тем не менее, вышеприведенное отображение дерева решений слишком недружественно для людей. Сгенерированное дерево решений относительно простое. Это лучше. Если созданное нами дерево решений относительно сложное, вывод дерева решений через данные в формате JSON.
В связи с этим нам необходимо визуализировать дерево решений, и для визуализации в основном используется пакет Matplotlib. По поводу использования Matplotlib вы можете обратиться к документации и другим материалам, а с обычно используемым им интерфейсом Taoye также позже разберется.
import numpy as np
import pandas as pd
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建训数据集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 样本数据集相关信息,前面几项代表属性特征,最后一项表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
labels = ["年纪", "工作", "房子", "信用"]
return np.array(data), labels
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:找出对应属性特征值的样本,比如找出所有年纪为青年的样本数据集
"""
def handle_data(data, axis, value):
result_data = list()
for item in data:
if item[axis] == value:
reduced_data = item[: axis].tolist()
reduced_data.extend(item[axis + 1:])
result_data.append(reduced_data)
return result_data
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算最大的信息增益,并输出其所对应的特征索引
"""
def calc_information_gain(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
max_information_gain, best_feature = 0.0, -1 # 初始化最大信息增益和对应的特征索引
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy = 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
temp_information_gain = base_entropy - new_entropy # 计算信息增益
print("第%d个属性特征所对应的的增益为%.3f" % (index + 1, temp_information_gain)) # 输出每个特征的信息增益
if (temp_information_gain > max_information_gain):
max_information_gain, best_feature = temp_information_gain, index # 更新信息增益,确定的最大的信息增益对应的索引
return best_feature
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建决策树
"""
def establish_decision_tree(data, labels, feat_labels):
cat_list = [item[-1] for item in data]
if (cat_list.count(cat_list[0]) == len(cat_list)): return cat_list[0] # 数据集中的类别只有一种
best_feature_index = calc_information_gain(data) # 通过信息增益优先选取最好的属性特征
best_label = labels[best_feature_index] # 属性特征对应的标签内容
# feat_labels表示已选取的属性;新建一个决策树节点;将属性标签列表中删除已选取的属性
feat_labels.append(best_label); decision_tree = {best_label: dict()}; del(labels[best_feature_index])
feature_values = [item[best_feature_index] for item in data]
unique_values = set(feature_values) # 获取最优属性对应值的set集合
for value in unique_values:
sub_label = labels[:]
decision_tree[best_label][value] = establish_decision_tree(np.array(handle_data(data, best_feature_index, value)), sub_label, feat_labels)
return decision_tree
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:统计决策树当中的叶子节点数目,以及决策树的深度
"""
def get_leaf_number_and_tree_depth(decision_tree):
leaf_number, first_key, tree_depth = 0, next(iter(decision_tree)), 0; second_dict = decision_tree[first_key]
for key in second_dict.keys():
if type(second_dict.get(key)).__name__ == "dict":
temp_number, temp_depth = get_leaf_number_and_tree_depth(second_dict[key])
leaf_number, curr_depth = leaf_number + temp_number, 1 + temp_depth
else: leaf_number += 1; curr_depth = 1
if curr_depth > tree_depth: tree_depth = curr_depth
return leaf_number, tree_depth
from matplotlib.font_manager import FontProperties
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:绘制节点
"""
def plot_node(node_text, center_pt, parent_pt, node_type):
arrow_args = dict(arrowstyle = "<-")
font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14) # 设置字体
create_plot.ax1.annotate(node_text, xy=parent_pt, xycoords='axes fraction',
xytext=center_pt, textcoords='axes fraction',
va="center", ha="center", bbox=node_type, arrowprops=arrow_args, FontProperties=font)
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:标注有向边的值
"""
def tag_text(cntr_pt, parent_pt, node_text):
x_mid = (parent_pt[0] - cntr_pt[0]) / 2.0 + cntr_pt[0]
y_mid = (parent_pt[1] - cntr_pt[1]) / 2.0 + cntr_pt[1]
create_plot.ax1.text(x_mid, y_mid, node_text, va="center", ha="center", rotation=30)
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:绘制决策树
"""
def plot_tree(decision_tree, parent_pt, node_text):
decision_node = dict(boxstyle="sawtooth", fc="0.8")
leaf_node = dict(boxstyle = "round4", fc = "0.8")
leaf_number, tree_depth = get_leaf_number_and_tree_depth(decision_tree)
first_key = next(iter(decision_tree))
cntr_pt = (plot_tree.xOff + (1.0 + float(leaf_number)) / 2.0 / plot_tree.totalW, plot_tree.yOff)
tag_text(cntr_pt, parent_pt, node_text); plot_node(first_key, cntr_pt, parent_pt, decision_node)
second_dict = decision_tree[first_key]
plot_tree.yOff = plot_tree.yOff - 1.0 / plot_tree.totalD
for key in second_dict.keys():
if type(second_dict[key]).__name__ == 'dict': plot_tree(second_dict[key], cntr_pt, str(key))
else:
plot_tree.xOff = plot_tree.xOff + 1.0 / plot_tree.totalW
plot_node(second_dict[key], (plot_tree.xOff, plot_tree.yOff), cntr_pt, leaf_node)
tag_text((plot_tree.xOff, plot_tree.yOff), cntr_pt, str(key))
plot_tree.yOff = plot_tree.yOff + 1.0 / plot_tree.totalD
from matplotlib import pyplot as plt
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建决策树
"""
def create_plot(in_tree):
fig = plt.figure(1, facecolor = "white")
fig.clf()
axprops = dict(xticks = [], yticks = [])
create_plot.ax1 = plt.subplot(111, frameon = False, **axprops)
leaf_number, tree_depth = get_leaf_number_and_tree_depth(in_tree)
plot_tree.totalW, plot_tree.totalD = float(leaf_number), float(tree_depth)
plot_tree.xOff = -0.5 / plot_tree.totalW; plot_tree.yOff = 1.0
plot_tree(in_tree, (0.5,1.0), '')
plt.show()
if __name__ == "__main__":
data, labels = establish_data()
decision_tree = establish_decision_tree(data, labels, list())
print(decision_tree)
print("决策树的叶子节点数和深度:", get_leaf_number_and_tree_depth(decision_tree))
create_plot(decision_tree)
Результат ручной визуализации дерева решений выглядит так:
Честно говоря, ручная визуализация деревьев решений с помощью Matplotlib действительно немного неудобна для программистов, у которых нет предыдущего опыта. приведенный выше кодПросто пойми, нет необходимости держаться за него, я представлю его позжепройти черезGraphviz
нарисовать дерево решений. Вот краткое описание приведенного выше кода:
-
get_leaf_number_and_tree_depth
Он в основном используется для подсчета количества листовых узлов в дереве решений и глубины дерева решений. Выбратьkey
соответствующийvalue
,судитьvalue
Является ли это типом словаря, если нет, это означает, что это конечный узел, если это так, это означает, что он не является конечным узлом.Разные ситуации обрабатываются по-разному. -
plot_node
Метод используется для рисования узлов.Тип шрифта задается здесь под окнами.Если это linux, то требуются дополнительные настройки. -
tag_text
Значение атрибута, используемое для обозначения направленного ребра, здесь оно в основном отмечено 1 и 0. 1 означает подтверждение атрибута, а 0 означает отрицание. -
plot_tree
Обход и рисование дерева решений, здесь вам нужно вызвать несколько методов, определенных ранее
2. Предсказание классификации на основе уже построенного дерева решений
После построения дерева решений на основе обучающих данных мы можем выполнить классификацию, применив модель дерева решений к фактическим данным. При классификации данных необходимо использовать дерево решений и вектор меток для построения дерева решений, затем программа сравнивает тестовые данные со значениями на дереве решений и рекурсивно выполняет процесс, пока не попадет в лист node; наконец, тестовые данные определяются как тип, к которому принадлежит конечный узел. - «Машинное обучение на практике»
Вполне понятно классифицировать тестовые данные исходя из того, что получена модель дерева решений.
Для этого мы определяемclassify
метод классификации:
"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:通过决策树模型对测试数据进行分类
"""
def classify(decision_tree, best_feature_labels, test_data):
first_node = next(iter(decision_tree))
second_dict = decision_tree[first_node]
feat_index = best_feature_labels.index(first_node)
for key in second_dict.keys():
if int(test_data[feat_index]) == int(key):
if type(second_dict[key]).__name__ == "dict": # 为字典说明还没到叶子节点
result_label = classify(second_dict[key], best_feature_labels, test_data)
else: result_label = second_dict[key]
return result_label
Мы тестируем четыре выборки данных соответственно, выборки (с домом, без работы), (с домом, с работой), (без дома, без работы), (без дома, с работой), используя список, чтобы указать, что они [1, 0], [1, 1], [0, 0], [0, 1], результаты следующие:
Видно, что все четыре набора данных могут быть успешно классифицированы.
3. Как сохранить и прочитать построенную модель дерева решений?
После построения дерева решений, если мы хотим сохранить модель, мы можем перейтиpickle
модуль для продолжения.
После сохранения модели нет необходимости повторно обучать модель в следующий раз, просто загрузите модель. Пример кода для сохранения и загрузки модели выглядит следующим образом (он очень простой, поэтому я не буду говорить больше):
import pickle
with open("DecisionTreeModel.txt", "wb") as f:
pickle.dump(decision_tree, f) # 保存决策树模型
f = open("DecisionTreeModel.txt", "rb")
decision_tree = pickle.load(f) # 加载决策树模型
В-четвертых, через набор данных радужной оболочки (Iris) используйте Sklearn для построения дерева решений.
Теперь мы используем sklearn для реализации небольшого случая, Набор данных — это набор данных Iris, который обычно используется в машинном обучении. Для получения дополнительных сведений о классификации дерева решений вы можете перейти кsklearn.tree.DecisionTreeClassifier
Узнайте из документации:SCI kit-learn.org/stable/Modu…
Основной интерфейс, используемый для реализации классификации дерева решений в sklearn:sklearn.tree.DecisionTreeClassifier
, это в основном для построения модели дерева решений с помощью набора выборок данных. Кроме того, если мы хотим визуализировать дерево решений, нам также нужно использоватьexport_graphviz
. Конечно, в sklearn.tree есть и другие интерфейсы, которые вы можете вызвать.Я не буду вводить здесь слишком много, и читатели могут изучить их сами.
оsklearn.tree.DecisionTreeClassifier
Для использования, пожалуйста, обратитесь к:SCI kit-learn.org/stable/Modu…. Есть много встроенных параметров, которые в основном записываются здесь.8 параметров, что также удобно для последующего просмотра.Другие имеют возможность использовать его для поиска информации:
-
criterion
: Стандарт для выбора атрибута, значение по умолчаниюgini
, вы также можете выбратьentropy
,gini
значение Джини,entropy
это информационная энтропия, об этих двух мы уже говорили в предыдущей статье -
splitter
: Критерии выбора для узлов деления функций, по умолчанию являются лучшими и могут быть установлены как случайные. Значение по умолчанию «наилучшее» подходит, когда размер выборки невелик, а если размер выборки данных очень велик, при построении дерева решений рекомендуется «случайный». -
max_depth
: максимальная глубина дерева решений, по умолчанию — None. **Следует отметить, что эта глубина не включает корневой узел. ** Как правило, это значение можно игнорировать, если данных или признаков мало. Если модель имеет большой размер выборки и большое количество признаков, рекомендуется ограничить максимальную глубину, Конкретное значение зависит от распределения данных. -
max_features
: максимальное количество признаков, которые следует учитывать при разделении, по умолчанию — «Нет». Вообще говоря, если количество образцов невелико, например, менее 50, мы можем использовать значение по умолчанию «Нет».Если количество признаков очень велико, мы можем гибко использовать другие значения для управления максимальным количеством особенности, учитываемые при делении, с Контролирует время генерации дерева решений. Проверяйте документацию, когда она вам понадобится. -
min_samples_split
: Минимальное количество выборок, необходимое для внутреннего подразделения узла, по умолчанию 2. То есть, например, количество выборок, соответствующих одному из наших атрибутов, меньше, чемmin_samples_split
, даже если он удовлетворяет условию выбора приоритета, он все равно будет устранен. -
min_samples_leaf
: минимальное количество выборок для листовых узлов, по умолчанию 1. этоЗначение ограничивает минимальное количество выборок конечных узлов.Если количество конечных узлов меньше количества выборок, оно будет отсечено вместе с родственными узлами. Листовому узлу требуется минимальное количество выборок, то есть сколько выборок необходимо для подсчета конечного узла в конце листового узла.. Если установлено значение 1, даже если в этой категории всего 1 образец, будет построено дерево решений. -
max_leaf_nodes
: максимальное количество конечных узлов, по умолчанию — None. Ограничив максимальное количество конечных узлов, можно предотвратить переоснащение. Если ограничение добавлено, алгоритм построит оптимальное дерево решений в пределах максимального количества конечных узлов. Если признаков не много, это значение можно не учитывать, но если признаков много, то его можно ограничить, а конкретное значение получить через перекрестную проверку. -
random_state
: Начальное значение случайного числа, по умолчанию — None. Если случайное число не задано, случайное число связано с текущим системным временем, которое в каждый момент времени разное. Если установлено начальное число случайного числа, то одно и то же начальное число случайного числа будет генерировать одно и то же случайное число в разное время.
Кроме того, вDecisionTreeClassifier
Существует также много методов, которые можно вызвать ниже.Подробности см. в документации по использованию:
Далее воспользуемся sklearn для классификации набора данных радужной оболочки. Использованная литература:SCI kit-learn.org/stable/auto…
Код самого дерева решений построить несложно, в основном в визуализации, которая задействует множество операций Matplotlib для усиления эффекта визуализации.Полный код выглядит следующим образом:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier, plot_tree
class IrisDecisionTree:
"""
Explain:属性的初始化
Parameters:
n_classes: 鸢尾花的类别数
plot_colors: 不同类别花的颜色
plot_step: meshgrid网格的步长
"""
def __init__(self, n_classes, plot_colors, plot_step):
self.n_classes = n_classes
self.plot_colors = plot_colors
self.plot_step = plot_step
"""
Explain: 通过load_iris构建数据集
"""
def establish_data(self):
iris_info = load_iris()
return iris_info.data, iris_info.target, iris_info.feature_names, iris_info.target_names
"""
Explain:分类的可视化
"""
def show_result(self, x_data, y_label, feature_names, target_names):
# 选取两个属性来构建决策树,以方便可视化,其中列表内部元素代表属性对应的索引
for index, pair in enumerate([[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]):
sub_x_data, sub_y_label = x_data[:, pair], y_label
clf = DecisionTreeClassifier().fit(sub_x_data, sub_y_label) # 选取两个属性构建决策树
plt.subplot(2, 3, index + 1)
x_min, x_max = sub_x_data[:, 0].min() - 1, sub_x_data[:, 0].max() + 1 # 第一个属性
y_min, y_max = sub_x_data[:, 1].min() - 1, sub_x_data[:, 1].max() + 1 # 第二个属性
xx, yy = np.meshgrid(np.arange(x_min, x_max, self.plot_step), np.arange(y_min, y_max, self.plot_step))
plt.tight_layout(h_pad=0.5, w_pad=0.5, pad=2.5)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape) # 预测meshgrid内部每个元素的分类
cs = plt.contourf(xx, yy, Z, cmap = plt.cm.RdYlBu) # 绘制带有颜色的网格图
plt.xlabel(feature_names[pair[0]]); plt.ylabel(feature_names[pair[1]]) # 标注坐标轴标签
for i, color in zip(range(self.n_classes), self.plot_colors):
idx = np.where(sub_y_label == i)
plt.scatter(sub_x_data[idx, 0], sub_x_data[idx, 1], c=color, label=target_names[i],
cmap=plt.cm.RdYlBu, edgecolor='black', s=15) # 绘制数据样本集的散点图
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14) # 定义中文字体
plt.suptitle("通过决策树对鸢尾花数据进行可视化", fontproperties=font)
plt.legend(loc='lower right', borderpad=0, handletextpad=0)
plt.axis("tight")
plt.figure()
clf = DecisionTreeClassifier().fit(x_data, y_label) # 针对鸢尾花数据集的多重属性来构建决策树
plot_tree(clf, filled=True)
plt.show()
if __name__ == "__main__":
iris_decision_tree = IrisDecisionTree(3, "ryb", 0.02)
x_data, y_label, feature_names, target_names = iris_decision_tree.establish_data()
iris_decision_tree.show_result(x_data, y_label, feature_names, target_names)
Результат запуска следующий:
Визуализируя результаты, мы можем обнаружить, что есть два основных результата, и мы объясним их отдельно: Для набора данных радужной оболочки всего имеется четыре атрибутивных функции и три результата метки. Для облегчения визуализации на первой картинке выбираются только два атрибута для построения дерева решений.Четыре атрибута, выбираются два.Это очень просто.Каждый, кто изучал перестановку и комбинацию,должен знать,что существуютКаждое субизображение в первом изображении соответствует одной возможности. И разные цвета представляют разные классификации.Если цвет набора данных соответствует цвету внутри сетки, классификация верна. Поэтому интуитивно выбираяsepal length和petal length
Дерево решений, построенное по этим двум атрибутам, относительно хорошее. И второй рисунок — построить дерево решений для всех признаков атрибутов в наборе данных. Конкретные результаты можно просмотреть, запустив приведенный выше код самостоятельно (поскольку установлен шрифт шрифта, приведенный выше код необходимо запускать в Windows)
Мы можем обнаружить, что когда приведенный выше код визуализирует дерево решений, он используетsklearn.tree.plot_tree
, мы также упомянули, когда объясняли, как рисовать деревья решений через Matplotlib, используяgraphviz
Вы также можете визуализировать деревья решений, давайте посмотрим ниже!
graphviz
Вы не можете использовать pip для установки, и это будет очень медленно при использовании anaconda для установки, и даже несколько попыток могут не установить.Это произошло несколько дней назад, когда я помогал своим одноклассникам установить (это случай под окнами, это будет очень удобно в среде linux), поэтому здесь мы используем прямой проходwhl
файл для установки.
Предложение: для Pyer, который некоторое время использует Python, часто будут устанавливаться некоторые сторонние модули, некоторые из которых могут быть решены с помощью pip или conda, а некоторые будут сталкиваться с различными неизвестными ошибками в процессе установки. Поэтому читатели, столкнувшиеся с ошибками в процессе установки, могут попытаться пройтиwhl
файл для установки,whl
целевой адрес:Ууху. Парикмахерская. UCI. Квота / ~ идти будет немедленно / Пак Ючон…, который объединяет различные модули Pythonwhl
документ.
Откройте указанный выше URL-адрес -->ctrl + f
поискgraphviz
--> Требуется загрузкаgraphviz
установочный файл
Выполните установку по локальному целевому пути:
pip install graphviz‑0.15‑py3‑none‑any.whl
Кроме того, для Windows вам также необходимо перейти на официальный сайт, чтобы установить exe-файл графвиза, а затем добавить каталог bin в переменную среды. Адрес загрузки исполняемого файла:graphviz.org/download/
Если вы пользователь Linux, это удобнее, вы можете установить его напрямую через команду:
$ sudo apt install graphviz # Ubuntu
$ sudo apt install graphviz # Debian
На данный момент Graphviz установлен. Давайте воспользуемся им, чтобы визуализировать дерево решений, вIrisDecisionTree
добавить нижеshow_result_by_graphviz
метод:
"""
Explain:通过graphviz实现决策树的可视化
"""
def show_result_by_graphviz(self, x_data, y_label):
clf = DecisionTreeClassifier().fit(x_data, y_label)
iris_dot_data = tree.export_graphviz(clf, out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True, rounded=True,
special_characters=True)
import graphviz
graph = graphviz.Source(iris_dot_data); graph.render("iris")
После запуска в текущем каталоге будет сгенерирован pdf-файл, представляющий собой дерево решений после визуализации. Примечание. Вышеприведенное является простой классификацией дерева решений радужной оболочки, читатели могут посредничатьDecisionTreeClassifier
Параметры различных деревьев решений строятся для оценки плюсов и минусов каждого дерева решений.
Выше приведено полное содержание этой статьи. Здесь временно обновляется соответствующее содержимое дерева решений. Другое содержимое, такое как переобучение, обрезка и т. д., будет обновлено позже. Следующая серия статей о машинном обучении будет посвящена нелинейной модели СВМ печени.
не говори больше~~~
Я Taoye, я люблю учиться, делиться и люблю различные технологии. В свободное время я люблю играть в шахматы, слушать музыку и говорить об анимации. Я надеюсь использовать это для записи моего собственного процесса роста и жизни. Я также надеюсь, что смогу завести больше друзей-единомышленников в кругу, и приглашаю посетить WeChat Princess для получения большего количества контента:Циничный кодер.
Использованная литература:
[1] «Машинное обучение на практике»: издательство Питера Харрингтона «Народная почта и телекоммуникации».
[2] «Статистические методы обучения»: Li Hang, второе издание, издательство Университета Цинхуа.
[3] «Машинное обучение»: Чжоу Чжихуа, издательство Университета Цинхуа.
[4] Пакеты расширений Python:Ууху. Парикмахерская. UCI. Квота / ~ идти будет немедленно / Пак Ючон…
[5] sklearn.tree.DecisionTreeClassifier:SCI kit-learn.org/stable/Modu…
[6] Официальный сайт Graphviz:graphviz.org/
Рекомендуемое чтение
«Машинное обучение в действии» — Taoye расскажет, что за «призрак» представляет собой дерево решений
«Машинное обучение в действии» — анализ машин опорных векторов и оптимизация SMO
«Машинное обучение в действии» — анализ машин опорных векторов, разрыв линейного SVM одной рукой
print("Привет, NumPy!")
Что ты не можешь сделать, сначала поешь
Таойе проникла в штаб-квартиру черной платформы, и правда, стоящая за этим, была чрезвычайно ужасающей.
«База данных Dahua» — когда выполняется оператор SQL, какие небольшие действия выполняет нижний уровень?
В те годы Git, в который мы играли, действительно ароматный
Создание среды глубокого обучения на основе блокнота Ubuntu+Python+Tensorflow+Jupyter
Причудливый синтаксический анализ веб-страницы
Рука об руку, чтобы помочь вам понять технологию контейнеров Docker