【人工智能】机器学习之使用Python生成ID3决策树及使用sklearn的决策树算法对葡萄酒数据集进行分类

简介: 决策树的思想:给定一个集合,其中的每个样本由若干属性表示,决策树通过贪心的策略不断挑选最优的属性。常见的决策树算法有ID3,C4.5,CART算法等。

❤❤❤ID3算法

✅✅决策树的思想:

给定一个集合,其中的每个样本由若干属性表示,决策树通过贪心的策略不断挑选最优的属性。
常见的决策树算法有ID3,C4.5,CART算法等。

💤💤💤ID3算法:

        baseEntropy = self.calcShannonEnt(dataset) # 基础熵
        num = len(dataset) # 样本总数
        
        #子集中的概率
        subDataSet = self.splitDataSet(dataset, i, val)
        prob = len(subDataSet) / float(num) 
        
        # 条件熵
        newEntropy += prob * self.calcShannonEnt(subDataSet)
        
        # 信息增益
        infoGain = baseEntropy - newEntropy

💯1.先写绘图树方法,函数。

import matplotlib.pyplot as plt

decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")
arrow_args = dict(arrowstyle="<-")

def plotNode(nodeTxt, centerPt, parentPt, nodeType):
    createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction', \
                            xytext=centerPt, textcoords='axes fraction', \
                            va="center", ha="center", bbox=nodeType, arrowprops=arrow_args)

def getNumLeafs(myTree):
    numLeafs = 0
    firstStr = list(myTree.keys())[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            numLeafs += getNumLeafs(secondDict[key])
        else:
            numLeafs += 1
    return numLeafs

def getTreeDepth(myTree):
    maxDepth = 0
    firstStr = list(myTree.keys())[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            thisDepth = getTreeDepth(secondDict[key]) + 1
        else:
            thisDepth = 1
        if thisDepth > maxDepth:
            maxDepth = thisDepth
    return maxDepth

def plotMidText(cntrPt, parentPt, txtString):
    xMid = (parentPt[0] - cntrPt[0]) / 2.0 + cntrPt[0]
    yMid = (parentPt[1] - cntrPt[1]) / 2.0 + cntrPt[1]
    createPlot.ax1.text(xMid, yMid, txtString)

def plotTree(myTree, parentPt, nodeTxt):
    numLeafs = getNumLeafs(myTree)
    depth = getTreeDepth(myTree)
    firstStr = list(myTree.keys())[0]
    cntrPt = (plotTree.xOff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalw, plotTree.yOff)
    plotMidText(cntrPt, parentPt, nodeTxt)
    plotNode(firstStr, cntrPt, parentPt, decisionNode)
    secondDict = myTree[firstStr]
    plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalD
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict':
            plotTree(secondDict[key], cntrPt, str(key))
        else:
            plotTree.xOff = plotTree.xOff + 1.0 / plotTree.totalw
            plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)
            plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
    plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalD

def createPlot(inTree):
    fig = plt.figure(1, facecolor='white')
    fig.clf()
    axprops = dict(xticks=[], yticks=[])
    createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)
    plotTree.totalw = float(getNumLeafs(inTree))
    plotTree.totalD = float(getTreeDepth(inTree))
    plotTree.xOff = -0.5 / plotTree.totalw
    plotTree.yOff = 1.0
    plotTree(inTree, (0.5, 1.0), '')
    plt.show()

💯2.ID3决策树类

