决策树 信息熵 条件熵 基尼系数 信息增益 信息增益率 CART 随机森林
决策树:
决策树是一种树形结构,树内部每个节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶子节点代表一个分类类别。通过训练数据构建决策树,可以对未知数据进行分类,
上面的决策树深度depth为3
使用鸢尾花数据
import numpy as np
import matplotlib.pyplot as pltfrom sklearn import datasets
iris = datasets.load_iris()
X = iris.data[:,2:]
y = iris.targetplt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()
# 绘制边界
def plot_decision_boundary(model,axis):x0,x1 = np.meshgrid(np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)),np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)))x_new = np.c_[x0.ravel(),x1.ravel()]y_predict = model.predict(x_new)zz = y_predict.reshape(x0.shape)from matplotlib.colors import ListedColormapcustom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])plt.contourf(x0,x1,zz,cmap=custom_cmap)
使用sklearn中决策树 使用信息熵
from sklearn.tree import DecisionTreeClassifierdt_clf = DecisionTreeClassifier(max_depth=2, criterion='entropy')
dt_clf.fit(X,y)plot_decision_boundary(dt_clf, axis=[0.5,7.5,0,3])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()
问题:怎么构建决策树?每个节点在哪个维度做划分?我们的数据可能有成百上千个维度。
某个维度在哪个值上做划分呢?
我们可以用信息熵来处理
信息熵
熵在信息论中代表: 随机变量不确定度的度量
熵越大,数据的不确定性越高
熵越小,数据的不确定性越低
信息熵的计算公式:
H=−∑i=1kpilog(pi)H = - \sum_{i=1}^k p_i log(p_i)H=−i=1∑kpilog(pi)
pip_ipi 是指每种数据集中,有k类, 其每类在数据集中占的比例
因为 pip_ipi肯定是小于1的,所以 log(pi)log(p_i)log(pi)为负数,所以前面会有负号
这样就是整数了
右边的熵小,所以右边的数据比左边的数据更确定
如果 是 {1,0,0},其信息熵 H = -1x log(1) =0
最确定的情况下,信息熵为0.即信息熵的最小值为0
### 信息熵def entropy(p): # 假设只有两类return -p * np.log(p) - (1-p) * np.log(1-p)x = np.linspace(0.01, 0.99,200)
plt.plot(x, entropy(x))
plt.show()
信息熵曲线
所以上面的问题就是 划分后使得信息熵降低,达到最小值
所以就是在节点上划分最小值信息熵
模拟使用信息熵寻找最优划分
# 划分X,y
def split(X,y, d, value):index_a = [X[:,d] <=value]index_b = [X[:,d] > value]return X[index_a], X[index_b], y[index_a],y[index_b]from collections import Counter
from math import log
# 计算信息熵
def entropy(y):counter = Counter(y)res =0.0for num in counter.values():p = num/len(y)res += -p * log(p)return res# 循环寻找 最小信息熵
def try_split(X, y):best_entropy = float('inf')best_d, best_v = -1,-1for d in range(X.shape[1]):sorted_index = np.argsort(X[:,d])for i in range(1, len(X)):if X[sorted_index[i-1],d] != X[sorted_index[i],d]:v = (X[sorted_index[i-1],d] + X[sorted_index[i],d])/2X_l,X_r,y_l,y_r = split(X,y,d,v)e = entropy(y_l) + entropy(y_r)if e< best_entropy:best_entropy, best_d,best_v = e,d,vreturn best_entropy, best_d, best_v
将X,y 根据计算
try_split(X,y)
# (0.6931471805599453, 0, 2.45)
# 最小信息熵, 维度,维度的值
使用 维度,和维度的值 划分
best_d =0
best_v =2.45
X1_l,X1_r,y1_l,y1_r = split(X,y,best_d,best_v)
entropy(y1_l) # 0
entropy(y1_r) # 0.6931471805599453try_split(X1_r, y1_r) # 进行对信息熵不为0的在进行计算
# (0.4132278899361904, 1, 1.75)
基尼系数
和信息熵类似,基尼系数越高,数据随机性越强,不确定性越强
G=1−∑i=1kpi2G = 1 - \sum_{i=1}^k p_i^2G=1−i=1∑kpi2
当基尼数据为0,就是数据绝对确定,
对于二分类问题计算基尼系数:
G=1−x2−(1−x)2=1−x2−1+2x−x2=−2x2+2xG = 1 - x^2 -(1- x)^2 =1-x^2 -1 +2x - x^2 =-2x^2+2xG=1−x2−(1−x)2=1−x2−1+2x−x2=−2x2+2x
可以看出此图是一个抛物线,当各占50%是基尼系数最大
使用sklearn中的基尼系数
还是使用上面的鸢尾花数据
from sklearn.tree import DecisionTreeClassifierdt_clf = DecisionTreeClassifier(max_depth=2, criterion='gini') # 此处的变成 gini
dt_clf.fit(X,y)plot_decision_boundary(dt_clf, axis=[0.5,7.5,0,3])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()
模拟使用基尼系数划分
和上面使用 信息熵 的模拟 一样
def gini(y):counter = Counter(y)res =1.0for num in counter.values():p = num/len(y)res -= p**2return resdef try_gini_split(X, y):best_g = float('inf')best_d, best_v = -1,-1for d in range(X.shape[1]):sorted_index = np.argsort(X[:,d])for i in range(1, len(X)):if X[sorted_index[i-1],d] != X[sorted_index[i],d]:v = (X[sorted_index[i-1],d] + X[sorted_index[i],d])/2X_l,X_r,y_l,y_r = split(X,y,d,v)g = gini(y_l) + gini(y_r)if g< best_g:best_g, best_d,best_v = g,d,vreturn best_g, best_d, best_vtry_gini_split(X,y) # (0.5, 0, 2.45)X2_l,X2_r,y2_l,y2_r =split(X,y,0,2.45)
gini(y2_l) # 0
gini(y2_r) # 0.5 对 X2_r 再进行处理
因为信息熵要求log,所以信息熵的计算比基尼系数要慢一点。
scikit-learn 中默认为 基尼系数
大多数时候二者没有特别的效果优劣
条件熵
在某个分类条件下某个类别的信息熵叫做条件熵,类似于条件概率,在知道Y的情况下,X的不确定性。条件熵一般使用 表示,代表在Y条件下,X的信息熵。
上图中假设在“年龄”条件下,“是否购买电脑”的信息熵为:“年龄”列每个类别下对应的“是否购买电脑”信息熵的和。
信息增益 C3
信息熵-条件熵 =信息增益
代表熵的变化程度。分类前的信息熵减去分类后的信息熵。如特征Y对训练集D的信息增益为:
g(D,|Y) = H(X)-H(X|Y)
在“年龄”条件下,“是否购买电脑”的信息增益为:
g(是否购买电脑,年龄)=H(是否购买电脑)-H(是否购买电脑,年龄)=0.94-0.69=0.25
由以上可知,按照“记录ID”,“年龄”,“收入层次”,“学生”,“信用等级”列使用决策树来预测“是否购买电脑”,选择分类根分类条件时步骤:
a.计算“是否购买电脑”的信息熵
b.计算在已知各个列的条件熵
H(是够购买电脑|年龄),H(是够购买电脑|收入层次),H(是够购买电脑|是否学生),H(是够购买电脑|信用等级)
c.求各个条件下的信息增益,选择信息增益大的作为分类条件。选择中间节点时,以此类推。
在构建决策树时,选择信息增益大的属性作为分类节点的方法也叫ID3分类算法。
信息增益率 C4.5
在上图中,如果将“记录ID”也作为分类条件的话,由于“记录ID”对于“是否购买电脑”列的条件熵为0,可以得到“是否购买电脑”在“记录ID”这个分类条件下信息增益最大。如果选择“记录ID”作为分类条件,容易造成分支特别多,对已有记录ID的数据可以分类出结果,对于新的记录ID有可能不能成功的分类出结果。
使用信息增益来筛选分类条件,更倾向于选择更混杂的属性。容易出现过拟合问题。可以使用信息增益率来解决这个问题。
信息增益率的公式:gr(D,A) = g(D,A)/H(A),在某个条件下信息增益除以这个条件的信息熵。
例如:在“记录ID”条件下,“是否购买电脑”的信息增益最大,信息熵H(记录ID)也比较大,两者相除就是在“记录ID”条件下的信息增益率,结果比较小,消除了当某些属性比较混杂时,使用信息增益来选择分类条件的弊端。使用信息增益率来构建决策树的算法也叫C4.5算法。一般相对于信息增益来说,选择信息增益率选择分类条件比较合适。
如果决策树最后一个条件依然没能将数据准确分类,那么在这个节点上就可以使用概率来决定。看看哪些情况出现的多,该情况就是该节点的分类结果。
单棵决策树的缺点
1 运算量大,需要一次加载所有数据进内存,并且找寻分割条件是一个极耗资源的工作
2 训练样本中出现异常数据时,将会对决策树产生很大影响,抗干扰能力差
CART
Classification And Regression Tree
根据某一个维度d 和某一个阈值v进行二分
scikit-learn中的决策树实现都是CART
(还有别的种类:ID3,C4.5, C5.0)
- 复杂度:
预测:O(logm)
训练:O(nmlogm) 时间较长
容易产生过拟合,所以需要对决策树 减枝
剪枝:降低复杂度,解决过拟合- 如何剪枝:
- 限制深度 max_depth
- 如何剪枝:
from sklearn import datasets
# 创造数据
X,y = datasets.make_moons(noise=0.25, random_state=666)plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.show()
from sklearn.tree import DecisionTreeClassifierdt_clf = DecisionTreeClassifier() # 不限制深度,
dt_clf.fit(X,y)plot_decision_boundary(dt_clf, axis=[-1.5,2.5,-1.0,1.5])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()
可以发现出现了过拟合
当限制 深度后,设置其深度为2,
上图有可能会是欠拟合,所以我们需要多次调整
- 调整 min_samples_split 的值 。这个表示 最少多少个点才会进行划分分类处理。
dt_clf3 = DecisionTreeClassifier(min_samples_split=10)
dt_clf3.fit(X,y)
plot_decision_boundary(dt_clf3, axis=[-1.5,2.5,-1.0,1.5])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()
- min_samples_leaf 对于叶子节点最少要有多少个点
dt_clf4= DecisionTreeClassifier(min_samples_leaf=6)
dt_clf4.fit(X,y)
plot_decision_boundary(dt_clf4,axis=[-1.5,2.5,-1.0,1.5])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()
- 最多有多少个叶子节点 max_leaf_nodes
dt_clf5= DecisionTreeClassifier(max_leaf_nodes=4)
dt_clf5.fit(X,y)
plot_decision_boundary(dt_clf5,axis=[-1.5,2.5,-1.0,1.5])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()
- 上面这些参数,我们可以使用网格搜索的方式来获取最佳值
决策树解决回归问题
from sklearn import datasets
boston = datasets.load_boston()
X= boston.data
y = boston.targetfrom sklearn.model_selection import train_test_split
X_train,X_test, y_train,y_test = train_test_split(X,y,random_state=666)from sklearn.tree import DecisionTreeRegressordt_reg = DecisionTreeRegressor()
dt_reg.fit(X_train,y_train)
dt_reg.score(X_test,y_test) # 0.6
dt_reg.score(X_train,y_train) # 1.0 可以看出出现了过拟合
决策树很容易对训练数据出现过拟合,根据上面列举对的进行调参
决策树的学习曲线
当使用默认值时:
当max_depth=5时,学习曲线
决策树的局限性
决策边界平行于坐标轴
若果对上面的进行一下旋转,
它的决策边界会变成:
对个别数据非常敏感(非参数学习都有的特点)
删除一个点,重新训练后绘制,就发现模型变化了
随机森林
随机森林是由多个决策树组成。是用随机的方式建立一个森林,里面由很多决策树组成。随机森林中每一棵决策树之间都是没有关联的。得到随机森林之后,对于一个样本输入时,森林中的每一棵决策树都进行判断,看看这个样本属于哪一类,最终哪一类得到的结果最多,该输入的预测值就是哪一类。
随机森林中的决策树生成过程是对样本数据进行行采样和列采样,可以指定随机森林中的树的个数和属性个数,这样当训练集很大的时候,随机选取数据集的一部分,生成一棵树,重复上面过程,可以生成一堆形态各异的树,这些决策树构成随机森林。
随机森林中的每个决策树可以分布式的训练,解决了单棵决策树在数据量大的情况下预算量大的问题。当训练样本中出现异常数据时,决策树的抗干扰能力差,对于随机森林来说也解决了模型的抗干扰能力。
数据·
1 1:2 2:1 3:1 4:1 5:68
1 1:2 2:2 3:1 4:1 5:78
1 1:3 2:1 3:1 4:1 5:78
1 1:3 2:1 3:2 4:2 5:77
1 1:3 2:2 3:1 4:1 5:70
1 1:2 2:2 3:1 4:1 5:74
1 1:3 2:2 3:2 4:1 5:75
1 1:3 2:2 3:2 4:1 5:78
1 1:2 2:1 3:1 4:2 5:78
1 1:3 2:2 3:1 4:1 5:76
1 1:3 2:2 3:1 4:1 5:73
1 1:3 2:1 3:1 4:1 5:70
1 1:3 2:2 3:1 4:1 5:64
0 1:2 2:2 3:1 4:2 5:48
0 1:1 2:3 3:2 4:2 5:51
0 1:2 2:3 3:2 4:1 5:49
0 1:1 2:3 3:2 4:2 5:43
0 1:1 2:3 3:2 4:2 5:69
0 1:2 2:3 3:2 4:2 5:44
0 1:2 2:3 3:2 4:2 5:50
0 1:1 2:3 3:2 4:1 5:72
0 1:2 2:3 3:2 4:2 5:56
0 1:1 2:3 3:2 4:2 5:45
0 1:1 2:2 3:2 4:2 5:43
0 1:3 2:2 3:2 4:2 5:48
0 1:2 2:3 3:2 4:2 5:67
0 1:2 2:3 3:2 4:2 5:46
0 1:2 2:3 3:2 4:2 5:45
0 1:1 2:2 3:2 4:2 5:41
0 1:2 2:3 3:2 4:2 5:48
0 1:2 2:3 3:1 4:2 5:62
0 1:2 2:3 3:2 4:2 5:45
scala 代码
package rfimport org.apache.spark.mllib.tree.DecisionTree
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.{SparkContext, SparkConf}
/*** 决策树*/
object ClassificationDecisionTree {def main(args: Array[String]): Unit = {val conf = new SparkConf()conf.setAppName("analysItem")conf.setMaster("local[3]")val sc = new SparkContext(conf)val data = MLUtils.loadLibSVMFile(sc, "汽车数据样本.txt")// Split the data into training and test sets (30% held out for testing)val splits = data.randomSplit(Array(0.7, 0.3))val (trainingData, testData) = (splits(0), splits(1))//指明分类的类别val numClasses=2//指定离散变量,未指明的都当作连续变量处理//某列下有1,2,3类别 处理时候要自定为4类,虽然没有0,但是程序默认从0开始分类//这里天气维度有3类,但是要指明4,这里是个坑,后面以此类推val categoricalFeaturesInfo=Map[Int,Int](0->4,1->4,2->3,3->3)//设定评判标准 "gini"/"entropy"val impurity="entropy" //树的最大深度,太深运算量大也没有必要 剪枝 防止模型的过拟合!!!val maxDepth=3//设置离散化程度,连续数据需要离散化,分成32个区间,默认其实就是32,分割的区间保证数量差不多 这个参数也可以进行剪枝val maxBins=32//生成模型val model =DecisionTree.trainClassifier(trainingData,numClasses,categoricalFeaturesInfo,impurity,maxDepth,maxBins)//测试val labelAndPreds = testData.map { point =>val prediction = model.predict(point.features)(point.label, prediction)}val testErr = labelAndPreds.filter(r => r._1 != r._2).count().toDouble / testData.count()println("Test Error = " + testErr)println("Learned classification tree model:\n" + model.toDebugString)}
}
随机森林
package rfimport org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.mllib.util.MLUtils
import org.apache.spark.mllib.tree.RandomForest
/*** 随机森林* */
object ClassificationRandomForest {def main(args: Array[String]): Unit = {val conf = new SparkConf()conf.setAppName("analysItem")conf.setMaster("local[3]")val sc = new SparkContext(conf)//读取数据val data = MLUtils.loadLibSVMFile(sc,"汽车数据样本.txt")//将样本按7:3的比例分成val splits = data.randomSplit(Array(0.7, 0.3))val (trainingData, testData) = (splits(0), splits(1))//分类数val numClasses = 2// categoricalFeaturesInfo 为空,意味着所有的特征为连续型变量val categoricalFeaturesInfo =Map[Int, Int](0->4,1->4,2->3,3->3)//树的个数val numTrees = 3 //特征子集采样策略,auto 表示算法自主选取//"auto"根据特征数量在4个中进行选择// 1:all 全部特征 。2:sqrt 把特征数量开根号后随机选择的 。 3:log2 取对数个。 4:onethird 三分之一val featureSubsetStrategy = "auto"//纯度计算 "gini"/"entropy"val impurity = "entropy"//树的最大层次val maxDepth = 3//特征最大装箱数,即连续数据离散化的区间val maxBins = 32//训练随机森林分类器,trainClassifier 返回的是 RandomForestModel 对象val model = RandomForest.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo,numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins)
// //打印模型
// println(model.toDebugString)//保存模型//model.save(sc,"汽车保险")//在测试集上进行测试val count = testData.map { point =>val prediction = model.predict(point.features)// Math.abs(prediction-point.label)(prediction,point.label)}.filter(r => r._1 != r._2).count()println("Test Error = " + count.toDouble/testData.count().toDouble)println("model "+model.toDebugString)}
}
决策树 信息熵 条件熵 基尼系数 信息增益 信息增益率 CART 随机森林相关推荐
- 决策树 随机森林 xgboost_推荐收藏 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost总结...
作者:ChrisCao https://zhuanlan.zhihu.com/p/75468124 一. 决策树决策树是一个有监督分类模型,本质是选择一个最大信息增益的特征值进行分割,直到达到结束条件 ...
- 决策树 随机森林 xgboost_从决策树到随机森林理论篇从人话到鬼话:看不懂来找我麻烦...
从决策树产生的一些列的问题,过度到随机森林: 全文大概要阅读10分钟: 随机森林算法范畴 监督学习分类算法,基模型是由决策树组成 决策树 决策树模型与学习 特征选择 决策树生成 决策树剪枝 CART算 ...
- 5000字干货 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost总结
作者:ChrisCao https://zhuanlan.zhihu.com/p/75468124 大家好,我是小z 今天分享一波机器学习的干货~ 一. 决策树 决策树是一个有监督分类模型,本质是选择 ...
- 随机森林实例:利用基于CART算法的随机森林(Random Forest)树分类方法对于红酒质量进行预测
随机森林实例:利用基于CART算法的随机森林(Random Forest)树分类方法对于红酒质量进行预测 1.引言 2.理论基础 2.1 什么是决策树 2.2 特征选择的算法 2.2.1 ID3:基于 ...
- 决策树Decision Tree 和随机森林RandomForest基本概念(一)
文章目录 一.决策树介绍 1.1 什么是决策树 1.2 决策树种类 1.3 决策树学习过程 1.4 Entropy(熵) 1.5 information gain(信息增益) 1.6 信息论 1.8 ...
- 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost总结
作者:ChrisCao https://zhuanlan.zhihu.com/p/75468124 一. 决策树 决策树是一个有监督分类模型,本质是选择一个最大信息增益的特征值进行输的分割,直到达到结 ...
- 机器学习(4):决策树和随机森林
最近自己会把自己个人博客中的文章陆陆续续的复制到CSDN上来,欢迎大家关注我的个人博客 zuzhiang.cn,以及我的github. 本文将讲解决策树和随机森林的基本思想,以及信息增益.信息增益率( ...
- 机器学习基础——分类算法之决策树、随机森林、Titanic乘客生存分类
目录 1 认识决策树 1.1 信息增益.信息熵的计算 1.2 举例计算编辑 1.3 决策树的分类依据 1.4 sklearn决策树API 2 泰坦尼克号乘客生存分类 2.1 案例背景 2.2 数据 ...
- 机器学习(八)KNN,SVM,朴素贝叶斯,决策树与随机森林
机器学习(八)KNN,SVM,朴素贝叶斯,决策树与随机森林 参考: https://zhuanlan.zhihu.com/p/61341071 1.KNN-K最近邻(K-Nearest Neighbo ...
最新文章
- node.js 微信小程序 部署服务器_微信小程序云开发环境部署,及添加数据
- (精简)Spring框架的IoC(替代工厂类实现方法)和AOP(定义规则,约定大于配置)
- Understanding transient variables in Java and how they are practically used in HashMap---reference
- c语言入门中冒泡排序的例题,选择排序和冒泡排序例题解析(c语言)
- Bean实例化三种方式
- git checkoutbranch 回退到某个版本进行修改
- Struts2环境搭建
- 谷歌推出开源工具DeepVariant,用深度学习识别基因变异
- C#DbHelperOleDb,Access数据库帮助类 (转载)
- http://blog.sina.com.cn/s/blog_6a01140c0100wimi.html
- oracle注释 kole_t2u,oracle4
- Code[VS]1302 小矮人
- java 怎么调用clojure_从java调用Clojure时Clojure状态的范围
- URI和URL的区别和关联
- python凹多边形分割_Unity 凹多边形三角剖分
- 丝杠螺母传动机构设计
- 模拟调节器和数字计算机如何实现PID控制,模拟PID-调节器设计及数字化实现.doc...
- Maven的依赖与最佳配置(转载自Maven实战 作者许晓斌)
- C04-算法达人修炼营学习安排及方法指导
- 小白入门 - PHP简介
热门文章
- 观察者模式——机房监控系统
- catia转stp有破面_CATIA破面修复教程.ppt
- 【Timm】create_model所提供的ViT模型概览
- css 设置 th 宽度,javascript
- 修改注册表锁定IE主页
- [COGS 2051] 王者之剑
- Spring Data JAP框架处理表关系的步骤(一对一外键关联
- 重装金蝶专业版后服务器不显示错误,金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示服务器不是有效的,请重新设置...
- UI框架-element
- python dajngo+vue 钉钉三方登录群机器人验证码