关于决策树的一些介绍(二)

我之前写过一篇关于决策树的文章,但在那篇文章里没有提及基尼系数,信息熵与信息增益等相关问题,所以我将在这篇文章中进行补充。

一、 决策树的一份python代码

首先,我先给出一份最基础的决策树代码,在这里,由于没有指定criterion系数,所有默认采用基尼系数,不过在之后我还将具体些地讲述基尼系数。

代码如下:

python 复制代码
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score


# 导入数据
iris = load_iris()
X = iris.data
y = iris.target
# 划分
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42)
# 决策树实例化
clf = DecisionTreeClassifier(random_state=1024)
# 拟合
clf.fit(X_train,y_train)
# 预测
y_pre = clf.predict(X_test)
# 计算准确率
accuracy =  accuracy_score(y_test,y_pre)
print("The true target: {}".format(y_test))
print("The predict target: {}".format(y_pre))
print(accuracy)

它的输出为:

The true target: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1

0]

The predict target: [1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0 1 0 0 2 1

0]

1.0

二、 基尼系数

接下来,我们就详细些地来看下基尼系数。首先,我们要知道基尼系数是来 对于不确定性给出一个值的,也就是说基尼系数的含义就是不确定程度。它可以用符号表示为:

我们以iris数据集来解释下:

2.1 计算分割前的基尼系数

首先我们知道在数据集中有三种类别,每种类别都是50个,一共有150个,那么就有50/150=1/3,也就是:

2.2 计算分割后的基尼系数

假设我们有一阈值t,并且将根据这个阈值来将数据集分割为两个部分,那么我们就需要分别计算左侧和右侧的基尼系数,并加权。

我们假设左边有nL个,右边有nR个,并且总数为n个,那么就会产生两个基尼系数:GL与GR,

我们选择最小的阈值t,来作为最佳的分割点。

2.3 实际代码
python 复制代码
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

# 导入数据
iris = load_iris()
X = iris.data
y = iris.target
# 划分
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42)
# 选择花瓣长度作为特征
feature_index = 2  # 花瓣长度
thresholds = np.linspace(X[:, feature_index].min(), X[:, feature_index].max(), num=10)

# 计算
for threshold in thresholds:
    left_indices = X[:, feature_index] < threshold
    right_indices = ~left_indices
    # 左侧子节点的样本
    left_y = y[left_indices]
    left_n = len(left_y)
    # 右侧子节点的样本
    right_y = y[right_indices]
    right_n = len(right_y)
    # 确保子节点中至少有一个样本
    if left_n == 0 or right_n == 0:
        continue
    # 计算每个子节点的基尼系数
    g_left = 1 - sum([(np.sum(left_y == c) / left_n) ** 2 for c in range(3)])
    g_right = 1 - sum([(np.sum(right_y == c) / right_n) ** 2 for c in range(3)])
    # 计算分割后的基尼系数
    g_split = (left_n / (left_n + right_n)) * g_left + (right_n / (left_n + right_n)) * g_right
    print(f"Threshold: {threshold}, Split Gini: {g_split}")
# 分割
clf = DecisionTreeClassifier(criterion='gini', random_state=1234)
clf.fit(X_train, y_train)
# 预测
y_pred = clf.predict(X_test)
# 计算
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy: {}".format(accuracy))

结果如下:

Threshold: 1.6555555555555554, Split Gini: 0.389937106918239

Threshold: 2.311111111111111, Split Gini: 0.3333333333333333

Threshold: 2.966666666666667, Split Gini: 0.3333333333333333

Threshold: 3.6222222222222222, Split Gini: 0.383485309017224

Threshold: 4.277777777777778, Split Gini: 0.4438118958666904

Threshold: 4.933333333333334, Split Gini: 0.40858416945373466

Threshold: 5.588888888888889, Split Gini: 0.5333333333333333

Threshold: 6.2444444444444445, Split Gini: 0.638888888888889

Threshold: 6.9, Split Gini: 0.6621923937360179

Accuracy: 1.0

不过,我们在使用时可以直接使用sklearn的基尼系数分类器,而不需要手动设置,并且效果也并不会差。sklearn使用基尼系数分类器的代码如下:

python 复制代码
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

# 导入数据
iris = load_iris()
X = iris.data
y = iris.target
# 划分
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42)
# 使用决策树分类器进行分割
clf = DecisionTreeClassifier(criterion='gini', random_state=1024)
clf.fit(X_train, y_train)
# 预测
y_pred = clf.predict(X_test)
# 计算
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy: {}".format(accuracy))

