1. 前言与核心概念
1.1 什么是多层感知机(MLP/DNN)
多层感知机(Multi-Layer Perceptron, MLP),也常被称为深度神经网络(Deep Neural Network, DNN)的基础形式,是人工神经网络中最基础且最核心的模型之一。MLP 是由至少三层节点(神经元)组成的网络:一个输入层、一个输出层和至少一个隐藏层。MLP 通过在神经元之间引入非线性激活,这也是使其具备学习和逼近任意复杂非线性函数的能力的唯一原因。

该 MLP 结构如下:
- 输入层 (Input Layer): 4个神经元
- 隐藏层 (Hidden Layer): 1个隐藏层,包含5个神经元
- 输出层 (Output Layer): 3个神经元
对于输入向量 $\mathbf{x} \in \mathbb{R}^4$,模型的计算流程为:
1. 隐藏层计算(特征提取)
- 权重矩阵 $\mathbf{W}_H$: $\in \mathbb{R}^{\mathbf{5} \times \mathbf{4}}$
- 偏置向量 $\mathbf{b}_H$: $\in \mathbb{R}^{\mathbf{5}}$
- 激活函数 $f_H$: 必须是非线性的(如 ReLU, Sigmoid, Tanh)。
- 激活输出 $\mathbf{h}$: $\in \mathbb{R}^{\mathbf{5}}$ (即下一层的输入)。
2. 输出层计算(最终决策)
- 权重矩阵 $\mathbf{W}_O$: $\in \mathbb{R}^{\mathbf{3} \times \mathbf{5}}$
- 偏置向量 $\mathbf{b}_O$: $\in \mathbb{R}^{\mathbf{3}}$
- 激活函数 $f_O$:
- 分类任务:通常使用 Softmax(将 Logits 转换为概率分布)。
- 回归任务:通常使用恒等函数(即 $f(z)=z$)。
- 最终输出 $\mathbf{y}$: $\in \mathbb{R}^{\mathbf{3}}$。
1.2 MLP与线性模型的区别
| 特性 | 线性模型(如感知机、线性回归) | 多层感知机 (MLP) |
|---|---|---|
| 层数 | 1层(输入直接到输出) | 至少3层(输入、至少1个隐藏层、输出) |
| 激活函数 | 无(线性转换)或不可导的阶跃函数。 | 必须使用非线性且可导的函数(如 ReLU, Sigmoid)。 |
| 可分性 | 只能处理线性可分的数据。 | 可以处理非线性可分的复杂数据。 |
| 核心能力 | 只能拟合线性边界。 | 能够拟合任意形状的决策边界。 |
| 数学区别 | $y = Wx + b$ | $y = f_O(W_O f_H(W_H x + b_H) + b_O)$ |
MLP引入了非线性激活函数,并将特征映射到高维空间。非线性激活是 MLP 具备非线性拟合能力的唯一原因。如 1.1 什么是多层感知机(MLP/DNN)的示例MLP中,隐藏层的作用是将输入数据从 $\mathbb{R}^4$ 空间映射到 $\mathbb{R}^5$ 特征空间,并通过非线性 $f_H$ 引入数据的非线性组合特征。
如果隐藏层全部使用线性激活(如 $f(z) = z$),那么无论堆叠多少层,模型仍然等价于一个单层的线性模型,以下公式推导可以证明:
2. 模型结构与数学原理
2.1 基本单元: 神经元
MLP 的核心是神经元(或节点),它模拟了生物神经元的处理过程,是网络进行计算的基本单位。
I. 神经元的计算过程
每个神经元接收来自上一层多个神经元的输入,执行两个核心步骤:
-
线性组合 (Weighted Sum):计算输入的加权和,并加上偏置项 $b$。
$$ z = \sum_{i=1}^{N} w_i x_i + b = \mathbf{w}^T \mathbf{x} + b $$- $x_i$: 来自上一层的输入。
- $w_i$: 对应输入的权重,表示该输入的重要性。
- $b$: 偏置项 (Bias),用于调整决策边界。
-
非线性激活 (Activation):将线性组合的结果 $z$ 通过一个非线性激活函数 $f$ 进行转换。这是信息的处理。
$$ a = f(z) = f(\mathbf{w}^T \mathbf{x} + b) $$- $a$: 神经元的最终输出(激活值),将作为下一层神经元的输入。
II. 权重与偏置的作用
- 权重 $\mathbf{w}$: 决定了输入信号的强度和重要性,是模型学习到的核心特征。
- 偏置 $b$: 独立于输入,用于平移激活函数的输出,使得神经元在输入全为零时也能被激活,使得决策边界可以不在原点,增强模型的拟合能力。
2.2 网络架构 (输入层、隐藏层、输出层)
MLP 是一种经典的前馈神经网络 (Feedforward Network),信息从输入层单向流向输出层,层内神经元之间无连接。
I. 输入层 (Input Layer)
- 功能: 接收原始输入数据,如图片像素值、文本嵌入向量或特征数值。
- 特点: 不进行复杂的权重计算和非线性激活,仅负责数据的传入和分配。神经元的数量等于输入特征的维度。
II. 隐藏层 (Hidden Layer)
- 功能: 进行特征的抽象、组合和非线性转换。随着层数的加深,可以提取越来越复杂的抽象特征。
- 特点: MLP 的“深度”由隐藏层的数量决定。每个隐藏层神经元都与前一层的所有神经元和后一层的所有神经元相连(全连接)。
III. 输出层 (Output Layer)
- 功能: 根据任务目标输出最终结果。
- 激活函数:
- 回归 (Regression):通常使用恒等函数 $f(z)=z$。
- 二分类 (Binary Classification):使用 Sigmoid 函数,将输出映射到 $[0, 1]$ 概率。
- 多分类 (Multi-class Classification):使用 Softmax 函数,将输出映射为互斥的概率分布,和为 1。
2.3. 激活函数的选取与作用 (ReLU, Sigmoid, Tanh)
激活函数是 MLP 能够解决非线性问题的唯一关键因素。
| 激活函数 | 公式 | 值域 | 优点 | 缺点/应用场景 |
|---|---|---|---|---|
| ReLU (Rectified Linear Unit) | $f(z) = \max(0, z)$ | $[0, \infty)$ | 计算高效,解决梯度消失(在正区间),收敛速度快。 | Dead ReLU 问题(当一个较大的梯度流过一个ReLU神经元,更新后的权重可能使得该神经元对所有训练样本的输入都为负,导致其输出恒为0,梯度也恒为0,从此无法再更新。死亡)。 |
| Sigmoid (Logistic) | $f(z) = \frac{1}{1 + e^{-z}}$ | $(0, 1)$ | 将输出压缩到概率范围,常用于二分类输出层。 | 容易产生梯度消失(在两端饱和),计算代价较高。 |
| Tanh (Hyperbolic Tangent) | $f(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}$ | $(-1, 1)$ | 输出以 0 为中心(均值为 0),有利于下一层的优化。 | 仍存在梯度消失问题(在两端饱和)。 |






