用Python代码破解机器学习期末考:决策树、神经网络与SVM实战指南

期末考试临近,面对满屏的算法公式和抽象概念,你是否感到无从下手?传统的死记硬背不仅效率低下,更容易在考场上遇到变式题时束手无策。本文将带你用Python和Scikit-learn构建三个核心算法的可视化实验,把枯燥的理论转化为可运行的代码。通过 DecisionTreeClassifier 观察预剪枝效果,用 MLPClassifier 调试神经网络层数,再用 SVC 绘制决策边界——这些实战操作不仅能帮你理解考试重点,更能培养真正的工程思维。

1. 决策树:从信息增益到剪枝实战

决策树在考试中常考划分属性和剪枝处理。我们先通过代码生成一个模拟数据集:

from sklearn.datasets import make_classification
X, y = make_classification(n_samples=500, n_features=4, 
                          n_informative=3, n_redundant=1,
                          random_state=42)

1.1 三种划分标准对比

Scikit-learn支持三种划分标准,对应不同算法:

  • 信息增益(ID3) criterion="entropy"
  • 基尼指数(CART) criterion="gini" (默认)
  • 增益率(C4.5) :需自定义实现

比较不同标准的效果:

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score

criteria = ["gini", "entropy"]
for c in criteria:
    clf = DecisionTreeClassifier(criterion=c, random_state=42)
    scores = cross_val_score(clf, X, y, cv=5)
    print(f"{c}平均准确率: {scores.mean():.3f}")

1.2 预剪枝与后剪枝实验

考试常考剪枝的区别和效果。预剪枝通过参数控制:

参数 作用 对应考题
max_depth 限制树的最大深度 预剪枝实现方式
min_samples_split 节点分裂最小样本数 过拟合控制
min_impurity_decrease 分裂最小增益阈值 停止条件
# 未剪枝的树
full_tree = DecisionTreeClassifier(random_state=42)
full_tree.fit(X, y)
print("未剪枝树深度:", full_tree.get_depth())

# 预剪枝的树
pruned_tree = DecisionTreeClassifier(max_depth=3, random_state=42)
pruned_tree.fit(X, y)
print("剪枝后深度:", pruned_tree.get_depth())

可视化决策边界对比:

import matplotlib.pyplot as plt
from sklearn.inspection import DecisionBoundaryDisplay

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
DecisionBoundaryDisplay.from_estimator(
    full_tree, X[:, :2], response_method="predict", ax=ax1,
    alpha=0.5, cmap=plt.cm.Paired
)
ax1.scatter(X[:, 0], X[:, 1], c=y, edgecolor="k")
ax1.set_title("未剪枝决策边界")

DecisionBoundaryDisplay.from_estimator(
    pruned_tree, X[:, :2], response_method="predict", ax=ax2,
    alpha=0.5, cmap=plt.cm.Paired
)
ax2.scatter(X[:, 0], X[:, 1], c=y, edgecolor="k")
ax2.set_title("预剪枝决策边界")
plt.show()

2. 神经网络:从感知机到BP算法

2.1 单层感知机的局限性

考试常考感知机无法解决异或问题。用代码验证:

from sklearn.linear_model import Perceptron

X_xor = [[0,0], [0,1], [1,0], [1,1]]
y_xor = [0, 1, 1, 0]

perceptron = Perceptron(random_state=42)
perceptron.fit(X_xor, y_xor)
print("感知机在异或问题的准确率:", perceptron.score(X_xor, y_xor))

2.2 多层神经网络实现

使用 MLPClassifier 演示BP算法:

from sklearn.neural_network import MLPClassifier

mlp = MLPClassifier(hidden_layer_sizes=(4,), 
                    activation="relu",
                    solver="adam",
                    learning_rate_init=0.01,
                    max_iter=500,
                    random_state=42)
mlp.fit(X, y)

# 观察训练过程中的损失变化
plt.plot(mlp.loss_curve_)
plt.xlabel("迭代次数")
plt.ylabel("损失值")
plt.title("BP算法训练过程")
plt.show()

