在看决策树之前,先看下之前说过的逻辑回归
上图为判断是否要交往的逻辑回归算法图
把身高,财富,颜值分别与w1,w2,w3相乘求和得到一个结果。
(其中w1为高的权重,如果比较在意身高,那么w1就会偏大一些,那么w1,w2,w3具体数值是怎么来的呢,就是从你上万次的相亲经验中总结出来的,例如,有很多次相亲对方有钱也很帅,但就是身高太低没同意,这时w1的值就会偏大)
得到结果后通过sigmond函数把值转化为0-1之间,这就得到了是否要交往的概率。
决策树
决策树就是 一个一个的去做条件判断
代码实现
import numpy as npimport matplotlib.pyplot as pltfrom sklearn import datasets# 获取鸢尾花数据iris = datasets.load_iris()# 只使用最后两个特征(因为要在平台图上显示)X = iris.data[:, 2:]y = iris.target#显示数据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.tree import DecisionTreeClassifierdt_clf = DecisionTreeClassifier(max_depth=2, criterion='entropy')dt_clf.fit(X, y)DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=2,max_features=None, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, presort=False,random_state=None, splitter='best')#显示决策边界函数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)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()
由结果图可以看出 决策树如下
当x<2.4时,分为A类,剩余部分当Y<1.4时,分为B类,剩余分为C类
什么是决策树?
非参数学习
可以解决多分类问题
也可以解决回归问题
问题思考
每个节点在哪个纬度做划分?(相亲问题,为什么先判断身高?)某个维度在哪个值上做划分?(相亲问题,为什么低于1米7就不交往?)信息熵
熵在信息论中代表,随机变量不确定度的度量 - 熵越大,数据的不确定性越高 - 熵越小,数据的不确定性越低
公式:
其中 k代表的是一共多少种类(比如鸢尾花中一共有3类) 代表每一类所占的比例 负号是因为肯定为小数,log()肯定小于0,所以要乘于-1
举例
比如3类鸢尾花中,每一类各占
即{, , }
则
比如每一类各占(
)
则 H = 0
所以,当各占1/3时,熵比较大,数据的不确定性较高
(就像箱子里有个数相同不同颜色的小球,每次抹到小球的颜色不确定性很高,如果都是白球,每次抹到小球的颜色就很确定)
二分类公式
如果一类的所点的比例为x,则另一类所占的比例就为(1-x)
代码展示
import numpy as npimport matplotlib.pyplot as plt# 二分类信息熵计算函数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=0.5时,信息熵取得最大值,此时数据不确定性最高
使用信息熵寻找最优划分
# 划分函数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 Counterfrom 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 resdef try_split(X,y):# 存储最小的信息熵,默认为正无穷best_entropy = float('inf')# 存储最优的纬度(在哪一列进行划分),best_d = -1# 在最优的纬度上找出最优的划分值best_v = -1# 对所有的列进行循环for d in range(X.shape[1]):# 对d列的值进行排序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])/2# 通过这个中间值,把数据化分为两部分(左,右)X_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,v,return best_entropy,best_d,best_v# 对数据进行划分,看结果best_entropy, best_d, best_v = try_split(X, y)print('best_entropy = ', best_entropy)print('best_d =', best_d)print('best_v =', best_v)best_entropy = 0.6931471805599453best_d = 0best_v = 2.45
由结果可以看出,先从第0个纬度开始化分,最优划分值为2.45,也就是从x=2.45处进行划分
X1_l, X1_r, y1_l, y1_r = split(X,y,best_d, best_v)entropy(y1_l)0.0
根据上图也可以看出 所有的蓝球完全被划分出来了,所以它的信息熵值为0
# 对另一部分继续划分best_entropy2, best_d2, best_v2 = try_split(X1_r, y1_r)print('best_entropy = ', best_entropy2)print('best_d =', best_d2)print('best_v =', best_v2)best_entropy = 0.4132278899361904best_d = 1best_v = 1.75
由结果可以看出,这次从第1个纬度开始化分,最优划分值为1.75,也就是y=1.75处进行划分
X2_l, X2_r, y2_l, y2_r = split(X1_r,y1_r,best_d2, best_v2)print(entropy(y2_l))print(entropy(y2_r))0.308495450831103860.10473243910508653
从结果可以看处,此时的信息熵还不为0,说明还可以继续划分。
基尼系数
它与信息熵具有同样的性质,
公式为:
举例
比如3类鸢尾花中,每一类各占
即{, , }
则
比如每一类各占(
)
则 G = 0
二分类公式
代码实现
# 创建决策树from sklearn.tree import DecisionTreeClassifierdt_clf = DecisionTreeClassifier(max_depth=2,criterion='gini')dt_clf.fit(X,y)DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=2,max_features=None, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, presort=False,random_state=None, splitter='best')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()
# 代码同信息熵类似from collections import Counterfrom math import logdef gini(y):counter = Counter(y)res = 1.0for num in counter.values():p = num/len(y)res -= p **2return resdef try_split(X,y):best_g = float('inf')best_d = -1best_v = -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,v,return best_entropy,best_d,best_v# 对数据进行划分,看结果best_g, best_d, best_v = try_split(X, y)print('best_g = ', best_g)print('best_d =', best_d)print('best_v =', best_v)best_g = 0.6931471805599453best_d = 0best_v = 2.45
由结果可以看出,它与信息熵的结果一样
信息熵 vs 基尼系数
信息熵的计算比基尼系数稍慢sklearn 中莫认使用的为基尼系数二者没有特别的效果优劣CART
Classification And Regression Tree
根据某一个维度d和一个维度阈值v进行二分
CART与决策书的超参数
import numpy as npimport matplotlib.pyplot as plt# 加载模拟数据from sklearn import datasetsX, 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)DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,max_features=None, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, presort=False,random_state=None, splitter='best')# 绘制决策边界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.show()
上图每个点都被分了类,显然过拟合了
# 限制最大深度为2dt_clf = DecisionTreeClassifier(max_depth=2)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.show()
从结果可以看出,分界线非常清晰,但有点没有被正确区分出来
但如果过多的点没有被正确分类 ,就是欠拟合
min_samples_split
这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。
默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
例子,有大概10万样本,建立决策树时,选择min_samples_split=10。可以作为参考
dt_clf = DecisionTreeClassifier(min_samples_split=10)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.show()
min_samples_leaf
这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。
默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。
如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
10万样本项目使用min_samples_leaf的值为5,仅供参考。
dt_clf = DecisionTreeClassifier(min_samples_leaf=3)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.show()
max_leaf_nodes
通过限制最大叶子节点数,可以防止过拟合,默认是"None”,即不限制最大的叶子节点数。
如果加了限制,算法会建立在最大叶子节点数内最优的决策树。
如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到
dt_clf = DecisionTreeClassifier(max_leaf_nodes=4)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.show()
决策树解决回归问题
import numpy as npimport matplotlib.pyplot as pltfrom sklearn import datasetsboston = datasets.load_boston()X = boston.datay = boston.targetfrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=222)from sklearn.tree import DecisionTreeRegressordt_reg = DecisionTreeRegressor()dt_reg.fit(X_train, y_train)DecisionTreeRegressor(criterion='mse', max_depth=None, max_features=None,max_leaf_nodes=None, min_impurity_decrease=0.0,min_impurity_split=None, min_samples_leaf=1,min_samples_split=2, min_weight_fraction_leaf=0.0,presort=False, random_state=None, splitter='best')# 测试预测结果得分dt_reg.score(X_test,y_test)0.84717433148686# 测试一下训练数据的得分dt_reg.score(X_train,y_train)1.0
对于回归问题,预测为百分百正确,说明预测过拟合了
如果觉得《决策树对鸢尾花数据两特征组合分类python代码的结果_机器学习笔记-决策树》对你有帮助,请点赞、收藏,并留下你的观点哦!