class ID3Tree(object):
    def __init__(self):
        self.tree = {}  # ID3 Tree
        self.dataSet = []  # 数据集
        self.labels = []  # 标签集

    def getDataSet(self, dataset, labels):
        self.dataSet = dataset
        self.labels = labels

    def train(self):
        # labels = copy.deepcopy(self.labels)
        labels = self.labels[:]
        self.tree = self.buildTree(self.dataSet, labels)

    def buildTree(self, dataSet, labels):
        classList = [ds[-1] for ds in dataSet]  # 提取样本的类别
        if classList.count(classList[0]) == len(classList):  # 单一类别
            return classList[0]
        if len(dataSet[0]) == 1:  # 没有属性需要划分了
            return self.classify(classList)

        bestFeat = self.findBestSplit(dataSet)  # 选取最大增益的属性序号
        bestFeatLabel = labels[bestFeat]
        tree = {bestFeatLabel: {}}  # 构造一个新的树结点
        del (labels[bestFeat])  # 从总属性列表中去除最大增益属性

        featValues = [ds[bestFeat] for ds in dataSet]  # 抽取最大增益属性的取值列表
        uniqueFeatValues = set(featValues)  # 选取最大增益属性的数值类别

        for value in uniqueFeatValues:  # 对于每一个属性类别
            subLabels = labels[:]
            subDataSet = self.splitDataSet(dataSet, bestFeat, value)  # 分裂结点
            subTree = self.buildTree(subDataSet, subLabels)  # 递归构造子树
            tree[bestFeatLabel][value] = subTree
        return tree

    # 计算出现次数最多的类别标签
    def classify(self, classList):
        items = dict([(classList.count(i), i) for i in classList])
        return items[max(items.keys())]

    # 计算最优特征
    def findBestSplit(self, dataset):
        numFeatures = len(dataset[0]) - 1
        baseEntropy = self.calcShannonEnt(dataset) # 基础熵
        num = len(dataset) # 样本总数
        bestInfoGain = 0.0
        bestFeat = -1  # 初始化最优特征向量轴
        # 遍历数据集各列,寻找最优特征轴
        for i in range(numFeatures):
            featValues = [ds[i] for ds in dataset]
            uniqueFeatValues = set(featValues)
            newEntropy = 0.0
            # 按列和唯一值,计算信息熵
            for val in uniqueFeatValues:
                subDataSet = self.splitDataSet(dataset, i, val)
                prob = len(subDataSet) / float(num) # 子集中的概率
                newEntropy += prob * self.calcShannonEnt(subDataSet)
            infoGain = baseEntropy - newEntropy # 信息增益
            if infoGain > bestInfoGain: # 挑选最大值
                bestInfoGain = baseEntropy - newEntropy
                bestFeat = i
        return bestFeat

    # 从dataset数据集的feat特征中,选取值为value的数据
    def splitDataSet(self, dataset, feat, values):
        retDataSet = []
        for featVec in dataset:
            if featVec[feat] == values:
                reducedFeatVec = featVec[:feat]
                reducedFeatVec.extend(featVec[feat + 1:])
                retDataSet.append(reducedFeatVec)
        return retDataSet

    # 计算dataSet的信息熵
    def calcShannonEnt(self, dataSet):
        num = len(dataSet)  # 样本集总数
        classList = [c[-1] for c in dataSet]  # 抽取分类信息
        labelCounts = {}
        for cs in set(classList):  # 对每个分类进行计数
            labelCounts[cs] = classList.count(cs)

        shannonEnt = 0.0
        for key in labelCounts:
            prob = labelCounts[key] / float(num)
            shannonEnt -= prob * log2(prob)
        return shannonEnt

    # 预测。对输入对象进行ID3分类
    def predict(self, tree, newObject):
        #    判断输入值是否为“dict”
        while type(tree).__name__ == 'dict':
            key = list(tree.keys())[0]
            tree = tree[key][newObject[key]]
        return tree

💲💲💲给出数据集,标签集:

dataSet = [[1, 1, 1, 1,1, 1, 'Yes'],
               [2, 1, 2, 1,1, 1, 'Yes'],
               [2, 1, 1, 1,1, 1, 'Yes'],
               [1, 1, 2, 1,1, 1, 'Yes'],
               [3, 1, 1, 1,1, 1, 'Yes'],
               [1,2, 1, 1,2, 2, 'Yes'],
               [2, 2, 1, 2,2, 2, 'Yes'],
               [2, 2, 1, 1,2, 1, 'Yes'],
               [2, 2, 2, 2,2, 1, 'No'],
               [1,3, 3, 1,3, 2, 'No'],
               [3, 3, 3, 3,3, 1, 'No'],
               [3, 1, 1, 3,3, 2, 'No'],
               [1, 2, 1, 2,1, 1, 'No'],
               [3,2, 2, 2,1, 1, 'No'],
               [2, 2, 1, 1,2, 2, 'No'],
               [3, 1, 1, 3,3, 1, 'No'],
               [1, 1, 2, 2,2, 1, 'No'],]

    #'色泽', '根蒂', '敲声', '纹理','脐部', '触感'
    features = ['seze', 'gendi', 'qiaosheng', 'wenli','qibu', 'chugan'] 

💞💞完整代码

from math import log2
import treePlotter