关键参数对应考试重点:

  • hidden_layer_sizes :隐层神经元数量(网络结构)
  • activation :激活函数类型(sigmoid/tanh/relu)
  • learning_rate_init :初始学习率(影响收敛性)

2.3 过拟合控制实验

对比不同隐层大小的效果:

hidden_layers = [(2,), (10,), (50,50)]
for layers in hidden_layers:
    mlp = MLPClassifier(hidden_layer_sizes=layers, random_state=42)
    scores = cross_val_score(mlp, X, y, cv=5)
    print(f"{layers}层结构准确率: {scores.mean():.3f}")

3. SVM:从线性可分到核技巧

3.1 三种SVM对比实现

考试重点区分三类支持向量机:

from sklearn.svm import SVC

# 线性可分SVM(硬间隔)
linear_svc = SVC(kernel="linear", C=1000)
linear_svc.fit(X[:, :2], y)

# 线性SVM(软间隔)
soft_svc = SVC(kernel="linear", C=0.1)
soft_svc.fit(X[:, :2], y)

# 非线性SVM(RBF核)
rbf_svc = SVC(kernel="rbf", gamma=1, C=1)
rbf_svc.fit(X[:, :2], y)

3.2 决策边界可视化

理解支持向量的概念:

fig, axes = plt.subplots(1, 3, figsize=(18, 5))
titles = ["硬间隔线性SVM", "软间隔线性SVM", "RBF核SVM"]
for ax, model, title in zip(axes, [linear_svc, soft_svc, rbf_svc], titles):
    DecisionBoundaryDisplay.from_estimator(
        model, X[:, :2], response_method="predict", ax=ax,
        alpha=0.5, cmap=plt.cm.Paired
    )
    ax.scatter(X[:, 0], X[:, 1], c=y, edgecolor="k")
    # 标记支持向量
    sv = model.support_vectors_
    ax.scatter(sv[:, 0], sv[:, 1], facecolors="none", edgecolors="r", s=100)
    ax.set_title(title)
plt.show()

3.3 正则化参数C的影响

考试常考正则化参数的作用:

C_values = [0.001, 0.1, 1, 10, 100]
for C in C_values:
    svc = SVC(kernel="linear", C=C)
    scores = cross_val_score(svc, X[:, :2], y, cv=5)
    print(f"C={C}时的准确率: {scores.mean():.3f}")

4. 综合复习策略与代码模板

4.1 高频考点代码模板

收藏这些代码片段应对考试大题:

# 模型评估模板(留出法+k折交叉验证)
from sklearn.model_selection import train_test_split, cross_val_score

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
model = DecisionTreeClassifier(max_depth=3)
model.fit(X_train, y_train)
print("留出法测试集准确率:", model.score(X_test, y_test))

scores = cross_val_score(model, X, y, cv=5)
print("5折交叉验证平均准确率:", scores.mean())

# 混淆矩阵与分类报告
from sklearn.metrics import classification_report, confusion_matrix

y_pred = model.predict(X_test)
print("混淆矩阵:\n", confusion_matrix(y_test, y_pred))
print("分类报告:\n", classification_report(y_test, y_pred))

4.2 常见考题破解技巧

  • 过拟合/欠拟合判断 :观察训练集和测试集表现差距
  • 算法对比题 :用 cross_val_score 快速比较多个模型
  • 参数分析题 :网格搜索可视化参数影响
# 参数搜索可视化示例
import numpy as np
from sklearn.model_selection import validation_curve

param_range = np.logspace(-3, 3, 7)
train_scores, test_scores = validation_curve(
    SVC(kernel="rbf"), X[:, :2], y,
    param_name="gamma", param_range=param_range,
    cv=5
)

plt.plot(param_range, train_scores.mean(axis=1), label="训练得分")
plt.plot(param_range, test_scores.mean(axis=1), label="验证得分")
plt.xscale("log")
plt.xlabel("gamma参数")
plt.ylabel("准确率")
plt.legend()
plt.show()

把这份代码保存为Jupyter Notebook,遇到相关考题时快速调试验证。比如当题目问"增大gamma参数对RBF核SVM有什么影响"时,直接运行最后一个代码块就能得到直观答案。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