资讯动态

深入解析mmdetection train.py:从训练崩溃到高效调优

发布时间:2026/10/18 2:26:02 来源:尧图企业网站定制
1. 从一次训练崩溃说起为什么要啃train.py刚接触mmdetection那会儿我最常干的事就是照着官方文档敲一行命令然后祈祷它能跑通。配置文件改一改数据集路径填一填python tools/train.py configs/xxx.py回车接下来就是漫长的等待。跑通了皆大欢喜跑不通就抓瞎——报错信息指向某个我根本没打开过的文件堆栈里全是train.py第几百行的调用链那一刻我才意识到想真正用好这个框架光会改配置文件是不够的得把train.py这个入口脚本吃透。train.py在mmdetection里扮演的角色有点像一家餐厅的前厅经理。你作为顾客用户只需要点菜指定配置文件但前厅经理要做的事情远不止把菜单递给后厨他要确认食材齐不齐数据集加载、安排厨师分工分布式环境初始化、盯着出菜节奏训练循环调度、处理突发状况日志与检查点保存。你如果只关心菜好不好吃那确实不用管经理在忙什么但一旦菜上慢了或者上错了你就得知道问题出在哪个环节。这篇文章面向的是已经跑通过mmdetection基础训练、但遇到问题只能靠搜索引擎碰运气的开发者。我会把train.py从参数解析到训练循环的完整链路拆开讲清楚每一段代码在干什么、为什么这么设计、以及实际调试时哪些地方最容易踩坑。读完你至少能做到三件事第一看到训练报错时能快速定位是配置问题、环境问题还是数据问题第二知道怎么在不改源码的前提下通过命令行参数微调训练行为第三理解mmdetection的训练调度逻辑为后续自定义训练流程打基础。需要说明的是mmdetection版本迭代较快不同版本train.py的细节会有差异但核心骨架是稳定的。我下面基于常见的2.x版本结构来讲如果你用的是其他版本思路完全通用具体行号不必对号入座。2. train.py的整体骨架与设计思路2.1 入口脚本为什么这么薄第一次打开train.py的人往往会失望——它太短了。核心逻辑拢共就那么几十行大量功能都被封装在mmdet.apis和mmcv里。这种薄入口的设计不是偷懒而是有明确考量的。如果把所有训练逻辑都堆在train.py里会带来两个问题。一是复用困难你想在另一个脚本里调用同样的训练流程就得复制粘贴一大堆代码。二是维护噩梦训练逻辑一旦要改得同时改好几个入口脚本。mmdetection的做法是把训练流程抽象成train_detector函数放在apis里train.py只负责三件事——解析命令行参数、加载配置文件、调用训练函数。这样任何需要训练的入口比如分布式训练脚本、模型搜索脚本都能复用同一套逻辑。我个人的体会是理解这个分层之后调试思路会清晰很多。如果报错发生在参数解析阶段那问题在train.py本身或者你的命令行输入如果报错发生在配置加载阶段问题在配置文件或注册机制如果报错发生在训练循环里那就要去apis/train.py里找答案。很多人一看到报错就懵其实第一步应该是看堆栈最底部是哪个文件这直接决定了排查方向。2.2 参数解析那些你天天用却没细看的选项train.py用argparse定义了若干命令行参数常用的有config、--work-dir、--resume-from、--no-validate、--seed、--deterministic、--gpus、--launcher等。这些参数不是随便设计的每一个都对应着训练流程中一个可调节的环节。config是唯一的位置参数必须提供指向配置文件路径。这里有个细节mmdetection支持配置文件继承你传进去的config可能通过_base_字段继承了多个基础配置。加载时会做递归合并最终得到一个完整的配置字典。如果你发现某个参数没生效先检查是不是被继承链里的其他配置覆盖了。--work-dir指定工作目录日志、检查点、可视化结果都往这里放。如果不指定默认在work_dirs下按配置文件路径生成一个目录。我强烈建议每次训练都显式指定--work-dir尤其是做对比实验时否则一堆实验的输出混在一起事后根本分不清哪个是哪个。--resume-from用于从某个检查点恢复训练。注意它和--load-from的区别resume-from会恢复优化器状态、学习率调度器状态和epoch计数是真正的断点续训load-from只加载模型权重优化器重新初始化适合微调场景。这两个参数搞混是新手常见错误会导致学习率曲线出现诡异的跳变。--no-validate关闭训练过程中的验证。默认情况下每个epoch结束后会在验证集上跑一遍这会显著增加训练时间。如果你在做快速原型验证或者验证集很大可以先用这个参数关掉等模型基本稳定了再开。--seed和--deterministic控制随机性。--seed设置随机种子--deterministic会进一步设置cuDNN为确定性模式。这里有个权衡确定性模式会让训练速度下降因为一些高效的cuDNN算法是非确定性的。如果你在复现别人的实验建议两个都开如果是正常训练只设seed就够了。--gpus和--launcher是分布式训练相关参数。单卡训练时--gpus 1即可多卡时--gpus 4配合--launcher pytorch使用。这里容易踩的坑是--gpus的数量必须和实际可见的GPU数量匹配否则会报错。如果你用CUDA_VISIBLE_DEVICES限制了可见GPU--gpus要按限制后的数量来写。2.3 配置加载与注册机制框架的神经系统配置文件加载看似简单背后是mmdetection的注册机制在支撑。当你写model dict(typeFasterRCNN, ...)时框架会根据type字段去注册表里找对应的类。这个注册表是通过装饰器在模块导入时动态构建的。理解这一点很重要因为它解释了一个常见困惑为什么我自定义了一个模型类配置文件里写了typeMyModel却报not registered原因通常是你的模块没有被导入。mmdetection在mmdet/models/__init__.py里统一导入了各个子模块如果你把自定义模型放在别的目录需要确保它被正确导入或者在配置里用custom_imports字段显式导入。配置加载还有一个细节是cfg对象的访问方式。mmdetection用的是mmcv.Config支持点号访问和字典访问两种方式。cfg.model.type和cfg[model][type]等价。但要注意如果某个键不存在点号访问会报AttributeError而字典访问可以配合get方法返回默认值。在写自定义代码时这个区别会影响你的容错逻辑。3. 训练主循环从数据加载到梯度更新的完整链路3.1 分布式环境初始化单卡和多卡的分水岭train.py在调用训练函数之前会根据--launcher参数决定是否初始化分布式环境。单卡训练时这一步基本是透明的多卡训练时这里做的事情就多了设置进程组、分配rank、绑定GPU、同步随机种子。分布式初始化的核心是init_dist函数。它会根据launcher类型pytorch、slurm、mpi等调用对应的后端初始化方法。以pytorch为例它会设置MASTER_ADDR、MASTER_PORT、RANK、WORLD_SIZE等环境变量然后调用torch.distributed.init_process_group。这里有个实际调试中很有用的知识点分布式训练卡住不动十有八九是进程间通信出了问题。常见原因包括端口被占用、防火墙拦截、各节点环境变量不一致。排查方法是先确认MASTER_PORT没有被其他进程占用然后检查各节点的MASTER_ADDR是否指向同一个可达地址。如果是单机多卡这些问题一般不会出现跨机多卡才需要特别关注。另一个容易忽略的点是随机种子的同步。分布式训练时如果各进程的随机种子不一致数据增强的结果会不同虽然不影响正确性但会影响实验的可复现性。mmdetection在初始化分布式环境后会统一设置种子确保各进程行为一致。3.2 数据加载build_dataset与build_dataloader配置加载完成后框架会根据cfg.data构建数据集和数据加载器。这一步的核心函数是build_dataset和build_dataloader它们根据配置中的type字段实例化对应的类。数据集构建时有几个参数直接影响训练效果和速度。samples_per_gpu旧版叫imgs_per_gpu决定每个GPU上每个batch的样本数这个值受显存限制。workers_per_gpu决定每个GPU的数据加载进程数这个值受CPU核心数限制。我见过不少人把workers_per_gpu设得很大以为能加速结果CPU成为瓶颈反而拖慢了训练。经验值是设为CPU核心数的1/4到1/2具体要看数据增强的复杂度。数据增强管道pipeline是在数据集构建时确定的。mmdetection的pipeline是一系列变换操作的列表每个操作有type和参数。这里有个性能陷阱如果pipeline里有耗时的CPU操作比如大尺寸图像的resize而workers_per_gpu又设得不够GPU就会经常等待数据利用率上不去。用nvidia-smi看GPU利用率如果频繁在0%和100%之间跳动基本可以确定是数据加载瓶颈。提示调试数据加载问题时可以临时把workers_per_gpu设为0这样数据加载在主进程中进行报错信息更直观。但正式训练时一定要设大于0否则速度会慢很多。3.3 模型构建与权重初始化模型构建通过build_detector完成它根据cfg.model实例化检测器。这里涉及backbone、neck、head等多个组件的组装每个组件也是通过注册机制查找的。权重初始化有两种情况。从头训练时各层按默认策略初始化通常是Kaiming或Xavier。加载预训练权重时通过load_from指定检查点路径框架会做权重加载和匹配。这里有个常见问题预训练权重和当前模型结构不完全匹配时加载会报错或部分加载。mmdetection的处理策略是如果键名匹配就加载不匹配就跳过并打印警告。所以看到missing keys或unexpected keys的警告不必惊慌关键看缺失的是不是核心层。我个人的经验是做迁移学习时backbone的权重通常能完整加载neck和head的权重往往需要重新训练。如果你加载的预训练模型是在不同数据集上训练的类别数可能不一致这时head的分类层权重会被跳过这是正常现象。3.4 优化器与学习率调度器配置优化器和学习率调度器在配置文件的optimizer和lr_config字段中定义。优化器常见的有SGD、Adam、AdamW检测任务中SGD用得最多因为它在大批量训练时泛化性更好。学习率调度器控制学习率随训练进程的变化。常见策略有step、cosine、poly等。step策略在预设的epoch处衰减学习率简单直接cosine策略按余弦曲线平滑衰减近年来越来越流行poly策略按多项式衰减在一些检测论文中常见。这里有个参数计算需要说明。假设你用SGD基础学习率lr0.02这是针对batch_size168卡×2样本设定的。如果你改成4卡×2样本总batch_size变成8学习率应该按比例调整为0.01。这个线性缩放规则不是绝对的但在检测任务中是个合理的起点。如果不调整学习率相对batch_size偏大训练可能不稳定。warmup策略也值得关注。它让学习率从很小的值逐渐升到设定值避免训练初期梯度爆炸。warmup_iters和warmup_ratio控制升温的步数和起始比例。对于大batch训练或者从随机初始化开始训练warmup几乎是必需的。3.5 训练循环内部epoch、iter与hook机制真正的训练循环在apis/train.py的train_detector函数里。外层是epoch循环内层是iter循环。每个iter做四件事取数据、前向传播、计算损失、反向传播更新参数。mmdetection在训练循环中嵌入了hook机制这是它灵活性的重要来源。Hook可以在训练的不同阶段插入自定义逻辑比如学习率调整、日志记录、检查点保存、梯度裁剪等。常见的hook包括IterTimerHook计时、LrUpdaterHook学习率更新、CheckpointHook保存检查点、LoggerHook日志输出、EvalHook验证。理解hook的执行顺序很重要。以LrUpdaterHook为例它在每个iter开始前调整学习率OptimizerHook在反向传播后更新参数CheckpointHook在指定epoch结束后保存模型。如果你自定义了hook要清楚它应该在哪个阶段执行通过priority参数控制顺序。这里有个实际调试技巧如果你发现学习率曲线不对先检查LrUpdaterHook的配置如果发现检查点保存频率不对检查CheckpointHook的interval参数如果验证结果异常检查EvalHook的interval和验证配置。Hook机制让每个功能模块化排查时也能按模块定位。4. 实操中的关键环节与参数调优4.1 从零跑通一次训练完整命令与配置检查清单假设你已经装好了mmdetection数据集也准备好了下面是一次完整训练的典型流程。第一步确认配置文件路径。配置文件通常在configs目录下按模型和数据集组织。比如configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py。如果你用自己的数据集需要修改配置中的data字段或者写一个继承配置覆盖相关部分。第二步检查关键配置项。我习惯在训练前用Python快速加载配置并打印几个关键值from mmcv import Config cfg Config.fromfile(configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py) print(cfg.data.train.type) print(cfg.data.train.ann_file) print(cfg.data.train.img_prefix) print(cfg.model.type) print(cfg.optimizer.lr) print(cfg.total_epochs)这一步能提前发现路径错误、类别数不匹配等问题比训练跑起来再报错要高效得多。第三步启动训练。单卡命令python tools/train.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py \ --work-dir work_dirs/faster_rcnn_exp1 \ --seed 42 \ --deterministic多卡命令bash tools/dist_train.sh configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py 4 \ --work-dir work_dirs/faster_rcnn_exp1 \ --seed 42第四步观察日志。训练启动后日志会输出到终端和work-dir下的日志文件。重点关注loss是否正常下降、学习率是否符合预期、GPU利用率是否合理。如果loss一开始就nan检查学习率是否过大或数据是否有问题如果loss不下降检查学习率是否过小或数据标注是否有误。4.2 学习率与batch size的配合一个容易翻车的细节学习率和batch size的配合是训练中最容易出问题的地方。前面提到线性缩放规则这里展开说一下。假设官方配置是8卡×2样本lr0.02。你现在只有4卡想保持相同的训练效果。总batch size从16变成8按线性缩放lr应该设为0.01。但这里有个陷阱学习率减半后训练可能会变慢需要更多epoch才能收敛。如果你不想增加epoch可以适当调大学习率但要承担训练不稳定的风险。另一个相关参数是warmup_iters。它通常和总iter数挂钩。总iter数 (数据集大小 / 总batch size) × epoch数。如果你改了batch size总iter数变了warmup_iters也应该相应调整。官方配置里的warmup_iters通常是500或1000这个值在大多数情况下够用但如果你的数据集特别小或特别大可能需要调整。我踩过的一个坑是改了batch size但忘了改学习率结果训练loss震荡得厉害调了好久才发现是学习率相对batch size偏大。后来我养成了一个习惯每次改batch size一定同步检查学习率、warmup相关参数并在日志里确认实际学习率曲线是否符合预期。4.3 检查点管理与恢复训练别让意外中断白费功夫训练过程中最怕的就是意外中断——断电、显存溢出、误操作。mmdetection默认每个epoch保存一次检查点保存在work-dir下命名格式是epoch_*.pth。最新的检查点还会额外保存一份latest.pth方便恢复。恢复训练用--resume-frompython tools/train.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py \ --work-dir work_dirs/faster_rcnn_exp1 \ --resume-from work_dirs/faster_rcnn_exp1/latest.pth这里有个细节resume-from会恢复epoch计数训练会从下一个epoch继续。如果你用load-fromepoch计数从0开始学习率调度也会重新开始这通常不是你想要的效果。检查点保存频率可以通过配置调整。在checkpoint_config里设置interval比如interval5表示每5个epoch保存一次。对于长时间训练我建议保留interval1因为检查点文件虽然占空间但关键时刻能救命。如果磁盘空间紧张可以设置max_keep_ckpts限制保留的检查点数量。注意恢复训练时确保配置文件没有改动。如果改了模型结构或数据集恢复训练可能会报错或产生不可预期的结果。如果确实需要改配置建议用load-from加载权重重新开始训练。4.4 日志解读从loss曲线看训练状态mmdetection的日志输出很详细但信息量大也意味着容易看花眼。我通常关注几个关键指标。分类损失loss_cls和回归损失loss_bbox是检测任务的核心指标。正常情况下两者都应该稳步下降后期趋于平缓。如果loss_cls下降但loss_bbox不降可能是回归分支的学习率不够或者正样本太少。如果两者都震荡可能是学习率过大或batch size太小。学习率lr在日志中也会输出。确认实际学习率和预期一致尤其是在用了warmup或自定义调度器时。我见过有人配置了cosine调度但日志里学习率是阶梯下降最后发现是配置文件继承链里有个step调度覆盖了cosine。GPU利用率不是日志直接输出的需要用nvidia-smi或watch -n 1 nvidia-smi观察。理想的训练过程中GPU利用率应该在80%以上且相对稳定。如果利用率低且波动大说明数据加载是瓶颈考虑增加workers_per_gpu或简化数据增强。还有一个容易被忽略的指标是每个iter的耗时。日志里通常会输出time字段。如果耗时突然增加可能是数据加载变慢、GPU降频或出现了内存交换。排查时先看CPU和内存使用情况再看GPU温度和功耗。5. 常见问题与排查技巧实录5.1 启动阶段报错配置、路径与依赖问题启动阶段报错是最常见的好在排查相对容易因为报错信息通常比较明确。报错FileNotFoundError: [Errno 2] No such file or directory: xxx/annotations/instances_train2017.json这是数据集路径配置错误。检查配置文件中的ann_file和img_prefix确保路径存在且正确。如果是相对路径注意它是相对于运行目录还是配置文件目录。mmdetection通常使用相对于项目根目录的路径所以建议从项目根目录运行命令。报错KeyError: xxx is not in the models registry这是注册问题。可能原因有两个一是type字段拼写错误检查配置文件中对应模块的type值二是自定义模块没有被导入需要在配置文件中添加custom_imports字段或者在mmdet/models/__init__.py中导入。报错AssertionError: Thenum_classes(80) in Shared2FCBBoxHead of MMDataParallel does not matches the length ofCLASSES(20) in CocoDataset这是类别数不匹配。你的数据集类别数和模型配置的类别数不一致。修改配置文件中的num_classes或者检查数据集标注文件中的类别定义。报错RuntimeError: CUDA out of memory显存不足。解决方法有几种减小samples_per_gpu、减小输入图像尺寸、使用更小的模型、开启梯度累积。梯度累积可以在不增加显存的情况下模拟大batch配置里设置optimizer_config dict(typeGradientCumulativeOptimizerHook, cumulative_iters4)即可。5.2 训练中异常loss nan、不收敛与显存溢出loss变成nan这是最让人头疼的问题之一。常见原因按概率排序学习率过大、数据中有异常值比如标注框宽高为0或负、混合精度训练配置不当、模型初始化有问题。排查步骤先把学习率调小一个数量级看是否还nan。如果还nan检查数据标注用脚本统计标注框的宽高分布排除异常值。如果用了混合精度先关掉试试。如果还不行检查模型初始化尤其是自定义模块的初始化逻辑。loss不下降或下降很慢可能原因学习率过小、数据增强过强、模型容量不足、正负样本极度不平衡。先确认学习率是否合理然后检查数据增强管道看看有没有过于激进的变换。如果数据增强没问题考虑换更大的模型或者调整正负样本采样策略。训练中途显存溢出有时候训练刚开始没问题跑了一段时间才溢出。这通常是因为某些操作会累积显存比如日志中保存了太多中间变量、验证时没有释放显存。检查EvalHook的配置确保验证后释放缓存。另外如果用了--no-validate训练中途不会验证显存溢出可能推迟到检查点保存时这时检查CheckpointHook是否保存了优化器状态会占额外显存。5.3 性能瓶颈GPU利用率低与数据加载慢GPU利用率低是训练速度慢的主要原因。用nvidia-smi -l 1观察如果利用率经常低于50%说明GPU在等数据。第一步增加workers_per_gpu。从2开始逐步增加到4、8观察利用率变化。但不要超过CPU核心数否则进程切换开销会抵消收益。第二步检查数据增强管道。如果pipeline里有特别耗时的操作考虑简化或替换。比如大尺寸图像的resize很耗时可以在数据加载前就统一resize到接近目标尺寸减少在线resize的开销。第三步检查磁盘IO。如果数据集在机械硬盘上读取速度可能成为瓶颈。把数据集放到SSD上或者用内存缓存如果数据集不大。mmdetection支持data_root指向内存文件系统但需要足够的内存。第四步检查是否有CPU竞争。如果同一台机器上跑了其他任务CPU资源被抢占数据加载会变慢。用top或htop查看CPU使用情况确保训练进程能拿到足够的CPU时间。5.4 常见问题速查表问题现象可能原因排查方法解决方案启动报FileNotFoundError数据集路径错误检查配置中ann_file和img_prefix修正路径确保从项目根目录运行启动报KeyError注册表type拼写错误或模块未导入检查type值和custom_imports修正type或添加导入启动报类别数不匹配num_classes与数据集不一致检查配置和标注文件修改num_classes启动报CUDA OOM显存不足减小samples_per_gpu或图像尺寸调整batch size或开启梯度累积loss变nan学习率过大或数据异常调小学习率检查标注调整学习率清洗数据loss不下降学习率过小或增强过强检查学习率和pipeline调整学习率简化增强GPU利用率低数据加载瓶颈nvidia-smi观察利用率增加workers优化数据管道训练中途OOM显存累积检查验证和检查点配置调整EvalHook和CheckpointHook恢复训练学习率跳变用了load-from而非resume-from检查命令行参数改用resume-from多卡训练卡住通信问题检查端口和环境变量更换端口统一环境配置6. 自定义扩展在train.py基础上做文章6.1 自定义Hook不改源码实现训练过程监控mmdetection的hook机制允许你在不改动框架源码的情况下插入自定义逻辑。比如你想在每个epoch结束后记录GPU显存使用情况可以写一个自定义hook。from mmcv.runner import Hook import torch class GpuMemHook(Hook): def after_train_epoch(self, runner): if torch.cuda.is_available(): mem torch.cuda.max_memory_allocated() / 1024**3 runner.logger.info(fMax GPU memory: {mem:.2f} GB) torch.cuda.reset_peak_memory_stats()然后在配置文件中注册custom_hooks [dict(typeGpuMemHook)]这个hook会在每个epoch结束后输出峰值显存帮助你了解显存使用趋势。如果显存逐渐增长可能存在显存泄漏需要进一步排查。自定义hook的关键是理解hook的触发时机。before_run、after_run、before_train_epoch、after_train_epoch、before_train_iter、after_train_iter等选择正确的时机插入逻辑。优先级通过priority参数控制数值越小越早执行。6.2 自定义学习率策略从配置到实现内置的学习率策略不满足需求时可以自定义。mmdetection支持通过lr_config的policy字段指定自定义策略但更灵活的方式是写一个自定义hook。from mmcv.runner.hooks import LrUpdaterHook class MyLrHook(LrUpdaterHook): def get_lr(self, runner, base_lr): progress runner.epoch / runner.max_epochs # 自定义策略前一半epoch保持后一半线性衰减 if progress 0.5: return base_lr else: return base_lr * (1 - (progress - 0.5) * 2)注册方式和普通hook一样。这里要注意get_lr返回的是当前iter的学习率框架会自动应用到优化器。如果你需要更复杂的逻辑比如按iter而非epoch调整可以在before_train_iter里直接修改优化器的param_groups。我个人的经验是自定义学习率策略时先在小数据集上快速验证曲线是否符合预期再上大规模训练。学习率策略对训练结果影响很大值得花时间调试。6.3 多任务训练与梯度累积的配置技巧多任务训练在检测中很常见比如同时做检测和分割。mmdetection通过model配置支持多任务但训练时的损失权重需要仔细调整。梯度累积是另一个实用技巧。当显存不足以支撑大batch时用梯度累积模拟。配置方法optimizer_config dict( typeGradientCumulativeOptimizerHook, cumulative_iters4 )这表示每4个iter更新一次参数等效batch size扩大4倍。注意学习率也要相应调整通常按等效batch size线性缩放。梯度累积的代价是训练速度略慢因为参数更新频率降低但换来的是更稳定的训练和更好的泛化。使用梯度累积时BatchNorm的行为需要注意。如果模型里有BN层累积的多个iter的数据会分别做BN统计量会有偏差。一种解决方案是改用SyncBN它在多个iter间同步统计量但会引入通信开销。另一种方案是接受这个偏差实践中影响通常不大。7. 一些零散但有用的经验训练日志里有个Epoch [x][y/z]的格式x是当前epochy是当前iterz是总iter数。如果你发现z和预期不符检查数据集大小和batch size的计算。总iter数 ceil(数据集大小 / (samples_per_gpu × gpu数量))。如果数据集有采样策略比如按类别平衡采样实际iter数可能不同。配置文件里的total_epochs和lr_config里的step要配合。比如total_epochs12step[8, 11]表示在第8和第11个epoch衰减学习率。如果改了total_epochs但忘了改step学习率衰减时机就不对了。验证集的评估指标在训练日志里会输出常见的是bbox mAP。如果mAP波动很大可能是验证集太小或者评估间隔太短。增大验证集或降低评估频率可以让曲线更平滑。但评估频率太低又可能错过最佳检查点需要权衡。最后说一个关于随机种子的细节。即使设了--seed如果--deterministic没开结果仍然可能有微小差异。这是因为cuDNN的某些算法是非确定性的。如果你在做严格的对比实验建议两个都开并接受训练速度的下降。如果只是正常训练设seed就够了差异通常在可接受范围内。训练完成后检查点文件可以用来做推理。推理脚本是tools/test.py用法和训练类似。如果你想把模型导出成其他格式比如ONNXmmdetection也提供了相应的工具但那是另一个话题了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