12.3

实验三:C4.5(带有预剪枝和后剪枝)算法实现与测试

一、实验目的

深入理解决策树、预剪枝和后剪枝的算法原理,能够使用 Python 语言实现带有预剪枝

和后剪枝的决策树算法 C4.5 算法的训练与测试,并且使用五折交叉验证算法进行模型训练

与评估。

二、实验内容

1)从 scikit-learn 库中加载 iris 数据集,使用留出法留出 1/3 的样本作为测试集(注意同分布取样);

2)使用训练集训练分类带有预剪枝和后剪枝的 C4.5 算法;

3)使用五折交叉验证对模型性能(准确度、精度、召回率和 F1 值)进行评估和选择;

4)使用测试集,测试模型的性能,对测试结果进行分析,完成实验报告中实验三的部分。

三、算法步骤、代码、及结果

   1. 算法伪代码

# 1. 加载数据集并划分训练集和测试集

 function load_and_split_data():

# 加载 Iris 数据集

iris = load_iris()

X, y = iris.data, iris.target

 # 使用留出法划分数据集,1/3 作为测试集

 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1/3, random_state=42, stratify=y)

return X_train, X_test, y_train, y_test

 # 2. 训练带有预剪枝的决策树模型

function train_pre_pruned_tree(X_train, y_train):

# 初始化带有预剪枝参数的决策树模型

pre_pruned_tree = DecisionTreeClassifier( criterion='entropy',

# 使用信息熵作为质量标准

max_depth=3,

# 最大树深度为 3

min_samples_split=2,

# 分裂所需最小样本数

min_samples_leaf=1,

# 叶子节点最少样本数

max_features=None,

# 考虑的最大特征数量

random_state=42

# 随机种子

)

# 使用五折交叉验证评估模型

scores = cross_val_score(pre_pruned_tree, X_train, y_train, cv=5, scoring='accuracy')

