TensorFlow Models 仓库 DeepLab FAQ 深度解析:骨干网络扩展、自定义数据集、BN 微调与多卡训练实战
2026/9/7 4:58:33 网站建设 项目流程

TensorFlow Models 仓库 DeepLab FAQ 深度解析:骨干网络扩展、自定义数据集、BN 微调与多卡训练实战

【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models

本文以 research/deeplab/g3doc/faq.md(官方 FAQ)为骨架,逐条展开其背后对应的 DeepLab 训练/评估脚本与源码实现。读者在读完本文后,将能够独立完成:更换网络骨干(ResNet 等)、接入自定义分割数据集、复现官方精度基线、合理配置output_stride/atrous_rates/eval_crop_size、微调 BatchNorm 参数,以及排查多 GPU 同步 / 异步训练缓慢等问题。


1. FAQ 定位与适用代码范围

本 FAQ 服务于仓库中的 DeepLab 语义分割实现,主体代码位于 research/deeplab:

  • 训练入口 train.py
  • 评估入口 eval.py
  • 公共 flag 定义 common.py
  • 骨干网络工厂 core/feature_extractor.py
  • 数据集构建脚本 datasets 与数据集描述 data_generator.py

需要注意一个前提:FAQ 覆盖的 train.py / eval.py 等脚本依赖tensorflow.contribtf.app.flagstf.contrib.slim等 TF 1.x 接口,阅读后续命令与配置时应以本项目源码实际内容为准,并留意运行环境的 TensorFlow 版本前提。

FAQ 的 9 个问题可划分为四类主题:模型扩展(Q1/Q3/Q4)、数据接入(Q2)、训练调优(Q5/Q8)、分布式与复现(Q6/Q7/Q9)。下面按主题聚类展开,而不是机械复述问题。


2. 更换网络骨干(ResNet、Xception、MobileNet 与 NAS 系列)

Q1:除了自带的骨干(如 Xception),想用 ResNet 等网络怎么办?

结论:官方 FAQ 给出的做法是直接修改 core/feature_extractor.py 以支持更多骨干。而在当前仓库实际版本中,该文件已内置networks_map(见 feature_extractor.py 第 232-248 行),预置骨干包括:

模型系列可用变体
MobileNetmobilenet_v2mobilenet_edgetpumobilenet_v3_large_segmobilenet_v3_small_seg
ResNetresnet_v1_18/18_betaresnet_v1_50/50_betaresnet_v1_101/101_beta
Xceptionxception_41xception_65xception_71
NASnas_pnasnetnas_hnasnet

也就是说,如果你想要的 ResNet 变体已在这个列表内,并不需要修改源码,只需在训练 / 评估命令中通过公共 flag--model_variant=resnet_v1_50_beta指定即可(该 flag 定义于 common.py)。DeepLab 的feature_extractor主分发逻辑位于 feature_extractor.py 第 609-676 行,它会按model_variant名称把请求路由到对应网络工厂,并统一接收output_stridemulti_griddepth_multiplieris_trainingfine_tune_batch_norm等高层参数;同时每个系列使用独立的arg_scope(如 ResNet 使用batch_norm_decay=0.95batch_norm_epsilon=1e-5,Xception 使用decay=0.9997epsilon=1e-3)。

若确实需要全新骨干,需要理解 get_network 的注册机制:模型名必须是networks_map的键,否则会抛出ValueError: Unsupported network(对应校验逻辑在 feature_extractor.py 第 696-697 行)。因此扩展新网络的标准流程是:在networks_map中注册新的名字→网络函数,并在arg_scopes_map中提供配套的arg_scope,然后为新网络补齐对应的预处理函数映射,最后在feature_extractor主分发函数中新增一个elif分支。参考 core/resnet_v1_beta.py、core/xception.py 即可看到既有网络的注册实现范式。

不同骨干在更换时还需联动修改几个配套 flag,FAQ 与源码注释给出的约定如下:

  • resnet_v1_{50,101}_beta官方 checkpoint 要求--multi_grid=[1,2,4](见 common.py 中multi_grid的注释);
  • xception_65推荐--atrous_rates=[6,12,18]output_stride=16)或[12,24,36]output_stride=8);
  • mobilenet_v2系列不设置atrous_rates,即decoder_output_stride=None
  • --model_variant默认值是mobilenet_v2(见 common.py)。

3. 在自定义数据集上训练

Q2:想在其它数据集上训练怎么办?

