generative-ai-for-beginners 课程数据剖析:从零构建多层感知机——机器学习形式化、梯度下降与反向传播
本文以 data/own_framework.md 这份课程核心讲义为主体,系统讲解从单层感知机扩展为多层感知机(Multi-Layered Perceptron, MLP)的完整技术脉络:机器学习问题的形式化定义、损失函数选择、梯度下降与随机梯度下降(SGD)的优化机制、链式法则推导出的反向传播算法。读完后,你将能够独立搭建一个模块化的 Python 神经网络框架来构建和训练 MLP,并理解该讲义在 RAG(检索增强生成)课程中作为"被检索知识"的实际角色。
讲义定位:它为什么出现在 RAG 课程里
在 generative-ai-for-beginners 的第 15 课(RAG 与向量数据库)中,data/ 目录下的三份 Markdown 讲义——perceptron.md、own_framework.md、frameworks.md——被用作演示知识库:它们先被切块(chunking)、转换为向量嵌入(embeddings)并写入向量数据库,再供检索流程回答"什么是感知机(perceptron)"这类问题。课程 README 和 notebook-rag-vector-databases.ipynb 中可以看到三份讲义被加载进 DataFrame 的完整过程。
因此,本文一方面深入讲义本身的技术内容(MLP 与反向传播),另一方面也会说明这份文档如何被切块、嵌入、检索,从而印证课程"用自己的数据为 LLM 提供 grounding"的核心主张。
从单层感知机到多层感知机:扩展动机
讲义开篇承接前一篇 perceptron.md 的结论:单层感知机是一个线性二分类模型,只能处理线性可分的数据。own_framework.md 明确列出将模型扩展为更灵活框架的三个目标:
- 在二分类之外支持多分类(multi-class classification);
- 在分类之外支持回归问题(regression);
- 能够分离线性不可分的类别。
同时,讲义宣布将开发一个自有的 Python 模块化框架,用于构建不同的神经网络架构。这三个目标正是引入"隐藏层 + 非线性激活"的直接原因:单层的线性函数 f(x)=wx+b 无法表达非线性决策边界,而多层结构配合非线性激活函数可以逼近任意复杂的输入-输出映射。
机器学习问题的形式化
讲义"Formalization of Machine Learning"一节给出了标准的问题设定:给定带标签的训练数据集 X 与 Y,需要构建一个模型函数 f 使其预测尽可能准确,预测质量由损失函数(Loss function)ℒ 度量。讲义区分了两类常用损失:
| 问题类型 | 常用损失函数 |
|---|---|
| 回归(预测一个数值) | 绝对误差 ∑i|f(x(i))-y(i)|,或平方误差 ∑i(f(x(i))-y(i))2 |
| 分类 | 0-1 损失(本质上等价于模型的准确率 accuracy),或对数损失(logistic loss) |
对于单层感知机,f 是线性函数 f(x)=wx+b(w 为权重矩阵,x 为输入特征向量,b 为偏置向量);在不同神经网络架构中,f 可以取更复杂的形态。讲义特别强调分类场景的一个工程细节:
分类任务通常希望网络输出对应类别的概率。为了把任意数值转换为概率(例如归一化输出),常用 softmax 函数 σ,此时 f 变为 f(x)=σ(wx+b)。
在上述定义中,w 和 b 统称为参数 θ=⟨w, b⟩。给定数据集 ⟨X, Y⟩,就可以把全数据集的总误差表示为参数 θ 的函数。讲义在此给出了神经网络的训练目标:
✅ 神经网络训练的目标,就是通过调整参数 θ 来最小化误差。
这一句是整个后续内容(梯度下降、反向传播)的理论锚点:所有优化算法都在服务"最小化 ℒ(θ)"这一件事。
梯度下降优化:训练循环的数学基础
讲义接着引入函数优化的经典方法——梯度下降(gradient descent)。其思想是:计算损失函数对参数的导数(多维情形即梯度),然后朝使误差减小的方向更新参数。形式化步骤为:
- 用随机值初始化参数 w(0)、b(0);
- 重复以下步骤多次:
- w(i+1) = w(i) - η∂ℒ/∂w
- b(i+1) = b(i) - η∂ℒ/∂b
其中 η 即学习率(learning rate)——这一点可与前置讲义 perceptron.md 中的权重更新公式 w(t+1) = w(t) - η∇E(w) 相互印证,两篇讲义使用的是同一套优化范式。
讲义还澄清了工业实践与教科书定义之间的关键差异:理论上,每步优化应基于完整数据集计算损失(损失本身是所有训练样本的求和);但现实中,每次都取数据集的一个小子集——minibatch(小批量)——并用子集计算梯度。由于子集每次随机抽取,这种方法被称为随机梯度下降(SGD, stochastic gradient descent)。这条说明直接解释了现代训练循环中"按 batch 迭代"的设计由来:它不是近似的权宜之计,而是大规模数据集上唯一可行的计算方式。
多层感知机与反向传播
这是讲义最核心的章节。单层网络只能分类线性可分的数据;为构建更丰富的模型,可以把若干层网络组合起来。数学上,函数 f 的计算被拆分为多步:
- z1 = w1x + b1
- z2 = w2α(z1) + b2
- f = σ(z2)
其中 α 是非线性激活函数,σ 是 softmax 函数,参数集合为 θ=⟨w1, b1, w2, b2⟩。注意 α(z1) 这一项:正是它在层与层之间注入了非线性,使网络具备了表达线性不可分边界的能力。
梯度下降算法本身不变,但多层结构让梯度计算变难了。利用链式求导法则(chain rule),讲义给出两层网络的完整推导:
- ∂ℒ/∂w2 = (∂ℒ/∂σ)(∂σ/∂z2)(∂z2/∂w2)
- ∂ℒ/∂w1 = (∂ℒ/∂σ)(∂σ/∂z2)(∂z2/∂α)(∂α/∂z1)(∂z1/∂w1)
✅ 链式求导法则用于计算损失函数对各个参数的导数。
讲义点出了反向传播(backpropagation,'backprop')得以高效存在的结构原因:上述所有表达式的最左侧因子完全相同。这意味着可以从损失函数出发,"反向"沿着计算图逐层传递梯度,每一层只需计算一次上游梯度,就能服务该层所有参数的更新——计算量与层数线性相关,而不是按参数组合爆炸。这正是"反向传播"名称的由来:从 loss 出发,沿计算图向后传播。讲义同时注明"反向传播将在配套 notebook 中更深入地展开",其挑战(Challenge)部分正是要求读者亲手实现一个构建和训练多层感知机的自有框架,通过它看清现代神经网络的内部运作机制。
讲义在 RAG 流程中的落地:从 Markdown 到检索回答
讲义的技术内容并非孤立存在——在本仓库中,它正是 RAG 应用的知识来源。结合 15 课 README 与 notebook-rag-vector-databases.ipynb,可以把 own_framework.md 的生命周期拆解为四步:
1. 切块(Chunking)。 讲义全文被按长度切分。README 中给出了课程使用的切块函数(定义于 notebook 的 split_text(text, max_length, min_length) 单元格,约第 293 行),按词累积、以最大/最小长度约束生成 chunk。讲义中每一段独立的数学定义(损失函数、梯度下降公式、链式法则表达式)因此成为独立的检索单元。
2. 嵌入(Embedding)。 notebook 中的 create_embeddings(text, model=None)(约第 1458 行)把 chunk 文本转换为向量,存入同时包含 chunks、path、embeddings 列的 DataFrame——path 列的值即为 data/own_framework.md 这样的仓库相对路径,这是检索结果能溯源到具体文档的依据。
3. 检索(Retrieval)。 以本地向量索引为例,README 展示了用 scikit-learn 建立球树近邻索引的完整代码:
from sklearn.neighbors import NearestNeighbors
embeddings = flattened_df['embeddings'].to_list()
# Create the search index
nbrs = NearestNeighbors(n_neighbors=5, algorithm='ball_tree').fit(embeddings)
# To query the index, you can use the kneighbors method
distances, indices = nbrs.kneighbors(embeddings)
4. 生成(Augmented Generation)。 notebook 的最终单元格(约第 2873 行)与 README 的 chatbot 代码一致:以"what is a perceptron?"为查询,将问题嵌入为向量,用 nbrs.kneighbors([query_vector]) 检索最相似的文档块,把检索到的 chunk 与用户输入拼接后发给 LLM(README 示例使用 gpt-4o-mini,temperature=0.7、max_output_tokens=800)。检索命中的正是 data/perceptron.md 与 data/own_framework.md 中的段落——notebook 的实际运行输出可以看到,模型回答里"perceptron 用于二分类、加权输入之和经阶跃函数决定输出"等细节,都源自这两份讲义的被检索内容。
这个闭环恰好呼应了讲义自身的内容层级:perceptron.md 讲单层线性模型,own_framework.md 讲多层非线性模型(本文主体),frameworks.md 再讲 TensorFlow/PyTorch 这类提供张量运算与自动求导(自动反向传播)的工业框架——三份文档构成一条从"手写 backprop"到"使用框架自动微分"的完整学习链。
练习与作业:把框架用起来
讲义按课程惯例给出了三个实践出口:
- Challenge:进入配套 notebook,自行实现一个构建和训练 MLP 的框架,从细节层面观察现代神经网络如何运作;
- Review & Self Study:反向传播是 AI/ML 中的通用算法,值得深入自学;
- Assignment:用本课构建的框架解决 MNIST 手写数字分类问题——这是对"多分类"与"非线性激活"能力最直接的检验,也与前置讲义中"用感知机区分两个手写数字"的作业形成递进。
小结
data/own_framework.md 用不到百行的篇幅完成了三件事:把神经网络训练形式化为"以参数 θ 为变量最小化损失函数"的优化问题,把训练循环锚定在梯度下降/SGD 的 minibatch 机制上,并借链式法则推导出反向传播的可行性与高效性。在 generative-ai-for-beginners 仓库中,它既是一份可以独立读懂的 MLP 入门讲义,又是 RAG 课程演示"私有文档 → 切块 → 嵌入 → 检索 → grounding 生成"全链路的核心语料,两个角色互相印证了课程"用检索增强让 LLM 回答有据可依"的主线。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00