class ID3Tree(object):
    def __init__(self):
        self.tree = {}  # ID3 Tree
        self.dataSet = []  # 数据集
        self.labels = []  # 标签集

    def getDataSet(self, dataset, labels):
        self.dataSet = dataset
        self.labels = labels

    def train(self):
        # labels = copy.deepcopy(self.labels)
        labels = self.labels[:]
        self.tree = self.buildTree(self.dataSet, labels)

    def buildTree(self, dataSet, labels):
        classList = [ds[-1] for ds in dataSet]  # 提取样本的类别
        if classList.count(classList[0]) == len(classList):  # 单一类别
            return classList[0]
        if len(dataSet[0]) == 1:  # 没有属性需要划分了
            return self.classify(classList)

        bestFeat = self.findBestSplit(dataSet)  # 选取最大增益的属性序号
        bestFeatLabel = labels[bestFeat]
        tree = {bestFeatLabel: {}}  # 构造一个新的树结点
        del (labels[bestFeat])  # 从总属性列表中去除最大增益属性

        featValues = [ds[bestFeat] for ds in dataSet]  # 抽取最大增益属性的取值列表
        uniqueFeatValues = set(featValues)  # 选取最大增益属性的数值类别

        for value in uniqueFeatValues:  # 对于每一个属性类别
            subLabels = labels[:]
            subDataSet = self.splitDataSet(dataSet, bestFeat, value)  # 分裂结点
            subTree = self.buildTree(subDataSet, subLabels)  # 递归构造子树
            tree[bestFeatLabel][value] = subTree
        return tree

    # 计算出现次数最多的类别标签
    def classify(self, classList):
        items = dict([(classList.count(i), i) for i in classList])
        return items[max(items.keys())]

    # 计算最优特征
    def findBestSplit(self, dataset):
        numFeatures = len(dataset[0]) - 1
        baseEntropy = self.calcShannonEnt(dataset) # 基础熵
        num = len(dataset) # 样本总数
        bestInfoGain = 0.0
        bestFeat = -1  # 初始化最优特征向量轴
        # 遍历数据集各列,寻找最优特征轴
        for i in range(numFeatures):
            featValues = [ds[i] for ds in dataset]
            uniqueFeatValues = set(featValues)
            newEntropy = 0.0
            # 按列和唯一值,计算信息熵
            for val in uniqueFeatValues:
                subDataSet = self.splitDataSet(dataset, i, val)
                prob = len(subDataSet) / float(num) # 子集中的概率
                newEntropy += prob * self.calcShannonEnt(subDataSet)
            infoGain = baseEntropy - newEntropy # 信息增益
            if infoGain > bestInfoGain: # 挑选最大值
                bestInfoGain = baseEntropy - newEntropy
                bestFeat = i
        return bestFeat

    # 从dataset数据集的feat特征中,选取值为value的数据
    def splitDataSet(self, dataset, feat, values):
        retDataSet = []
        for featVec in dataset:
            if featVec[feat] == values:
                reducedFeatVec = featVec[:feat]
                reducedFeatVec.extend(featVec[feat + 1:])
                retDataSet.append(reducedFeatVec)
        return retDataSet

    # 计算dataSet的信息熵
    def calcShannonEnt(self, dataSet):
        num = len(dataSet)  # 样本集总数
        classList = [c[-1] for c in dataSet]  # 抽取分类信息
        labelCounts = {}
        for cs in set(classList):  # 对每个分类进行计数
            labelCounts[cs] = classList.count(cs)

        shannonEnt = 0.0
        for key in labelCounts:
            prob = labelCounts[key] / float(num)
            shannonEnt -= prob * log2(prob)
        return shannonEnt

    # 预测。对输入对象进行ID3分类
    def predict(self, tree, newObject):
        #    判断输入值是否为“dict”
        while type(tree).__name__ == 'dict':
            key = list(tree.keys())[0]
            tree = tree[key][newObject[key]]
        return tree