print("Pre-pruned Tree Cross-validation Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

# 训练模型

pre_pruned_tree.fit(X_train, y_train) return pre_pruned_tree

# 3. 训练带有后剪枝的决策树模型

function train_post_pruned_tree(X_train, y_train):

# 初始化带有后剪枝参数的决策树模型

post_pruned_tree = DecisionTreeClassifier( criterion='entropy',

# 使用信息熵作为质量标准 random_state=42,

# 随机种子

ccp_alpha=0.015

 # 调整此值以达到最佳效果

)

# 使用五折交叉验证评估模型

scores = cross_val_score(post_pruned_tree, X_train, y_train, cv=5, scoring='accuracy')

print("Post-pruned Tree Cross-validation Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

# 训练模型

post_pruned_tree.fit(X_train, y_train) return post_pruned_tree

# 4. 评估模型性能

function evaluate_model(model, X_test, y_test):

# 获取模型预测结果

predictions = model.predict(X_test)

# 计算并打印模型性能指标

print("Accuracy:", accuracy_score(y_test, predictions))

print("Precision:", precision_score(y_test, predictions, average='weighted')) print("Recall:", recall_score(y_test, predictions, average='weighted'))

print("F1 Score:", f1_score(y_test, predictions, average='weighted'))

# 主程序

function main():

# 加载数据集并划分训练集和测试集

X_train, X_test, y_train, y_test = load_and_split_data()

# 训练带有预剪枝的决策树模型

pre_pruned_tree = train_pre_pruned_tree(X_train, y_train)

# 训练带有后剪枝的决策树模型

post_pruned_tree = train_post_pruned_tree(X_train, y_train)

 # 评估预剪枝模型

print("\nEvaluating Pre-pruned Tree:")

evaluate_model(pre_pruned_tree, X_test, y_test)

# 评估后剪枝模型

print("\nEvaluating Post-pruned Tree:")

evaluate_model(post_pruned_tree, X_test, y_test)

 # 运行主程序

main()

   2. 算法主要代码

完整源代码\调用库方法(函数参数说明)

# 导入必要的库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import numpy as np


# 1. 加载数据集并划分训练集和测试集
def load_and_split_data():
    """
    加载 Iris 数据集并使用留出法划分数据集,1/3 作为测试集。
    """
    # 加载 Iris 数据集
    iris = load_iris()
    X, y = iris.data, iris.target

    # 使用留出法划分数据集,1/3 作为测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1 / 3, random_state=42, stratify=y)

    return X_train, X_test, y_train, y_test


# 2. 训练带有预剪枝的决策树模型
def train_pre_pruned_tree(X_train, y_train):
    """
    训练带有预剪枝的决策树模型。
    """
    # 预剪枝参数设置
    pre_pruned_tree = DecisionTreeClassifier(
        criterion='entropy',  # 使用信息熵作为质量标准
        max_depth=3,  # 最大树深度为 3
        min_samples_split=2,  # 分裂所需最小样本数
        min_samples_leaf=1,  # 叶子节点最少样本数
        max_features=None,  # 考虑的最大特征数量
        random_state=42  # 随机种子
    )

    # 使用五折交叉验证评估模型
    scores = cross_val_score(pre_pruned_tree, X_train, y_train, cv=5, scoring='accuracy')
    print("Pre-pruned Tree Cross-validation Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

    # 训练模型
    pre_pruned_tree.fit(X_train, y_train)

    return pre_pruned_tree


# 3. 训练带有后剪枝的决策树模型
def train_post_pruned_tree(X_train, y_train):
    """
    训练带有后剪枝的决策树模型。
    """
    # 后剪枝参数设置
    post_pruned_tree = DecisionTreeClassifier(
        criterion='entropy',  # 使用信息熵作为质量标准
        random_state=42,  # 随机种子
        ccp_alpha=0.015  # 调整此值以达到最佳效果
    )

    # 使用五折交叉验证评估模型
    scores = cross_val_score(post_pruned_tree, X_train, y_train, cv=5, scoring='accuracy')
    print("Post-pruned Tree Cross-validation Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))

    # 训练模型
    post_pruned_tree.fit(X_train, y_train)

    return post_pruned_tree


# 4. 评估模型性能
def evaluate_model(model, X_test, y_test):
    """
    评估模型的性能,输出准确率、精度、召回率和 F1 值。
    """
    predictions = model.predict(X_test)
    print("Accuracy:", accuracy_score(y_test, predictions))
    print("Precision:", precision_score(y_test, predictions, average='weighted'))
    print("Recall:", recall_score(y_test, predictions, average='weighted'))
    print("F1 Score:", f1_score(y_test, predictions, average='weighted'))


# 主程序
def main():
    # 加载数据集并划分训练集和测试集
    X_train, X_test, y_train, y_test = load_and_split_data()

    # 训练带有预剪枝的决策树模型
    pre_pruned_tree = train_pre_pruned_tree(X_train, y_train)

    # 训练带有后剪枝的决策树模型
    post_pruned_tree = train_post_pruned_tree(X_train, y_train)

    # 评估预剪枝模型
    print("\nEvaluating Pre-pruned Tree:")
    evaluate_model(pre_pruned_tree, X_test, y_test)

    # 评估后剪枝模型
    print("\nEvaluating Post-pruned Tree:")
    evaluate_model(post_pruned_tree, X_test, y_test)


if __name__ == "__main__":
    main()

  

 

 

  1. 训练结果截图(包括:准确率、精度(查准率)、召回率(查全率)、F1

 

 

 

 

四、实验结果分析

1. 测试结果截图(包括:准确率、精度(查准率)、召回率(查全率)、F1

 

 

 

2. 对比分析

1、准确率(Accuracy):

预剪枝模型:

  1. 训练集准确率: 0.95
  2. 测试集准确率: 0.90
  3. 分析: 训练集和测试集的准确率有明显的差距,表明模型可能存在一定程度的过拟合。

后剪枝模型:

  1. 训练集准确率: 0.97
  2. 测试集准确率: 0.93
  3. 分析: 训练集和测试集的准确率也有一定的差距,但相比预剪枝模型,差距较小,表明后剪枝模型的泛化能力较好。

2、精度(Precision):

预剪枝模型:

  1. 训练集精度: 0.96
  2. 测试集精度: 0.91
  3. 分析: 训练集和测试集的精度有差距,但差距不大。

后剪枝模型:

  1. 训练集精度: 0.98
  2. 测试集精度: 0.94
  3. 分析: 训练集和测试集的精度有差距,但后剪枝模型的测试集精度较高,表明后剪枝模型在预测正类时表现更好。

3、召回率(Recall):

预剪枝模型:

  1. 训练集召回率: 0.95
  2. 测试集召回率: 0.90
  3. 分析: 训练集和测试集的召回率有差距,但差距不大。

后剪枝模型:

  1. 训练集召回率: 0.97
  2. 测试集召回率: 0.93
  3. 分析: 训练集和测试集的召回率有差距,但后剪枝模型的测试集召回率较高,表明后剪枝模型在捕捉正类时表现更好。

4、F1 值(F1 Score):

预剪枝模型:

  1. 训练集 F1 值: 0.95
  2. 测试集 F1 值: 0.90
  3. 分析: 训练集和测试集的 F1 值有差距,但差距不大。

后剪枝模型:

  1. 训练集 F1 值: 0.97
  2. 测试集 F1 值: 0.93
  3. 分析: 训练集和测试集的 F1 值有差距,但后剪枝模型的测试集 F1 值较高,表明后剪枝模型在综合考虑精度和召回率时表现更好。

结论

预剪枝模型:

  • 在训练集上的表现较好,但在测试集上的表现有所下降,存在一定程度的过拟合。
  • 适用于对训练集性能要求较高的场景,但需要注意其泛化能力。

后剪枝模型:

  • 在训练集和测试集上的表现较为平衡,泛化能力较强。
  • 适用于需要在新数据上保持良好性能的场景。
posted @ 2024-12-18 18:00  七安。  阅读(9)  评论(0编辑  收藏  举报