一、Python实现决策树

我们看一组实例,贷款申请样本数据表。


python校准曲线和决策曲线的代码_python校准曲线和决策曲线的代码

希望通过所给的训练数据学习一个贷款申请的决策树,用以对未来的贷款申请进行分类,即当新的客户提出贷款申请时,根据申请人的特征利用决策树决定是否批准贷款申请。

在编写代码之前,我们先对数据集进行属性标注。

  • 年龄:0代表青年,1代表中年,2代表老年;
  • 有工作:0代表否,1代表是;
  • 有自己的房子:0代表否,1代表是;
  • 信贷情况:0代表一般,1代表好,2代表非常好;
  • 类别(是否给贷款):no代表否,yes代表是。

确定这些之后,我们就可以创建数据集,并计算经验熵了,代码编写如下:

# -*- coding: UTF-8 -*-
from math import log
'''
程序来源:https://zhuanlan.zhihu.com/p/28688281,决策树用于决定是否放贷。
'''
def createDataSet():
    '''
    1)在Python当中定义一个函数,以一个冒号开始,并且缩进
    2)在Python当中,return [表达式] 结束函数,选择性地返回一个值给调用方。
       不带表达式的return相当于返回 None。
    '''
    dataSet = [
               [0, 0, 0, 0, 'no'], [0, 0, 0, 1, 'no'], [0, 1, 0, 1, 'yes'],
               [0, 1, 1, 0, 'yes'],[0, 0, 0, 0, 'no'], [1, 0, 0, 0, 'no'],
               [1, 0, 0, 1, 'no'], [1, 1, 1, 1, 'yes'],[1, 0, 1, 2, 'yes'],
               [1, 0, 1, 2, 'yes'],[2, 0, 1, 2, 'yes'],[2, 0, 1, 1, 'yes'],
               [2, 1, 0, 1, 'yes'],[2, 1, 0, 2, 'yes'],[2, 0, 0, 0, 'no']
              ]
    '''
    python中的中括号[ ]:代表list列表数据类型,列表是一种可变的序列。
    '''
    labels = ['不放贷', '放贷'] #分类属性
    return dataSet, labels     #返回数据集和分类属性
    '''
    python返回多值
    python函数可以返回多个值吗?答案是肯定的。
    比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的坐标:
    # math包提供了sin()和 cos()函数,我们先用import引用它:
    import math
    def move(x, y, step, angle):
        nx = x + step * math.cos(angle)
        ny = y - step * math.sin(angle)
        return nx, ny
    print(move(100, 100, 60, math.pi / 6))
    '''
def calcShannonEnt(dataSet):
    numEntires = len(dataSet)  #返回数据集的个数(15),return the number of items of a sequence or collection.
    labelCounts = {}           #保存每个标签(Label)出现次数的字典
    '''
      python当中“{}”表示字典,具体用法如下
      字典写法:d={'a':1,'b':2}
      基本字典操作方法:
      (1)求元素个数:len(d) => 2
      (2)用键访问值:d['a'] => 1
      (3)修改值:d['a']=3
      (4)删除: del d['a']
      (5)成员资格: 'a' in d
     '''
    for featVec in dataSet:                           #对每组特征向量进行统计
        currentLabel = featVec[-1]                    #提取标签(Label)信息
        '''
        python当中“[]”表示索引
        arr[-1]表示数组(序列)的最后一个元素,这样第一次执行的时候currentLable就取最后一个元素“no”,然后执行下面的if语句,再第二次执行for语句...
        '''
        if currentLabel not in labelCounts.keys():    #如果标签(Label)没有放入统计次数的字典,添加进去,开始执行的时候,由于容器是空的,因此第一遍labelCounts['no']是满足if语句的,因此会执行后面的语句,此时labelCounts['no']=0,再次执行后面的语句labelCounts['no']=1
            '''
            1)labelCounts.keys()列出字典所有的key,什么是key,就是mapreduce方法当中的key-value,键值对
            dict = { 1 : 2, 'a' : 'b', 'hello' : 'world' }
            dict.keys() 
            ['a', 1, 'hello']  
            ()
            2)在Python当中用tab来进行缩进,这个地方if相对于前面的for是缩进了的,因此是for循环的子判断
            '''
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1                #Label计数
        '''
        1)labelCounts[currentLabel] = labelCounts[currentLabel]+1
        2)这个地方需要注意的是,labelCounts[currentLabel] += 1 和if语句的缩进相同
        因此它不是if语句的一部分,而是for语句的一部分,同理后面的shannonEnt = 0.0
        它并不是for语句的一部分,而是calcShannonEnt这个函数(方法)的一部分
        '''
    shannonEnt = 0.0                                #经验熵(香农熵)
    '''
    Python定义变量的方法和scala有一些类似,并不像Java那样需要声明变量的类型,而是直接进行类型推断即可
    相比于Scala,Python更省,甚至连val都省略掉了
    '''
    for key in labelCounts:                            #计算香农熵
        prob = float(labelCounts[key]) / numEntires    #选择该标签(Label)的概率
        shannonEnt -= prob * log(prob, 2)            #利用公式计算
    return shannonEnt                                #返回经验熵(香农熵)
if __name__ == '__main__':
    '''
    关于这句话的意思,知乎有不少答案
    1)__name__ 是当前模块名,当模块被直接运行时模块名为 __main__ 。
    这句话的意思就是,当模块被直接运行时,以下代码块将被运行,当模块是被导入时,代码块不被运行。
    2)编写私有化部分 ,这句代码以上的部分,可以被其它的调用,以下的部分只有这个文件自己可以看见
    如果文件被调用了,其他人是无法看见私有化部分的
    转自知乎https://www.zhihu.com/question/49136398
    '''
    dataSet, features = createDataSet()
    '''
    Python多变量赋值
    data = ("shiyanlou", "China", "Python")
    name, country, language = data
    print(name)     ==>"shiyanlou"
    print(country)  ==>"China"
    print(language) ==>"Python"
    '''
    print(dataSet)
    print(calcShannonEnt(dataSet))

\