if __name__ == '__main__':
    def createDataSet():
        dataSet = [[1, 1, 1, 1,1, 1, 'Yes'],
                   [2, 1, 2, 1,1, 1, 'Yes'],
                   [2, 1, 1, 1,1, 1, 'Yes'],
                   [1, 1, 2, 1,1, 1, 'Yes'],
                   [3, 1, 1, 1,1, 1, 'Yes'],
                   [1,2, 1, 1,2, 2, 'Yes'],
                   [2, 2, 1, 2,2, 2, 'Yes'],
                   [2, 2, 1, 1,2, 1, 'Yes'],
                   [2, 2, 2, 2,2, 1, 'No'],
                   [1,3, 3, 1,3, 2, 'No'],
                   [3, 3, 3, 3,3, 1, 'No'],
                   [3, 1, 1, 3,3, 2, 'No'],
                   [1, 2, 1, 2,1, 1, 'No'],
                   [3,2, 2, 2,1, 1, 'No'],
                   [2, 2, 1, 1,2, 2, 'No'],
                   [3, 1, 1, 3,3, 1, 'No'],
                   [1, 1, 2, 2,2, 1, 'No'],]

        #'色泽', '根蒂', '敲声', '纹理','脐部', '触感'
        features = ['seze', 'gendi', 'qiaosheng', 'wenli','qibu', 'chugan'] 
        
        return dataSet, features

    id3 = ID3Tree()  # 创建一个ID3决策树
    ds, labels = createDataSet()
    id3.getDataSet(ds, labels)
    id3.train()  # 训练ID3决策树
    print(id3.tree)  # 输出ID3决策树
    print(id3.predict(id3.tree,{'seze':2,'gendi':2,'qiaosheng':1,'wenli':1,'qibu':1,'chugan':1}))
    treePlotter.createPlot(id3.tree)

💥💥生成决策树:

在这里插入图片描述

💌💌💌ID3算法实例

💨💨1.使用sklearn的决策树算法对葡萄酒数据集进行分类,要求:

(1)划分训练集和测试集(测试集占20%)

(2)对测试集的预测类别标签和真实标签进行对比

(3)输出分类的准确率

(4)调整参数比较不同算法(ID3, CART)的分类效果。

🕳🕳2. 利用给定ID3算法,画出下列训练集的决策树。

在这里插入图片描述

🍇🍇🍇1.葡萄酒分类

🚲🚲🚲(1)划分训练集和测试集(测试集占20%)

test_size等于几就是测试集占比
x_train, x_test, y_train, y_test = train_test_split(

   X, Y, test_size=0.2, random_state=0)

🚓🚓(2)对测试集的预测类别标签和真实标签进行对比

预测类别标签
y_predict = clf.predict(x_test)
对比
pd.concat([pd.DataFrame(x_test), pd.DataFrame(y_test), pd.DataFrame(y_predict)], axis=1)

🛹🛹(3)输出分类的准确率

clf.fit(x_train, y_train)
score = clf.score(x_test, y_test)

🏍🛵🏍(4)调整参数比较不同算法(ID3, CART)的分类效果。

采用ID3算法进行计算
clf = tree.DecisionTreeClassifier(criterion="entropy")
采用CART算法进行计算
clf = tree.DecisionTreeClassifier(criterion="gini")

🚀🚀🚀完整代码:

# 导入相关库
from sklearn.model_selection import train_test_split
from sklearn import tree
from sklearn.datasets import load_wine
import pandas as pd
# 导入数据集
wine = load_wine()
X = wine.data
Y = wine.target
features_name = wine.feature_names
print(features_name)
print(pd.concat([pd.DataFrame(X), pd.DataFrame(Y)], axis=1))
# 打印数据
# 划分数据集,数据集划分为测试集占20%;
x_train, x_test, y_train, y_test = train_test_split(
        X, Y, test_size=0.2, random_state=0)

# 采用ID3算法进行计算
clf = tree.DecisionTreeClassifier(criterion="entropy")
# 采用CART算法进行计算
# clf = tree.DecisionTreeClassifier(criterion="gini")
# 获取模型
clf.fit(x_train, y_train)
score = clf.score(x_test, y_test)
y_predict = clf.predict(x_test)
print('准确率为:', score)
# 对测试集的预测类别标签和真实标签进行对比
print(pd.concat([pd.DataFrame(x_test), pd.DataFrame(y_test), pd.DataFrame(y_predict)], axis=1))

🚀🚀🚀结果:

在这里插入图片描述

🛰🛰🌌2.只需修改数据集,标签集即可

🚩🚩部分代码:

