English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Деревья решений обычно используются в машинном обучении для классификации.
Преимущества: низкая сложность вычислений, легко понимаемые результаты, нечувствительность к отсутствию промежуточных значений, может обрабатывать данные с несовместимыми признаками.
Недостатки: может возникнуть проблема чрезмерного соответствия.
Применяется к типам данных: числовым и категориальным.
1. Информация о增益е
Цель разделения данных заключается в том, чтобы сделать неупорядоченные данные более упорядоченными. Одним из методов организации хаотических данных является использование мер информации из теории информации. Как правило, используется информация о增益е, которая представляет собой уменьшение энтропии данных до и после их разделения. Информация с большей хаотичностью имеет большую энтропию, а наибольший增益 информации является лучшим выбором.
熵定义为信息的期望,符号xi的信息定义为:
其中p(xi)为该分类的概率。
熵,即信息的期望值为:
计算信息熵的代码如下:
def calcShannonEnt(dataSet): numEntries = len(dataSet) labelCounts = {} для featVec в dataSet: currentLabel = featVec[-1] if currentLabel not in labelCounts: labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 shannonEnt = 0 for key in labelCounts: shannonEnt = shannonEnt - (labelCounts[key]/numEntries)*math.log2(labelCounts[key]/numEntries) возврат shannonEnt
可以根据信息熵,按照获取最大信息增益的方法划分数据集。
2.划分数据集
划分数据集就是将所有符合要求的元素抽出来。
def splitDataSet(dataSet,axis,value): retDataset = [] для featVec в dataSet: если featVec[axis] == value: newVec = featVec[:axis] newVec.extend(featVec[axis+1:]) retDataset.append(newVec) возврат retDataset
3.选择最好的数据集划分方式
信息增益是熵的减少或者是信息无序度的减少。
def chooseBestFeatureToSplit(dataSet): numFeatures = длина dataSet[0] - 1 bestInfoGain = 0 bestFeature = -1 baseEntropy = calcShannonEnt(dataSet) для i в range(numFeatures): allValue = [example[i] for example in dataSet]#列表推倒,创建新的列表 allValue = set(allValue)#最快得到列表中唯一元素值的方法 newEntropy = 0 для value в allValue: splitset = splitDataSet(dataSet,i,value) newEntropy = newEntropy + длина splitset / длина dataSet * calcShannonEnt(splitset) infoGain = baseEntropy - newEntropy если infoGain > bestInfoGain: bestInfoGain = infoGain bestFeature = i возврат bestFeature
4.递归创建决策树
结束条件为:程序遍历完所有划分数据集的属性,或每个分支下的所有实例都具有相同的分类。
当数据集已经处理了所有属性,但是类标签还不唯一时,采用多数表决的方式决定叶子节点的类型。
def majorityCnt(classList): classCount = {} для value в classList: если value не в classCount: classCount[value] = 0 classCount[value] += 1 classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) возврат classCount[0][0]
生成决策树:
def createTree(dataSet,labels): classList = [example[-1] для example в dataSet] labelsCopy = labels[:] если classList.count(classList[0]) равна len(classList): возврат classList[0] если длина dataSet[0] равна 1: return majorityCnt(classList) bestFeature = chooseBestFeatureToSplit(dataSet) bestLabel = labelsCopy[bestFeature] myTree = {bestLabel:{}} featureValues = [example[bestFeature] for example in dataSet] featureValues = set(featureValues) del(labelsCopy[bestFeature]) for value in featureValues: subLabels = labelsCopy[:] myTree[bestLabel][value] = createTree(splitDataSet(dataSet, bestFeature, value), subLabels) return myTree
5.测试算法——使用决策树分类
同样采用递归的方式得到分类结果。
def classify(inputTree, featLabels, testVec): currentFeat = list(inputTree.keys())[0] secondTree = inputTree[currentFeat] try: featureIndex = featLabels.index(currentFeat) except ValueError as err: print('yes') try: for value in secondTree.keys(): if value == testVec[featureIndex]: if type(secondTree[value]).__name__ == 'dict': classLabel = classify(secondTree[value], featLabels, testVec) else: classLabel = secondTree[value] return classLabel except AttributeError: print(secondTree)
6.完整代码如下
import numpy as np import math import operator def createDataSet(): dataSet = [[1,1,'yes'], [1,1,'yes'], [1,0,'no'], [0,1,'no'], [0,1,'no'],] label = ['no surfacing','flippers'] return dataSet, label def calcShannonEnt(dataSet): numEntries = len(dataSet) labelCounts = {} для featVec в dataSet: currentLabel = featVec[-1] if currentLabel not in labelCounts: labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1 shannonEnt = 0 for key in labelCounts: shannonEnt = shannonEnt - (labelCounts[key]/numEntries)*math.log2(labelCounts[key]/numEntries) возврат shannonEnt def splitDataSet(dataSet,axis,value): retDataset = [] для featVec в dataSet: если featVec[axis] == value: newVec = featVec[:axis] newVec.extend(featVec[axis+1:]) retDataset.append(newVec) возврат retDataset def chooseBestFeatureToSplit(dataSet): numFeatures = длина dataSet[0] - 1 bestInfoGain = 0 bestFeature = -1 baseEntropy = calcShannonEnt(dataSet) для i в range(numFeatures): allValue = [example[i] for example in dataSet] allValue = set(allValue) newEntropy = 0 для value в allValue: splitset = splitDataSet(dataSet,i,value) newEntropy = newEntropy + длина splitset / длина dataSet * calcShannonEnt(splitset) infoGain = baseEntropy - newEntropy если infoGain > bestInfoGain: bestInfoGain = infoGain bestFeature = i возврат bestFeature def majorityCnt(classList): classCount = {} для value в classList: если value не в classCount: classCount[value] = 0 classCount[value] += 1 classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) возврат classCount[0][0] def createTree(dataSet,labels): classList = [example[-1] для example в dataSet] labelsCopy = labels[:] если classList.count(classList[0]) равна len(classList): возврат classList[0] если длина dataSet[0] равна 1: return majorityCnt(classList) bestFeature = chooseBestFeatureToSplit(dataSet) bestLabel = labelsCopy[bestFeature] myTree = {bestLabel:{}} featureValues = [example[bestFeature] for example in dataSet] featureValues = set(featureValues) del(labelsCopy[bestFeature]) for value in featureValues: subLabels = labelsCopy[:] myTree[bestLabel][value] = createTree(splitDataSet(dataSet, bestFeature, value), subLabels) return myTree def classify(inputTree, featLabels, testVec): currentFeat = list(inputTree.keys())[0] secondTree = inputTree[currentFeat] try: featureIndex = featLabels.index(currentFeat) except ValueError as err: print('yes') try: for value in secondTree.keys(): if value == testVec[featureIndex]: if type(secondTree[value]).__name__ == 'dict': classLabel = classify(secondTree[value], featLabels, testVec) else: classLabel = secondTree[value] return classLabel except AttributeError: print(secondTree) if __name__ == "__main__": dataset, label = createDataSet() myTree = createTree(dataset,label) a = [1,1] print(classify(myTree,label,a))
7. Программные хитрости
Разница между extend и append
newVec.extend(featVec[axis+1:]) retDataset.append(newVec)
extend([]), добавляет каждый элемент списка в новый список
append() добавляет содержимое скобок в качестве нового элемента в новый список
Списковый спред
Создание нового списка
allValue = [example[i] for example in dataSet]
Изъятие уникальных элементов из списка
allValue = set(allValue)
Сортировка списка/тuples, функция sorted()
classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
Копирование списка
labelsCopy = labels[:]
Загрузка кода и данных:Дерево решений
Вот весь контент статьи, мы надеемся, что он поможет вам в изучении, и我们也 надеемся на вашу поддержку и поддержку учебника Yanyao.
Заявление: контент этой статьи был взят из Интернета, авторские права принадлежат их владельцам, контент был предоставлен пользователями Интернета, сайт не обладает правами собственности, не был отредактирован вручную, и не несет ответственности за соответствующие юридические последствия. Если вы обнаружите спорный материал, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма замените # на @) для жалоб,并提供相关证据. При подтверждении факта, сайт немедленно удалит спорный материал.