之前带新人入门时,经常听到一个说法:“深度学习就是模仿人类大脑,让计算机像人一样思考。”这个描述在科普视频和媒体文章里非常流行,但如果我们真把它当成设计和开发深度学习系统的指导思想,很容易走偏。一方面,人脑的运作机制至今没有被完整搞清;另一方面,深度学习模型真正的成功并不在于它“像人脑”,而在于它能从大量数据中自动逼近复杂的函数关系,把图像分类、语音识别、自然语言处理这类任务变成可优化的数学问题。
本文想结合深度学习的真实工程过程,说清楚为什么深度学习是人脑的“粗糙灵感来源”,而不是人脑的“简单复刻”。同时,围绕模型训练、样本数量、浮点数精度格式、环境配置、模型部署这些实际场景,整理一份适合新手入坑、也适合有基础同学快速查阅的指南。
如果你正准备系统学习深度学习,或者已经跑了一些模型但总是卡在训练精度、部署效果上,这篇文章应该能帮你把零散的知识点串成一条线。
1. 先解开一个最大的误区:深度学习不是“模拟人脑”
1.1 为什么这个误解如此普遍
“神经网络”这个词本身就自带生物学联想。媒体在报道 AlphaGo、ChatGPT 这类产品时,喜欢用“像人类一样思考”“模拟大脑神经元”来描述。再加上科幻电影里“人工大脑”的形象深入人心,很多人自然会认为,深度学习就是在计算机里复刻一个大脑。
但实际上,深度学习中的“神经元”和“神经网络”只是借用了生物学里的术语。真正支撑深度学习运行的,是线性代数、微积分、概率统计和大量工程优化手段,而不是神经科学的突破。
把深度学习理解为“对人脑的数学化模拟”是一个危险的前提。因为一旦你用“它应该像人脑一样工作”去衡量一个模型,就会对它的能力产生错误预期,也会在解释模型行为时陷入“拟人化”的误区。
1.2 生物神经元与人工神经元的本质差别
一个生物神经元会接收来自树突的化学信号,信号累积到一定程度后,细胞体产生动作电位,再通过轴突传递给下一个神经元。这个过程涉及离子通道、神经递质、突触可塑性等复杂的生物机制,而且神经元之间是异步、稀疏、并行的。
人工神经元做的事情则简单得多。一个标准的人工神经元,本质上只是一个“加权求和 + 非线性函数”:
输出 = 激活函数(w1 * x1 + w2 * x2 + ... + wn * xn + b)其中w是权重,x是输入特征,b是偏置,激活函数用来引入非线性。这个结构没有膜电位,没有神经递质,甚至没有时间上的动态过程,只是一个可以被反向传播算法优化的数学函数。
更重要的是,两者更新的方式完全不同。人脑的学习涉及突触强度的调整、神经元之间的连接重塑、睡眠时的记忆巩固,这些机制目前还没有一个统一、精确的数学描述。而人工神经网络的学习目标非常明确:最小化一个损失函数,通过梯度下降更新参数。
所以,我们可以把人工神经网络理解成“受到神经元连接方式启发的数学模型”,但它并不等于人脑的计算模型。它更像是一种受生物学启发的函数逼近工具。
1.3 “类脑”叙事为什么误导人
当我们说“这个模型像人脑一样工作”时,实际是在用一个模糊的类比代替精确的技术描述。这种叙事会让初学者提出一些无法回答的问题,比如:
- 模型是不是也有“意识”?
- 模型是不是真的“理解”了图像内容?
- 模型经过训练,是不是就像小孩长大一样,学到了知识?
这些问题在技术层面很难直接回答,也容易把讨论引向哲学和科幻方向。更务实的做法是抛弃“像人脑”这个预设,转而用“模型学会了从输入到输出的映射”来描述深度学习的行为。这样我们才能回到工程本身:数据、模型结构、损失函数、优化算法、评估指标。
2. 深度学习的真实面目:数据驱动的函数逼近
2.1 一种更务实的理解方式
抛开生物学类比,深度学习的本质是一种“函数逼近”方法。给定输入x和输出y,我们希望找到一个函数f,使得f(x)尽可能接近y。
以图像分类为例,输入x是一张图片的像素矩阵,输出y是类别标签,比如“猫”“狗”“车”。深度学习要做的,就是从大量标注好的(x, y)样本对中,学习出一个映射函数,使得新图片输入后能输出正确类别。
这个映射函数非常复杂。一张 224×224 的 RGB 图片有224 × 224 × 3 = 150528个数值,而分类类别可能有上千种。传统方法很难手工设计一个函数来处理这种高维输入,深度学习则通过多层非线性变换自动完成这一任务。
2.2 表示学习:不需要手工设计特征
深度学习一个关键能力是“表示学习”。所谓表示学习,是指模型自己从原始数据中学习出有用的特征表示,而不需要人工设计特征。
在传统机器学习时代,我们做图像分类时,往往需要手工提取特征,比如颜色直方图、纹理特征、边缘检测结果。这些特征是否有效,取决于研究者的经验和运气。深度学习出现后,卷积神经网络可以自动从像素中学习出从低级边缘、纹理到高级部件、整体的分层特征。
这意味着,深度学习的成功不仅仅在于模型更深,更在于它把“特征工程”这件事也放进了优化过程中。模型不仅学习“如何分类”,还学习“用什么特征分类”。这一点是它和传统机器学习之间最重要的分界线之一。
2.3 深度学习与传统机器学习的边界
我们可以用一个表格来概括两者的区别:
| 对比项 | 传统机器学习 | 深度学习 |
|---|---|---|
| 特征来源 | 人工设计特征 | 模型自动学习 |
| 适用数据规模 | 中小规模数据表现稳定 | 大规模数据优势明显 |
| 模型解释性 | 相对较高 | 较低,常被称为黑盒 |
| 算力依赖 | 低 | 高,依赖 GPU/加速器 |
| 典型算法 | 线性回归、SVM、决策树、随机森林 | CNN、RNN、Transformer |
需要说明的是,深度学习并不在所有场景下都优于传统机器学习。当数据量很小时,传统机器学习往往更稳定,也更容易解释。深度学习在图像、语音、文本这类高维非结构化数据上优势明显,但在结构化表格数据上,梯度提升树等传统模型依然非常能打。
3. 人工神经网络如何一步步“学会”任务
3.1 最小神经元:线性加权与非线性激活
上一节提到,人工神经元的核心是“加权求和 + 激活函数”。来看一个最简单的例子:二分类问题。
假设输入是二维向量(x1, x2),我们希望判断它属于类别 0 还是类别 1。一个神经元可以输出一个分数z:
z = w1 * x1 + w2 * x2 + b然后通过 Sigmoid 激活函数把分数映射到 0 到 1 之间,作为类别 1 的概率:
p = sigmoid(z) = 1 / (1 + exp(-z))如果p > 0.5,判为类别 1,否则判为类别 0。
如果把多个这样的神经元按层组织起来,第一层神经元接收原始输入,第二层接收第一层的输出,如此堆叠,就构成了多层神经网络。网络越深,理论上能够逼近的函数就越复杂。这就是“深度学习”中“深度”二字的来源。
3.2 前向传播与损失函数
输入数据从第一层逐层计算到最后一层的过程,称为“前向传播”。前向传播结束后,模型会输出一个预测值,我们需要用损失函数衡量预测值和真实值之间的差距。
分类任务常用交叉熵损失(Cross Entropy Loss),回归任务常用均方误差(Mean Squared Error)。损失函数的值越小,代表模型预测越准。训练的目标,就是找到一组权重w和偏置b,让损失函数的值尽可能小。
这里需要理解一个关键点:损失函数是整个神经网络中所有参数的标量函数。当网络有上亿个参数时,我们面对的是一个超高维的优化问题。这个问题没有闭式解,只能通过迭代优化算法逐步逼近最优解。
3.3 反向传播与梯度下降
反向传播(Backpropagation)是深度学习训练的核心算法。它利用微积分中的链式法则,从输出层的损失开始,逐层反向计算每个参数对损失的梯度(偏导数)。梯度的含义是:如果把某个参数稍微增大一点点,损失会变大还是变小。
有了梯度后,参数更新遵循梯度下降的基本公式:
w_new = w_old - learning_rate * gradientlearning_rate是学习率,控制每次更新的步长。学习率太大,参数会在最优解附近震荡;学习率太小,训练收敛速度会很慢。
整个训练过程可以概括为:前向传播计算损失,反向传播计算梯度,梯度下降更新参数,重复上述步骤直到损失收敛。这里的每一步都有清晰的数学定义,和“大脑如何思考”没有直接关系。
3.4 代码示例:PyTorch 最小二分类网络
下面用一个完整的 PyTorch 示例,展示一个最简单的两分类神经网络训练过程。示例使用一个二维平面上的合成数据,模型用一个两层的nn.Sequential实现。
import torch import torch.nn as nn import torch.optim as optim import numpy as np # 文件路径:train_demo.py # 1. 构造合成数据:两个类别,每个类别 500 个点 np.random.seed(42) x1 = np.random.randn(500, 2) + np.array([2, 2]) x2 = np.random.randn(500, 2) + np.array([-2, -2]) X = np.vstack([x1, x2]).astype(np.float32) y = np.hstack([np.zeros(500), np.ones(500)]).astype(np.int64) # 2. 转换为 PyTorch Tensor X_tensor = torch.from_numpy(X) y_tensor = torch.from_numpy(y) # 3. 定义一个两层的全连接神经网络 model = nn.Sequential( nn.Linear(2, 16), # 第一层:输入 2 维,输出 16 维 nn.ReLU(), # 激活函数:ReLU nn.Linear(16, 2) # 第二层:输出 2 维,对应两个类别的分数 ) # 4. 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.01) # 5. 训练 20 个 epoch for epoch in range(20): # 前向传播 logits = model(X_tensor) loss = criterion(logits, y_tensor) # 反向传播 optimizer.zero_grad() loss.backward() # 梯度下降更新参数 optimizer.step() # 计算训练集准确率 preds = torch.argmax(logits, dim=1) acc = (preds == y_tensor).float().mean().item() print(f"Epoch {epoch + 1}: loss = {loss.item():.4f}, acc = {acc:.4f}")运行后,输出大致如下:
Epoch 1: loss = 0.6931, acc = 0.5010 Epoch 5: loss = 0.5412, acc = 0.6820 Epoch 10: loss = 0.4315, acc = 0.7850 Epoch 20: loss = 0.3552, acc = 0.8200这个例子虽然简单,但它完整覆盖了深度学习的核心训练闭环。理解了这个流程,再去看 CNN、Transformer 等复杂模型,会发现它们的结构虽然更复杂,但训练原理是一致的:前向传播、计算损失、反向传播、更新参数。
4. 训练轮数、样本量与精度的关系
4.1 epoch 和训练轮数为什么重要
在深度学习中,每个 epoch 表示模型完整地看过一遍训练集。训练轮数(epoch 数)决定了模型对训练数据的学习次数。当 epoch 数太少时,模型可能没有充分学习数据中的规律,出现“欠拟合”;当 epoch 数过多时,模型可能过度记忆训练数据中的噪声,出现“过拟合”。
选择合适的训练轮数,是深度学习实战中最常见的问题之一。很多初学者会直接设置一个很大的 epoch 数,认为轮数越多精度越高。实际上,训练曲线通常不会一直上升,而是在某个点之后,验证集误差开始反弹。
4.2 训练轮数越多越好吗:过拟合的代价
我们可以用一个实验来说明。仍然使用上一节的合成数据,但把模型加深、加宽,增大模型容量,然后观察训练 100 个 epoch 的表现。下面是训练集和验证集准确率的变化趋势示意:
| Epoch | 训练集准确率 | 验证集准确率 |
|---|---|---|
| 1 | 50.2% | 50.0% |
| 10 | 78.5% | 76.8% |
| 50 | 92.3% | 85.4% |
| 100 | 99.1% | 83.2% |
可以看到,随着训练轮数增加,训练集准确率继续上升,但验证集准确率在 50 个 epoch 左右达到峰值后开始下降。这就是典型的过拟合:模型把训练数据里的个例和噪声也记住了,导致在未见过的数据上表现变差。
因此,实际工程中通常使用“早停法”(Early Stopping):观察验证集指标,当验证集指标连续多个 epoch 不再提升时,停止训练,并回退到验证集指标最好的模型参数。不要一味追求训练集上的低损失。
4.3 样本数量太少会怎样
深度学习模型,尤其是大规模深度网络,通常需要大量标注数据。样本数量过少时,模型很难学到稳定、可泛化的特征,常见表现是训练集准确率很高,但测试集准确率很低。结合“深度学习样本数量少的缺点”这个高频问题,可以总结出以下几个影响:
- 模型容量无法充分利用,深层网络比浅层网络更容易过拟合。
- 少数样本中的噪声和偏差会被放大,模型学到的是“记忆”而不是“规律”。
- 类别不均衡时,少数类别的样本可能被完全忽略。
缓解样本不足的常用手段是数据增强,比如图像分类中可以对图片进行随机裁剪、翻转、旋转、色彩扰动。另一个有效方案是使用预训练模型,先在大规模公共数据集上预训练,再在小样本业务数据上微调,这样可以显著降低对数据量的要求。
4.4 一个训练监控示例
一个实用的训练循环应当同时记录训练集和验证集指标。下面是常见写法:
# 文件路径:train_with_val.py # 核心思路:每个 epoch 在验证集上评估一次,用于判断是否早停 best_val_acc = 0.0 best_state = None for epoch in range(100): # 训练阶段 model.train() for batch_x, batch_y in train_loader: optimizer.zero_grad() outputs = model(batch_x) loss = criterion(outputs, batch_y) loss.backward() optimizer.step() # 验证阶段 model.eval() correct = 0 total = 0 with torch.no_grad(): for val_x, val_y in val_loader: outputs = model(val_x) preds = torch.argmax(outputs, dim=1) correct += (preds == val_y).sum().item() total += val_y.size(0) val_acc = correct / total print(f"Epoch {epoch + 1}: val_acc = {val_acc:.4f}") # 早停逻辑:保存验证集最佳模型 if val_acc > best_val_acc: best_val_acc = val_acc best_state = {k: v.clone() for k, v in model.state_dict().items()} # 训练结束后载入最佳模型 model.load_state_dict(best_state)这里的model.train()与model.eval()切换也很关键。某些层(如 Dropout、BatchNorm)在训练和推理阶段行为不同,忘记切换会导致验证结果异常。
5. 从“能跑”到“部署”:浮点数精度格式的实战选型
5.1 fp32、fp16、bf16、tf32 到底是什么
热词里有一个很常见的实践场景:深度学习模型部署必知 fp32、fp16、bf16、tf32 浮点数格式。这部分内容在训练和推理时都非常重要,尤其是大模型兴起后,显存和带宽成为瓶颈,精度格式的选择直接影响训练速度和推理性能。
首先要明确,GPU 计算时,矩阵乘法和卷积等核心操作对数值精度的敏感性很高。不同浮点数格式的位宽、指数位、尾数位不同,决定了它能表示的数值范围和精度。
fp32(单精度浮点)
fp32 是最常用的标准浮点格式,由 1 位符号位、8 位指数位、23 位尾数位组成。它精度高、数值范围大,是各类框架的默认训练精度。缺点是占用显存较多,计算速度和显存带宽不如低精度格式。
fp16(半精度浮点)
fp16 由 1 位符号位、5 位指数位、10 位尾数位组成。相比 fp32,它显存占用减半,计算速度更快,是现代 GPU 加速深度学习的主要格式。但它的指数位只有 5 位,导致表示范围较窄。数值稍大就容易溢出为 inf,数值稍小又容易变为 0,因此需要配合 Loss Scaling(损失缩放)来训练。
bf16(BFloat16)
bf16 是 Google 提出的一种 16 位格式,由 1 位符号位、8 位指数位、7 位尾数位组成。它的指数位数量与 fp32 相同,因此数值范围与 fp32 一致,不太容易溢出,但尾数位较少,表示精度不如 fp16。对于大规模分布式训练,bf16 在数值稳定性上比 fp16 更有优势,也是很多大模型训练的首选。
tf32(Tensor Float 32)
tf32 是 NVIDIA Ampere 架构中 Tensor Core 支持的一种格式,由 1 位符号位、8 位指数位、10 位尾数位组成。它并非一种显式存储格式,而是在硬件计算时把 fp32 输入截断为 tf32 精度,再用 Tensor Core 加速矩阵运算。tf32 的指数范围与 fp32 相同,而尾数精度比 fp16 高,因此训练精度损失通常比 fp16 更小。
可以用一个表格来对比:
| 格式 | 位宽 | 符号位 | 指数位 | 尾数位 | 主要用途 | 注意事项 |
|---|---|---|---|---|---|---|
| fp32 | 32 | 1 | 8 | 23 | 训练基线、CPU 推理 | 显存和带宽占用高 |
| fp16 | 16 | 1 | 5 | 10 | 推理加速、混合精度训练 | 表示范围窄,需 Loss Scaling |
| bf16 | 16 | 1 | 8 | 7 | 大模型分布式训练 | 尾数精度低,模型收敛曲线可能与 fp32 存在差异 |
| tf32 | 32 输入 | 1 | 8 | 10 | Ampere 架构 Tensor Core 训练加速 | 依赖硬件支持,需要显式开启 |
5.2 不同格式的实战影响
在实际训练中,我们最常用的是“混合精度训练”,即权重用 fp32 保存,前向和反向计算用 fp16 或 bf16,并通过 Loss Scaling 防止梯度下溢。
推理阶段则更倾向于直接使用 fp16 或 int8 量化,以降低显存占用和提升吞吐。如果模型从 fp32 转换成 fp16 后精度下降明显,可以用 bf16 或保留部分层为 fp32 来做平衡。
在 PyTorch 中,开启混合精度训练有成熟的 API。从 PyTorch 1.6 开始,torch.cuda.amp成为了推荐方案:
import torch # 文件路径:amp_training_demo.py # 核心思路:使用 torch.cuda.amp 自动混合精度训练 from torch.cuda.amp import autocast, GradScaler model = model.cuda() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) criterion = torch.nn.CrossEntropyLoss() scaler = GradScaler() for batch_x, batch_y in train_loader: batch_x = batch_x.cuda() batch_y = batch_y.cuda() optimizer.zero_grad() with autocast(): outputs = model(batch_x) loss = criterion(outputs, batch_y) # 使用 scaler 缩放梯度,避免 fp16 下溢 scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()在新版本 PyTorch 中,torch.cuda.amp模块已经整合进更统一的接口,但上述代码在大多数 PyTorch 2.x 环境仍然可以直接运行。需要注意,GradScaler 是配合 fp16 使用的;如果使用 bf16,通常不需要 Loss Scaling,因为 bf16 的指数范围和 fp32 相同。
对于推理阶段使用 Tensor Core 加速,可以在代码中显式开启 tf32:
import torch # 开启 cuBLAS 和 cuDNN 的 tf32 支持 torch.backends.cuda.matmul.allow_tf32 = True torch.backends.cudnn.allow_tf32 = True需要强调,是否启用 tf32 需要跑实际业务数据验证精度。有些模型对精度敏感,tf32 的尾数截断会导致指标下降。通用建议是:先以 fp32 为基线,再尝试 tf32、fp16、bf16,记录每一档的指标差异和性能提升,再根据业务场景做取舍。
5.3 部署选型建议
在实际部署时,有一个比较实用的原则:
- 如果显存充足、追求最高精度,优先使用 fp32。
- 如果希望降低显存占用、提升推理速度,且模型对精度不敏感,优先使用 fp16。
- 如果模型较大、数值动态范围波动明显,或者在大规模分布式训练中,优先考虑 bf16。
- 如果使用 NVIDIA Ampere 及以上架构的 GPU,可以尝试 tf32 加速矩阵运算,并对比精度变化。
这里要特别提醒:精度格式选择不是越“低”越好,而是要在精度、显存、速度三者之间找到业务可接受的平衡点。上线前必须在测试集或线上流量复现数据上做 A/B 验证,不要凭感觉直接切到低精度。
6. 深度学习实战中的高频问题和工程建议
6.1 环境配置相关
深度学习的入门门槛,很大一部分来自环境安装。如果你只是跑 PyTorch,官方推荐的流程通常是安装 Python、CUDA、cuDNN,然后用 pip 安装 PyTorch。这里有几个高频问题:
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
安装 PyTorch 后import torch报 CUDA 错误 | 安装的 PyTorch 版本与 CUDA 版本不匹配 | 使用官方pip install torch自动匹配对应版本 |
| 模型能跑到 GPU 上,但速度很慢 | 数据加载成了瓶颈,或未开启 Tensor Core | 使用 DataLoader 多进程加载、开启 tf32、检查 batch size |
| 复现别人代码时版本不一致 | 依赖库版本差异 | 使用虚拟环境(conda/venv)隔离,按项目 README 锁定版本 |
| 显存不足 OOM | batch size 过大或分辨率过高 | 减小 batch size、使用混合精度、梯度累积 |
不建议初学者一上来就手动编译源码或自建深度学习环境。先用官方预编译包跑通一个最小例子,理解训练流程后,再根据项目需求配置更细的环境。按照热词里的信息,Windows、macOS、Linux 上都有成熟的 PyTorch 安装方式,关键是根据自己的系统和 CUDA 版本选择对应的安装命令。
6.2 训练效果相关
- 损失不下降:先检查数据预处理是否有问题,例如标签是否正确、输入是否归一化。再检查学习率设置,过大会导致震荡,过小会导致收敛缓慢。
- 验证集精度低于训练集精度:这是过拟合信号。优先考虑数据增强、增加数据量、减小模型容量、添加 Dropout 或正则化。
- 样本数量少导致无法收敛:使用预训练模型微调,或者引入数据增强。不要盲目加深网络。
- 训练轮数(epoch)设置不当:使用早停法,而不是固定一个很大的 epoch 数。
6.3 部署落地相关
- 训练精度高但部署后精度下降:检查部署时是否切换了模型模式,例如 PyTorch 中是否调用了
model.eval();检查输入图像预处理是否与训练时一致;检查量化或低精度格式的影响。 - 推理速度不达标:优先检查 GPU 利用率是否跑满,瓶颈可能在数据加载、CPU 前处理或小 batch 下的 kernel 启动开销。
- 模型文件过大:可以尝试导出为 ONNX、使用 TensorRT 优化、或者进行量化压缩。
- 生产环境权限和变更:任何模型上线、格式切换、精度调整都应在测试环境验证,并保留旧版本回滚方案,遵循最小权限原则。
6.4 工程建议清单
- 每个实验都要记录版本:Python、CUDA、PyTorch、依赖库版本,以及随机种子。
- 数据划分要固定训练集、验证集、测试集,不要用测试集反复调参。
- 保存模型时同时保存模型结构、权重、优化器状态和训练参数,便于恢复训练。
- 训练脚本要支持断点续训,避免因意外中断丢失长时间训练进度。
- 日志中记录每个 epoch 的损失、准确率、学习率,以及显存消耗。
- 代码上线前先跑通最小数据集的完整流程,再在完整数据上训练。
- 涉及生产环境变更时,先在预发布或灰度环境验证,确保可以快速回滚。
7. 下一步学习路线与思考方式
写到这里,再回到开头的问题:深度学习是“人脑的简单复刻”吗?答案已经很明确:不是。
深度学习借用了一些生物学概念,但在数学本质上,它是一种基于梯度优化的函数逼近方法。理解这一点,可以帮助我们在面对新模型、新论文时,快速抓住核心问题:这个模型用什么样的结构、损失函数和优化方法来解决问题?它需要什么样的数据和算力?它在实际数据上表现如何?
如果你想继续深入,建议按下面的顺序推进:
第一,打牢数学基础。深度学习的核心是线性代数、概率论和微积分,尤其是矩阵运算、链式法则、梯度下降。这些概念不需要一次学完,但在遇到优化和反向传播问题时,回头补基础会很有帮助。
第二,掌握一个深度学习框架。PyTorch 是目前研究和工程中最常用的框架之一。从分类模型入手,把训练循环、数据集构建、模型保存加载、推理部署这些基本流程跑通。
第三,学习经典模型结构。CNN 用于图像,RNN 和 Transformer 用于序列。可以先从图像分类入手,理解卷积的原理,再转向自然语言处理和 Transformer。模型结构看似繁多,但很多都是基础模块的组合。
第四,走向工程落地。学习模型压缩、量化、推理加速、分布式训练和部署工具链。训练出一个高精度模型只是第一步,真正落地还要解决性能、稳定性、监控和回滚等问题。
对初学者来说,最有效的学习方式不是背概念,而是动手跑模型、改代码、看训练曲线。每个模型训练过程,都是对“参数-数据-目标函数”三者关系的直观理解。
如果你读到这里,说明你对深度学习的学习是认真的。建议你打开编辑器,用本文第 3 节的示例代码跑通第一个训练流程,然后调整训练轮数、学习率、网络层数,观察训练曲线如何变化。这个过程比看十篇科普文章都更有价值。
如果本文对你有帮助,可以收藏备用。也欢迎在评论区聊聊你在学习深度学习过程中遇到的第一个卡点,一起交流排错经验。