【python机器学习】决策树(二)

目录

一、基尼系数

二、决策树中的超参数

三、决策树解决回归问题

四、决策树的局限性



一、基尼系数

在决策树中,基尼系数是一种衡量数据集纯度的指标。在构建决策树时,基尼系数可以用来确定每个节点上哪个特征是最好的分割特征。基尼系数越小,表示数据集的纯度越高。 它和上一小节提到的信息熵类似。

【python机器学习】决策树(二)_第1张图片

代码示例:

import numpy as np
import matplotlib.pyplot as plt

from sklearn import datasets

iris = datasets.load_iris()
X = iris.data[:,2:] 
y = iris.target

#创建决策树分类器
from sklearn.tree import DecisionTreeClassifier

dt_clf = DecisionTreeClassifier(max_depth=2, criterion="gini", random_state=42)  
#此时criterion系数由entropy(信息熵)变为gini(基尼系数)
dt_clf.fit(X, y)

#使用基尼系数进行划分
from collections import Counter
from math import log

def split(X, y, d, value):  #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]

#计算基尼系数
def gini(y):
    counter = Counter(y)
    res = 1.0
    for num in counter.values():
        p = num / len(y)
        res -= p ** 2
    return res

#在所有数据上寻找维度和值
def try_split(X, y):
    
    best_g = float('inf')
    best_d, best_v = -1, -1
    for d in range(X.shape[1]):
        sorted_index = np.argsort(X[:,d])
        for i in range(1, len(X)):
            if X[sorted_index[i], d] != X[sorted_index[i-1], d]:
                v = (X[sorted_index[i], d] + X[sorted_index[i-1], d])/2
                X_l, X_r, y_l, y_r = split(X, y, d, v)
                p_l, p_r = len(X_l) / len(X), len(X_r) / len(X)
                g = p_l * gini(y_l) + p_r * gini(y_r)
                if g < best_g:
                    best_g, best_d, best_v = g, d, v
                
    return best_g, best_d, best_v


best_g, best_d, best_v = try_split(X, y)

X1_l, X1_r, y1_l, y1_r = split(X, y, best_d, best_v)


gini(y1_l)
#0.0

gini(y1_r)
#0.5

#对右子树继续进行划分
best_g2, best_d2, best_v2 = try_split(X1_r, y1_r)
X2_l, X2_r, y2_l, y2_r = split(X1_r, y1_r, best_d2, best_v2)

gini(y2_l)
gini(y2_r)

运行结果:

【python机器学习】决策树(二)_第2张图片

信息熵与基尼系数的区别在于:

  • 信息熵的计算比基尼系数稍慢
  • sklearn中默认为基尼系数
  • 两者之间没有特别的效果优劣

二、决策树中的超参数

超参数可以用来调节算法的性能和模型的复杂度,以下是一些常见的决策树超参数:

  • 最大深度(max_depth):决策树的最大深度,用来控制决策树的复杂度和过拟合风险。

  • 最小样本数(min_samples_split):决策树节点分裂的最小样本数,用来控制决策树的生长过程和过拟合风险。

  • 最小叶子节点样本数(min_samples_leaf):叶子节点包含的最小样本数,用来控制决策树的生长过程和过拟合风险。

  • 最大叶子节点数(max_leaf_nodes):限制决策树的最大叶子节点数,用来控制决策树的复杂度和过拟合风险。

代码示例:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

X, y = datasets.make_moons(noise=0.25, random_state=666)

#绘制决策边界
def plot_decision_boundary(model, axis):
    
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]

    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    
    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

from sklearn.tree import DecisionTreeClassifier
dt_clf2 = DecisionTreeClassifier(max_depth=2)  #最大深度
dt_clf2.fit(X, y)

'''
plot_decision_boundary(dt_clf2, 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()
'''
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.show()
'''

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.show()
'''
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.show()

运行结果:

【python机器学习】决策树(二)_第3张图片

 

以上代码是分别传入决策树中的各个参数得到的结果,同时我们也可以通过网格搜索的方式将这些参数组合起来,来调整模型结果。

三、决策树解决回归问题

使用sklearn中DecisionTreeRegressor来解决,它与DecisionTreeClassifier的超参数都是相同的,区别在于最后得到的结果是分类结果还是回归结果。

代码示例:

boston = datasets.load_boston()
X = boston.data
y = boston.target

from 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 DecisionTreeRegressor

dt_reg = DecisionTreeRegressor()  #可以传入超参数进行调节
dt_reg.fit(X_train, y_train)

dt_reg.score(X_test, y_test)

四、决策树的局限性

根据前面的例子我们可以看出,决策树的决策边界都是与x轴和y轴平行的,对于这类决策边界,它具备一定的局限性。

假设现在有两类数据,分别为红色和蓝色。通过决策树的决策边界绘制如下,事实上这是不对的,因为我们可以直接通过一根斜线来进行区分。

【python机器学习】决策树(二)_第4张图片

另外,决策树边界也对个别数据特别敏感。当我们删除 X、Y 的一个数据时,会发现绘制出的决策边界发生了很大变化。这也是所有非参数学习普遍存在的缺点,高度依赖调整超参数。

你可能感兴趣的:(机器学习,算法,决策树)