• CART决策树的上机实现


     CART决策树的上机实现

    1.1 题目的主要研究内容(宋体四号加粗左对齐)

    1. 小组任务描述:

    熟悉和掌握决策树的分类原理、实质和过程,掌握决策树典型算法(ID3、C4.5、CART)的核心思想和实现过程。

    1. 我的主要工作

    程序实现CART算法。

    理解GINI函数的意义与CART算法的实现原理,在不使用sklearn和使用sklearn的情况下分别实现小数据集和较大数据集的决策树生成。

    1.2 题目研究的工作基础或实验条件

    (1)硬件环境:计算机

    (2)软件环境:windows系统,python环境,pycharm编辑器

    1.3 设计思想

    在使用机器学习库sklearn和不使用sklearn两种情况下分别实现CART算法例程。

    1.4 流程图

    1.4.1不使用sklearn机器学习库

    所用数据集为某产品销量与三个特征的关系,共34组数据,下图列出了数据集部分数据。

    图 1所用数据集示例

    主要程序由本组C4.5算法程序修改而来,将C4.5算法程序中的计算信息增益和信息增益率换成计算Gini指数,在选择最优特征时选择使Gini指数最小的特征。主程序流程图如图2所示

    图 2主程序流程图

    1.4.2 使用sklearn机器学习库

    由于上一种方法数据集数据量过小,使得无论是训练结果还是预测结果的准确率都偏低,故我有在鸢尾花数据集上再次进行了决策树的训练,为了使程序更加简洁易读,我使用了sklearn机器学习工具库进行编程。主程序流程图如图3所示

    图 3鸢尾花决策树主程序流程图

    1.5 主要程序代码(要求必须有注释)

    1.5.1 不使用sklearn机器学习库

    def main():

        #获取训练集,所有属性名称,每个属性的类别,所有标签(最后一列)    

        dataTrain, featureNames, featureNamesSet,labelList = readDataSet("data/ex3data.csv")

        print("dataTrain: \n",dataTrain,"\n","featureNames:\n",featureNames,"\n","featureNamesSet:\n",featureNamesSet,"\n","labelList:\n",labelList)

        #获取测试集

        #train= pd.read_csv("data/ex3data.csv")

        #test = pd.read_csv("data/ex3data.csv")

        train= pd.read_csv("data/ex3data.csv")[:25]

        test = pd.read_csv("data/ex3data.csv")[25:34]

        #print("train:\n",train[:10])

        print("train:\n",train[:10])

        print("test:\n",test[:10])

        #生成决策树

        t0 = time.time()

        tree = createFullDecisionTree(dataTrain, featureNames,featureNamesSet,labelList)

        t1 = time.time()

        print("CART算法生成决策树的时间开销:",(t1 - t0)*(10**6),"us")

        createPlot(tree,"fig/CART.png")

        predictTrain = train.apply(lambda x: tree_predict(tree, x), axis=1)

        label_list = train.iloc[:, -1]

        score = accuracy_score(label_list, predictTrain)

        print('训练补全分支准确率为:' + repr(score * 100) + '%')

        #预测

        y_predict = test.apply(lambda x: tree_predict(tree, x), axis=1)

        label_list = test.iloc[:, -1]

        score = accuracy_score(label_list, y_predict)

        print('测试集补全分支准确率为:' + repr(score * 100) + '%')

    def createFullDecisionTree(dataSet, featureNames, featureNamesSet, labelListParent):

        labelList = [x[-1] for x in dataSet]

        if(len(dataSet) == 0):                                  # 如果数据集为空,返回父节点标签列表的主要标签

            return mainLabel(labelListParent)

        elif(len(dataSet[0]) == 1):                             # 没有可划分的属性,选出最多的label作为该数据集的标签

            return mainLabel(labelList)                         

        elif(labelList.count(labelList[0]) == len(labelList)):  # 全部都属于同一个Label,返回labList[0]

            return labelList[0]

        # 不满足上面的边界情况则需要创建新的分支节点

        bestFeatureIndex = chooseBestFeature_CART(dataSet)      # 根据信息增益,选择数据集中最好的特征下标

        bestFeatureName = featureNames.pop(bestFeatureIndex)    # 取出属性类别

        myTree = {bestFeatureName: {}}                          # 新建节点,一个字典

        featureList = featureNamesSet.pop(bestFeatureIndex)     # 取出最佳属性的类别

        featureSet = set(featureList)                           # 剔除属性类别集合

        for feature in featureSet:                              # 遍历最佳属性所有取值

            featureNamesNext = featureNames[:]                  

            featureNamesSetNext = featureNamesSet[:][:]

            splitedDataSet = splitDataSet(dataSet, bestFeatureIndex, feature)   # 剔除最佳特征

            # 递归地生成新的节点

            # featureNames:数据属性类别, featureNamesSet:属性类别集合, labelListParent:父节点标签列表

            # 一个二叉树

            myTree[bestFeatureName][feature] = createFullDecisionTree(splitedDataSet, featureNamesNext, featureNamesSetNext, labelList)

    return myTree

    1.5.2 使用sklearn机器学习库

    from sklearn.tree import DecisionTreeClassifier, export_graphviz

    from sklearn import datasets

    #from sklearn.cross_validation import train_test_split

    from sklearn.metrics import accuracy_score

    from sklearn.model_selection import KFold

    from sklearn.model_selection import train_test_split

    # 加载鸢尾花数据集

    iris = datasets.load_iris()

    print(iris)

    # 特征数据

    iris_feature = iris.data

    #print(iris_feature)

    # 分类数据

    iris_target = iris.target

    #print(iris_target)

    # 将数据随机的分为训练集和测试集

    feature_train, feature_test, target_train, target_test = train_test_split(iris_feature, iris_target, test_size=0.33,random_state=56)

    # random_state乱序程度

    # 模型训练

    # 导入决策树,所有参数为默认,还可以引入损失函数(信息熵,基尼指数);

    dt_model = DecisionTreeClassifier(criterion='gini')

    # 用决策树训练

    dt_model.fit(feature_train, target_train)

    # 使用测试数据测试

    predict_results = dt_model.predict(feature_test)

    #

    export_graphviz(

        dt_model, #刚刚训练好的树模型

        out_file="iris_tree2.dot", #

        feature_names=iris.feature_names[:],

        class_names=iris.target_names, #标签设置

        rounded=True,

        filled=True

    )

    # 利用测试数据测试

    print(predict_results)

    print(target_test)

    # 以下两种评比测试结果,传入参数有区别

    scores = dt_model.score(feature_test, target_test)

    print(scores)

    print('scores2=',accuracy_score(predict_results, target_test))

    1.6 运行结果及分析

    1.6.1 不使用sklearn机器学习库

    图 4 在小数据集上生成的决策树

    图 5 决策树准确率

    1.6.1 使用sklearn机器学习库

    图 6 在鸢尾花数据集上使用sklearn生成的决策树

    通过以上两个代码结果我们可以看出

    1. 在较小数据集上生成的决策树准确率较低,很可能并不能良好的预测新数据的结果。
    2. 使用sklearn训练决策树比不用sklearn简便了很多,其代码也更加通俗易懂,同时sklearn能更好的理解不同种类的数据集,例如在鸢尾花数据集中,特征是一些分布不均匀的小数,sklearn能自动选取合适的特征阈值对某一特征进行二分叉,但如果不使用sklearn,我们就只能手动编程去实验。
  • 相关阅读:
    mac M1上的效率工具——Alfred(附M1配置workflows)
    C语言指针操作(二)通过指针引用数组
    通用汽车在华加速推出智能电动车型
    Guacamole Web端配置使用
    postgre 12.11单实例安装文档
    lua和C++调用学习笔记系列一
    springboot高校专业招生信息管理系统jsp001
    linux常见环境安装
    构建数字孪生微电网,实现能源系统一体化管控
    WebGIS系列(二):影像与切片
  • 原文地址:https://blog.csdn.net/weixin_41984456/article/details/127571738