机器学习 day3 决策树算法

1. 目的

通过历史数据计算,得到一颗决策树
在这里插入图片描述
在这里插入图片描述

2. 优缺点

优点

  1. 易于理解:即使对于非分析背景的人来说,决策树输出也很容易理解。它不需要任何统计知识来阅
    读和解释它们。它的图形表示非常直观。
  2. 在数据探索中很有用:决策树是识别最重要变量和两个或多个变量之间关系的最快方法之一。在决
    策树的帮助下,我们可以创建具有更好预测目标变量能力的新变量(特征)。你可以参考一篇文章
    (Trick to enhance power of regression model)。它也可以用于数据探索阶段。例如,我们正
    在研究一个问题,即我们有数百个变量可用的信息,决策树将有助于识别最重要的变量。
  3. 需要更少的数据清理:与其他一些建模技术相比,它需要更少的数据清理。它不受异常值和缺失值
    的影响。
  4. 数据类型不是约束:它可以处理数字和分类变量。
  5. 非参数方法:决策树被认为是非参数方法。这意味着决策树没有关于空间分布和分类器结构的假
    设。

缺点
6. 过拟合:过拟合是决策树模型最实用的难点之一。 通过设置模型参数和修剪的约束来解决这个问
题。
7. 不适合连续变量:在处理连续数值变量时,决策树在对不同类别的变量进行分类时会丢失信息。

3. 信息熵 entropy

计算方法:

在这里插入图片描述

导库:

import numpy as np 
import matplotlib.pyplot as plt
import pandas as pd 

导数据集:

watermelon = pd.read_excel('决策树-西瓜.xlsx')
watermelon

在这里插入图片描述

首先计算原本的信息熵:

在这里插入图片描述

resulte_ = watermelon['好瓜'].value_counts(normalize=True)
resulte_

否 0.529412
是 0.470588
Name: 好瓜, dtype: float64

Entropy = -(resulte_[0]*np.log2(resulte_[0])+resulte_[1]*np.log2(resulte_[1]))
Entropy

0.9975025463691153

计算色泽特征下的信息熵:

在这里插入图片描述

取数据集D1 D1为色泽=青绿的数据子集
D1 = watermelon[watermelon['色泽']=='青绿']

resulte_D1 = D1['好瓜'].value_counts(normalize=True)
#resulte_D1 查看色泽为青绿的好瓜坏瓜的占比

Entropy_D1 = -np.sum(resulte_D1*np.log2(resulte_D1))
#计算色泽=青绿的子集的信息熵
取子集D2 D2 为色泽=乌黑的数据子集
D2 = watermelon[watermelon['色泽']=='乌黑']
# D2 为色泽=乌黑的子集
resulte_D2 = D2['好瓜'].value_counts(normalize=True)
#resulte_D2 查看色泽为乌黑的好瓜坏瓜的占比
Entropy_D2 = -np.sum(resulte_D2*np.log2(resulte_D2))
#resulte_D2 查看色泽为乌黑的好瓜坏瓜的占比
取子集D3 D3为色泽=浅白的数据子集
D3 = watermelon[watermelon['色泽']=='浅白']
resulte_D3 = D3['好瓜'].value_counts(normalize=True)
Entropy_D3 = -np.sum(resulte_D3*np.log2(resulte_D3))

结果:

Entropy_D1,Entropy_D2,Entropy_D3  # (1.0, 0.9182958340544896, 0.7219280948873623)

(1.0, 0.9182958340544896, 0.7219280948873623)

计算色泽特征的信息熵:

Entropy_color = resulte_color[0]*Entropy_D1+Entropy_D2*resulte_color[1]+Entropy_D3*resulte_color[2]
Entropy_color  # 0.88937738110375

0.88937738110375

封装计算特征信息熵的函数:

# data原始数据文本
# column特征名
#label 标签名
def entropy(data,column,label):
    result_all = data[column].value_counts(normalize = True)
    
    En_ = []
    #result_all 为样本子集的占比
    for feature in result_all.index:
        #feature 为特征column的取值
        
        sub_datasezts = data[data[column]==feature]
        #取出特征column = feature子集(色泽=青绿)
        
        resulte_sub = sub_datasezts[label].value_counts(normalize = True)
        #特征子集中标签的pi
        
        entropy_sub = -np.sum(resulte_sub*np.log2(resulte_sub))
        #特征子集的entropy
        
        En_.append(entropy_sub)
        # 存储子集的entropy
        
    entropy = np.sum(result_all*np.array(En_))
    #计算特征column的entropy
    return entropy

