- 教程
- 人工智能
- 机器学习
- 深度学习
【免费下载链接】AI-For-Beginners
12 Weeks, 24 Lessons, AI for All!
导读
本文基于 AI-For-Beginners 课程第三部分《神经网络导论》(对应 lessons/3-NeuralNetworks/README.md)整理而成。该部分是整个课程从符号 AI 迈向现代深度学习的关键转折点,回答了"大脑的数学化模型究竟是什么、如何用数据训练它"这一核心问题。读完本文,你将理解机器学习与神经网络的基本形式化定义、单个神经元与感知机的数学模型与训练算法(梯度下降)、多层感知机与反向传播的原理,以及 PyTorch 与 TensorFlow/Keras 两大主流框架的分工,并掌握识别与应对过拟合的实战技巧。
神经网络:大脑的数学化模型
在课程前面的导论中,我们已经讨论过实现智能的路径之一——训练一个计算机模型(即"人工大脑")。自 20 世纪中叶以来,研究者尝试了各种数学模型,直到近年来这一方向取得了巨大成功。这些大脑的数学模型就被称为神经网络(Neural Networks)。
神经网络有时也被称为人工神经网络(Artificial Neural Networks,ANN),以明确我们讨论的是数学模型,而非真实的神经元网络。
从生物学的角度看,我们的大脑由神经细胞(神经元)构成,每个神经元拥有多个"输入"(树突)和单个"输出"(轴突)。树突与轴突都能传导电信号,而它们之间的连接——突触——具有可变的导电性,这种导电性受神经递质调节。这正是神经网络模型的生物学灵感来源:
神经元的数学模型
最简单的神经元数学模型包含若干输入 X₁, …, XN、一个输出 Y,以及一组权重 W₁, …, WN,输出按下式计算:
Y = f(Σᵢ XᵢWᵢ)
其中 f 是某种非线性激活函数。
早期神经元模型由 Warren McCulloch 与 Walter Pitts 在 1943 年的经典论文A logical calculus of the ideas immanent in nervous activity中提出;Donald Hebb 在其著作The Organization of Behavior: A Neuropsychological Theory中则提出了这些网络如何被训练的思路(即"赫布学习"的雏形)。
机器学习:神经网络的学科母体
神经网络是更大学科——机器学习(Machine Learning)——的一部分。机器学习的核心目标是用数据训练计算机模型,使其能够解决问题。机器学习是人工智能的重要组成部分,但本课程并不覆盖经典机器学习(经典 ML 可参见课程姊妹项目 Machine Learning for Beginners)。
数据集的形式化表示
在机器学习中,我们假设存在一组样本数据集X及对应的输出值Y。样本通常是 N 维向量,由特征(features)组成;输出则被称为标签(labels)。
- 当输入与输出以张量表示时,输入数据集是一个 M×N 矩阵,其中 M 是样本数,N 是特征数;
- 输出标签 Y 是长度为 M 的向量。
两类最常见的机器学习问题
课程聚焦以下两类问题:
- 分类(Classification):将输入对象划分到两个或多个类别中;
- 回归(Regression):为每个输入样本预测一个数值。
本课程的后续内容只关注神经网络模型这一类解决方案。
本节课程地图:四步走
本节(第 3 部分)围绕以下四个主题展开,层层递进:
- 感知机(Perceptron)——最早的二分类神经网络模型之一;
- 多层网络(Multi-Layered Perceptron)——配合 OwnFramework.ipynb 从零搭建自己的神经网络框架;
- 神经网络框架(Frameworks)——配套 PyTorch 入门笔记本 与 Keras/TensorFlow 入门笔记本;
- 过拟合(Overfitting)——深度学习实战中必须掌握的核心概念。
感知机:最早的二分类神经网络
感知机是历史上最早的神经网络实现之一。1957 年,Cornell Aeronautical Laboratory 的 Frank Rosenblatt 实现了名为 "Mark-1" 的硬件装置,用于识别三角形、正方形、圆形等基本几何图形。
- 输入图像由 20×20 的光电池阵列表示,因此网络有400 个输入和1 个二值输出;
- 这个简单网络只包含一个神经元,也被称为阈值逻辑单元(threshold logic unit);
- 训练阶段,网络权重扮演着"电位器"的角色,需要人工调节。
感知机模型与阶跃激活函数
假设模型有 N 个特征,输入向量大小为 N。感知机是二分类模型:对每个输入向量 x,其输出为 +1 或 -1(取决于类别)。输出计算公式为:
y(x) = f(wᵀx)
其中 f 是阶跃激活函数:
f(x) = +1 当 x ≥ 0;f(x) = -1 当 x < 0。
一般线性模型还应包含偏置项 b(即 y = f(wᵀx + b))。在 Perceptron.ipynb 中,代码通过给输入特征追加一个恒等于 1 的额外维度来"吸收"偏置,从而简化模型——这是实现中的关键技巧。
训练感知机:感知机准则与梯度下降
训练感知机就是要找到一个权重向量 w,使大多数样本被正确分类,即误差最小。该误差 E 由感知机准则(perceptron criterion)定义:
E(w) = -Σ wᵀxᵢtᵢ
其中:
- 求和只对被错误分类的训练样本 i 进行;
- xᵢ 是输入数据,tᵢ 对负例与正例分别取 -1 与 +1。
该准则被看作权重 w 的函数,我们的目标是最小化它。通常采用梯度下降(gradient descent)方法:先取初始权重 w⁽⁰⁾,然后每一步按下式更新权重:
w⁽ᵗ⁺¹⁾ = w⁽ᵗ⁾ - η∇E(w)
这里 η 是学习率(learning rate),∇E(w) 是 E 的梯度。计算梯度后可以得到更新公式:
w⁽ᵗ⁺¹⁾ = w⁽ᵗ⁾ + Σηxᵢtᵢ
Python 训练算法(仓库真实代码)
在 Perceptron.ipynb 中,训练算法实现如下(与原文档示例一致,并带注释说明):
def train(positive_examples, negative_examples, num_iterations=100, learning_rate=0.01): num_dims = positive_examples.shape[1] # 初始化权重:为简单起见用 0,随机初始化也是好主意 weights = np.zeros((num_dims, 1)) pos_count = positive_examples.shape[0] neg_count = negative_examples.shape[0] report_frequency = 10 for i in range(num_iterations): # 每次迭代随机挑选一个正例和一个负例 pos = random.choice(positive_examples) neg = random.choice(negative_examples) z = np.dot(pos, weights) if z < 0: # 正例被误分类为负例 weights = weights + learning_rate * pos.reshape(weights.shape) z = np.dot(neg, weights) if z >= 0: # 负例被误分类为正例 weights = weights - learning_rate * neg.reshape(weights.shape) # 周期性打印全体样本上的当前准确率 if i % report_frequency == 0: pos_out = np.dot(positive_examples, weights) neg_out = np.dot(negative_examples, weights) pos_correct = (pos_out >= 0).sum() / float(pos_count) neg_correct = (neg_out < 0).sum() / float(neg_count) print("Iteration={}, pos correct={}, neg correct={}".format(i, pos_correct, neg_correct)) return weights该代码直接实现了梯度下降更新公式 w⁽ᵗ⁺¹⁾ = w⁽ᵗ⁾ + ηxₙtₙ。在仓库示例输出中可以看到,初始准确率约 50%,经过若干轮迭代后很快提升到接近 90%。
学习率:关键超参数
learning_rate参数(默认 0.01)控制每一步训练中权重的调整幅度:
- 较大的学习率(如 1.0)使感知机学习更快,但可能越过最优解;
- 较小的学习率(如 0.001)收敛更慢,但可能更精确地收敛。
Perceptron.ipynb 还提供了学习率对比实验(learning_rates = [0.001, 0.01, 0.1, 1.0]四宫格决策边界图)以及基于ipywidgets的交互式滑块,可以直观观察不同学习率下决策边界与最终权重值(w₀、w₁、偏置)的变化。
评估与扩展
- 测试集评估:训练完成后,将测试数据同样补一维,乘上权重矩阵,检查结果符号是否与标签(+1/-1)一致,求和后除以样本数即得准确率;
- 动手实验:感知机应用与玩具问题、真实问题演练见 Perceptron.ipynb;进一步的多分类任务(完整的手写数字识别)见 lab 说明 与 PerceptronMultiClass.ipynb。
多层感知机:从线性到非线性
单层感知机只能处理线性可分的数据。在 04-OwnFramework 一节中,模型被扩展为更灵活的框架,实现三个目标:
- 在二分类之外支持多分类;
- 在分类之外支持回归问题;
- 分离线性不可分的类别。
同时,课程将用 Python 开发一个模块化框架,用于构建不同的神经网络架构。
机器学习问题的形式化
- 训练数据集X带标签Y,需构建模型 f 做出最准确的预测;
- 预测质量由损失函数ℒ 衡量。
常用损失函数:
- 回归(预测数值):绝对误差Σᵢ|f(x⁽ⁱ⁾)-y⁽ⁱ⁾|,或平方误差Σᵢ(f(x⁽ⁱ⁾)-y⁽ⁱ⁾)²;
- 分类:0-1 损失(本质等同于模型准确率),或逻辑损失(logistic loss)。
对于单层感知机,f 是线性函数 f(x)=wx+b(w 为权重矩阵,x 为输入特征向量,b 为偏置向量);不同网络架构下 f 可更复杂。
分类问题中通常希望网络输出对应类别的概率。为把任意数值转换为概率(归一化输出),常用softmax函数 σ,此时 f(x)=σ(wx+b)。
w 与 b 合称为参数θ=⟨w,b⟩。给定数据集 ⟨X,Y⟩,整体误差可写成参数 θ 的函数。神经网络训练的目标就是通过改变参数 θ 使误差最小化。
梯度下降优化与随机梯度下降(SGD)
梯度下降是著名的函数优化方法:计算损失函数对参数的导数(多维情况下称为梯度),并按使误差减小的方向调整参数:
- 用随机值初始化参数 w⁽⁰⁾, b⁽⁰⁾;
- 多次重复更新:
- w⁽ⁱ⁺¹⁾ = w⁽ⁱ⁾ - η∂ℒ/∂w
- b⁽ⁱ⁺¹⁾ = b⁽ⁱ⁾ - η∂ℒ/∂b
训练时,优化步骤本应按整个数据集计算(损失是对全部训练样本求和得到的),但在实际中我们取数据集的小部分——小批量(minibatches)——基于数据子集计算梯度。由于每次子集随机抽取,这种方法称为随机梯度下降(Stochastic Gradient Descent,SGD)。
反向传播:多层网络的训练方法
单层网络只能分类线性可分的类别。组合多层网络后,函数 f 形式更复杂,分多步计算:
- z₁ = w₁x + b₁
- z₂ = w₂α(z₁) + b₂
- f = σ(z₂)
其中 α 是非线性激活函数,σ 是 softmax 函数,参数 θ = ⟨w₁, b₁, w₂, b₂⟩。
梯度下降算法保持不变,但梯度计算更困难。借助链式求导法则可计算:
- ∂ℒ/∂w₂ = (∂ℒ/∂σ)(∂σ/∂z₂)(∂z₂/∂w₂)
- ∂ℒ/∂w₁ = (∂ℒ/∂σ)(∂σ/∂z₂)(∂z₂/∂α)(∂α/∂z₁)(∂z₁/∂w₁)
这些表达式最左侧的部分相同,因此可以从损失函数出发,沿计算图"向后"高效地逐层计算导数。这种训练多层感知机的方法因此被称为反向传播(backpropagation,简称 backprop)。
仓库中的自研框架实现
OwnFramework.ipynb 从零实现了完整的自研框架,关键组件包括:
- 各层
forward方法:定义前向计算(如net.forward(train_x[0:10])); - Softmax 层:σ(z_c) = e^(z_c)/Σⱼe^(z_j),用于把任意输出值归一化为概率;
- CrossEntropyLoss 类(交叉熵损失):
forward(p, y)中通过p_of_y = p[np.arange(len(y)), y]取正确类概率,再取-log_prob.mean()对全部样本求均值。仓库注释特别强调:损失函数必须对整个数据集(或小批量)返回一个数值,因此需要.mean()聚合; backward方法:在每个层内手工编写导数计算,实现反向传播(例如dlog_softmax[np.arange(len(self.y)), self.y] -= 1.0/len(self.y)的损失反向传播实现);- 训练循环:
train_epoch(net, train_x, train_labels, loss=CrossEntropyLoss(), batch_size=4, lr=0.1),采用小批量 SGD。
将各层组合起来便构成计算图(computational graph),例如z = net.forward(train_x[0:10]) → p = softmax.forward(z) → loss = cross_ent_loss.forward(p, train_labels[0:10])。
实验任务:使用本课自建框架完成 MNIST 手写数字分类,见 lab 说明 与 MyFW_MNIST.ipynb(仓库 data/mnist.pkl.gz 即提供了 MNIST 数据)。
神经网络框架:PyTorch 与 TensorFlow/Keras
自研框架需要手工为每个表达式编写导数,这显然不可持续。要高效训练神经网络,框架必须提供两个能力:
- 张量运算:乘法、加法,以及 sigmoid、softmax 等函数计算;
- 自动梯度计算:对所有表达式求梯度,以执行梯度下降优化。
此外,深度网络训练计算量巨大,框架还应支持在GPU(或 TPU 等专用计算单元)上并行计算。
术语 "parallelize"(并行化)指把计算分布到多个设备上执行。
当前最流行的两个神经网络框架是TensorFlow与PyTorch,它们都提供底层 API 与高层 API:
| 层级 | TensorFlow | PyTorch |
|---|---|---|
| 低层 API | TensorFlow | PyTorch |
| 高层 API | Keras | PyTorch Lightning |
- 低层 API:允许构建所谓的计算图——定义给定输入参数下如何计算输出(通常是损失函数),有 GPU 时可将计算图推送到 GPU 上执行;同时提供对计算图求导、计算梯度的函数,用于优化模型参数。低层 API 对训练过程控制力更强,在研究新架构时大量使用;
- 高层 API:把神经网络视为层的序列(sequence of layers),极大简化了常见网络的构建;训练模型通常只需准备好数据,然后调用
fit函数即可。
两种 API 可以混用:例如用低层 API 开发自定义网络层,再将其嵌入高层 API 构建并训练的大网络中;或用高层 API 将网络定义为层序列,再用自研的低层训练循环做优化。两者基于相同的基本概念,设计上可以良好协同。
课程中大部分内容同时提供 PyTorch 与 TensorFlow 两个版本,可选择偏好框架并只浏览对应笔记本;建议从低层 API 和张量入手理解原理,赶时间的话也可以直接跳至高层的 API 笔记本。
仓库配套实践笔记本
| 层级 | TensorFlow | PyTorch |
|---|---|---|
| 低层 API | IntroKerasTF.ipynb | IntroPyTorch.ipynb |
| 高层 API | IntroKeras.ipynb | PyTorch Lightning |
以 IntroPyTorch.ipynb 为例,仓库实际展示了:
- 张量基础:
torch.tensor创建、torch.randn(size=(10,3))随机张量、torch.exp、torch.sum等运算,以及add_原地操作与requires_grad=True; - 自动微分(autograd):对
c = torch.mean(torch.sqrt(torch.square(a) + torch.square(b)))这类复合表达式调用backward()自动计算梯度,验证了"对任意可定义表达式求梯度"的框架能力; - 线性回归训练:
w = torch.tensor([100.0], requires_grad=True),前向torch.matmul(x, w) + b,损失torch.mean(torch.square(labels - predictions)),并支持device = 'cuda' if torch.cuda.is_available() else 'cpu'的设备切换; - 数据集管理:
torch.utils.data.TensorDataset+DataLoader(dataset, batch_size=16)的小批量数据加载机制; - 二分类模型:自定义
torch.nn.Module子类,配合torch.nn.functional.binary_cross_entropy_with_logits训练。
实验任务:使用 PyTorch 或 TensorFlow,用单层与多层全连接网络解决两个分类问题,见 lab 说明 与 LabFrameworks.ipynb。
过拟合:训练深度学习模型必须避开的陷阱
过拟合是机器学习中极其重要的概念。考虑用模型去逼近 5 个数据点(下图中 x 标记)的问题:
| 线性模型(2 个参数) | 非线性模型(7 个参数) |
|---|---|
| 训练误差 = 5.3 | 训练误差 = 0 |
| 验证误差 = 5.1 | 验证误差 = 20 |
- 左侧:直线近似效果好。因为参数数量合适,模型正确把握了数据点分布背后的规律;
- 右侧:模型过于强大。仅有 5 个点却有 7 个参数,模型可以调整得穿过所有点,使训练误差为 0,但这也使它无法理解数据背后的真实模式,导致验证误差极高。
因此,在模型的丰富度(参数数量)与训练样本数量之间取得正确平衡至关重要。
过拟合产生的原因
- 训练数据不足;
- 模型过于强大;
- 输入数据噪声过多。
如何检测过拟合
从上面的对比可以看出,过拟合可以通过"训练误差极低 + 验证误差很高"来识别。通常训练过程中训练误差与验证误差都会先下降,但到某个节点后验证误差可能停止下降并开始上升——这就是过拟合的信号,提示我们应在此处停止训练(或至少保存一份模型快照)。
如何预防过拟合
发现过拟合时可采取以下措施之一:
- 增加训练数据量;
- 降低模型复杂度;
- 使用正则化技术,例如 Dropout(课程后续章节会介绍)。
过拟合与偏差-方差权衡
过拟合实际上是统计学中更普遍问题——偏差-方差权衡(Bias-Variance Tradeoff)的一个特例。模型误差可分解为两类:
- 偏差误差(Bias error):算法未能正确捕获训练数据之间的关系,可能源于模型能力不足(欠拟合,underfitting);
- 方差误差(Variance error):模型拟合了输入数据中的噪声而非有意义的关系(过拟合)。
训练过程中,偏差误差下降(模型逐渐学会逼近数据),方差误差上升。因此,在恰当的时机停止训练至关重要——无论是手动(检测到过拟合时)还是自动(引入正则化)——以防止过拟合。
结语与实践路径
本节从"神经网络是大脑的数学模型"这一基本思想出发,完成了从单层感知机、多层感知机与反向传播、到现代深度学习框架的完整知识闭环:
- 阅读本节主文档 README 建立整体认知;
- 用 Perceptron.ipynb 动手实现并可视化感知机的训练与决策边界,再完成 多分类 lab;
- 跟随 OwnFramework.ipynb 从零构建自己的神经网络框架,并在 MyFW_MNIST.ipynb 上验证 MNIST 分类;
- 在 PyTorch 与 TensorFlow/Keras 笔记本中体验现代框架的张量运算、自动微分与小批量训练,完成 Frameworks lab;
- 时刻警惕过拟合,善用验证集监控与正则化手段。
这一部分为后续计算机视觉(卷积网络)、NLP(RNN 与 Transformer)等章节奠定了统一的神经网络理论基础——理解"计算图 + 梯度下降 + 反向传播"这一三元组,你就掌握了现代深度学习最核心的心智模型。
- 教程
- 人工智能
- 机器学习
- 深度学习
【免费下载链接】AI-For-Beginners
12 Weeks, 24 Lessons, AI for All!
相关推荐
AI-For-Beginners 神经网络入门:从感知机到 PyTorch 的完整学习路线
AI For Beginners 神经网络入门:从感知机到 PyTorch 的完整学习路线 本篇文章基于 AI For Beginners 开源课程中"神经网络
教程人工智能机器学习深度学习AI for Beginners 神经网络入门:从感知机到现代深度学习框架
AI for Beginners 神经网络入门:从感知机到现代深度学习框架 导读 本文是 AI for Beginners 课程第 3 大章《神经网络(Neur
教程人工智能机器学习深度学习AI-For-Beginners 神经网络入门指南:从感知机到现代深度学习框架
AI For Beginners 神经网络入门指南:从感知机到现代深度学习框架 本指南以 AI For Beginners 课程第三部分"神经网络"( less
教程人工智能机器学习深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考