是否打球的决策树算法(python 文件读取,决策树,误差计算)

一、数据集

PlayTennis.txt

    利用打网球数据集PlayTenis构建决策树,该数据集的特性如下:
    属性包括天气(outlook)、温度(temperature)、湿度(humidity)、是否有风(windy),样本个数为14。
    标签为今天是否去打网球(play)。
    具体数据如下(如果不能运行,尝试在末尾加回车)

    1   sunny      hot       high      FALSE  no
    2   sunny      hot       high      TRUE   no
    3   overcast   hot       high      FALSE  yes
    4   rainy      mild      high      FALSE  yes
    5   rainy      cool      normal    FALSE  yes
    6   rainy      cool      normal    TRUE   no
    7   overcast   cool      normal    TRUE   yes
    8   sunny      mild      high      FALSE  no
    9   sunny      cool      normal    FALSE  yes
    10  rainy      mild      normal    FALSE  yes

二、代码

import math


def xiangtong(D, A):  # D中所有A类元素是否相同
    for i in A:  # 循环看D中所有A类元素
        if len(set(D[i])) > 1:  # 如果里面节点类型不一样
            return False  # 返回False
    return True  # 返回True


def deDv(D, a, v):  # 得到Dv
    Dv = [[], [], [], [], []]
    for i in range(len(D[a])):  # 属性a列遍历
        if D[a][i] == v:  # 找到属性v
            for j in range(len(D)):  # D属性遍历
                Dv[j].append(D[j][i])  # D的属性加到Dv上
    return Dv  # 返回Dv


def Ent(D):  # Ent(D)  信息熵
    x = list(set(D[4]))  # 取得无重复元素的列表
    x = x[0]  # D中样本标签第一类
    c = 0  # 计数
    for j in D[4]:  # 遍历标签
        if j == x:  # 如果标签一样
            c = c + 1  # 计数加一
    pk1 = c / len(D[4])  # 第一类标签的频率
    if pk1 == 0 or pk1 == 1:  # 如果有0(防止log 0)
        return 0  # 信息熵为 0
    pk2 = 1 - c / len(D[4])  # 第二类标签的频率
    return -(pk1 * math.log(pk1, 2) + pk2 * math.log(pk2, 2))  # 只有两种标签


def Gain(D, i):  # 求信息增益
    sum = 0  # 划分后信息熵(Ent求和)
    for j in set(D[i]):  # 遍历D[i]的不同属性
        Dv = deDv(D, i, j)  # 得到Dv
        sum = sum + len(Dv[0]) / len(D[0]) * Ent(Dv)  # 求划分后信息熵
    return Ent(D) - sum  # 信息增益:初始信息熵减去划分后信息熵


def TreeGenerate(D, A):  # 递归生成决策树
    y = []  # 生成节点
    if len(set(D[4])) == 1:  # 如果里面节点类型一样
        return D[4][0]  # 返回这个值
    if len(A) == 0 or xiangtong(D, A):  # 如果A为空或者D中所有A类元素相同
        return max(D[4], key=D[4].count)  # 返回D中最多的取值
    G = []  # 以属性A分类的信息增益
    for i in A:
        G.append(Gain(D, i))  # 计算所有的信息增益
    G = G.index(max(G))  # 得到a*位置在G中的下标(最优划分属性)
    G = A[G]  # 得到a*位置在D中的下标
    y.append(G)
    for i in set(D[G]):  # 最优划分属性每个取值
        y1 = [i]  # 生成分支
        Dv = deDv(D, G, i)  # 得到Dv
        if len(Dv) == 0:  # Dv为空
            y1.append(max(D[4], key=D[4].count))  # D中最多的取值
        else:
            A1 = A[:]
            A1.remove(G)  # 产生去除a*的A
            y1.append(TreeGenerate(Dv[:], A1[:]))  # 递归调用
        y.append(y1)
    return y


def panduan(D, y, i):
    if isinstance(y, str):  # 如果是字符串,说明是结果
        return y    # 返回结果
    if isinstance(y[0], int):  # 如果是数字,说明是分类列
        x = D[y[0]]  # 取分类列
        for j in range(1, len(y)):  # 遍历这一分类变量所有类型
            y1 = y[j]   # 取分支
            if x[i] == y1[0]:  # 找取到该分类
                return panduan(D, y1[1], i)  # 递归分支


def wucha(D, y):  # 计算分类误差
    c = 0  # 误差数
    for i in range(len(D[0])):
        if not panduan(D, y, i) == D[4][i]: # 决策树判断不等于标签
            c = c + 1   # 误差数加一
    return c / len(D[0])    #返回误差比例


f = open('PlayTennis.txt', 'r')  # 读文件
x = [[], [], [], [], []]  # 天气、温度、湿度、是否有风、打球
x1 = [[], [], [], [], []]
x2 = [[], [], [], [], []]
y = []  # 分支节点[分支类,[分支节点1],[分支节点2]···]  递归决策树
y1 = []
while 1:
    yihang = f.readline()  # 读一行
    if len(yihang) <= 1:  # 读到末尾结束
        break
    fenkai = yihang.split(' ')  # 按空格分开
    fenkai = sorted(set(fenkai), key=fenkai.index)  # 去除重复元素
    for i in range(5):
        x[i].append(fenkai[i + 2])  # 加到x中
print('数据集===============================================')
for i in range(len(x)):
    print(x[i])
x1 = x[:]
A = [0, 1, 2, 3]  # 属性
print('全训练决策树===============================================')
y = TreeGenerate(x1[:], A[:])  # 开始训练
print(y, '\n拆分:')
for i in range(len(y)):  # 输出决策树
    print(y[i])
print('误差率:', wucha(x[:], y[:]) * 100, '%')
print('2/3训练决策树==============================================')
for i in range(len(x1)):  # 截取部分训练集
    x2[i] = x1[i][6:9]
    x1[i] = x1[i][0:6]
y1 = TreeGenerate(x1, A[:])  # 开始训练
print(y1, '\n拆分:')
for i in range(len(y1)):  # 输出决策树
    print(y1[i])
print('误差率:', wucha(x2, y1[:]) * 100, '%')

三、结果

是否打球的决策树算法(python 文件读取,决策树,误差计算)_第1张图片

 此程序全部做训练集生成的决策树手工绘制为:

你可能感兴趣的:(python,算法,决策树)