结论:FAQ 建议修改build_{cityscapes,voc2012}_data.pysegmentation_dataset.py来构建自己的数据集。结合当前仓库源码,这条路径可分为两个清晰步骤:

第一步:把自有数据转成 TFRecord。数据集目录 datasets 提供了参考脚本:

  • build_voc2012_data.py:把 PASCAL VOC 2012 组织成 TFRecord,配套的自动化脚本是 download_and_convert_voc2012.sh;
  • build_cityscapes_data.py:Cityscapes 版本,配套 convert_cityscapes.sh;
  • build_data.py:被上述脚本复用的公共转换函数(解析图像与标注、生成 sharded TFRecord)。

你的数据集在转换时可以参考build_voc2012_data.py顶部注释约定的目录结构(JPEGImages/SegmentationClass/ImageSets/Segmentation分层)以及 TFRecord 中每个 Example 应包含的字段(如image/encoded、语义标注等)。

第二步:在数据集注册表中登记新数据集。FAQ 所提到的segmentation_dataset.py在当前仓库中已迁入 deprecated/segmentation_dataset.py(标记为废弃),当前活跃的数据集描述文件是 datasets/data_generator.py。它以DatasetDescriptornamedtuple 描述数据集三项属性(见 data_generator.py 第 58-69 行):

  • splits_to_sizes:各 split(train / val / test)的样本数;
  • num_classes:语义类别数(含背景,PASCAL 为 21,Cityscapes 为 19,ADE20K 为 151);
  • ignore_label:忽略标签值(PASCAL 与 Cityscapes 均为 255,ADE20K 为 0)。

仓库内置的三个数据集描述符(data_generator.py 第 71-100 行)可作为模板:

数据集主要 splitsnum_classesignore_label
cityscapestrain_fine: 2975、val_fine: 500、train_coarse: 22973 …19255
pascal_voc_segtrain: 1464、train_aug: 10582、trainval: 2913、val: 144921255
ade20ktrain: 20210、val: 20001510

新数据集只需仿照这组描述符,把它加入 data_generator.py 第 102-106 行的_DATASETS_INFORMATION字典,再通过--dataset=xxx--dataset_dir=xxx--train_split/--eval_split指定,即可复用 DeepLab 完整的数据预处理(缩放、裁剪、随机翻转等)管线。


4. 训练增强集与 DenseCRF 两个“为什么”

Q3:PASCAL VOC 增强训练集(augmented training set)从哪里来?

官方 FAQ 指出:PASCAL VOC 增强训练集由 Bharath Hariharan 等人提供(论文Semantic Contours from Inverse Detectors,ICCV 2011),由其项目主页发布;若在研究中使用了该数据集应引用该论文。这也是 data_generator.py 中train_aug: 10582这个分卷的由来——即官方 1464 张train加上 SBD 提供的增强标注后扩展到 10582 张。仓库 local_test.sh 与 local_test_mobilenetv2.sh 默认下载的初始化 checkpoint(deeplabv3_pascal_train_aug系列)正是在这一增强集上预训练的。

Q4:为什么实现里不包含 DenseCRF?

FAQ 的答复很坦诚:作者并未尝试后处理 DenseCRF,因此不包含在实现中;感兴趣者可参考 Philipp Krähenbühl 与 Vladlen Koltun 的论文Efficient Inference in Fully Connected CRFs with Gaussian Edge Potentials(NIPS 2011)。这说明 DeepLab 官方发布的精度数据并未叠加 DenseCRF 后处理,用户若追求更高指标可以自行在 logits/概率图上外接 CRF,但这不在仓库提供范围内。


5. 自己训练时如何微调 BatchNorm(Q5 逐条展开)

Q5:想自己训练并同时微调 BatchNorm 参数,应该怎么做?

FAQ 首先给出了一条省资源捷径:直接从官方已训好 BN 参数的 checkpoint 开始微调——使用较小学习率、设置fine_tune_batch_norm=false,并因为学习率小而拉长训练步数。在此基础上,FAQ 给出了四条自训建议,逐条对应源码中的 flag:

  1. 调大输出步长:设置--output_stride=16,甚至32;同时必须按比例调整 ASPP 空洞率。例如output_stride=32时 FAQ 建议--atrous_rates=3,6,9;作为对照,output_stride=16的 Xception 常用[6,12,18]。其原理是增大 output_stride 会降低骨干末端特征图的分辨率下采样倍数,从而降低整体计算量。

  2. 尽可能多用 GPU、加大 batch:训练脚本的多卡(clone)机制由 train.py 的部署相关 flag 控制,详见下文第 6 节。需要特别注意的是 train.py 中的 batch 整除校验:

    assert FLAGS.train_batch_size % config.num_clones == 0 clone_batch_size = FLAGS.train_batch_size // config.num_clones

    train_batch_size必须能被 GPU 数量整除,真正的每卡批大小是整除结果。

  3. 缩小训练裁剪尺寸:把 train.py 的train_crop_size(默认"513,513")调小,例如 513×513 甚至 321×321,以换取更大 batch。

  4. 换用更轻量的骨干:如 MobileNet-v2(--model_variant=mobilenet_v2)。

