Введение
В предыдущей статье в основном были представлены следующие аспекты:
- Введение в деревья решений
- Поток дерева решений
- Определение энтропии и как вычислить энтропию
- Определение прироста информации и как рассчитать прирост информации
- Разделите наборы данных в соответствии с полученной информацией
На основе нового набора данных (набора данных контактных линз) в этой статье реализовано построение деревьев решений, сохранение и загрузка деревьев решений, использование деревьев решений для классификации и визуализация деревьев решений. слишком много обзора, сосредоточенного на этих четырех аспектах.
Давайте сначала посмотрим на набор данных:
Этот источник данных из базы данных UCI, которая имеет 4 функции:age(возраст),prescript(симптом),astigmatic(вспышка),tearRate(скорость разрыва) и класс этикетки, который включает в себя твердые материалы, мягкие материалы и не должен носиться.
Для удобства обработки образцы обрабатывают следующим образом:
- возраст: молодой—>0, пред->1, пресбиопический—>2
- предписание: миопа — > 0, гипер — > 1
- астигматический: нет—>0, да—>1
- слезоточивость: пониженная—>0, нормальная—>1
В-четвертых, построение дерева решений
Прежде чем строить дерево решений, давайте рассмотрим принципы работы первых нескольких подмодулей: сначала получить исходный набор данных, а затем разделить набор данных на основе оптимальных признаков.Когда набор данных содержит более двух, после первого разделение, данные будут разделены на переход к следующему узлу в дереве, где данные разделены, процесс заключается в обработке набора данных с использованием принципа рекурсии.
Когда это закончится? Когда программа завершает работу над всеми свойствами всех разделенных наборов данных или всеми экземплярами, классификация всех экземпляров в каждой ветви заканчивается.
Процесс построения дерева решений состоит в том, чтобы заполнить словарь с данными, разделяемыми каждый раз. Когда заканчивается деление набора данных, заполнение данных в словарь также заканчивается. Этот процесс также является рекурсионным процессом, а также строительство Дерево решений завершено. код показывает, как показано ниже:
def CreateTree(DataSet):
#获取所有特征标签
index_list = list(DataSet.columns)
#获取最后一列(分类标签)的类别
label_series = DataSet.iloc[:,-1].value_counts()
#判断类别标签最多一个是否等于数据样本数、或者数据集是否只有一列
if label_series[0]==DataSet.shape[0] or DataSet.shape[1] == 1:
return label_series.index[0] #返回类标签
# 获取最优特征列索引
col = ChooseBF(DataSet)
# 获取最优特征
BestFeature = index_list[col]
#将最优特征依次填入字典中
TheTree = {BestFeature:{}}
# 从标签列表中删去该特征标签
del index_list[col]
#提取最佳切分列的所有属性值
value_list = set(DataSet.iloc[:,col])
#利用递归方法建树,每次对象为当前最优特征
for value in value_list:
TheTree[BeatFeature][value] = CreateTree(splitSet(DataSet,col,value))
return TheTree
Первое условие остановки рекурсивной функции состоит в том, что все метки классов одинаковы, а второе условие остановки рекурсивной функции состоит в том, что все признаки в наборе данных израсходованы, то есть набор данных не может быть далее разделен ; словарная переменная TheTree хранит всю информацию о дереве, BestFeature — текущий оптимальный признак.
Наконец, код перебирает все значения атрибутов текущего оптимального признака, рекурсивно вызывает функцию CreateTree() для каждого деления набора данных, а входящим параметром является набор данных после каждого деления, а возвращаемое значение будет вставлено в словарь TheTree , после завершения рекурсии в словарь будет вложено много данных, представляющих информацию о листовых узлах.
Словарь TheTree получается следующим образом:
{'tearRate': {0: 'no lenses', 1: {'astigmatic': {0: {'age': {0: 'soft', 1: 'soft', 2: {'prescript': {0: 'no lenses', 1: 'soft'}}}}, 1: {'prescript': {0: 'hard', 1: {'age': {0: 'hard', 1: 'no lenses', 2: 'no lenses'}}}}}}}}
Начиная слева, первый ключевой ключ — tearRate, это означает, что среди всех признаков признак tearRate имеет наибольший прирост информации, при этом признаке снижение (разделение) данных происходит быстрее всего, а значение этого ключевого слова равно также словарь. Второе ключевое слово представляет собой набор данных, разделенный функциями tearRate, а значения этих ключевых слов являются дочерними узлами узла tearRate.
Значения могут быть метками классов или другим словарем. Если значением является метка класса, дочерний узел является конечным узлом; если значением является другой словарь, дочерний узел является узлом суждения, и дерево решений формируется путем повторения этого формата.
5. Сохранение и загрузка деревьев решений
Есть много способов сохранить деревья решений, но принцип тот же, а именно сериализация и десериализация.Здесь представлены следующие два метода.
#第一种方法
np.save('TheTree.npy',TheTree)
read_tree = np.load('TheTree.npy',allow_pickle=True).item()
Первый метод заключается в использованииnumpyв библиотекеsaveметод, вы можете сохранить дерево решений в формате словаря какnpyфайл, при чтении дерева его нужно добавить после методаitem(), поскольку данные, которые мы храним, относятся к типу словаря, если это тип матрицы, их необходимо удалить.
#第二种方法
import pickle
def storeTree(inputTree, filename):
fw = open(filename,'wb')
pickle.dump(inputTree,fw)
fw.close()
def grabTree(filename):
fr = open(filename,'rb')
return pickle.load(fr)
Второй метод заключается в использованииpickleбиблиотекаdumpМетод сериализует данные и при чтении используетloadМетод может загружать данные, здесь следует отметить, что независимо от того, записываются они или читаются, они должны быть в двоичном формате, иначе произойдет ошибка.
6. Используйте классификацию дерева решений
После построения дерева решений его можно использовать для классификации фактических данных.При выполнении классификации данных вам необходимо передать дерево решений, список меток функций и тестовые данные для классификации. Затем программа будет сравнивать тестовые данные со значениями в дереве решений, рекурсивно выполнять процесс до тех пор, пока он не войдет в конечный узел, и окончательным результатом классификации будет тип конечного узла. код показывает, как показано ниже:
#传入的数据为决策树、数据集特征标签、测试数据
def classify(inputTree,labels,testVec):
#获取决策树的第一个节点
FirstStr = list(inputTree.keys())[0]
#取第一个节点外下一个字典
SecondDict = inputTree[FirstStr]
'''
{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
{0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}
{0: 'no', 1: 'yes'}
'''
#取第一个节点在labels里的索引
feat_index = labels.index(FirstStr)
#遍历字典中的key
for key in SecondDict.keys():
#比较testVec里的值与树节点的值,如果达到叶子节点,返回类标签
if testVec[feat_index]==key:
#如果下一个字典中的仍包含字典,则递归继续比较
if type(SecondDict[key])==dict :
classlabel = classify(SecondDict[key],labels,testVec)
else:
#直到最后取到类标签
classlabel = SecondDict[key]
return classlabel
где список меток функций передается вlabelsРоль заключается в том, чтобы помочь определить индекс каждой оптимальной функции в наборе данных, используяindexМетод находит в текущем списке первый элемент, соответствующий переменной FirstStr, затем код рекурсивно обходит все дерево и сравнивает тестовые данныеtestVecЗначение в переменной и значение узла дерева до тех пор, пока не будет достигнут конечный узел, и будет возвращена классификационная метка текущего узла.
Здесь мы используем дерево, построенное из данных предыдущей статьи, чтобы сделатьSecondDictНапример, его функция — получить значение оптимального признака (первого ключа) в текущем словаре для достижения эффекта рекурсивного сравнения с тестовыми данными.
classlabel = classify(inputTree,labels,[0,1,0,0])
'''
no lenses
'''
Выполняя эту функцию, можно сравнивать поступающие данные с данными в исходном тексте, а полученные результаты классификации согласуются.
Семь, визуализация дерева решений
Основное преимущество деревьев решений заключается в том, что они интуитивно понятны и просты для понимания. но черезmatplotlibРисование дерева решений из библиотеки — очень сложный процесс, и вот ленивое введение в относительно простой метод.
Graphviz — это инструмент для рисования графиков, который может рисовать множество графических структур, но входящие данные должны быть в точечном формате, поэтому здесь мы используемsklearnПолученное дерево решений визуализируется.
Graphviz нужно скачать вручную, а после установки настроить окружение, и добавить путь к папке в системную переменнуюPathи, наконец, введите cmddot -versionЕсли появится информация о версии, это означает, что конфигурация установки прошла успешно.
Код визуализации дерева решений выглядит следующим образом:
from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
import pydotplus
import graphviz
def pic_tree(DataSet):
#所有特征数据
feature_train = DataSet.iloc[:, :-1]
#类标签数据
the_label = DataSet.iloc[:, -1]
#unique将类标签去重
labels = the_label.unique().tolist()
#以类标签的在列表中的索引代替该标签——转化成数字
the_label = the_label.apply(lambda x: labels.index(x))
#训练数据
clf = DecisionTreeClassifier()
clf = clf.fit(feature_train, the_label)
#绘图过程
dot_data = tree.export_graphviz(clf, out_file=None, feature_names=['age','prescript','astigmatic','tearRate'],
class_names=['no lenses', 'soft','hard'], filled=True, rounded=True,
special_characters=True)
# 两种方法
# 1.利用graphviz库生成PDF图片
pic = graphviz.Source(dot_data)
pic.render('lense')
# 2.利用pydotplus库将Dot格式转成PDF
#graph = pydotplus.graph_from_dot_data(dot_data)
#return graph.write_pdf("lense.pdf")
Здесь также есть два способа сгенерировать изображение дерева решений: первый — использовать библиотеку graphviz.SourceМетод создает изображение в формате PDF. Второй метод должен использовать библиотеку pydotplus для преобразования формата Dot в PDF. Окончательное изображение визуализации выглядит следующим образом:
Суммировать
Таким образом, были введены соответствующие знания о деревьях решений.Вообще говоря, этот алгоритм классификации прост для понимания, но очень важен, поскольку закладывает основу для последующего обучения случайных лесов.Каждый алгоритм имеет свою подходящую среду. , и у деревьев решений тоже есть свои недостатки.
Преимущества деревьев решений:
- Вычислительная сложность невелика, а выходные результаты легко понять.
- Нечувствителен к промежуточным пропущенным значениям.
- Может обрабатывать нерелевантные данные о функциях.
- Деревья можно изобразить графически.
Недостатки деревьев решений:
- Переобучение происходит, когда дерево решений слишком сложное.
- Он относительно нестабилен, и когда данные изменяются относительно мало, это также приводит к созданию разных деревьев.
- Когда образцы не сбалансированы, разные веса могут привести к смещению дерева.
Официальный аккаунт [Toffee Cat] может получить исходный код и данные для справки, ответив на «контактные линзы» в фоновом режиме, спасибо за чтение.