从零手写神经网络框架:AI-For-Beginners 多层级感知机(MLP)与反向传播实战指南

发布时间:2026/10/9 2:33:06
从零手写神经网络框架:AI-For-Beginners 多层级感知机(MLP)与反向传播实战指南 教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载本篇技术指南以 AI-For-Beginners 课程的Own Framework自建框架一课为核心系统讲解如何用 Python 与 NumPy 从零构建一个模块化的多层感知机框架从机器学习问题的数学形式化、损失函数与梯度下降到 Softmax、交叉熵损失与反向传播的逐层实现并最终将该框架应用于 MNIST 手写数字分类实验。读完本文你将掌握神经网络训练的本质流程前向传播 反向传播 参数更新并能够亲手实现Linear、Softmax、CrossEntropyLoss、Net等核心组件理解现代深度学习框架背后的原理。课程背景与配套资源本课属于 AI-For-Beginners 课程体系中神经网络入门章节位于 lessons/3-NeuralNetworks/README.md 的第三个子单元04-OwnFramework。上一课 感知机Perceptron 介绍的是最简单的单层感知机——一个线性二分类模型本课则将其扩展为更灵活的框架使我们可以在二分类之外执行多类别分类在分类之外解决回归问题分离线性不可分的类别构建模块化的 Python 框架自由组合不同的神经网络架构。配套的核心资源全部位于 lessons/3-NeuralNetworks/04-OwnFramework核心讲义 README.md实战演练 OwnFramework.ipynb逐步完成框架搭建课后实验 lab/README.md 与 lab/MyFW_MNIST.ipynb要求用自建框架完成 MNIST 分类。机器学习问题的形式化模型、参数与损失函数我们从数学上形式化机器学习问题。假设有一个训练数据集X及其标签Y我们需要构建一个模型f使其预测尽可能准确。预测质量由损失函数Loss Functionℒ 度量。常见损失函数包括回归问题预测一个数值可使用绝对误差∑~i~|f(x^(i)^)−y^(i)^|或平方误差∑~i~(f(x^(i)^)−y^(i)^)²分类问题使用0-1 loss本质上等价于模型的准确率或logistic loss逻辑损失。对于单层感知机函数f被定义为线性函数f(x)wxb其中w是权重矩阵x是输入特征向量b是偏置向量。在不同神经网络架构中该函数可以呈现更复杂的形式。在分类场景中我们通常希望网络输出各类别的概率。为把任意数值转换为概率即归一化输出常用softmax函数 σ此时函数f变为f(x)σ(wxb)。在上面的定义中w与b被称为参数记作 θ⟨w,b⟩。给定数据集 ⟨X,Y⟩我们可以把整个数据集上的总体误差看成参数 θ 的函数。✅神经网络训练的目标就是通过调整参数 θ 使误差最小化。在 OwnFramework.ipynb 中这一形式化被进一步写为模型f~θ~(x) 由参数集 θ 决定训练即求解最优化问题 θ argmin~θ~ ℒ(f~θ~(X),Y)。该笔记本还通过plot_loss_functions可视化地展示了回归的绝对损失、平方损失以及分类的 0-1 损失与 logistic 损失曲线的差异——例如 logistic 损失在预测概率趋于 0 时会急剧增大反映出差一点与差很多之间的代价差别。梯度下降优化从全量到随机小批量函数优化有一种经典方法叫梯度下降Gradient Descent。其思想是计算损失函数关于参数的导数多维情形下称为梯度然后沿使误差减小的方向调整参数。可形式化为用随机值初始化参数 w^(0)^、b^(0)^反复执行以下步骤w^(i1)^ w^(i)^ − η·∂ℒ/∂wb^(i1)^ b^(i)^ − η·∂ℒ/∂b其中 η 是学习率learning rate。理论上优化步长应基于整个数据集计算因为损失是所有训练样本之和。但在实践中我们每次只取数据集的一小部分——称为minibatches小批量基于这批子集计算梯度。由于每次随机选取子集这种方法被称为随机梯度下降Stochastic Gradient DescentSGD。在笔记本的训练循环中batch_size4就是该机制的直观体现。多层感知机与反向传播如上所述单层网络只能分类线性可分的类别。为了构建更丰富的模型可以把多层网络组合起来。数学上这意味着函数f具有更复杂的形式分多个步骤计算z~1~ w~1~x b~1~z~2~ w~2~α(z~1~) b~2~f σ(z~2~)这里α 是非线性激活函数σ 是 softmax 函数参数集为 θ⟨w~1~,b~1~,w~2~,b~2~⟩。梯度下降算法保持不变但计算梯度会变得更困难。借助链式求导法则可以这样计算导数∂ℒ/∂w~2~ (∂ℒ/∂σ)(∂σ/∂z~2~)(∂z~2~/∂w~2~)∂ℒ/∂w~1~ (∂ℒ/∂σ)(∂σ/∂z~2~)(∂z~2~/∂α)(∂α/∂z~1~)(∂z~1~/∂w~1~)✅ 链式求导法则用于计算损失函数关于各层参数的导数。注意观察上面所有表达式的最左侧部分完全相同。因此我们可以从损失函数出发沿计算图反向逐层高效地求出导数。这正是多层感知机训练方法被称为**反向传播Backpropagation简称 backprop**的原因。从源码实现角度看一次训练往返包含两个阶段见 OwnFramework.ipynb前向传播Forward pass对给定输入小批量计算损失函数值反向传播Backward pass将误差沿计算图逐层回传以最小化该误差并更新模型参数。源码级实现用 Python 构建自己的神经网络框架下面我们跟随笔记本逐步实现一个真正可运行的模块化框架。其设计哲学与 PyTorch/Keras 等现代框架高度一致每个层都是一个带forward前向与backward反向方法的类。第一步线性层Linear Layer网络架构上我们把二分类数据集当作多分类处理两个输出对应两个类别输出值更大的类别即为预测结果模型定义为f~θ~(x) W×x b参数 θ⟨W,b*⟩。线性层用 Python 类实现forward负责计算W与b在创建时初始化权重用随机值、偏置用零class Linear: def __init__(self, nin, nout): self.W np.random.normal(0, 1.0/np.sqrt(nin), (nout, nin)) self.b np.zeros((1, nout)) def forward(self, x): return np.dot(x, self.W.T) self.b net Linear(2, 2) net.forward(train_x[0:5])由于使用 NumPy 运算网络天然支持向量化一次性传入一批输入即可得到一批输出。权重初始化采用1.0/np.sqrt(nin)缩放的高斯分布这是一种简单的规模控制手段避免输入维度增大时线性组合的方差过大。第二步Softmax——把输出变成概率如前面公式 σ(z~c~) e^z~c~ / ∑~j~ e^z~j~ 所示softmax 将所有类别的输出归一化为和为 1 的概率分布可以解读为类别集 C 上的概率分布 q σ(z~c~) p̂(c|x)。数值实现上先减去每行最大值zmaxkeepdimsTrue再取指数这是为了数值稳定性防止大指数溢出class Softmax: def forward(self, z): zmax z.max(axis1, keepdimsTrue) expz np.exp(z - zmax) Z expz.sum(axis1, keepdimsTrue) return expz / Z当类别数超过 2 时softmax 同样会跨全部类别归一化——这正是 MNIST 多分类架构10 个输出神经元所依赖的机制。第三步交叉熵损失Cross-Entropy Loss分类任务中的损失通常是 logistic 损失的推广即交叉熵损失cross-entropy loss。它度量两个任意概率分布之间的相似程度。在我们这里第一个分布是网络输出的概率第二个是one-hot分布指定类别概率为 1其余为 0。此时交叉熵损失可简化为 −log p~c~其中c是期望类别p~c~是网络给出的该类别概率。若网络对期望类别输出概率 1交叉熵损失为 0期望类别的概率越接近 0损失越高可趋于无穷大。实现上forward接收两个输入网络前一层的输出p与期望类别y。关键点损失必须对小批量返回一个标量因此取所有样本的均值.mean()class CrossEntropyLoss: def forward(self, p, y): self.p p self.y y p_of_y p[np.arange(len(y)), y] log_prob np.log(p_of_y) return -log_prob.mean() # 对所有输入样本求平均第四步计算图与前向求值将上述层依次组合便得到一张计算图computational graph。给定训练集或其一部分可以按如下方式计算损失见笔记本中z net.forward(...)、p softmax.forward(z)、loss cross_ent_loss.forward(p, ...)的调用链z net.forward(train_x[0:10]) p softmax.forward(z) loss cross_ent_loss.forward(p, train_labels[0:10])第五步反向传播的手动实现为实现反向传播需要为每个节点补上backward函数它负责计算导数并把误差向上一层回传同时实现参数更新。以线性层 z x×W b 为例其局部导数为 ∂z/∂W x、∂z/∂b 1若要在输出端补偿误差 Δz则需按 Δx Δz×W、ΔW Δz×x、Δb Δz 更新。重要计算不是针对单个样本独立进行而是针对整个小批量。ΔW 与 Δb 在整个小批量上累积计算x 的维度为 R^(minibatch × nclass)^。class Linear: def __init__(self, nin, nout): self.W np.random.normal(0, 1.0/np.sqrt(nin), (nout, nin)) self.b np.zeros((1, nout)) self.dW np.zeros_like(self.W) self.db np.zeros_like(self.b) def forward(self, x): self.x x return np.dot(x, self.W.T) self.b def backward(self, dz): dx np.dot(dz, self.W) dW np.dot(dz.T, self.x) db dz.sum(axis0) self.dW dW self.db db return dx def update(self, lr): self.W - lr * self.dW self.b - lr * self.dbSoftmax 与交叉熵损失的 backward 也一并实现softmax 的雅可比公式为pdp - p * pdp.sum(axis1, keepdimsTrue)交叉熵对未归一化 logits 的梯度以dlog_softmax / self.p形式给出从而构成完整可训练的最小网络。第六步训练循环Training Loop现在可以编写训练循环遍历数据集逐小批量执行优化。完整遍历一遍数据集称为一个epoch。以learning_rate0.1、batch_size4为例单 epoch 内每个小批量都经历前向 → 反向 → 更新三步lin Linear(2, 2); softmax Softmax(); cross_ent_loss CrossEntropyLoss() learning_rate 0.1 batch_size 4 for i in range(0, len(train_x), batch_size): xb train_x[i:ibatch_size] yb train_labels[i:ibatch_size] # 前向传播 z lin.forward(xb); p softmax.forward(z); loss cross_ent_loss.forward(p, yb) # 反向传播 dp cross_ent_loss.backward(loss); dz softmax.backward(dp); dx lin.backward(dz) lin.update(learning_rate)笔记本中该模型在一个 epoch 内即可把准确率从约 50% 提升到约 80%直观体现了梯度下降的收敛过程。第七步Net 类——层的容器与组合多数神经网络无非是层的组合因此可以构建一个Net类把层堆叠起来让前向/反向遍历的逻辑自动化。它内部维护一个layers列表add()追加新层forward按顺序逐层前向backward按逆序逐层反向update只对实现了update方法的层即含参数的层执行参数更新class Net: def __init__(self): self.layers [] def add(self, l): self.layers.append(l) def forward(self, x): for l in self.layers: x l.forward(x) return x def backward(self, z): for l in self.layers[::-1]: z l.backward(z) return z def update(self, lr): for l in self.layers: if update in l.__dir__(): l.update(lr)引入Net之后模型定义与训练变得非常整洁笔记本输出示例初始loss0.6212, accuracy0.6875单 epoch 后训练loss0.4437, accuracy0.8测试集loss0.4768, accuracy0.85。配合train_and_plot等辅助函数还可以实时绘制训练/验证准确率曲线与决策边界用等高线图可视化网络输出的类别划分直观观察网络学习过程。多层模型为什么需要非线性激活函数在两层Linear之间必须插入非线性激活函数如tanh。原因很本质多个线性函数复合仍然是线性函数——若没有非线性多层线性层的表达能力与单层无异。笔记本中的Tanh层实现同样遵循 forward/backward 范式其反向公式利用了 tanh 的导数性质1−y²class Tanh: def forward(self, x): y np.tanh(x) self.y y return y def backward(self, dy): return (1.0 - self.y**2) * dy叠加多个含非线性的层之所以有意义是因为多层模型能够准确分类线性不可分的数据集。数学上多层感知机表示为更复杂的函数f~θ~z~1~ W~1~×x b~1~z~2~ W~2~×α(z~1~) b~2~f σ(z~2~)。其梯度同样可用链式法则展开且各表达式开头共享相同因子因此反向传播可以穿过多个线性层持续向计算图更深处调整权重。可以证明两层模型在神经元数量足够时能够分类任何凸数据集三层网络几乎能分类任意数据集。笔记本中构造了Linear(2,10) → Tanh → Linear(10,2) → Softmax的两层网络并用较小的学习率lr0.01训练 30 个 epoch以观察决策边界如何逐步演化。为什么不总是用深层模型——过拟合与偏差-方差权衡既然多层模型比单层更强大、更具表达力为什么我们不全用多层模型答案在于过拟合overfitting。其核心思想是模型越强大就越能拟合训练数据但要让模型对未见过的数据正确泛化需要的训练数据也越多。线性模型单层训练损失可能较高——即所谓欠拟合underfitting模型表达能力不足无法正确分离全部数据。但验证损失与训练损失大致相当模型很可能在测试数据上泛化良好。复杂的多层模型训练损失很低——表达力足够能很好地拟合训练数据但验证损失可能远高于训练损失并在训练过程中开始上升——因为模型记住了训练点丢失了全局图像。上图中x表示训练数据o表示验证数据。左侧是线性单层模型对数据本质拟合得不错右侧是过拟合模型对训练数据拟合得完美但对任何其他数据都失去意义验证误差非常高。要点总结Takeaways简单模型更少的层、更少的神经元、低参数量的低容量更不容易过拟合更复杂的模型更多层、每层更多神经元、高容量很可能过拟合需要监控验证误差确保它不会随着进一步训练而开始上升更复杂的模型需要更多数据来训练解决过拟合的途径简化模型或增加训练数据量偏差-方差权衡Bias-variance trade-off提示我们需要在模型能力与数据量、过拟合与欠拟合之间取得折中关于需要多少层、多少参数并没有统一配方——最好的方式是通过实验探索。课后实验用自建框架求解 MNIST课程要求把本课构建的框架用于一个真实任务MNIST 手写数字分类。任务说明见 lab/README.md起始笔记本为 lab/MyFW_MNIST.ipynb。任务分别使用 1 层、2 层和 3 层感知机解决 MNIST 手写数字分类问题全部基于本课开发的框架完成。MNIST 数据集mnist.pkl.gz训练样本(42000, 784)即 42000 个 784 维像素特征向量位于仓库 data/mnist.pkl.gz笔记本会先下载并用gzip -d解压再进行加载与切分。完成实验后请尝试回答以下问题这些也是本实验的核心考核点层间激活函数会影响网络性能吗这个任务需要 2 层还是 3 层网络训练网络时是否遇到问题尤其是随着层数增加训练过程中网络的权重如何变化可以绘制权重最大绝对值随 epoch 的变化曲线以理解两者关系。结语本课的核心收获不只是会调框架而是亲手把现代神经网络的骨架从零搭起来从损失函数与梯度下降的数学形式到 Softmax 概率归一化与交叉熵损失再到链式法则驱动的反向传播、模块化的Net层容器最后通过 MNIST 实验体会容量、数据量与过拟合之间的微妙权衡。理解了这些底层机理无论是后续课程中引入 PyTorch/Keras 等 框架课程还是进一步学习 卷积神经网络、Transformer 等现代架构都将事半功倍。赞分享教程人工智能机器学习深度学习【免费下载链接】AI-For-Beginners12 Weeks, 24 Lessons, AI for All!项目地址https://gitcode.com/GitHub_Trending/ai/AI-For-Beginners点击查看免费下载相关推荐从零手写神经网络框架AI-For-Beginners 之多层感知机MLP与反向传播实战从零手写神经网络框架AI For Beginners 之多层感知机MLP与反向传播实战 导读 本文是开源课程 AI For Beginners http教程人工智能机器学习深度学习从感知机到多层感知机在 generative-ai-for-beginners 中手写反向传播与自己的神经网络框架从感知机到多层感知机在 generative ai for beginners 中手写反向传播与自己的神经网络框架 本篇技术指南以 generative ai教程人工智能大模型从感知机到多层感知机在 Generative AI for Beginners 中从零构建神经网络框架与反向传播从感知机到多层感知机在 Generative AI for Beginners 中从零构建神经网络框架与反向传播 本文对应仓库中的 own_framework教程人工智能大模型上一篇5分钟搭好自己的Obsidian中文社区论坛一份免费开源方案下一篇ClawX 原生 ACP 聊天通道Main 侧 stdio 会话路由与 Renderer 时间线归约架构全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询