课程 4:高级机器学习模型 - SVM 与神经网络

本课程介绍两种强大且广泛使用的机器学习模型:支持向量机 (SVM) 和神经网络 (NN)。这些模型能够捕捉数据中的复杂模式,并通常在各种任务上实现高准确率。

1. 支持向量机 (SVM)

支持向量机是用于分类和回归分析的监督学习模型。它们在高维空间中尤其有效,并且当维度数量超过样本数量时表现出色。

SVM 的核心概念

  • 超平面 (Hyperplane):在一个 N 维空间中(N 是特征的数量),超平面是一个维度为 N-1 的平坦仿射子空间。对于分类,SVM 旨在找到能够最佳区分不同类别数据点的超平面。在二维空间中,超平面是一条线;在三维空间中,它是一个平面。
  • 间隔 (Margin):间隔是超平面与任一类别最近数据点之间的距离。SVM 试图最大化这个间隔。通常,较大的间隔能带来更好的泛化性能(在未见过的数据上错误率更低)。
  • 支持向量 (Support Vectors):这些是离超平面最近的数据点,它们影响超平面的位置和方向。如果移除这些点,最优超平面将会改变。它们是数据集中的关键元素。
  • 核技巧 (Kernel Trick):SVM 可以使用所谓的核技巧高效地执行非线性分类,它隐式地将输入映射到高维特征空间。

SVM 核函数

核函数定义了 SVM 如何将数据映射到更高维度以找到分离超平面。核函数的选择取决于数据的结构。

  • 线性核 (Linear Kernel):kernel='linear'

    当数据线性可分时使用。它是最简单的核函数。
    公式: K(x, x') = xTx'

  • 多项式核 (Polynomial Kernel):kernel='poly'

    可以拟合非线性决策边界。它有一个度参数,控制边界的灵活性。
    公式: K(x, x') = (γ * xTx' + r)d (其中 d 是度, γ 是 gamma, r 是 coef0)

  • 径向基函数核 (Radial Basis Function (RBF) Kernel):kernel='rbf'

    一个非常流行且灵活的核函数。它可以将样本映射到更高维空间,并能处理复杂的非线性关系。它有一个 gamma 参数 (γ),定义了单个训练样本的影响范围。
    公式: K(x, x') = exp(-γ ||x - x'||2)

Python 示例:用于分类的 SVM (scikit-learn)

from sklearn.svm import SVC
from sklearn.datasets import make_classification, make_moons
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
import matplotlib.pyplot as plt
import numpy as np

# 生成线性可分数据
X_linear, y_linear = make_classification(n_samples=100, n_features=2, n_redundant=0, n_informative=2,
                                           random_state=1, n_clusters_per_class=1)
X_train_lin, X_test_lin, y_train_lin, y_test_lin = train_test_split(X_linear, y_linear, test_size=0.3, random_state=42)

# 为 SVM 缩放特征
scaler_lin = StandardScaler()
X_train_lin_scaled = scaler_lin.fit_transform(X_train_lin)
X_test_lin_scaled = scaler_lin.transform(X_test_lin)

# 使用线性核的 SVM
svm_linear = SVC(kernel='linear')
svm_linear.fit(X_train_lin_scaled, y_train_lin)
y_pred_linear = svm_linear.predict(X_test_lin_scaled)
print(f"SVM (线性核) 准确率: {metrics.accuracy_score(y_test_lin, y_pred_linear):.2f}") # "SVM (Linear Kernel) Accuracy:"

# 生成非线性可分数据 (月亮形状)
X_moons, y_moons = make_moons(n_samples=100, noise=0.15, random_state=42)
X_train_moons, X_test_moons, y_train_moons, y_test_moons = train_test_split(X_moons, y_moons, test_size=0.3, random_state=42)

scaler_moons = StandardScaler()
X_train_moons_scaled = scaler_moons.fit_transform(X_train_moons)
X_test_moons_scaled = scaler_moons.transform(X_test_moons)

# 使用 RBF 核的 SVM
svm_rbf = SVC(kernel='rbf', gamma='auto') # gamma='auto' 使用 1/n_features
svm_rbf.fit(X_train_moons_scaled, y_train_moons)
y_pred_rbf = svm_rbf.predict(X_test_moons_scaled)
print(f"SVM (RBF 核) 在月亮数据集上的准确率: {metrics.accuracy_score(y_test_moons, y_pred_rbf):.2f}") # "SVM (RBF Kernel) Accuracy on Moons:"

# --- 可选:绘制决策边界 (更复杂的代码) ---
# 这部分通常在 Jupyter notebook 中完成以获得更好的可视化效果
def plot_decision_boundary(X, y, model, title):
    plt.figure(figsize=(8,5))
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                         np.arange(y_min, y_max, 0.02))
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    plt.contourf(xx, yy, Z, alpha=0.4, cmap=plt.cm.coolwarm)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=20, edgecolor='k', cmap=plt.cm.coolwarm)
    plt.title(title)
    # plt.show() # 如果在本地运行,取消注释以显示