围绕 BN 微调,源码还揭示了几个容易踩坑的配套约束,一并列出:

  • batch 与 BN 的关系:train.py 第 123-127 行 注释明确指出:当fine_tune_batch_norm=True时,batch size 至少要大于 12(大于 16 更佳),否则应设fine_tune_batch_norm=false以省显存;
  • learning rate 经验值:train.py 第 93-96 行 注释给出:在 PASCAL 增强训练集(train_aug)上全量训练用base_learning_rate=0.007;在trainval上微调用0.0001
  • weight decay 经验值:train.py 第 129-132 行 注释给出:MobileNet-v2 / Xception 系列用0.00004,ResNet 系列用0.0001
  • fine_tune_batch_norm的默认值为 True(train.py 第 171 行),而该 flag 会最终影响骨干网络中is_training的传递——见 feature_extractor.py 第 619/637/646/666 行,只有is_training and fine_tune_batch_norm同时成立时 BN 层才处于训练态更新滑动均值。

6. 多机异步训练与多 GPU 部署

Q6:如何异步训练?

FAQ 给出的做法是:在 train.py 中设置num_replicas(训练机器数)与num_ps_tasks(参数服务器数,FAQ 建议num_ps_tasks ≈ num_replicas / 2),详见slim.deployment.model_deploy。当前仓库中该模块位于 research/slim/deployment 目录下。

对应到 train.py 的实际用法:

  • --num_clones:每台机器上复制的模型份数(即单机多卡数,默认 1);
  • --clone_on_cpu:是否把 clone 放在 CPU 上;
  • --num_replicas:参与训练的 worker(机器)总数,默认 1;
  • --num_ps_tasks:参数服务器数量,默认 0 表示参数由 worker 本地维护,非 0 才进入 PS 异步架构
  • --task:当前进程的任务 ID;
  • --master:TensorFlow server 的 BNS 地址;
  • --startup_delay_steps:各 replica 启动的错峰步数,默认 15,训练时会按task * startup_delay_steps计算延迟(见 train.py 第 393 行)。

训练主函数通过model_deploy.DeploymentConfig(...)(train.py 第 276-281 行)统一管理输入、变量、优化器的设备摆放,再由create_clones+optimize_clones完成 clone 创建与梯度聚合。所谓“异步”即多个 worker / PS 并存时不再做全局同步的梯度等待。


7. 复现官方精度:从 local_test.sh 开始

Q7:用了官方 checkpoint 也复现不出论文精度?

FAQ 给出的排查法门是:先跑通官方脚本,再逐步改动、一次只改一处。仓库恰好提供了两个开箱即用的基线复现脚本:

  • local_test.sh:Xception_65 骨干;
  • local_test_mobilenetv2.sh:MobileNet-v2 骨干。

两个脚本的执行流程基本一致(在research/deeplab目录下运行):

  1. 先执行python model_test.py(MobileNet 版为-v)验证 PYTHONPATH 是否已包含researchresearch/slim(脚本通过export PYTHONPATH=$PYTHONPATH:\pwd`:`pwd`/slim实现,注意脚本会cd ..` 到 research 目录);
  2. 调用 download_and_convert_voc2012.sh 下载并转换 PASCAL VOC 2012 数据;
  3. 下载官方初始化 checkpoint(Xception 版为deeplabv3_pascal_train_aug_2018_01_04.tar.gz,MobileNet 版为deeplabv3_mnv2_pascal_train_aug_2018_01_29.tar.gz);
  4. train_split=trainvaltrain_crop_size=513,513train_batch_size=4fine_tune_batch_norm=true训练 10 步(仅冒烟验证);
  5. 在完整 val 集(1449 张)上评估;
  6. 可视化、导出 frozen graph。

两个脚本的注释里写明了基于官方 checkpoint 应复现的参考指标(作为基线核对锚点):

  • Xception_65 版预期mIOU ≈ 82.20%(local_test.sh 注释);
  • MobileNet-v2 版预期mIOU ≈ 75.34%(local_test_mobilenetv2.sh 注释)。