if __name__ == '__main__':
    def createDataSet():
        dataSet = [[1, 1, 1, 1, 'No'],
                   [1, 1, 1, 2,  'No'],
                   [2, 1, 1, 1,  'Yes'],
                   [3, 2, 1, 1,  'Yes'],
                   [3, 3, 2, 1,  'Yes'],
                   [3, 3, 2, 2,  'No'],
                   [2, 3, 2, 2,  'Yes'],
                   [1, 2, 1, 1,  'No'],
                   [1, 3, 2, 1,  'Yes'],
                   [3, 2, 2, 1,  'Yes'],
                   [1, 2, 2, 2,  'Yes'],
                   [2, 2, 1, 2,  'Yes'],
                   [2, 1, 2, 1,  'Yes'],
                   [3, 2, 1, 2,  'No'], ]
        features = ['outlook', 'temp', 'humidity', 'windy']

        return dataSet, features


    id3 = ID3Tree()  # 创建一个ID3决策树
    ds, labels = createDataSet()
    id3.getDataSet(ds, labels)
    id3.train()  # 训练ID3决策树
    print(id3.tree)  # 输出ID3决策树
    print(id3.predict(id3.tree, {'outlook': 2, 'temp': 2, 'humidity': 1, 'windy': 1}))
    treePlotter.createPlot(id3.tree)

🍽🍽🌼🌼结果:

在这里插入图片描述
在这里插入图片描述

目录
相关文章
|
5天前
|
机器学习/深度学习 人工智能 物联网
通义灵码在人工智能与机器学习领域的应用
通义灵码不仅在物联网领域表现出色,还在人工智能、机器学习、金融、医疗和教育等领域展现出广泛应用前景。本文探讨了其在这些领域的具体应用,如模型训练、风险评估、医疗影像诊断等,并总结了其提高开发效率、降低门槛、促进合作和推动创新的优势。
通义灵码在人工智能与机器学习领域的应用
|
6天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
8天前
|
机器学习/深度学习 人工智能 算法
人工智能与机器学习的融合之旅
【10月更文挑战第37天】本文将探讨AI和机器学习如何相互交织,共同推动技术发展的边界。我们将深入分析这两个概念,了解它们是如何互相影响,以及这种融合如何塑造我们的未来。文章不仅会揭示AI和机器学习之间的联系,还会通过实际案例展示它们如何协同工作,以解决现实世界的问题。
|
6天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
29 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
6天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
22 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
11天前
|
机器学习/深度学习 人工智能 安全
人工智能与机器学习在网络安全中的应用
人工智能与机器学习在网络安全中的应用
32 0
|
6天前
|
人工智能 算法 安全
人工智能在医疗诊断中的应用与前景####
本文旨在探讨人工智能(AI)技术在医疗诊断领域的应用现状、面临的挑战以及未来的发展趋势。随着科技的不断进步,AI技术正逐步渗透到医疗行业的各个环节,尤其在提高诊断准确性和效率方面展现出巨大潜力。通过分析当前AI在医学影像分析、疾病预测、个性化治疗方案制定等方面的实际应用案例,我们可以预见到一个更加智能化、精准化的医疗服务体系正在形成。然而,数据隐私保护、算法透明度及伦理问题仍是制约其进一步发展的关键因素。本文还将讨论这些挑战的可能解决方案,并对AI如何更好地服务于人类健康事业提出展望。 ####
|
5天前
|
机器学习/深度学习 人工智能 算法
人工智能在医疗诊断中的应用与挑战
本文探讨了人工智能(AI)在医疗诊断领域的应用及其面临的挑战。随着技术的不断进步,AI已经在医学影像分析、疾病预测和个性化治疗等方面展现出巨大潜力。然而,数据隐私、算法透明度以及临床整合等问题仍然是亟待解决的关键问题。本文旨在通过分析当前AI技术在医疗诊断中的具体应用案例,探讨其带来的优势和潜在风险,并提出相应的解决策略,以期为未来AI在医疗领域的深入应用提供参考。
28 3
|
5天前
|
机器学习/深度学习 人工智能 自然语言处理
探索人工智能在教育领域的应用与挑战
随着科技的不断进步,人工智能(AI)技术已经深入到社会的各个领域,其中教育领域尤为突出。本文旨在探讨人工智能在教育领域的应用现状、面临的挑战以及未来的发展趋势。通过分析AI技术如何改变传统教学模式,提高教育质量和效率,同时指出其在实际应用中可能遇到的问题和挑战,为未来教育的发展提供参考。
34 2
|
11天前
|
机器学习/深度学习 人工智能 搜索推荐
深度探索人工智能在医疗影像诊断中的应用与挑战####
本文深入剖析了人工智能(AI)技术,特别是深度学习算法在医疗影像诊断领域的创新应用,探讨其如何重塑传统诊断流程,提升诊断效率与准确性。同时,文章也客观分析了当前AI医疗影像面临的主要挑战,包括数据隐私、模型解释性及临床整合难题,并展望了未来发展趋势。 ####