深度学习和神经网络最基础的mlp,从最基础的开始讲
好的,我们来详细拆解多层感知机(Multilayer Perceptron, MLP),这是理解和构建几乎所有深度学习模型的最基础砖块。我们会从最核心的概念开始,逐步深入。
核心思想:模仿大脑(简化版)
想象一下大脑中的神经元:它接收来自其他神经元的信号(输入),如果接收到的信号总和足够强(超过某个阈值),它就会被激活(输出一个信号),并传递给其他神经元。
MLP 试图用数学和计算来模拟这个简单的过程,构建一个由人工神经元(也叫节点或单元)组成的网络。
第一步:基础单元 - 人工神经元(Perceptron)
单个神经元(感知机)是 MLP 的最小构成元素。它做了三件事:
接收输入: 接收多个输入信号 x1, x2, …, xn。这些信号可以来自原始数据(输入层)或前一层神经元的输出(隐藏层/输出层)。
计算加权和: 每个输入 xi 都与一个权重 wi 相关联。权重表示该输入的重要程度。神经元将所有输入的加权和加上一个偏置 b(可以理解为激活难易程度的调节器):
加权和 (z) = (w1 * x1) + (w2 * x2) + … + (wn * xn) + b
用向量表示更简洁: z = w · x + b (其中 w 是权重向量 [w1, w2, …, wn], x 是输入向量 [x1, x2, …, xn])
应用激活函数: 加权和 z 被送入一个激活函数 f()。这个函数决定了神经元是否被“激活”以及激活的程度(输出什么值)。
输出 (a) = f(z) = f(w · x + b)
关键角色:激活函数 (Activation Function)
为什么需要激活函数?因为如果没有它(或者使用线性函数 f(z) = z),无论堆叠多少层神经元,整个网络仍然只能表示线性关系。激活函数引入了非线性,使神经网络能够学习和逼近极其复杂的函数。常用的激活函数有:
Sigmoid: f(z) = 1 / (1 + e^{-z})
将输出压缩到 (0, 1) 之间。以前非常流行,常用于输出层做二分类(输出可以解释为概率)。问题:存在梯度消失(训练困难)。
Tanh (Hyperbolic Tangent): f(z) = (e^z - e^{-z}) / (e^z + e^{-z})
将输出压缩到 (-1, 1) 之间。输出是零中心的(均值在0附近)。比 Sigmoid 更常用在隐藏层。也存在梯度消失问题。
ReLU (Rectified Linear Unit): f(z) = max(0, z)
现代 MLP/DL 隐藏层的标准选择! 计算极其简单高效。解决了 Sigmoid/Tanh 的梯度消失问题(在正区间梯度恒为1)。问题:可能导致“神经元死亡”(输出恒为0且无法恢复)。
Leaky ReLU: f(z) = max(αz, z) (α 是一个很小的正数,如 0.01)
尝试解决 ReLU 的死亡问题,在负区间给予一个小的梯度。
Softmax: (主要用于输出层做多分类)
将多个神经元的输出转化为一个概率分布。每个输出值在 (0, 1) 之间,且所有输出值之和为 1。Softmax(z_i) = e^{z_i} / Σ_j e^{z_j}
示意图:一个接收3个输入的人工神经元及其计算过程 (f 代表激活函数)
第二步:构建网络 - 层 (Layers)
单个神经元能力有限。MLP 的强大之处在于将许多神经元组织成层(Layers),并将这些层连接起来。
输入层 (Input Layer):
不是计算层,只是表示原始数据的入口。
层中的每个“神经元”代表输入数据的一个特征(如图像的一个像素值、一条文本记录的某个数值)。
节点数量等于输入数据的特征维度。
隐藏层 (Hidden Layers):
位于输入层和输出层之间。这是模型进行复杂特征学习和变换的地方。
一个 MLP 可以有一个或多个隐藏层。“多层”指的就是包含至少一个隐藏层。
每个隐藏层包含若干个神经元(节点)。层中每个神经元接收来自前一层所有神经元的输出作为自己的输入。
隐藏层的神经元通常会应用非线性激活函数(如 ReLU)。
输出层 (Output Layer):
网络的最后一层,产生最终的预测结果。
节点数量和激活函数的选择取决于任务类型:
回归任务 (预测连续值): 通常1个节点(或者对应多个要预测的值),激活函数用线性函数(f(z)=z)或 ReLU(预测非负数)。
二分类任务: 1个节点,激活函数用 Sigmoid(输出概率)。
多分类任务 (K个类): K个节点(每个节点对应一个类别的概率),激活函数用 Softmax(输出概率分布)。
关键概念:全连接 (Fully Connected - FC / Dense)
MLP 的显著特点是相邻两层之间的神经元是全连接的。这意味着:
第 L 层中的每一个神经元都与第 L-1 层中的每一个神经元有连接。
每条连接都有一个独立的权重 w。这就是为什么 MLP 也叫全连接网络 (Fully Connected Network - FCN) 或 密集层 (Dense Layer)。
隐藏层或输出层的每个神经元还有自己的偏置 b。
示意图:一个具有1个输入层(3个特征)、1个隐藏层(4个神经元,使用激活函数如ReLU)、1个输出层(1个神经元,激活函数如Sigmoid用于二分类)的MLP。注意层与层之间是全连接的。
第三步:工作流程 - 前向传播 (Forward Propagation)
当你把一组输入数据(如一张图片的像素值向量)送入网络时,信息是如何从输入层流动到输出层产生预测的呢?这个过程叫做前向传播。
输入层接收: 数据 x = [x1, x2, …, xn] 被送入输入层节点。
隐藏层1计算:
输入层的值作为隐藏层1的输入。
隐藏层1的每个神经元 j 计算其加权和 z_j^1 = w_j^1 · x + b_j^1。(上标 1 表示第1层(隐藏层1))
对加权和 z_j^1 应用激活函数 a_j^1 = f1(z_j1)(如 ReLU)。a_j^1 是神经元 j 的输出。
隐藏层1的所有输出组合成向量 a^1 = [a_1^1, a_2^1, …, a_m^1](假设隐藏层1有 m 个神经元)。
隐藏层2计算(如果有):
隐藏层1的输出 a^1 作为隐藏层2的输入。
隐藏层2的每个神经元 k 计算 z_k^2 = w_k^2 · a^1 + b_k^2。
应用激活函数 a_k^2 = f2(z_k2)。
得到输出向量 a^2。
输出层计算:
最后一个隐藏层(假设是隐藏层2)的输出 a^2 作为输出层的输入。
输出层每个神经元 p 计算 z_p^{out} = w_p^{out} · a^2 + b_p^{out}。
应用输出层特定的激活函数 a_p^{out} = f{out}(z_p{out})(如 Sigmoid 或 Softmax)。
得到最终的预测输出 y_pred = a^{out}(可能是一个标量、一个向量等)。
总结前向传播: 输入 x -> 加权和(z) + 激活(f) -> 隐藏层输出(a) -> 加权和(z) + 激活(f) -> … -> 输出层加权和(z_out) + 输出激活(f_out) -> 预测 y_pred
第四步:学习过程 - 训练(反向传播与优化)
网络初始化时,权重 w 和偏置 b 通常是随机设置的。前向传播得到的预测 y_pred 肯定不准。训练的目标就是找到一组最优的 w 和 b,使得网络在训练数据上的预测 y_pred 尽可能接近真实值 y_true。
- 定义损失函数 (Loss Function)
我们需要一个衡量预测 y_pred 和真实 y_true 之间差距的指标。这就是损失函数 L(y_true, y_pred)。常见的有:
均方误差 (MSE): 回归任务。L = (1/N) Σ (y_true - y_pred)^2
二元交叉熵 (Binary Cross Entropy): 二分类任务。
分类交叉熵 (Categorical Cross Entropy): 多分类任务。
目标:最小化总损失 L。
- 反向传播 (Backpropagation) - 计算梯度
这是 MLP 学习的核心算法(由 Hinton 等人推广)。关键思想:利用微积分的链式法则,计算损失函数 L 相对于网络中每一个权重 w 和每一个偏置 b 的偏导数(梯度)。
梯度 ∂L/∂w: 表示当权重 w 发生微小变化时,损失 L 会如何变化。它告诉我们 w 应该朝哪个方向(增大还是减小)调整才能减少 L。
梯度 ∂L/∂b: 同理,表示偏置 b 的变化对损失 L 的影响。
反向传播的过程是从输出层反向传播回输入层:
计算输出层神经元输出的梯度 ∂L/∂a^{out}。
利用链式法则,计算输出层神经元的输入(即 z^{out})的梯度 ∂L/∂z^{out}(这通常涉及到激活函数的导数)。
利用 ∂L/∂z^{out},计算输出层的权重梯度 ∂L/∂w^{out} 和偏置梯度 ∂L/∂b^{out}。
将 ∂L/∂z^{out} 继续向后传播,计算前一隐藏层的输出梯度 ∂L/∂a^{hidden}。
重复步骤 2-4,逐层向后传播,直到计算出所有层(包括第一隐藏层)的权重和偏置的梯度 ∂L/∂w 和 ∂L/∂b。
3. 优化器 (Optimizer) - 更新参数
拿到所有参数的梯度 (∂L/∂w, ∂L/∂b) 后,我们需要用它来更新参数,使损失减小。最简单的更新规则是梯度下降 (Gradient Descent):
w_new = w_old - η * (∂L/∂w)
b_new = b_old - η * (∂L/∂b)
η 是学习率 (Learning Rate):一个非常重要的超参数,控制每次更新的步长。太小则学习太慢;太大则可能跳过最小值甚至导致发散。
更高级的优化器(如 Adam, SGD with Momentum, RMSprop)在基本梯度下降的基础上改进,通常收敛更快、更稳定。它们引入了动量、自适应学习率等机制。
训练循环 (Training Loop)
训练一个 MLP 就是在数据集上反复执行以下步骤多次(称为 Epochs):
前向传播: 输入一批 (Batch) 数据,计算预测 y_pred。
计算损失: 计算这批数据的损失 L(y_true, y_pred)。
反向传播: 计算损失 L 对所有权重 w 和偏置 b 的梯度 (∂L/∂w, ∂L/∂b)。
参数更新: 使用优化器(如梯度下降或其变种)根据梯度更新 w 和 b。
这个过程不断迭代,直到损失不再显著下降(收敛)或达到预设的训练轮数。
总结 MLP 的关键特点
结构: 输入层、一个或多个隐藏层(全连接)、输出层。
连接: 层间全连接。
非线性: 依赖于非线性激活函数(如 ReLU)来学习复杂模式。
监督学习: 需要带标签的数据进行训练(有 y_true)。
万能逼近器: 理论上,一个具有足够多神经元(宽度)的隐藏层或足够多隐藏层(深度)的 MLP 可以逼近任何连续函数(Universal Approximation Theorem)。这是其强大表达力的基础。
缺点 / 挑战:
参数多: 全连接导致权重数量巨大(层宽 x 下层宽),尤其在处理高维数据(如图像)时。这带来:
计算开销大
容易过拟合(模型过度记忆训练数据,泛化能力差) - 需要通过正则化(如 Dropout, L1/L2 weight decay)、数据增强等技术缓解。
空间结构信息丢失: 对于图像、音频等具有局部空间或时间相关性的数据,将所有输入(如图像像素)展平为一维向量送入 MLP 会破坏这种结构信息。这正是 CNN 被提出的原因。
序列信息处理困难: 标准 MLP 无法有效处理序列数据(如文本、时间序列)中的长期依赖关系。RNN/LSTM/Transformer 被设计来解决这个问题。
为什么还要学 MLP?
尽管 MLP 在处理图像、序列等数据时有明显局限(通常被 CNN、RNN 取代),但它仍然是深度学习的基础:
理解基石: 理解了 MLP 中的神经元、层、激活函数、前向传播、反向传播、梯度下降、损失函数等概念,就掌握了理解几乎所有复杂神经网络架构的核心原理。
理论支撑: 万能逼近定理展示了神经网络的潜力。
基础构件: 即使在 CNN 和 RNN 中,全连接层(MLP)也经常作为最终的分类器/回归器出现在网络的末端。
适用场景: 对于结构化数据(表格数据,如 CSV 文件),MLP 仍然是非常常用且有效的模型。
学习 MLP 是进入深度学习世界的必备第一步。理解了它,你就获得了一把打开更复杂模型(CNN, RNN, Transformer…)大门的钥匙。