如果你连这些官方数值都对不上,说明问题大概率出在环境、数据转换或 flag 组合而非模型本身;此时按 FAQ 建议“一次只改一处”逐步对比即可定位差异。更多公开 checkpoint 的清单可参考 research/deeplab/g3doc/model_zoo.md,PASCAL 与 Cityscapes 的专项用法分别见 research/deeplab/g3doc/pascal.md 与 research/deeplab/g3doc/cityscapes.md。


8. eval_crop_size 的计算规则

Q8:评估时eval_crop_size该设多大?

FAQ 给出的规则:DeepLab 评估采用整图推理(whole-image inference),因此:

eval_crop_size = output_stride × k + 1,其中 k 为整数,取值应使结果尺寸略大于数据集中最大的图像边长。

其原因是 DeepLab 的空洞卷积输出空间分辨率与输入满足输入尺寸 = output_stride × 整数 + 1的关系,只有满足这一约束才能让全分辨率(无下采样丢信息)的卷积对齐成立。FAQ 给出两个可直接套用的案例:

数据集图像尺寸output_stride 相关约定推荐 eval_crop_size
PASCAL VOC最大边 51216×32+1=513513×513
Cityscapes统一 1024×204816×64+1=1025、16×128+1=20491025×2049

与代码对应:eval_crop_size是 eval.py 中的DEFINE_listflag(默认也是"513,513"),它在构建评估数据集(eval.py 第 98 行)与模型ModelOptions(eval.py 第 116 行)时被解析成[height, width],并进一步用于给输入张量set_shape(eval.py 第 121-125 行),保证静态图中整图推理与度量计算的一致性。

同理,训练侧的train_crop_size与评估侧可以不同(例如训练用小图、评估用整图大尺寸),这也是 train.py 中atrous_rates/output_stride注释 特别指出的“train 与 eval 可各自独立设置”。


9. 多 GPU 训练变慢的排查

Q9:为什么多 GPU 训练反而很慢?

FAQ 给出的首要排查方向是数据输入管线(preprocessing)线程不足,并建议把num_readers从默认值调大,例如改为 4(原文档链接指向 train.py 中num_readers = 4的设置处)。

对照当前仓库源码:在 train.py 构建训练数据集的位置,data_generator.Dataset(...)的调用中num_readers=4硬编码值,并非命令行 flag;也就是说本仓库版本默认就已采用 4 个 reader。如果自训仍觉输入瓶颈,可在此处与num_readers相邻的批处理参数(batch size、shuffle、repeat、scale augmentation 范围等)上做调优——需要说明的是,从源码结构看,num_readers这个量在当前版本并未暴露为 flag,需修改源码实现,改动前请务必先跑通第 7 节的基线脚本。作为对照,评估侧 eval.py 构建数据集时使用的是num_readers=2,可结合eval_interval_secs(默认 5 分钟,见 eval.py 第 51-52 行)判断评估循环是否拖累了整体节奏。

更广义地说,“多卡变慢”还应检查第 6 节提到的train_batch_size是否能被num_clones整除(整除校验失败会直接报错),以及每卡实际 batch 是否过小导致 BN 统计与计算吞吐同时劣化。


10. FAQ 相关参考论文

以下为官方 FAQ 在正文与参考文献中引用的文献,此处以可检索的题录形式给出(原始文档中附有论文/数据集官方页面链接):

  1. Deep Residual Learning for Image Recognition—— Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun,CVPR 2016(ResNet 骨干出处)。
  2. Semantic Contours from Inverse Detectors—— Bharath Hariharan, Pablo Arbelaez, Lubomir Bourdev, Subhransu Maji, Jitendra Malik,ICCV 2011(PASCAL 增强训练集 SBD 出处)。
  3. Efficient Inference in Fully Connected CRFs with Gaussian Edge Potentials—— Philipp Krähenbühl, Vladlen Koltun,NIPS 2011(DenseCRF 后处理出处)。

小结:把 FAQ 与源码对照阅读后会发现,绝大多数问题的答案都收敛到几条核心约束上——output_stride与输入尺寸的对齐(Q8)、ASPP 空洞率与骨干/步长的联动(Q1/Q5)、BN 训练态与 batch size 的联动(Q5)、部署粒度与 batch 整除性(Q6/Q9)。先跑通 local_test.sh 建立基线,再按本节归纳的规则逐条修改 flag,是使用本仓库 DeepLab 实现最稳妥的实践路径。

【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询