# plot_decision_boundary(X_train_lin_scaled, y_train_lin, svm_linear, "SVM 线性核 - 训练数据") # "SVM with Linear Kernel - Training Data"
# plot_decision_boundary(X_train_moons_scaled, y_train_moons, svm_rbf, "SVM RBF 核 - 训练数据 (月亮形)") # "SVM with RBF Kernel - Training Data (Moons)"
print("绘制决策边界有助于可视化 SVM 如何分离数据 (代码已注释掉)。") # "Plotting decision boundaries can help visualize how SVM separates data (code commented out)."

2. 神经网络 (NN)

神经网络受到人脑的启发,是一套试图通过模仿人脑运作方式来识别数据集中潜在关系的算法。它们可以适应复杂的非线性模式。

神经网络的基本概念

  • 神经元 (或节点/感知器):神经网络的基本处理单元。它接收一个或多个输入,对它们应用权重,加上偏置,将它们求和,然后通过激活函数传递这个和以产生输出。
  • 层 (Layers):
    • 输入层 (Input Layer):接收原始输入特征。
    • 隐藏层 (Hidden Layers):位于输入层和输出层之间的一个或多个层。这些层对输入数据执行转换,使网络能够学习复杂特征。
    • 输出层 (Output Layer):产生最终结果(例如,分类中的类别概率,回归中的连续值)。
  • 权重和偏置 (Weights and Biases):网络在训练过程中学习的参数。权重决定神经元之间连接的强度,偏置允许神经元在所有输入为零时仍被激活。
  • 激活函数 (Activation Function):向网络引入非线性,使其能够学习比线性模型更复杂的模式。常见的激活函数包括:
    • Sigmoid:将值压缩到 0 和 1 之间。常用于二元分类的输出层。
    • ReLU (Rectified Linear Unit):如果输入为正,则直接输出输入;否则输出零。因其效率高而广泛用于隐藏层。(max(0, x))
    • Tanh (Hyperbolic Tangent):将值压缩到 -1 和 1 之间。
    • Softmax:常用于多类别分类的输出层,因为它将输出转换为总和为 1 的概率。

简单前馈神经网络架构

在前馈神经网络中,信息仅单向流动——从输入层,通过隐藏层,到输出层。网络中没有循环或回路(与循环神经网络不同)。

训练过程包括:

  1. 前向传播 (Forward Propagation):输入数据逐层通过网络馈送以产生输出。
  2. 损失计算 (Loss Calculation):使用损失函数(例如,分类中的交叉熵)将网络的输出与实际目标值进行比较。
  3. 反向传播 (Backward Propagation / Backpropagation):将误差反向传播回网络,并调整权重和偏置(例如,使用梯度下降)以最小化误差。
这种前向传播、损失计算和反向传播的迭代过程就是网络“学习”的方式。

Python 示例:用于分类的简单神经网络 (scikit-learn MLPClassifier)

MLPClassifier 代表多层感知器分类器。它是 scikit-learn 中可用的基本前馈神经网络,适用于较小的数据集和入门示例。

from sklearn.neural_network import MLPClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn import metrics

# 加载标准数据集 (Iris)
iris = load_iris()
X, y = iris.data, iris.target

# 分割数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 缩放特征 (对神经网络很重要)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 创建 MLPClassifier 对象
# hidden_layer_sizes=(10, 5) 表示两个隐藏层,一个有 10 个神经元,一个有 5 个神经元。
# max_iter 对于允许网络收敛很重要。
mlp = MLPClassifier(hidden_layer_sizes=(10, 5), max_iter=500, activation='relu', solver='adam', random_state=1)
# 常用激活函数: 'relu', 'tanh', 'logistic' (sigmoid)
# 常用求解器: 'adam' (不错的默认选择), 'sgd'

# 训练分类器
mlp.fit(X_train_scaled, y_train)

# 在测试集上预测
y_pred_mlp = mlp.predict(X_test_scaled)

print(f"神经网络 (MLPClassifier) 准确率: {metrics.accuracy_score(y_test, y_pred_mlp):.2f}") # "Neural Network (MLPClassifier) Accuracy:"
print(f"MLP 收敛迭代次数: {mlp.n_iter_}") # "MLP Iterations to converge:"
print(f"MLP 损失: {mlp.loss_}") # "MLP Loss:"

# 对于更复杂的神经网络,通常使用像 TensorFlow with Keras 或 PyTorch 这样的库。
# 它们在定义自定义架构、层和训练循环方面提供了更大的灵活性。
# 示例 (概念性的,没有 TensorFlow/Keras 无法运行):
# model = keras.Sequential([
#     keras.layers.Dense(128, activation='relu', input_shape=(X_train_scaled.shape[1],)),
#     keras.layers.Dense(64, activation='relu'),
#     keras.layers.Dense(3, activation='softmax') # 假设 Iris 有 3 个类别
# ])
# model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# model.fit(X_train_scaled, y_train, epochs=10)
print("要构建更复杂的神经网络,TensorFlow/Keras 或 PyTorch 是首选库。") # "For building more complex neural networks, TensorFlow/Keras or PyTorch are the go-to libraries."

结论

支持向量机和神经网络是机器学习工具箱中的强大工具。SVM 在寻找最优分离边界方面表现出色,尤其是在高维空间中;而神经网络在建模非常复杂的非线性关系方面提供了极大的灵活性,构成了深度学习的基础。理解它们的核心原理是有效应用它们的关键。