2.4. 通用近似定理 (Universal Approximation Theorem)
I. 定理描述
理论上,一个包含至少一个隐藏层、且隐藏层使用非线性激活函数的多层感知机,只要拥有足够的隐藏层神经元数量和正确的权重,它就能以任意精度逼近(近似)任何连续函数。
II. 核心意义
- 能力保证: 该定理从数学上保证了MLP在理论上具备处理任何复杂数据映射和建模的能力。无论数据间的关系有多复杂、多非线性,MLP 都能找到一种拟合它的方式。
- 深度而非宽度: 虽然该定理最初是为单隐藏层网络证明的,但现代深度学习的发展表明,通过增加隐藏层的深度(而非仅仅增加宽度/神经元数量)通常能更高效、更好地学习特征的层次结构。
3. 算法训练与优化
MLP 的训练过程是一个迭代优化过程,目标是找到一组权重和偏置,使得模型的预测值与真实值之间的损失最小化。
3.1. 损失函数 (Loss Function: MSE, CrossEntropy)
损失函数(或目标函数)用于衡量模型预测输出 $\mathbf{y}{\text{pred}}$ 与真实标签 $\mathbf{y}{\text{true}}$ 之间的差异。选择合适的损失函数至关重要。
| 损失函数 | 公式/名称 | 任务类型 | 作用与特点 |
|---|---|---|---|
| 均方误差 (MSE) | $L(\mathbf{y}, \hat{\mathbf{y}}) = \frac{1}{N} \sum (\mathbf{y}_i - \hat{\mathbf{y}}_i)^2$ | 回归 (Regression) | 计算预测值与真实值差的平方平均值。适用于预测连续数值的任务。 |
| 交叉熵 (Cross Entropy) | $L(\mathbf{y}, \hat{\mathbf{y}}) = - \sum_{i} y_i \log(\hat{y}_i)$ | 分类 (Classification) | 衡量两个概率分布之间的差异。是分类任务的默认损失函数。PyTorch的 nn.CrossEntropyLoss 期望的输入是未经Softmax的原始Logits,而标签是类别索引(非one-hot编码)。 |
| 二元交叉熵 (BCE) | $L = - [y \log(\hat{y}) + (1-y) \log(1-\hat{y})]$ | 二分类 | 专用于二分类问题,常配合 Sigmoid 激活函数使用。 |
【工程提示】 在分类任务中,框架(如 PyTorch)通常提供 CrossEntropyLoss,它会自动包含 Softmax 操作,从而提高数值稳定性。
3.2. 核心算法:反向传播 (Backpropagation)
反向传播是训练 MLP 的核心算法,它利用链式法则(Chain Rule)高效地计算损失函数对网络中所有权重和偏置的梯度。
I. 流程概要
训练过程分两个主要阶段:
- 前向传播 (Forward Pass):
- 数据从输入层经过隐藏层到达输出层,计算得到预测值 $\mathbf{y}_{\text{pred}}$。
- 根据 $\mathbf{y}{\text{pred}}$ 和 $\mathbf{y}{\text{true}}$ 计算损失 $L$。
- 反向传播 (Backward Pass):
- 从输出层开始,将损失 $L$ 的梯度向后传递。
- 核心: 利用链式法则,计算损失 $L$ 关于每一层权重 $\mathbf{W}$ 和偏置 $\mathbf{b}$ 的偏导数 $\frac{\partial L}{\partial \mathbf{W}}$ 和 $\frac{\partial L}{\partial \mathbf{b}}$。
- 目的: 获得梯度,指导优化器如何调整参数。
II. 链式法则应用(以隐藏层权重为例)
隐藏层权重 $\mathbf{W}_H$ 的梯度计算公式为:
其中,$\mathbf{z}_H = \mathbf{W}_H \mathbf{x} + \mathbf{b}_H$。
【关键点】 由于 MLP 使用了可导的非线性激活函数,这保证了所有中间变量和参数的导数都可以被精确计算,使得反向传播成为可能。
3.3. 优化器 (Optimizer: SGD, Adam, Adagrad)
优化器使用反向传播计算得到的梯度来更新模型的参数,以最小化损失函数。
| 优化器 | 更新机制 | 优点 | 适用性 |
|---|---|---|---|
| SGD (Stochastic Gradient Descent) | 简单梯度下降。 | 计算简单,内存占用小。 | 基础,学习率调整困难。 |
| Adam (Adaptive Moment Estimation) | 结合一阶矩(动量)和二阶矩(自适应学习率)。 | 收敛速度快,对学习率不敏感,性能稳定。 | 最常用的默认优化器,适用于大多数深度学习任务。 |
| Adagrad (Adaptive Gradient) | 为稀疏特征的参数提供更大的更新。 | 学习率自适应,无需手动调整所有维度。 | 历史梯度累积可能导致学习率过早衰减。 |
3.4. 正则化与防止过拟合 (Dropout, L1/L2)
过拟合 (Overfitting) 是指模型在训练集上表现优异,但在未见过的测试集上性能急剧下降的现象。正则化是缓解过拟合的关键手段。
I. 权重正则化 (L1/L2)
将权重的大小作为惩罚项加入到损失函数中,鼓励模型使用较小的权重值,从而简化模型,降低复杂度。
-
L2 正则化 (Weight Decay):
$$ L_{\text{total}} = L_{\text{original}} + \lambda \sum \mathbf{W}^2 $$- 效果: 促使权重趋近于零,但不会完全归零。是最常用的正则化手段。
-
L1 正则化:
$$ L_{\text{total}} = L_{\text{original}} + \lambda \sum |\mathbf{W}| $$- 效果: 可以将不重要的权重稀疏化(即置为零),有助于特征选择。
II. Dropout (暂退法)
- 机制: 在训练过程中,以概率 $p$ 随机地“关闭”隐藏层的神经元(将其输出设为零)。
- 效果:
- 防止神经元对特定特征的过度依赖。
- 迫使网络学习更加鲁棒(健壮)的特征。
- 可以理解为在训练阶段集成了多个不同的子网络。
4. 从零实现到框架实践
4.1. 基础实现 (Numpy/Python 原生实现)
import numpy as np
def relu(z):
"""ReLU 激活函数"""
return np.maximum(0, z)
def relu_derivative(z):
"""ReLU 的导数。当 z>0 时导数为1,否则为0。"""
return np.where(z > 0, 1, 0)
def softmax(z):
"""Softmax 函数,为防止数值溢出进行优化"""
# 减去每行的最大值可以保证 exp 的输入不会过大,从而避免溢出
exp_z = np.exp(z - np.max(z, axis=1, keepdims=True))
return exp_z / np.sum(exp_z, axis=1, keepdims=True)
def cross_entropy_loss(y_pred_proba, y_true_one_hot):
"""交叉熵损失函数"""
num_samples = y_pred_proba.shape[0]
epsilon = 1e-9
loss = -np.sum(y_true_one_hot * np.log(y_pred_proba + epsilon)) / num_samples
return loss
class MLP:
def __init__(self, input_size, hidden_size, output_size):
"""初始化权重和偏置"""
self.W1 = np.random.randn(input_size, hidden_size) * 0.01
self.b1 = np.zeros((1, hidden_size))
self.W2 = np.random.randn(hidden_size, output_size) * 0.01
self.b2 = np.zeros((1, output_size))
# 存储中间变量,用于反向传播
self.cache = {}
def forward(self, X):
"""前向传播"""
Z1 = X @ self.W1 + self.b1
A1 = relu(Z1)
Z2 = A1 @ self.W2 + self.b2
A2 = softmax(Z2) # A2 即为 y_pred_proba
self.cache = {"X": X, "Z1": Z1, "A1": A1, "Z2": Z2, "A2": A2}
return A2
def backward(self, y_true_one_hot):
"""反向传播,手动计算梯度"""
X, A1, A2 = self.cache["X"], self.cache["A1"], self.cache["A2"]
Z1 = self.cache["Z1"]
num_samples = X.shape[0]
# 计算输出层的梯度(Softmax+交叉熵的简化形式)
dZ2 = A2 - y_true_one_hot
# 计算W2的梯度
self.dW2 = (A1.T @ dZ2) / num_samples
self.db2 = np.sum(dZ2, axis=0, keepdims=True) / num_samples
# 反向传播到隐藏层
dA1 = dZ2 @ self.W2.T
# 计算隐藏层激活前的梯度(乘以ReLU的导数)
dZ1 = dA1 * relu_derivative(Z1)
self.dW1 = (X.T @ dZ1) / num_samples
self.db1 = np.sum(dZ1, axis=0, keepdims=True) / num_samples
def update_params(self, learning_rate):
"""使用梯度下降更新参数"""
self.W1 -= learning_rate * self.dW1
self.b1 -= learning_rate * self.db1
self.W2 -= learning_rate * self.dW2
self.b2 -= learning_rate * self.db2
# ----------------------------
# 4. 示例:训练一个简单的模型
# ----------------------------
if __name__ == '__main__':
# --- 超参数 ---
num_samples = 1000
input_size = 128
hidden_size = 64
output_size = 10
learning_rate = 0.5
epochs = 100
# --- 生成模拟数据 ---
# 创建随机的输入特征
X_train = np.random.rand(num_samples, input_size)
# 创建随机的one-hot编码标签
true_labels = np.random.randint(0, output_size, num_samples)
y_train_one_hot = np.eye(output_size)[true_labels]
# --- 初始化并训练模型 ---
model = MLP(input_size, hidden_size, output_size)
print("开始使用模拟数据进行训练...")
for epoch in range(epochs):
# 1. 前向传播
y_pred = model.forward(X_train)
# 2. 计算损失
loss = cross_entropy_loss(y_pred, y_train_one_hot)
# 3. 反向传播 (计算梯度)
model.backward(y_train_one_hot)
# 4. 更新参数
model.update_params(learning_rate)
# 每10个epoch打印一次信息
if (epoch + 1) % 10 == 0:
predicted_labels = np.argmax(y_pred, axis=1)
accuracy = np.mean(predicted_labels == true_labels) * 100
print(f"Epoch {epoch + 1}/{epochs}, Loss: {loss:.4f}, Accuracy: {accuracy:.2f}%")
print("\n训练完成!")
# 训练结束后,可以检查权重是否已更新
# print("W1 的一部分:", model.W1[:2, :2])
4.2. PyTorch实现 (以 nn.Linear 和 nn.Sequential 为例)
import torch
import torch.nn as nn
# 超参数
num_inputs, num_hiddens, num_outputs = 784, 256, 10
# 使用 nn.Sequential 构建 MLP
net = nn.Sequential(
nn.Flatten(), # 自动将输入展平为 (batch_size, 784)
nn.Linear(num_inputs, num_hiddens),
nn.ReLU(),
nn.Linear(num_hiddens, num_outputs)
)
# 获取参数(通常不需要显式调用,除非自定义优化器)
params = list(net.parameters())
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
for X, y in train_loader:
y_hat = net(X) # 自动展平 + 前向传播
loss = loss_fn(y_hat, y)
optimizer.zero_grad() # 清空上一轮的梯度,否则梯度会累积
loss.backward()
optimizer.step()
4.3. 性能优化技巧 (Batch Normalization, 权重初始化)
Batch Normalization:
- 减少内部协变量偏移(Internal Covariate Shift)
- 允许使用更高学习率
- 有一定正则化效果(可减少对 Dropout 的依赖)
在线性层之后、激活函数之前插入 nn.BatchNorm1d(全连接网络)或 nn.BatchNorm2d(CNN)。
权重初始化:
- 若权重初始化过大 → 激活值爆炸(梯度爆炸)
- 若权重初始化过小 → 激活值消失(梯度消失)
- 默认的
nn.Linear使用 Kaiming Uniform(针对 ReLU)或 Xavier(针对 Sigmoid/Tanh)初始化,但有时需显式控制。
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 数据
transform = transforms.ToTensor()
train_loader = DataLoader(
datasets.MNIST('./data', train=True, download=True, transform=transform),
batch_size=256, shuffle=True
)
# 模型
net = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 256),
nn.BatchNorm1d(256),
nn.ReLU(),
nn.Linear(256, 10)
)
# 初始化
def init_weights(m):
if isinstance(m, nn.Linear):
nn.init.kaiming_normal_(m.weight, nonlinearity='relu')
nn.init.zeros_(m.bias)
net.apply(init_weights)
net.to(device)
# 训练
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=1e-3)
net.train()
for epoch in range(10):
for X, y in train_loader:
X, y = X.to(device), y.to(device)
y_hat = net(X)
loss = loss_fn(y_hat, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f'Epoch {epoch + 1}, Loss: {loss.item():.4f}')
5. 经典应用场景与局限性
5.1 核心应用:作为处理表格数据的“瑞士军刀”
MLP最核心、最直接的应用场景是处理结构化数据(表格数据)。对于已经是向量形式的特征,MLP通过其强大的非线性拟合能力,成为回归和分类任务的默认基准模型。
I. 回归任务 (如:房价预测、销量预测)
- 任务目标: 预测一个或多个连续值。
- 核心思想: MLP学习输入特征(如房屋面积、地段)与输出目标(房价)之间复杂的、非线性的函数关系。
- 关键配置与实践指南:
| 配置项 | 推荐方案 | 作用与说明 |
|---|---|---|
| 输出层激活 | 恒等函数 (即不使用激活) | 直接输出预测值,不限制范围。 |
| 损失函数 | MSE (均方误差) 或 MAE (平均绝对误差) | MSE对异常值更敏感;MAE对异常值更鲁棒。 |
| 评估指标 | RMSE, MAE, R² (决定系数) | 全面评估模型的预测精度和解释力。 |
| 数据预处理 | 数值特征标准化、类别特征独热编码/嵌入 | 消除量纲影响,使模型能处理非数值特征。 |
| 工程技巧 | 对目标值取对数(log)、L2正则化、早停(Early Stopping) | 缓解目标值长尾分布问题;防止过拟合;在验证集性能不再提升时停止训练。 |
II. 分类任务 (如:信用评分、手写数字识别)
- 任务目标: 预测样本属于哪个类别。
- 核心思想: MLP学习一个复杂的决策边界,将不同类别的样本在高维特征空间中分离开。
- 关键配置与实践指南:
| 配置项 | 推荐方案 | 作用与说明 |
|---|---|---|
| 输出层激活 | Softmax (多分类) 或 Sigmoid (二分类) | 将输出 logits 转换为互斥的概率分布或独立的概率值。 |
| 损失函数 | 交叉熵损失 (Cross-Entropy Loss) | 分类任务的标准损失函数,衡量预测概率分布与真实分布的差距。 |
| 评估指标 | Accuracy, Precision, Recall, F1-Score, AUC | 从不同维度评估分类性能,尤其在类别不均衡时。 |
| 类别不均衡处理 | 加权交叉熵、Focal Loss、重采样 (Oversampling/Undersampling) | 提高少数类的权重,或调整样本分布,使模型更关注少数类。 |
| 正则化 | Dropout、L2正则化、批量归一化 (Batch Norm) | Dropout是分类任务中最有效的正则化手段之一;BN能加速收敛并提供轻微正则化效果。 |
5.2 进阶应用:作为复杂模型的“乐高积木”
在现代深度学习架构中,MLP很少单独作为主角,但它作为核心组件无处不在,承担着关键的特征变换和决策判别功能。
| 模型架构 | MLP的角色 | 核心功能与意义 |
|---|---|---|
| Transformer | 前馈网络 (FFN) | 在自注意力(信息混合)之后,对每个位置的特征进行独立的非线性变换和升维,增强模型的表达能力。是Transformer模型的核心部件之一。 |
| CNN | 分类头 (Classifier Head) | 在卷积层提取了空间特征后,将展平的特征图通过全连接层(MLP)映射到最终的类别得分,完成从特征到决策的转换。 |
| 图神经网络(GNN) | 节点/边更新函数 (Update Function) | 在聚合了邻居节点信息后,使用MLP对节点的表示向量进行非线性更新,从而学习更复杂的图结构特征。 |
| 推荐系统 | 深度部分 (Deep Part) 或 专家网络 (Expert Network) | 在Wide & Deep、DeepFM、MMoE等模型中,MLP负责学习特征之间的高阶、非线性交叉,捕捉用户和物品的深层关联。 |
5.3 固有局限性与使用警告
尽管MLP功能强大且通用,但其“通用”也意味着缺乏针对特定数据结构的“特长”。
- 缺乏归纳偏置 (Inductive Bias):
- 对空间结构不敏感: 与CNN的局部连接和权重共享不同,MLP将图像展平后处理,丢失了像素间的空间邻近关系。
- 对时序关系不敏感: 与RNN的循环结构不同,MLP无法直接建模序列数据中的时间依赖性。
- 参数量巨大且效率低下:
- 对于高维输入(如高清图像),全连接层的权重矩阵会变得异常庞大,导致巨大的计算和内存开销。CNN的参数共享机制在这一点上优势明显。
- 数据饥渴与易过拟合:
- 由于其极大的灵活性,MLP需要大量数据来学习有效的模式。在小数据集上,它极易记住训练数据中的噪声,导致过拟合。
- 在表格数据上并非总是最优:
- 在中小型表格数据集上,梯度提升树模型 (如XGBoost, LightGBM, CatBoost) 通常表现更优。树模型对特征缩放不敏感,能自动处理特征交互,并且可解释性更强。MLP通常需要更细致的调参和特征工程才能与之匹敌。
6. 总结与进阶学习
6.1 战略选型:MLP vs. 其他主流模型
| 模型类型 | 核心优势 (归纳偏置) | 最佳适用场景 | 何时应优先考虑MLP? |
|---|---|---|---|
| MLP | 通用函数逼近器 (无特定偏置) | 表格数据、已提取的特征向量 | 当输入是固定长度的向量,且特征间关系复杂、非线性时。作为其他模型的分类/回归头。 |
| CNN | 空间局部性 & 平移不变性 | 图像、视频、频谱图等网格结构数据 | 当任务不具备空间结构,或特征已被其他模型(如CNN)提取为向量后。 |
| RNN/LSTM | 时间依赖性 & 序列顺序 | 文本、语音、时间序列等序列数据 | 当序列的顺序和长程依赖不重要,或仅需对序列的整体摘要(如池化后的向量)进行分类时。 |
| Transformer | 全局依赖关系 (通过自注意力) | 自然语言处理、长序列、多模态任务 | 当计算资源有限,或任务不需要复杂的上下文依赖建模时。FFN本身就是Transformer的一部分。 |
| 树模型 (XGBoost) | 决策边界划分 & 特征交互 | 中小型表格数据,尤其是类别特征多的场景 | 当数据集规模巨大、需要端到端学习嵌入层、或需要与其他深度模型无缝集成时。 |
6.2 现代MLP的进阶武器库
基础MLP虽然简单,但通过结合现代深度学习技术,其性能和可训练性得到了极大的提升,使其在更深、更复杂的架构中保持竞争力。
I. 提升表达能力与训练稳定性
- 残差连接 (Residual Connections): 允许梯度直接“跳过”某些层,极大地缓解了深度MLP的梯度消失问题,使得训练非常深的网络成为可能。
- 高级激活函数:
- GELU/SwiGLU: 平滑且非单调的激活函数,在Transformer等现代模型中已取代ReLU,能提供更好的性能。SwiGLU通过门控机制进一步增强了表达能力。
- SIREN (Sinusoidal Representation Networks): 使用正弦函数作为激活,非常适合拟合带有复杂细节的隐式神经表示(如NeRF),能学习到高频信号。
- 归一化层 (Normalization Layers):
- BatchNorm: 加速收敛,稳定训练,允许更高的学习率。
- LayerNorm: 在Transformer和序列任务中更常用,对批次大小不敏感。
II. 提升效率与部署能力
- 专家混合 (Mixture of Experts, MoE): 将一个巨大的FFN替换为多个小型的“专家”网络和一个路由网络。每次只激活少数专家,从而在大幅增加模型参数的同时,保持计算成本不变,是构建超大规模模型的核心技术。
- 参数高效微调 (LoRA): 在预训练模型的线性层旁添加低秩矩阵进行训练,能够在不改动原模型权重的情况下,以极小的参数量实现高效微调。
- 模型压缩: 通过剪枝 (Pruning)、量化 (Quantization)等技术减小模型体积和计算量,使其适用于移动端或边缘设备。
III. 针对表格数据的专属进化
- 类别特征嵌入 (Categorical Embeddings): 使用可学习的嵌入向量来表示类别特征,比独热编码更高效,且能捕捉类别间的语义相似性。这是MLP处理表格数据的关键优势之一。
- 特征交叉的显式建模: 借鉴推荐系统的思想,模型如DeepFM、DCN-V2将MLP(Deep部分)与显式的特征交叉网络结合,自动学习重要的特征组合,弥补了MLP隐式学习交叉效率不高的短板。