计算:

features = watermelon.columns[1:-1]
features  # Index(['色泽', '根蒂', '敲声', '纹理', '脐部', '触感'], dtype='object')

columns   = watermelon.columns[1:-1]
entropy_ = []
for features in columns:
    entropy_.append(entropy(watermelon,features,'好瓜'))

[*zip(columns,entropy_)]

"""
[('色泽', 0.88937738110375),
 ('根蒂', 0.8548275868023224),
 ('敲声', 0.8567211127541194),
 ('纹理', 0.6169106490008467),
 ('脐部', 0.7083437635274363),
 ('触感', 0.9914560571925497)]
"""

结果:选择纹理作为根节点(信息熵小,信息增益就大)

4. sklearn 中的决策树

from sklearn.tree import DecisionTreeClassifier
DT = DecisionTreeClassifier(
    criterion='gini',
    max_depth=None, # 限制树的最大深度
    min_samples_split=2,
    min_samples_leaf=1,
    
    max_features=None,# 限制最大的特征个数
 
    max_leaf_nodes=None, 
    
    min_impurity_decrease=0.0,
    min_impurity_split=None,
    )

将特征转化为数字编码:

处理字符串通常有以下几种方式:

  • 有序变量(Ordinal Variable):字符串表示的数据有大小关系,那么可以对字符串进行序号化处理。
  • 分类变量(Categorical Variable)/ 名义变量(Nominal Variable):字符串表示的数据没有大小关系和等级之分,那么就可以使用独热编码处理成哑变量(虚拟变量)矩阵。
  • 定距变量(Scale Variable):数据有大小高低之分,可以进行加减运算。
watermelon['触感']=1*(watermelon['触感']=='硬滑')

独热编码:

from sklearn.preprocessing import OneHotEncoder
OH = OneHotEncoder().fit(watermelon[['色泽', '根蒂', '敲声', '纹理', '脐部']])
X = OH.transform(watermelon[['色泽', '根蒂', '敲声', '纹理', '脐部']]).toarray()
OH.categories_

"""
[array(['乌黑', '浅白', '青绿'], dtype=object),
 array(['硬挺', '稍蜷', '蜷缩'], dtype=object),
 array(['沉闷', '浊响', '清脆'], dtype=object),
 array(['模糊', '清晰', '稍糊'], dtype=object),
 array(['凹陷', '平坦', '稍凹'], dtype=object)]
"""

将处理好的编码转成 dataframe

X = pd.DataFrame(X,columns=OH.get_feature_names())
X['触感']=watermelon['触感']
X.head()
x0_乌黑x0_浅白x0_青绿x1_硬挺x1_稍蜷x1_蜷缩x2_沉闷x2_浊响x2_清脆x3_模糊x3_清晰x3_稍糊x4_凹陷x4_平坦x4_稍凹触感
00.00.01.00.00.01.00.01.00.00.01.00.01.00.00.01
11.00.00.00.00.01.01.00.00.00.01.00.01.00.00.01
21.00.00.00.00.01.00.01.00.00.01.00.01.00.00.01
30.00.01.00.00.01.01.00.00.00.01.00.01.00.00.01
40.01.00.00.00.01.00.01.00.00.01.00.01.00.00.01

测试并修改参数:

y = watermelon['好瓜']
from sklearn.model_selection import train_test_split

xtrain,xtest,ytrain,ytest = train_test_split(X,y)

训练集 1 测试集 0.6

score = []
score_train = []
for i in np.arange(1,20):
    DT = DecisionTreeClassifier(min_samples_leaf=i).fit(xtrain,ytrain)
    score_train.append(DT.score(xtrain,ytrain))
    score.append(DT.score(xtest,ytest))
plt.plot(np.arange(1,20),score_train,label = 'train')
plt.plot(np.arange(1,20),score,label = 'test')
plt.legend()

在这里插入图片描述
补充:另一种编码方式

from sklearn.preprocessing import OrdinalEncoder
OE = OrdinalEncoder().fit(df[['色泽', '根蒂', '敲声', '纹理', '脐部']])
OE.transform(df[['色泽', '根蒂', '敲声', '纹理', '脐部']])
OE.categories_
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值