有监督算法-决策树
一:算法概述
决策树:包括分类树/ 回归树,回归树较少用,所以这里主要介绍分类树
算法流程:特征选择–>决策树生成–>决策树剪枝
二:特征选择
2.1 香浓熵(信息熵)
熵代表信息混乱程度,越混乱熵就越高
熵的计算公式:
E
n
t
r
o
p
y
(
m
)
=
−
∑
i
=
1
k
p
i
l
o
g
2
p
i
Entropy(m) = -\sum_{i=1}^{k}p^ilog_2p^i
Entropy(m)=−i=1∑kpilog2pi
当p=0,则熵=0,因为确定性100%,没有信息混乱
#信息熵的计算
import numpy as np
p1 = 0.1
p2 = 0.9
s = -p1*np.log2(p1)-p2*np.log2(p2)
print(s)
基尼系数 Gini index
Φ ( p , 1 − p ) = 1 − ∑ i = 1 m p i 2 \Phi(p,1-p) = 1-\sum_{i=1}^{m}p_i^2 Φ(p,1−p)=1−i=1∑mpi2
分类误差 Classification error
Φ ( p , 1 − p ) = 1 − m a x ( p , 1 − p ) \Phi(p,1-p) = 1-max(p,1-p) Φ(p,1−p)=1−max(p,1−p)
信息熵的代码实现:
这里计算的是所有信息的熵,因为是通过标签列-性别 进行计算的,所以熵的值比较高
#信息熵的代码实现
#1.数据准备
import pandas as pd
import numpy as np
data = pd.DataFrame(
data={
'篮球':[0,1,1,1,0],
'游戏':[1,0,0,1,1],
'性别':[0,1,1,0,0],
}
)
print(data)
#通过标签列计算全部数据的熵
def entropy(data):
#获取行数
rows = data.shape[0]
#获取性别列,求每种类别的个数
sex_count = data.iloc[:,-1].value_counts()
#求概率值
p = sex_count / rows
#求熵
score = (-(p*np.log2(p))).sum()
return score
entropy(data) #0.9709505944546686
2.2 信息增益
较父节点(划分前)的不纯程度和分支节点(划分后)的不纯程度,它们的差越大,则意味着使用属性 a 来进行划分所获得的 “不纯度提升” 越大,测试条件效果越好。
公式:
信
息
增
益
=
I
(
父
节
点
)
−
I
(
子
节
点
)
父
节
点
代
表
总
体
的
信
息
熵
子
节
点
代
表
指
定
特
拆
分
之
后
的
信
息
熵
信息增益 = I(父节点) - I(子节点) \\ 父节点代表总体的信息熵 \\ 子节点代表指定特拆分之后的信息熵
信息增益=I(父节点)−I(子节点)父节点代表总体的信息熵子节点代表指定特拆分之后的信息熵
案例:计算篮球的信息熵
数据:
篮球 | 0 | 1 | 1 | 1 | 0 |
---|---|---|---|---|---|
游戏 | 0 | 0 | 0 | 0 | 1 |
性别 | 0 | 1 | 1 | 0 | 0 |
划分:因为计算的是篮球的信息熵,所以使用篮球特征进行分类
结论:
篮球特征的信息增益 = 0.97 - 0.55 = 0.42
同理计算游戏的信息增益 = 0.97 - 0.8 = 0.17
对比篮球和游戏的信息增益,说明篮球的特征带来的信息增益更大些,所以在仅有的这两个特征的前提下,应该使用篮球特征作为根节点进行拆分子节点
2.3 划分数据集
划分数据集的最大准则是选择最大信息增益,也就是信息下降最快的方向
代码实现最大信息增益的计算:
#最大信息增益计算
#1.数据集
import pandas as pd
import numpy as np
data = pd.DataFrame(
data={
'篮球':[0,1,1,1,0],
'游戏':[0,0,0,0,1],
'性别':[0,1,1,0,0],
}
)
print(data)
#2.返回整个数据集的信息熵
def allEnt(data):
#行数
n = data.shape[0]
#分类和分类的概率
cnt = data.iloc[:,-1].value_counts()
p = cnt/n
#信息熵
ent = (-p*np.log2(p)).sum()
return ent
#3.循环遍历每一列和标签列来计算信息熵
def preEnt(data):
#先计算总熵
allent = allEnt(data)
print('总体信息熵=',allent)
#总行数
rows = data.shape[0]
print('总行数=',rows)
#定义变量,用于对比哪个特征的信息增益最高
best = -1
#定义变量接收列标签,因为每次循环都会改变
axis = 0
for i in range(0,data.shape[1]-1): #每次取一列数据
flags = data.iloc[:,i].value_counts().index #获取每一列的种类
print(flags)
ent=0
for j in flags: #遍历每一列的分类,通过分类去标签列取每一个子节点的数据集(这个数据集会包括多余的特征,但是不影响调用函数 allEnt())
childSet = data[data.iloc[:,i]==j] #每一个子数据集
#print(childSet)
childEnt = allEnt(childSet) #调用上面的方法,求每个子集的信息熵
#print(childEnt)
ent += childEnt * (childSet.shape[0]/rows) #每个子节点的信息熵乘以权重 再累加
#计算信息增益
zy = allent - ent
print('第{}列的信息熵='.format(i),ent)
print('第{}列的信息增益='.format(i),zy)
#判断哪个特征的信息增益最高
if zy>= best:
best = zy #把最高的信息增益的数据赋值给best
axis = i #把最高信息增益的列标签赋值给axis
print('最高的信息增益=',best)
print('最高信息增益的列=',axis)
return best,axis
preEnt(data) #结果:(0.4199730940219749, 0),代表最高信息增益=0.42,产生最高信息增益的是第0列数据
2.4 按照给定列进行数据集划分
实际上就是上一步计算出信息增益最高的列,然后得到列标签,再进行划分数据集
目的:为后续进一步做划分而准备
#通过指定列和指定列的分类进行划分数据
#1.数据集
import pandas as pd
import numpy as np
data = pd.DataFrame(
data={
'篮球':[0,1,1,1,0],
'游戏':[0,0,0,0,1],
'性别':[0,1,1,0,0],
}
)
print(data)
#2.划分数据集,根据上面知道第0列是信息增益最高的列,所以使用第0列进行划分
def split(data,column,value):
col = data.columns[column] #找到指定列的名称
childSet = data[data.iloc[:,column]==value] #这里取得是 column 列里面值=value的数据
childSet = childSet.drop(col,axis=1) #把指定划分的列删除
return childSet
split(data,0,1) #
三:决策树算法
算法原理:递归
算法分类:ID3 / C4.5 / C5.0
递归约束的条件是:
- 程序遍历完所有划分数据集的属性
- 每个分支下的所有实例都具有相同的分类
- 当前节点包含的样本集合为空,不能划分
3.1 ID3
ID3 算法的核心是在决策树各个节点应用信息增益准则选择特征,递归地构建决策树。具体方法是:
- 从根节点开始,对节点计算所有可能的特征的信息增益。
- 选择信息增益最大的特征作为节点的特征,由该特征的不同取值建立子节点。
- 再对子节点调用以上方法,构建决策树。
- 直到所有特征的信息增益均很小或没有特征可以选择为止,最后得到一颗决策树。
ID3的缺点:
ID3 算法局限主要源于局部最优化条件,即信息增益的计算方法,其局限性主要有以下几点:
- 分支度越高(分类水平越多)的离散变量往往子节点的总信息熵更小,ID3 是按照某一列进行切
分, 有一些列的分类可能不会对结果有足够好的指示。极端情况下取 ID 作为切分字段,每个分类
的纯度都是 100%,因此这样的分类方式是没有效益的。 - 不能直接处理连续型变量,若要使用 ID3 处理连续型变量,则首先需要对连续变量进行离散化。
- 对缺失值较为敏感,使用 ID3 之前需要提前对缺失值进行处理。
- 没有剪枝的设置,容易导致过拟合,即在训练集上表现很好,测试集上表现很差
3.2 C4.5
C4.5比ID3更优的原因是:其修改局部最优化条件
- ID3 以息增益作为划分训练数据集的特征,存在偏向于选择取值较多的特征的问题
- C4.5 使用信息增益比(information gain ratio)可以对这一问题进行校正。
- 增益率准则对可取值数目较少的属性有所偏好,因此,C4.5 算法并不是直接选择增益率
最大的候选划分属性,而是使用了一种启发式:先从候选划分属性中找出信息增益高于平均水平的属
性, 再从中选择增益率最高的。
公式:
信
息
增
益
率
/
比
G
a
i
n
_
r
a
t
i
o
n
(
D
,
a
)
=
G
a
i
n
(
D
,
a
)
I
V
(
a
)
其
中
I
V
(
a
)
=
−
∑
v
=
1
V
∣
D
v
∣
∣
D
∣
l
o
g
2
∣
D
v
∣
∣
D
∣
I
V
(
a
)
称
呼
为
属
性
/
特
征
a
的
固
有
值
,
V
代
表
特
征
a
的
l
e
v
e
l
数
,
所
以
V
越
大
,
则
I
V
(
a
)
也
越
高
信息增益率/比 Gain\_ration(D,a) = \frac{Gain(D,a)}{IV(a)} \\ 其中 IV(a) = -\sum_{v=1}^{V}\frac{|D_v|}{|D|}log2\frac{|D_v|}{|D|} \\ IV(a)称呼为 属性/特征 a 的固有值,V代表特征a的level数,所以V越大,则IV(a)也越高
信息增益率/比Gain_ration(D,a)=IV(a)Gain(D,a)其中IV(a)=−v=1∑V∣D∣∣Dv∣log2∣D∣∣Dv∣IV(a)称呼为属性/特征a的固有值,V代表特征a的level数,所以V越大,则IV(a)也越高
计算信息增益率:
特征a | 特征b | 标签 | |
---|---|---|---|
0 | 0 | 1 | 是 |
1 | 0 | 1 | 是 |
2 | 0 | 0 | 不是 |
3 | 1 | 1 | 不是 |
4 | 1 | 1 | 不是 |
根据上面的数据,计算是否特征a的信息增益率:
IV(a) = -3/5log2(3/5)-2/5log2(2/5) = 0.971
总的信息熵: ent_all = -2/5log2(2/5) -3/5log2(3/5)= 0.97
特征a的信息熵:ent_a = -3/5*(2/3np.log2(2/3)+1/3np.log2(1/3))= 0.55
特征a的信息增益:Gain(D,a) = 0.97-0.55=0.42
特征a的信息增比:Gain_ration(D,a) = 0.55/0.97 = 0.432
C4.5怎么处理连续变量:
在 C4.5 中,同样还增加了针对连续变量的处理手段。如果输入特征字段是连续型变量,则算法首先会
对这一列数进行从小到大的排序,然后选取相邻的两个数的中间数作为切分数据集的备选点,若一个连
续 变量有 N 个值,则在 C4.5 的处理过程中将产生 N-1 个备选切分点,并且每个切分点都代表着一种二
叉树的切分方案
四:拟合度优化(CART算法)
判断是否过拟合或者欠拟合
剪枝
有一套决策树独有的防止过拟合的解决方案— —剪枝。
预剪枝 | 后剪枝 | |
---|---|---|
分支数 | 很多分支没有展开 | 保留了很多分支 |
拟合风险 | 降低过拟合风险,但由于贪心算法的本质禁止后续分支的展开,带来了欠拟合的风险 | 先生成决策树,自上而下逐一考核,欠拟合风险小,泛化能力较强 |
时间开销 | 训练和测试开销小 | 相对预剪枝小 |
所以,常用的是后剪枝
剪枝算法–CART算法:
- 分裂过程是一个二叉递归划分过程
- CART 预测变量 x 的类型既可以是连续型变量也可以是分类型变量(如果是连续变量,需要转化成哑变量)
- 数据应以其原始形式处理,不需要离散化
- 用于数值型预测时,并没有使用回归,而是基于到达叶节点的案例的平均值做出预测
CART算法的分裂准则:二叉分裂
二叉递归划分:条件成立向左,反之向右
- 对于连续变量:条件是属性小于等于最优分裂点
- 对于分类变量:条件是属性属于若干类
二叉分裂优点:
相比多路分裂导致数据碎片化的速度慢,允许在一个属性上重复分裂,即可以在一个属性上产生足够多
的分裂。两路分裂带来的树预测性能提升足以弥补其相应的树易读性损失。
对于属性不同的被预测变量 y 分裂准则不同:
- 分类树:Gini 准则。与之前的信息增益很类似,Gini 系数度量一个节点的不纯度。
- 回归树:一种常见的分割标准是标准偏差减少(Standard Deviation Reduction, SDR),类似于
- 最小均方误差 LS(least squares,预测错误的平方和)准则。
CART算法怎么剪枝:
五:sklean生成决策树
5.1 参数 criterion
criterion两个参数 | entropy信息熵 | gini基尼系数 |
---|---|---|
- | 对不纯度更加敏感,对不纯度惩罚最强 | |
- | 计算慢,因为涉及对数运算 | 不涉及对数运算,更快 |
- | 高纬/噪声很多的数据容易过拟合,如果模型欠拟合的时候可以选择信息熵 | 噪声高的数据使用 |
5.2 代码实现
#sklean 实现决策树
#1.导入需要的算法库和模块
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
plt.rcParams['font.sans-serif']=['Simhei']
plt.rcParams['axes.unicode_minus']=False
#2.准备数据
wine = load_wine()
wine.data.shape
wine.target
wine_pd=pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
#wine.feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315 稀释葡萄酒','脯氨酸']
wine.feature_names.append("result")
wine_pd.columns=wine.feature_names
wine_pd = wine_pd.rename(columns={
'alcohol':'酒精','malic_acid':'苹果酸',
'ash':'灰','alcalinity_of_ash':'灰的碱性',
'magnesium':'镁','total_phenols':'总酚',
'flavanoids':'类黄酮','nonflavanoid_phenols':'非黄烷类酚类',
'proanthocyanins':'花青素','color_intensity':'颜色强度',
'hue':'色调','od280/od315_of_diluted_wines':'od280/od315 稀释葡萄酒',
'proline':'脯氨酸','result':'标签'
})
print(wine_pd.head())
#3.划分训练集和测试集
Xtrain,Xtest,Ytrain,Ytest = train_test_split(wine_pd.iloc[:,:-1],wine_pd.iloc[:,-1],test_size=0.3,random_state=420)
#4.建立模型
clf = tree.DecisionTreeClassifier(criterion='gini') #使用gini参数,默认也是gini
#5.训练模型
clf = clf.fit(Xtrain,Ytrain)
#6.查看准确度
score = clf.score(Xtest,Ytest)
print(score) # 0.9444444444444444
#4.画树
#使用包: pip install graphviz , 还需要手动安装插件以及设置系统环境路径 PATH (包括 bin目录,以及bin目录下的 dot.exe 两个路径)
import graphviz
import matplotlib.pyplot as plt
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315 稀释葡萄酒','脯氨酸']
dot_data = tree.export_graphviz(clf, #模型
feature_names= feature_name, #特征列名称
class_names=["琴酒","雪莉","贝尔摩德"], #实际上对应 标签的 0 / 1 / 2
filled=True, #渲染颜色
)
graph = graphviz.Source(dot_data,filename='决策树PDF')
graph
export_graphviz生成一个DOT格式的决策树的参数:
- feature_names:每个属性的名字
- class_names:每个因变量类别的名字
- label:是否显示不纯度信息的标签,默认为"all"表都显示,可以是"root"或"none"
- filled:是否给每个结点的主分类绘制不同的颜色,默认为False
- out_file:输出的dot文件的名字,默认为None表示不输出文件,可以是自定义名字如"tree.dot"
- rounded:默认为Ture,表示对每个结点的边框加圆角,并使用Helvetica字体
- 更多参数:https://scikit-learn.org/stable/modules/generated/sklearn.tree.export_graphviz.html#sklearn.tree.export_graphviz
决策树初步外观:
六:决策树属性
1.clf.feature_importances_
显示每个特征重要性
clf.feature_importances_
[*zip(feature_name,clf.feature_importances_)]
2.clf.apply
返回每个预测样本的叶子索引
3.clf.tree_.node_count
返回树的节点个数
4.clf.tree_.feature
返回每个节点对应的属性索引值,-2 表示叶节点:
七:防止过拟合(剪枝参数)
7.1 参数random_state 随机种子
每次设置不同 随机种子,得出的树都不一样,所以
tree.DecisionTreeClassifier(
criterion="entropy"
,random_state=30 #这个随机种子可以随便变化
,splitter="random"
)
7.2 参数 splitter
splitter 有两个值:
1.splitter =‘best’
决策树在分支时虽然随机,但是还是会优先选择更重要的特征进行分支(重要性可以通过属性feature_importances_查看);
2.splitter =‘random’
可以降低过拟合的可能性,但是后剪枝还是使用下面的剪枝参数进行优化
tree.DecisionTreeClassifier(
criterion="entropy"
,random_state=30
,splitter="random" #best / random
)
7.3 剪枝参数:
7.3.1 max_depth 限制树的最大深度
建议从=3 开始尝试,看看拟合的效果再决定是否增加设定深度
7.3.2 min_samples_leaf 分支后每个节点至少包含的样本数量
数值太小,会过拟合,太大会欠拟合
建议从=5 开始使用,如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用
7.3.3 min_samples_split 每个节点至少要大于等于这个样本量才会被分支
7.3.4 max_features 限制分支时考虑的特征个数,超过限制个数的特征都会被舍弃
用来限制高维度数据的过拟合的剪枝参数,但其方法比较暴力,是直接限制可以使用的特征数量而强行使决策 树停下的参数,在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导致模型学习不足
如果希望通过降维的方式防止过拟合,建议使用 PCA,ICA 或者特征选择模块中的降维算法
7.3.5 min_impurity_decrease 限制信息增益的大小
信息增益小于设定数值的分支不会发生。这是在 0.19 版本中更新的功能,在 0.19 版本之前时使用 min_impurity_split
案例:
#数据准备 忽略,延用上面红酒分类的案例
#4.建立模型
clf = tree.DecisionTreeClassifier(criterion='gini',
random_state=420, #随机种子
splitter='random',#可以防止过拟合
#1.最大数深度,除了根节点,下面子节点的层数=max_depth
max_depth=5,
#2.子节点至少样本个数,如果是浮点类型则代表子节点占父节点的百分比
min_samples_leaf=0.1,
#3.子节点最小样本分支数,样本量要达到这个数量的节点才会被分支
min_samples_split=20,
#4.最大特征数,节点的特征数大于这个的节点就被舍弃
max_features=3,
#5.最小分支信息增益,当特征的信息增益小于设置值,就不会被分支了
min_impurity_split=0.1
) #使用gini参数,默认也是gini
#5.训练模型
clf = clf.fit(Xtrain,Ytrain)
#6.查看准确度
score = clf.score(Xtest,Ytest)
print(score) # 0.9444444444444444
#4.画树
#使用包: pip install graphviz
import graphviz
import matplotlib.pyplot as plt
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315 稀释葡萄酒','脯氨酸']
dot_data = tree.export_graphviz(clf, #模型
feature_names= feature_name, #特征列名称
class_names=["琴酒","雪莉","贝尔摩德"], #实际上对应 标签的 0 / 1 / 2
filled=True, #渲染颜色
)
graph = graphviz.Source
(dot_data,filename='决策树PDF')
graph
7.4 怎么确定最优的剪枝参数
这里使用学习曲线的方式,循环找出准确率/分数最大的最优参数
缺点:如果需要找所有参数的最优解,则需要嵌套多层循环,很麻烦
解决方案:网络搜索,后续更新
案例:使用学习曲线找出最大深度的最优解
#数据准备 忽略,延用上面红酒分类的案例
y=[]
for i in range(1,21):
#4.建立模型
clf = tree.DecisionTreeClassifier(criterion='gini',
random_state=420, #随机种子
splitter='random',#可以防止过拟合
max_depth=i #1.最大数深度
)
#5.训练模型
clf = clf.fit(Xtrain,Ytrain)
#6.查看准确度
score = clf.score(Xtest,Ytest)
y.append(score)
print(score) # 0.9444444444444444
#画图,学习曲线
import matplotlib.pyplot as plt
plt.plot(range(1,21),y)
plt.xticks(range(1,21))
7.5 总结
属性是在模型训练之后,能够调用查看的模型的各种性质 。对决策树来说,最重要的是feature_importances_,能够查看各个特征对模型的重要性。
- sklearn 中许多算法的接口都是相似的,比如说我们之前已经用到的 fit 和 score,几乎对每个算法都可以使用。除了这两个接口之外,决策树最常用的接口还有 apply 和 predict。
- apply 中输入测试集返回每个测试样本所在的叶子节点的索引。
- predict 输入测试集返回每个测试样本的标签。返回的内容一目了然并且非常容易,大家感兴趣可以自
己下去试试看。 - 在这里不得不提的是,所有接口中要求输入 Xtrain 和 Xtest 的部分,输入的特征矩阵必须至少是一个二
维矩阵。 sklearn 不接受任何一维矩阵作为特征矩阵被输入。如果你的数据的确只有一个特征,那必须
用 reshape(-1,1)来给矩阵增维。 - 分类树的八个参数,一个属性,四个接口,以及绘图所用的代码:
- 八个参数:Criterion;
- 两个随机性相关的参数(random_state,splitter);
- 五个剪枝参数 (max_depth, min_samples_split , min_samples_leaf , max_feature ,min_impurity_decrease) ;
- 一个属性:feature_importances_ ;
- 四个接口:fit,score,apply,predict
八:分类模型评估指标(class_weight)
8.1 第一种样本不均匀问题的方法
创建不均匀样本
#样本不均匀案例
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_blobs #这个是聚类产生数据集的方法
class_1=1000 #类别1 样本量
class_2=100 #类别2 样本量
centers=[[0,0],[2,2]] #两个类别的中心点
clusters_std=[2.5,0.5] #两个类别的方差
x,y = make_blobs(n_samples=[class_1,class_2],
centers=centers,
cluster_std=clusters_std,
random_state=420,
shuffle=False
)
plt.scatter(x[:,0],x[:,1],c=y,cmap='rainbow',s=10)
对比设置class_weight参数和不设置参数的得分:
#划分数据集
from sklearn.model_selection import train_test_split
Xtrain,Xtest,Ytrain,Ytest = train_test_split(x,y,test_size=0.2, random_state=420)
#创建模型
#1.不设置 class_weight
clf_01 = DecisionTreeClassifier()
clf_01 = clf_01.fit(Xtrain,Ytrain)
score_01 = clf_01.score(Xtest,Ytest)
print('不设置参数的得分=',score_01)
#2.设置 class_weight
clf_02 = DecisionTreeClassifier(class_weight='balanced')
clf_02 = clf_02.fit(Xtrain,Ytrain)
score_02 = clf_02.score(Xtest,Ytest)
print('设置参数的得分=',score_02)
结果: 针对不均匀样本,设置 class_weight 可以得到更高的分数
不设置参数的得分= 0.8954545454545455
设置参数的得分= 0.9045454545454545
九:分类模型评估指标(混淆矩阵–专用二分类样本不均衡)
9.1 混淆矩阵的概念
混淆矩阵是二分类问题的多维衡量指标体系,在样本不平衡时极其有用
在混淆矩阵中,我们将少数类认为是正例,多数类认为是负例
在决策树,随机森林这些分类算法里,即是说少数类是 1,多数类是 0
在 SVM 里,就是说少数类是 1,多数类是-1
预测值 | 预测值 | ||
---|---|---|---|
1 | 0 | ||
真实值 | 1 | 11 (TP) | 10 (FN) |
真实值 | 0 | 01 (FP) | 00 (TN) |
其中:
行代表预测情况,列则表示实际情况。
- 预测值为 1,记为 P(Positive)
- 预测值为 0,记为 N(Negative)
- 预测值与真实值相同,记为 T(True)
- 预测值与真实值相反,记为 F(False)
- 因此矩阵中四个元素分别表示:
◼ TP(True Positive): 真实为 1,预测作 1
◼ FN(False Negative): 真实为 1,预测作 0
◼ FP(False Positive): 真实为 0,预测作 1
◼ TN(True Negative): 真实为 0,预测作 0
9.2 模型效果评估
9.2.1 准确率 Accuracy
Accuracy = (11+00) / (11+00+10+01)
准确率 Accuracy 就是所有预测正确的所有样本除以总样本,通常来说越接近 1 越好。
记住少数类是1,多数类是 0
9.2.2 精确度 Precision , 又叫查准率
Precision = (11) / (11+01)
表示在所有预测结果为 1 的样例数中,实际为 1 的样例数所占比重。
精确度越低,意味着 01 比重很大,则代表你的模型对多数类 0 误判率越高,误伤了过多的多数类 (为什么是误判多数类?因为多数类记为0,少数类记为1)
9.2.3 召回率 Recall ,又被称为敏感度(sensitivity),真正率,查全率
Recall = (11) / (11+10)
表示所有真实为 1 的样本中,被我们预测正确的样本所占的比例
召回率越高,代表我们尽量捕捉出了越多的少数类
召回率越低,代表我们没有捕捉出足够的少数类
9.2.4 F1 measure
为了同时兼顾精确度和召回率,我们创造了两者的调和平均数作为考量两者平衡的综合性指标,称之为F1measure
F-measure = (2 * Precision) / (Precision + Recall)
F1 measure 在[0,1]之间分布,越接近 1 越好
9.2.5 假负率 False Negative Rate
它等于 1 - Recall,用于衡量所有真实为 1 的样本中,被我们错误判断为 0 的,通常用得不多。
FNR = (10) / (11 + 10)
9.2.6 ROC曲线 Receiver Operating Characteristic Curve
9.3 sklean 中的混淆矩阵
类 | 含义 |
---|---|
sklearn.metrics.confusion_matrix | 混淆矩阵 |
sklearn.metrics.accuracy_score | 准确率 |
sklearn.metrics.precision_score | 精确度 |
sklearn.metrics.recall_score | 召回率 |
sklearn.metrics.precision_recall_curve | 精确度-召回率平衡曲线 |
sklearn.metrics.f1_score | F1 measure |
对比上面案例两个模型 不平衡clf_01 / 平衡clf_02 之间的一些数据:
#导入混淆矩阵包
from sklearn import metrics
#1.对比clf_01 和 clf_02 的准确率
metrics.precision_score(Ytest,clf_01.predict(Xtest)) #0.6363636363636364
metrics.precision_score(Ytest,clf_02.predict(Xtest)) #0.6538461538461539
#2.对比召回率
metrics.recall_score(Ytest,clf_01.predict(Xtest)) #0.4827586206896552
metrics.recall_score(Ytest,clf_02.predict(Xtest)) #0.5862068965517241
#3.对比 F1 值
metrics.f1_score(Ytest,clf_01.predict(Xtest)) #0.5490196078431373
metrics.f1_score(Ytest,clf_02.predict(Xtest)) #0.6181818181818182
十:决策树算法优缺点
优点:
- 易于理解和解释,因为树木可以画出来被看见。
- 需要很少的数据准备。其他很多算法通常都需要数据规范化,需要创建虚拟变量并删除空值等。但请
注意,sklearn 中的决策树模块不支持对缺失值的处理。 - 使用树的成本(比如说,在预测数据的时候)是用于训练树的数据点的数量的对数,相比于其他算
法,这是一个很低的成本。 - 能够同时处理数字和分类数据,既可以做回归又可以做分类。其他技术通常专门用于分析仅具有一种
变量类型的数据集。 - 即使其假设在某种程度上违反了生成数据的真实模型,也能够表现良好。
缺点:
- 使用决策树可能创建过于复杂的树,这些树不能很好地推广数据。这称为过度拟合。修剪,设置 叶节
点所需的最小样本数或设置树的最大深度等机制是避免此问题所必需的,而这些参数的整合和调整对 初
学者来说会比较晦涩。 - 决策树可能不稳定,数据中微小的变化可能导致生成完全不同的树,这个问题需要通过集成算法来解
决。 - 决策树的学习是基于贪婪算法,它靠优化局部最优(每个节点的最优)来试图达到整体的最优,但这
种做法不能保证返回全局最优决策树。这个问题也可以由集成算法来解决,在随机森林中,特征和样本
会在分枝过程中被随机采样。 - 如果标签中的某些类占主导地位,决策树学习者会创建偏向主导类的树。因此,建议在拟合决策树之
前平衡数据集。