我们将这个代码与开头所给出的代码进行比较,不难发现唯一的不同之处就是在分割上有所不同,即:

python 复制代码
# 使用决策树分类器进行分割
clf = DecisionTreeClassifier(criterion='gini', random_state=1234)

这一行代码中多了参数criterion。

我们还可以将基尼系数对于iris数据集的划分进行可视化,结果为:

三、 信息熵与信息增益

接下来,我们就要认识下信息熵与信息增益。

3.1 信息熵

信息熵是统计学的一个定义,用于表示一组数据的混乱程度与不确定性,在决策树中,其则用于展示一棵树的纯度。对于一个具有k个类别的数据集D,其信息熵H(D)为:

3.2 信息增益

信息增益是用于衡量某个数据集在分割后其不确定性与混乱程度减少了多少。它是决策树中选择分割特征的重要依据之一。对于特征A来说,其信息增益可以表示为:

3.3 举例

假如我们有一数据集如下,其有两个类比0与1。

我们计算信息熵会有:

计算信息增益会有:

3.4 实际代码

同样的,我们用实际的python代码来展示,代码如下:

python 复制代码
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 划分
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42)
# 使用决策树分类器进行分割
clf = DecisionTreeClassifier(criterion='entropy', random_state=1234)
clf.fit(X_train, y_train)
# 预测测试集的结果
y_pred = clf.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy: {}".format(accuracy))

在决策树中,我往往只使用基尼系数与信息熵和信息增益之一来作为分类依据,而不会都使用。也同样的,我们要使用什么作为分类依据,我们就在criterion后填写什么,而不自行编写代码计算。

四、 多变量决策树

如果我们将每个属性看作坐标空间中的一个坐标轴,那么d个属性描述的样本就对应了d维空间的一个数据点,而对于样本的分类也就意味着在坐标空间中寻找不同类样本间的分类边界。在决策树中形成的分类边界会有一个明显的特征,就是轴平行,即它的分类边界由若干个与坐标轴平行的分段组成。但这样虽然对于最终的结果会有优秀的解释性,但复杂性也会很高,故而考虑采用斜的划分边界来对其进行简化。标题所说的"多变量决策树"就能实现。在这个多变量决策树中,我们不为每个非叶节点去寻找一个最优划分属性,而是试图建立一个合适的线性分类器。

还是用iris数据集来举例,首先是多变量的:

python 复制代码
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

# 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 实例化
clf = DecisionTreeClassifier(criterion='gini', random_state=1234)
clf.fit(X_train, y_train)
# 预测
y_pred = clf.predict(X_test)
# 计算
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")

# 生成分类报告
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
# 生成混淆矩阵
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred))

然后是单个特征的:

python 复制代码
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

# 加载数据集
iris = load_iris()
X = iris.data[:, [2]]  # 使用花瓣长度作为唯一特征
y = iris.target
# 划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 实例化
clf = DecisionTreeClassifier(criterion='gini', random_state=1234)
clf.fit(X_train, y_train)
# 预测
y_pred = clf.predict(X_test)
# 计算
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")

# 生成分类报告
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
# 生成混淆矩阵
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred))

其输出将分别是:

Accuracy: 1.00

Classification Report:

precision recall f1-score support

0 1.00 1.00 1.00 19

1 1.00 1.00 1.00 13

2 1.00 1.00 1.00 13

accuracy 1.00 45

macro avg 1.00 1.00 1.00 45

weighted avg 1.00 1.00 1.00 45

Confusion Matrix:

[[19 0 0]

[ 0 13 0]

[ 0 0 13]]

Accuracy: 0.96

Classification Report:

precision recall f1-score support

0 1.00 1.00 1.00 19

1 0.92 0.92 0.92 13

2 0.92 0.92 0.92 13

accuracy 0.96 45

macro avg 0.95 0.95 0.95 45

weighted avg 0.96 0.96 0.96 45

Confusion Matrix:

[[19 0 0]

[ 0 12 1]

[ 0 1 12]]

此上

相关推荐
Watermelo6174 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
乐之者v9 分钟前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神1 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人1 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
半盏茶香1 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
martian6651 小时前
【人工智能数学基础篇】——深入详解多变量微积分:在机器学习模型中优化损失函数时应用
人工智能·机器学习·微积分·数学基础
忘梓.2 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
算法·动态规划
人机与认知实验室2 小时前
人、机、环境中各有其神经网络系统
人工智能·深度学习·神经网络·机器学习
tinker在coding4 小时前
Coding Caprice - Linked-List 1
算法·leetcode