VGG19图像分类实战:从PyTorch训练到显存优化的完整指南
发布时间:2026/9/29 3:20:23来源:尧图网络
简介基于VGG19实现图像分类的完整实验配套资源面向深度学习初学者与人工智能部署开发者核心任务是使用预训练VGG19卷积神经网络在CPU和MLU机器学习单元两种硬件环境中完成图像类别预测与精度评估。压缩包共4个文件包含两个Python评估脚本分别面向CPU和MLU运行环境、一个INT8量化的VGG19模型文件以及一个辅助初始化脚本整体体积约95.86MB。目前已有2139人学习浏览。内容详细展示了VGG19的连续3×3卷积堆叠如何逐步提取图像特征以及池化层、全连接层与Softmax层在分类中的作用同时演示了图像尺寸调整、归一化等预处理步骤并对比INT8量化前后模型在存储占用和推理速度上的差异。通过分别在CPU与MLU上运行评估脚本读者能够直观感受不同硬件平台对深度学习推理性能的影响进而掌握模型部署与优化的基本方法。1. 智能计算系统实验4-1在做什么VGG19 图像分类的完整链路图像分类看起来是深度学习里最“入门”的任务但智能计算系统实验4-1的标题里同时压了三个关键词VGG19、图像分类、以及“从模型到系统”的完整链路。我带人做这个实验时有个反直觉的印象很多人半天就能把训练脚本跑起来但问到底层为什么选 VGG19、一张图前向一次要占多少显存、迁移学习里哪些层该冻哪些层该解冻能一次答对的人很少。这个实验真正的价值不是刷一个准确率数字而是让你把数据管线、模型定义、训练循环和评估指标串成一条能解释的完整链路。它适合刚接触 PyTorch 想完成课程实验的学生也适合想把手头图像分类任务换成成熟骨干网络的工程新手。2. 从 VGG19 网络结构到显存估算实验前先算清三笔账2.1 VGG19 的框架拆解为什么全是 3×3 卷积VGG19 的结构可以用一句话概括连续的 3×3 卷积堆叠成卷积块块之间用 2×2 max pooling 降分辨率最后接三层全连接做分类。数字 19 指的是有可训练参数的权重层数也就是 16 层卷积加 3 层全连接。用 3×3 卷积而不是 5×5 或 7×7是因为两个 3×3 卷积堆叠后的感受野等于一个 5×5三个堆叠等于一个 7×7但参数更少而且中间多了非线性激活拟合能力更强。这个设计思路在后续很多骨干网络里都延续了。常见做法是把网络按特征图分辨率分成五个 stage再加上分类头。以 224×224 输入为例前面五个 stage 经过 max pooling 后特征图从 224 依次降到 112、56、28、14、7最后一个卷积块输出的是 7×7×512 的激活。实验里如果你打印模型结构会看到 torchvision 的 vgg19 实现把卷积部分放在 features 里分类部分放在 classifier 里classifier 的前两层是 25088 维到 4096 维的全连接这是 VGG 系列最占显存的地方。阶段卷积层数 / 通道数输出尺寸最大池化Block 12 层64 通道224×224×642×2, stride 2Block 22 层128 通道112×112×1282×2, stride 2Block 34 层256 通道56×56×2562×2, stride 2Block 44 层512 通道28×28×5122×2, stride 2Block 54 层512 通道14×14×5122×2, stride 2Classifier4096-4096-10007×7×512 → 1×1000无实际实验里你把 print(model) 的输出和这个表对照着看基本能一眼定位每一层的输入输出后面改分类头时也能直接对应到层索引。2.2 显存估算为什么 batch 稍微一大就 OOMVGG19 的参数量大约是 5.48 亿fp32 下模型权重就要占 548M × 4 字节 ≈ 2.2GB。但图像分类训练时显存大头往往不是权重而是中间激活值。以 batch32、224×224 为例前向过程中每个卷积层都要保存一份输出供反向传播使用特征图最宽的阶段是 Block1 的 224×224×64 和 Block2 的 112×112×128这些中间结果累计起来经常超过 2GB再加上优化器状态、梯度batch32 在 8GB 显存上跑全量 VGG19 训练是有风险的。显存的粗略估算公式可以这样列总占用 ≈ 参数 梯度 优化器状态 激活。Adam 优化器会给每个参数额外保存一阶和二阶动量所以优化器状态这一项大约等于参数量的 8 字节也就是 4.4GB 左右。也就是说即使激活值全部优化掉光权重、梯度和优化器状态就接近 2.2 2.2 4.4 8.8GB。这也是为什么很多课程实验里推荐用 SGD 而不是 Adam 跑 VGG19SGD 的动量状态只相当于一份额外的参数拷贝省下接近 2GB。我在实验里给学生定的经验值是8GB 显存用 SGD batch16 混合精度否则很容易在第一个 epoch 就翻车。一个更稳妥的做法是先不写训练循环直接用一段小脚本前向一次并打印 torch.cuda.max_memory_allocated()。先把当前 batch 的峰值显存摸清楚再反推 batch size比凭感觉试要快得多。2.3 实验环境组合Python、PyTorch、CUDA 怎么配不出错这个实验最省心的环境组合我一般推荐 Python 3.10、PyTorch 2.x、CUDA 11.8 或 12.1。不需要追最新版本PyTorch 2.1 以上的 torchvision 对 VGG19 的预训练权重支持很稳定更高版本的主要收益在 torch.compile你可以在实验跑通后再开。环境准备的命令大致如下conda create -n vgg19 python3.10 -y conda activate vgg19 pip install torch2.1.2 torchvision0.16.2 --index-url https://download.pytorch.org/whl/cu121 pip install numpy pandas matplotlib tqdm tensorboard参数说明里有几个点需要解释。--index-url 指定的是 PyTorch 官方预编译 wheel 源cu121 表示 CUDA 12.1 版本电脑上装的是 11.8 就把这个后缀改成 cu118。torchvision 的版本必须和 torch 主版本对齐0.16.2 对应 2.1.2混装最常见的报错是 import torchvision 时直接段错误。tensorboard 不是必须的但用它看 loss 曲线比每次打印一串数字要直观很多。装好之后先用一条命令验证 GPU 能用python -c import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))如果输出里 cuda.is_available() 是 False多半是 PyTorch 装成了 CPU 版或者 CUDA 驱动版本太旧。检查 nvidia-smi 里的驱动版本和 PyTorch 要求的 CUDA 版本是否能对上这一步是最基本的排查。这里还有个容易忽略的细节课程实验平台的 GPU 可能不支持混合精度用的 bf16所以 amp 开启前先查一下 compute capability否则会白跑一个 epoch 才发现精度不支持。我把这部分放在动手前是因为 VGG19 这个模型很“重”环境配错往往不是立刻报错而是训练到一半崩。把这三笔账算清楚后面跑脚本时才不用反复试错。3. 图像分类数据准备让 VGG19 吃上 224×224 的 Tensor3.1 数据集怎么选ImageNet 子集、CIFAR-10 还是自建目录实验里最容易被低估的是数据准备。VGG19 预训练模型是在 ImageNet 上训的输入协议是 224×224 的 RGB 图像。你直接用 CIFAR-10 的 32×32 原图喂进去模型结构会直接报错如果 Resize 到 224×224虽然能跑但小图放大后分辨率损失严重准确率一般也不会好看。课程实验最常见的做法是我下面要写的两条路之一要么用 ImageNet 的某个子类集合要么用数据量几百到几千的森林图像分类这类自建数据集后者文件结构典型也方便后面画混淆矩阵。如果走自建数据目录必须符合 torchvision.datasets.ImageFolder 的约定也就是 train 和 val 下面各放一个按类别命名的子目录每个子目录里放该类别的图片data/ ├── train/ │ ├── forest/ # 森林场景图片 │ │ ├── img_001.jpg │ │ └── ... │ └── non_forest/ └── val/ ├── forest/ └── non_forest/ImageFolder 会自动把每个子目录名映射成从 0 开始的类别编号。这里有一个常见误区train 和 val 下的类别子目录名必须完全一致否则加载验证集时同名类别会被当成不同类别导致类别数翻倍。我见过有人把训练集写成 forest、验证集写成 forset跑起来不报错但准确率一直徘徊在 50% 上下排查了很久。如果实验环境网络受限下载 ImageNet 全量数据不现实建议退而求其次用 CIFAR-10 或公开的图像分类数据集下载链接。CIFAR-10 只有 32×32不是 VGG19 的最佳输入但把 torchvision 的 transforms 做对依然能拿到 85% 以上的 top-1足够完成实验报告。3.2 transforms 预处理为什么必须 Resize 到 224 并做 NormalizeVGG19 对输入的要求不只是尺寸还有数值范围。PyTorch 官方预训练权重的训练协议是先把图像短边 Resize 到 256再 CenterCrop 成 224×224最后用 ImageNet 的均值和标准差做标准化。均值是 [0.485, 0.456, 0.406]标准差是 [0.229, 0.224, 0.225]这些数字直接写死就行不是超参数。训练集和验证集的 transforms 应该分开写训练集要加随机增强验证集只做确定性预处理。常见写法如下from torchvision import transforms train_transform transforms.Compose([ transforms.RandomResizedCrop(224, scale(0.8, 1.0)), transforms.RandomHorizontalFlip(), transforms.ColorJitter(brightness0.2, contrast0.2, saturation0.2), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) val_transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])这里每个组件的含义要区分清楚。RandomResizedCrop 会随机裁剪一块区域并缩放到 224相当于同时做了裁剪和尺度扰动scale 控制最小裁剪面积占比设成 (0.8, 1.0) 是为了避免裁得太狠导致关键特征丢失RandomHorizontalFlip 是左右翻转对大多数自然图像有效ColorJitter 做亮度、对比度、饱和度的扰动对森林图像这类颜色敏感的数据要慎用颜色扰动太强反而会让模型学不到真实的颜色特征。ToTensor 会把 HWC 的 uint8 图像转成 CHW 的 float32并把像素值从 0~255 缩放到 0~1这一步必须放在 Normalize 前面。3.3 DataLoader 参数batch_size、num_workers、pin_memory 怎么配合数据管线里最容易让 CPU 变成瓶颈的是 DataLoader。VGG19 训练时 GPU 干活快、预处理慢如果 num_workers 不调训练过程会频繁出现 GPU 空闲等待数据。我的常用配置是from torch.utils.data import DataLoader train_loader DataLoader(train_dataset, batch_size16, shuffleTrue, num_workers4, pin_memoryTrue, drop_lastTrue) val_loader DataLoader(val_dataset, batch_size64, shuffleFalse, num_workers4, pin_memoryTrue)参数设定的逻辑是这样的。batch_size16 是因为 VGG19 权重和激活占用大8GB 显存下 16 是一个比较稳的起点显存够就加到 32OOM 就降到 8。num_workers4 表示用 4 个子进程做图像解码和 transform这个值不是越大越好Windows 系统下 num_workers 过大且没把训练代码包在 ifname main 里会直接报 RuntimeError这是多进程在 Windows 上的典型限制。pin_memoryTrue 会让 DataLoader 把数据放在锁页内存里GPU 拷贝时更快代价是占用一部分固定内存实验中一般建议开着。drop_lastTrue 在训练集里丢弃最后不足一个 batch 的样本避免 batch 大小突变导致统计不稳定VGG19 原版没有 BatchNorm但对后面做其他模型的实验习惯养成有好处。到这里数据准备就齐了。一个可以验证正确性的技巧先随机取一个 batch 用 imshow 把图显示出来确认增强后的图像没有失真到离谱再开始训练。这一步花不了 5 分钟能省掉后面整晚调参的无效时间。4. 用 PyTorch 跑通 VGG19 图像分类训练脚本与参数拆解4.1 加载预训练权重并替换分类头这一步是整个实验的核心。我们有两条路一是随机初始化从头训练二是加载 ImageNet 预训练权重做迁移学习。课程实验几乎都建议走第二条路因为 VGG19 参数量巨大在小型数据集上随机初始化很难收敛预训练权重则能让模型在第一个 epoch 就具备可用的特征提取能力。torchvision 从 0.13 开始推荐用 weights 参数而不是 pretrainedTrue。标准写法是import torch import torch.nn as nn from torchvision import models model models.vgg19(weightsmodels.VGG19_Weights.IMAGENET1K_V1) num_classes 2 # 以森林图像分类为例forest / non_forest # 替换分类头最后一层 in_features model.classifier[6].in_features model.classifier[6] nn.Linear(in_features, num_classes)这里有两个关键点。第一weightsmodels.VGG19_Weights.IMAGENET1K_V1 会自动下载约 548M 的权重文件到用户缓存目录第一次运行需要联网下载中断后重跑会自动断点续传。第二替换 classifier[6] 时VGG19 的分类头是一个 Sequential前五层是 ReLU 和 Dropout最后一层是输出 1000 类的 Linear。我们只替换最后一层in_features 从原层拿这样不管原模型输出是 1000 还是别的数量都不会写错。如果你想把特征层也冻住只训练新加的分类头常见做法是for param in model.features.parameters(): param.requires_grad False这行代码会把 features 里所有卷积层的参数冻结反向传播时不会计算这些参数的梯度显存占用明显下降。要不要冻结取决于数据量数据集只有几百张时冻结是保护伞有几千张以上时冻结反而会限制性能更适合全微调。4.2 训练循环与验证循环的标准写法下面是一份可以直接抄的训练脚本核心部分。为了控制篇幅我这里展示单 epoch 的关键逻辑完整的数据读取部分接上一章的 DataLoaderimport torch import torch.nn as nn from torch.optim import SGD model model.to(device) criterion nn.CrossEntropyLoss() optimizer SGD(model.parameters(), lr0.001, momentum0.9, weight_decay5e-4) scheduler torch.optim.lr_scheduler.StepLR(optimizer, step_size5, gamma0.1) for epoch in range(1, 16): model.train() total_loss, correct, total 0.0, 0, 0 for images, labels in train_loader: images, labels images.to(device), labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() total_loss loss.item() * images.size(0) correct (outputs.argmax(dim1) labels).sum().item() total images.size(0) train_acc correct / total train_loss total_loss / total model.eval() val_correct, val_total 0, 0 with torch.no_grad(): for images, labels in val_loader: images, labels images.to(device), labels.to(device) outputs model(images) val_correct (outputs.argmax(dim1) labels).sum().item() val_total images.size(0) val_acc val_correct / val_total print(fEpoch {epoch:02d} | Train Loss {train_loss:.4f} | Train Acc {train_acc:.4f} | Val Acc {val_acc:.4f}) scheduler.step()逻辑说明训练阶段必须调用 model.train()它会把 Dropout 打开、让 BatchNorm 更新统计量验证阶段必须 model.eval()并包在 torch.no_grad() 里否则会额外计算梯度白白多占一份显存。optimizer.zero_grad() 每步都要调用否则上一 batch 的梯度会累加到当前 batch 上loss 曲线会异常震荡。outputs.argmax(dim1) 取的是每个样本预测概率最大的类别下标和 labels 比较的结果就是 top-1 准确率。几个参数为什么要这么设需要单独说。SGD 的 momentum0.9 和 weight_decay5e-4 是图像分类迁移学习的经典组合weight_decay 就是 L2 正则能抑制过拟合。学习率 0.001 对应冻结特征层的场景如果是全微调我会降到 0.0001否则预训练权重会被大梯度一下子冲坏。StepLR 每 5 个 epoch 把学习率乘 0.1是让 loss 进入平台期后能继续下降的常用做法。epoch 设 15 是为了配合 step_size5 看到两次衰减的效果实际观察 loss 不再下降就可以提前停。4.3 迁移学习参数速查冻结、解冻与混合精度迁移学习的参数选择有很成熟的经验区间放进表格里一眼能看清场景特征层分类头学习率batch_sizeepoch数据量很小1000 张冻结训练1e-38~1610~20数据量中等几千张解冻顶层训练1e-416~3220~30数据量充足万级以上全部解冻训练1e-4~3e-43230冻结特征层时模型只更新最后一层 Linear参数量骤减训练速度很快解冻顶层时常见做法是先让分类头训几个 epoch再把 features 的最后几层 requires_grad 打开用更小的学习率继续训这样比一开始就全解冻稳定。手动控制层释放梯度的写法如下for param in model.features.parameters(): param.requires_grad False # 解冻 Block5features 中索引 24 之后的层 for param in model.features[24:].parameters(): param.requires_grad True要准确知道 24 这个数字对应的层可以先 print(model.features) 数一遍索引。BatchNorm 在原版 VGG19 里没有但如果换到其他变体会遇到需要注意的点冻结 BN 层参数不等于固定其统计量model.eval() 才管用这是另一处常见的坑。混合精度训练如今已经非常成熟在显存紧张时是后悔药级别的手段。开启方式是在训练循环外套一个 GradScalerscaler torch.cuda.amp.GradScaler() ... with torch.cuda.amp.autocast(): outputs model(images) loss criterion(outputs, labels) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()参数说明autocast 让模型内部计算自动用 fp16但梯度累积时仍以 fp32 保存避免精度下溢GradScaler 防止 fp16 梯度数值太小直接变成 0。开启 amp 后显存峰值通常能降 30%~40%代价是准确率有千分位级别的波动。如果你的 GPU 算力足够但显存只有 6GB这一步几乎是必选的。提示如果是课程实验提交前请固定随机种子并在训练开始时打印模型结构和参数量保证复现结果和报告对得上。5. VGG19 图像分类实验常见问题排查5 个坑的现象、原因与解决办法5.1 训练 loss 一开始贴在 6.9 附近好几个 epoch 不动现象第一个 epoch 打印出来的 loss 大约是 6.907然后缓慢下降或者干脆不动验证集准确率接近随机猜测。原因6.9 这个数字不是随机值。对于 1000 类分类任务如果模型最后一层输出接近全零交叉熵损失的期望就是 ln(1000)约等于 6.908。出现这个现象通常意味着两类情况一是分类头没有接上预训练权重随机初始化后梯度传不回去二是学习率太大导致预训练特征被迅速破坏。解决先确认加载预训练权重时没有把整个 model 覆盖掉或 strictFalse 后改动过大。然后在冻结特征层的前提下把学习率降到 1e-3 以下。如果用的是 Adam还要注意它和预训练权重搭配时的 warmup 问题一般建议先用 3~5 个 epoch 从 1e-5 线性升到目标学习率。我在实验中遇到这类问题90% 都是因为图省事直接全微调且 lr 开到了 1e-2把预训练权重冲坏了。5.2 GPU 显存溢出OOM 报错出现在第一个 epoch现象训练刚跑几步屏幕上出现 torch.cuda.OutOfMemoryError而且每次报错的位置可能不一样。原因VGG19 是显存大户。前面算过光模型加优化器状态就接近 8GB如果 batch size 设成 32 且开了 Adam8GB 显卡必炸。另一个隐性原因是验证阶段忘记包 torch.no_grad()或者保留了大量历史 tensor 没释放。解决分三步走。第一步把 batch_size 改成 8 或 16同时用 SGD 替换 Adam第二步开启混合精度前面 4.3 的 GradScaler 直接套用第三步检查是否误用了 GPU 大 tensor 当临时变量且没及时 del。如果以上都做了还不够考虑梯度累积把 4 个 batch_size8 的梯度累加后再更新等效于 batch_size32 的优化步长但峰值显存占用只有单 batch 的量级。梯度累积的关键代码是accum_steps 4 loss loss / accum_steps # 先缩放 loss.backward() if (step 1) % accum_steps 0: optimizer.step() optimizer.zero_grad()这里有个细节累积时要把每个 mini-batch 的 loss 除以累积步数否则等效学习率会变大 4 倍loss 曲线会发飘。这也是我从实践里学到的血泪经验加了累积却忘记除步数结果模型直接训崩。5.3 训练集准确率逼近 100%验证集却卡在 60%现象每 epoch 打印训练集 top-1 一路涨到 0.95 以上但验证集死活不涨两者差距越拉越大。原因这是典型的过拟合在小数据集上尤其明显。VGG19 有近 5.5 亿参数特征提取能力远超市数据集的信息量模型记住训练样本的细节而不是泛化规律。此外如果替换分类头时把原 VGG19 的 Dropout 层误删了过拟合会更早出现。解决优先加数据增强把 3.2 里 train_transform 的 ColorJitter、RandomResizedCrop 打开并考虑加 RandomRotation(10)其次调大分类头里的 DropoutVGG19 原版分类头里 dropout 默认是 0.5如果嫌激进可以改成 0.3再配合 early stopping监控验证集准确率连续 5 个 epoch 不上升就停止训练并回滚到最佳权重。回滚的常见做法是每轮结束保存 val_acc 最高的 state_dict而不是在跑完 15 个 epoch 之后后悔。5.4 加载预训练权重时 shape 对不上现象手动改了分类头之后执行 load_state_dict报 size mismatch for classifier.6: copying a param with shape torch.Size([1000, 4096])。原因预训练权重的最后一层输出是 1000而你的 num_classes 是 2两侧张量的第一维不一致PyTorch 拒绝加载整个字典。很多人把 strictFalse 当成万能解法但它只会跳过不匹配的层如果误拼错层名其他层也不会报错等于静默地用随机初始化危险很大。解决正确顺序是先加载完整预训练权重再替换分类头。torchvision 的 weights 参数已经在内部帮你完成了加载所以不要再单独 load_state_dict如果非要用 load_state_dict就先把 model.classifier[6] 替换回 1000 维再加载然后重新替换成新分类头。课程实验里我见过的最常见错误是反着做先换头再加载权重导致模型一直在随机初始化状态下训练准确率始终上不去。5.5 CPU 环境下训练慢到怀疑人生现象没有 GPU 的机器上一个 epoch 要跑几十分钟甚至几小时loss 曲线在终端里半天不动。原因VGG19 的 FLOPs 约为 19.6G这还是 224×224 输入下的数字。CPU 每秒能做的浮点运算有限全量训练不现实这不是玄学是量级问题。解决如果实验允许先砍输入尺寸把 Resize 目标从 224 改为 128训练量直接降到原来的三分之一左右或者换用 VGG16 甚至 ResNet18 先跑通流程实验报告里注明模型差异。如果必须用 VGG19可以配合全连接层使用 IMAGENET1K_FEATURES 版本权重并关闭验证阶段的梯度计算。实在不行用 torch.compile 对 CPU 也有一定加速代码只需在训练前加一行 model torch.compile(model)但首次运行需要额外的编译时间。对小规模实验我更建议先换小模型验证数据管线再上 VGG19避免把时间耗在等待上。6. 从“跑通”到“能答辩”VGG19 实验的进阶验证技巧实验报告如果只给一个最终准确率很难说明你真的理解了这套系统。我一般会建议在做完基础训练后补三件事每件事都不超一页代码量但能让结果质量明显不一样。第一算 top-5 准确率和画混淆矩阵。图像分类评估里 top-1 只是最严苛的指标VGG19 的 softmax 输出里第二个候选往往也有参考价值。验证时多取 outputs.topk(5, dim1)统计真实标签是否落在前五里能在报告里多一个解释维度再配合 sklearn 的 confusion_matrix 和 seaborn 画热力图能直观看出哪些类别互相混淆。对森林图像分类这类数据混淆图几乎每次都显示负样本容易被误判为正样本这一步能直接指向数据增强方向需要给负样本增加正样本中常见的颜色扰动。第二做一个单张图片的推理脚本作为验收标准。训练结束后写一个约 30 行的脚本读入任意一张图走 val_transform输出 top-3 类别和置信度这是“能答辩”的最低门槛。同时记录单张推理的耗时并注明是在什么硬件上测的这个数字在智能计算系统实验里比准确率更能体现“系统”二字的含义。第三如果要扩展视野可以和当前最新的图像分类模型做一组对照实验。比如用 torchvision 里的 ViT 或 Swin 替换 VGG19保持同一份数据和预处理观察在几百张图片的小数据集上transformer 图像分类模型往往调参更敏感、更容易欠拟合而 VGG19 虽然老却在小数据加迁移学习的场景下非常稳。这个对照结论写在实验报告里比单纯报一个 94% 有说服力得多。我的个人习惯是每跑一轮实验就把打印出的 loss 曲线、显存峰值和参数表存成一个固定命名的记录文件下次复现时直接读参数而不是翻聊天记录。这个习惯帮我在做智能计算系统实验时少走了很多弯路也让我现在给新人设参数时能直接说出“8GB 显存、SGD、batch 16、lr 1e-3”这样的组合。希望这些拆解对你做这一次实验有所帮助。本文还有配套的精品资源点击获取
网站建设高端定制企业官网