决策树:

决策树是一种树形结构,树内部每个节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶子节点代表一个分类类别。通过训练数据构建决策树,可以对未知数据进行分类,

上面的决策树深度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∑k​pi​log(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∑k​pi2​


当基尼数据为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 随机森林相关推荐

  1. 决策树 随机森林 xgboost_推荐收藏 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost总结...

    作者:ChrisCao https://zhuanlan.zhihu.com/p/75468124 一. 决策树决策树是一个有监督分类模型,本质是选择一个最大信息增益的特征值进行分割,直到达到结束条件 ...

  2. 决策树 随机森林 xgboost_从决策树到随机森林理论篇从人话到鬼话:看不懂来找我麻烦...

    从决策树产生的一些列的问题,过度到随机森林: 全文大概要阅读10分钟: 随机森林算法范畴 监督学习分类算法,基模型是由决策树组成 决策树 决策树模型与学习 特征选择 决策树生成 决策树剪枝 CART算 ...

  3. 5000字干货 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost总结

    作者:ChrisCao https://zhuanlan.zhihu.com/p/75468124 大家好,我是小z 今天分享一波机器学习的干货~ 一. 决策树 决策树是一个有监督分类模型,本质是选择 ...

  4. 随机森林实例:利用基于CART算法的随机森林(Random Forest)树分类方法对于红酒质量进行预测

    随机森林实例:利用基于CART算法的随机森林(Random Forest)树分类方法对于红酒质量进行预测 1.引言 2.理论基础 2.1 什么是决策树 2.2 特征选择的算法 2.2.1 ID3:基于 ...

  5. 决策树Decision Tree 和随机森林RandomForest基本概念(一)

    文章目录 一.决策树介绍 1.1 什么是决策树 1.2 决策树种类 1.3 决策树学习过程 1.4 Entropy(熵) 1.5 information gain(信息增益) 1.6 信息论 1.8 ...

  6. 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost总结

    作者:ChrisCao https://zhuanlan.zhihu.com/p/75468124 一. 决策树 决策树是一个有监督分类模型,本质是选择一个最大信息增益的特征值进行输的分割,直到达到结 ...

  7. 机器学习(4):决策树和随机森林

    最近自己会把自己个人博客中的文章陆陆续续的复制到CSDN上来,欢迎大家关注我的个人博客 zuzhiang.cn,以及我的github. 本文将讲解决策树和随机森林的基本思想,以及信息增益.信息增益率( ...

  8. 机器学习基础——分类算法之决策树、随机森林、Titanic乘客生存分类

    目录 1 认识决策树 1.1 信息增益.信息熵的计算 1.2 举例计算​编辑 1.3 决策树的分类依据 1.4 sklearn决策树API 2 泰坦尼克号乘客生存分类 2.1 案例背景 2.2  数据 ...

  9. 机器学习(八)KNN,SVM,朴素贝叶斯,决策树与随机森林

    机器学习(八)KNN,SVM,朴素贝叶斯,决策树与随机森林 参考: https://zhuanlan.zhihu.com/p/61341071 1.KNN-K最近邻(K-Nearest Neighbo ...

最新文章

  1. node.js 微信小程序 部署服务器_微信小程序云开发环境部署,及添加数据
  2. (精简)Spring框架的IoC(替代工厂类实现方法)和AOP(定义规则,约定大于配置)
  3. Understanding transient variables in Java and how they are practically used in HashMap---reference
  4. c语言入门中冒泡排序的例题,选择排序和冒泡排序例题解析(c语言)
  5. Bean实例化三种方式
  6. git checkoutbranch 回退到某个版本进行修改
  7. Struts2环境搭建
  8. 谷歌推出开源工具DeepVariant,用深度学习识别基因变异
  9. C#DbHelperOleDb,Access数据库帮助类 (转载)
  10. http://blog.sina.com.cn/s/blog_6a01140c0100wimi.html
  11. oracle注释 kole_t2u,oracle4
  12. Code[VS]1302 小矮人
  13. java 怎么调用clojure_从java调用Clojure时Clojure状态的范围
  14. URI和URL的区别和关联
  15. python凹多边形分割_Unity 凹多边形三角剖分
  16. 丝杠螺母传动机构设计
  17. 模拟调节器和数字计算机如何实现PID控制,模拟PID-调节器设计及数字化实现.doc...
  18. Maven的依赖与最佳配置(转载自Maven实战 作者许晓斌)
  19. C04-算法达人修炼营学习安排及方法指导
  20. 小白入门 - PHP简介

热门文章

  1. 观察者模式——机房监控系统
  2. catia转stp有破面_CATIA破面修复教程.ppt
  3. 【Timm】create_model所提供的ViT模型概览
  4. css 设置 th 宽度,javascript
  5. 修改注册表锁定IE主页
  6. [COGS 2051] 王者之剑
  7. Spring Data JAP框架处理表关系的步骤(一对一外键关联
  8. 重装金蝶专业版后服务器不显示错误,金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示服务器不是有效的,请重新设置...
  9. UI框架-element
  10. python dajngo+vue 钉钉三方登录群机器人验证码