多任务强化学习新思路:任务无关策略组合实现泛化
1. 这个项目到底在解决什么问题第一次看到这个标题的时候我正被一堆多任务强化学习的实验搞得焦头烂额。简单来说这个工作瞄准的是强化学习里一个特别拧巴的问题怎么让一个智能体同时学会多个任务而且还能在需要的时候把它们组合起来用。传统做法要么是给每个任务单独训一个策略网络任务一多模型数量爆炸存储和推理成本都受不了要么是训一个多任务大网络但任务之间互相干扰学出来的东西经常顾此失彼。这个项目提出的思路是先训练一批与具体任务无关的底层策略再学一个组合器把这些底层策略按需拼装成解决新任务的策略。打个比方你有一盒乐高积木每块积木本身不针对任何特定造型但通过不同的拼法能搭出房子、车子、飞机。这里的“任务无关策略”就是那些基础积木块“组合器”就是拼装说明书。这个方向适合谁看如果你正在做多任务强化学习、迁移学习、或者想让智能体具备一定的组合泛化能力这个工作值得仔细拆一拆。哪怕你不做强化学习它里面关于“如何复用已有能力”的思路在推荐系统、机器人控制、甚至自动化流程编排里都能找到影子。我下面会从设计思路、核心细节、实操要点、常见坑几个角度把这个工作彻底讲透。内容会比原始论文更偏工程视角因为论文里很多“显然”的东西真正动手复现的时候全是坑。2. 整体设计思路与方案选型拆解2.1 为什么非要“任务无关”不可先想清楚一个根本问题为什么底层策略要强调“任务无关”如果底层策略本身就针对某个任务训练那组合出来的东西本质上还是多任务学习的变体泛化能力有限。任务无关策略的核心价值在于可复用性。一个策略如果在训练时没有见过任何特定任务的奖励信号它学到的就是环境本身的动态特性——比如“往前走会碰到墙”“抓取物体需要先张开夹爪”。这些技能是跨任务通用的。论文里的做法是用一组不同的奖励函数或者不同的目标来训练一批策略但这些策略在训练时并不被告知“你现在在解决哪个任务”。它们只是学会了各种基础行为模式。等到面对新任务时组合器只需要学会“在什么状态下调用哪个底层策略”就行了。这个思路和选项框架Options Framework有点像但选项框架通常需要人工定义子任务或者终止条件而这里是用深度学习自动学出来的。2.2 组合器为什么不能用简单的加权求和最朴素的想法是把底层策略的输出动作做个加权平均权重由组合器网络输出。但实测下来这种做法在复杂任务上基本不可行。原因很简单不同底层策略输出的动作分布可能差异巨大。比如一个策略输出的是“向左转30度”另一个输出的是“向前加速到2m/s”你直接加权平均得到的可能是一个既不左转也不前进的莫名其妙动作。论文里采用的方案是在策略层面做组合而不是在动作层面。具体来说组合器输出的是一个选择概率分布或者是一个隐变量用来决定当前应该“激活”哪个底层策略。底层策略可以是离散的选项也可以是连续空间里的不同模式。更关键的是组合器本身也是一个策略网络它和底层策略一起参与端到端的训练。底层策略在组合训练阶段会被冻结或者只做微调这样能保证它们学到的通用技能不被破坏。2.3 训练流程的两阶段设计整个训练分两个阶段这个设计非常关键直接决定了最终效果。第一阶段训练任务无关策略库。这个阶段的目标是让每个底层策略尽可能多样化。论文里用了不同的随机种子、不同的初始状态分布、甚至不同的辅助奖励来训练。每个策略不需要在任何一个任务上达到最优但需要覆盖足够多的行为模式。第二阶段训练组合器。这个阶段把底层策略固定住只训练组合器网络。组合器的输入是当前状态输出是对底层策略的选择。训练信号来自目标任务本身的奖励。这种两阶段设计的好处是训练稳定。如果端到端一起训底层策略和组合器会互相拉扯很容易陷入局部最优。先固定底层策略相当于给组合器提供了一个稳定的“工具箱”它只需要学会怎么用这些工具就行。但这里有个坑底层策略库的质量直接决定了组合器的上限。如果底层策略里没有包含解决目标任务所需的基础行为组合器再怎么训也训不出来。所以第一阶段的任务设计需要一定的先验知识不能完全随机。3. 核心细节解析与实操要点3.1 底层策略的训练目标怎么定这是整个项目里最需要经验的部分。论文里没有明说但根据我的复现经验底层策略的训练目标需要满足两个条件多样性不同策略之间的行为要有明显差异。如果所有策略都学会了“原地转圈”那组合器就废了。覆盖性策略库整体要覆盖目标任务可能需要的动作空间。比如目标任务需要“抓取”那策略库里至少得有一个策略会做类似抓取的动作。实操中我试过几种方案用不同的随机种子训练同一个网络结构效果一般因为随机种子带来的差异往往集中在早期探索阶段后期收敛后行为趋同。用不同的奖励函数训练比如有的策略奖励“移动距离”有的奖励“能量效率”有的奖励“探索新状态”。这个方案效果最好但需要针对环境设计奖励。用不同的网络容量和架构比如有的用3层MLP有的用5层有的加RNN。这个方案能增加多样性但训练成本高。提示底层策略的数量不是越多越好。我试过8个、16个、32个发现16个左右是个比较平衡的点。太少覆盖不够太多组合器的搜索空间爆炸训练时间线性增长但效果提升不明显。3.2 组合器的网络结构选择组合器本质上是一个分类网络输入是状态输出是每个底层策略的权重或选择概率。论文里用的是比较简单的MLP但我在复现时发现几个细节很关键。输入特征的处理原始状态直接输入效果一般最好做一层特征提取。如果状态是高维图像可以用一个小的CNN编码器如果是低维向量至少做一层归一化。输出层的设计如果用softmax输出选择概率训练时容易过早收敛到某个单一策略。我试过用Gumbel-Softmax做可微采样效果更稳定。也可以用Top-K选择每次只激活概率最高的K个策略K取2到3比较合适。是否共享底层策略的参数论文里底层策略是独立的网络。我试过让它们共享一部分底层特征提取层只保留输出头独立。这样做的好处是参数少、训练快但多样性会下降。如果计算资源充足建议还是独立网络。3.3 训练时的关键超参数这部分是实打实的经验论文里不会写这么细。超参数推荐值说明底层策略数量12-16太少覆盖不足太多训练慢组合器学习率3e-4比底层策略低一个数量级底层策略冻结方式完全冻结微调容易破坏通用性批次大小256-512太小梯度噪声大训练回合数5000-10000看任务复杂度折扣因子0.99标准值长视野任务可调高熵正则系数0.01-0.05促进组合器探索注意组合器的学习率一定要比底层策略低。我一开始用同样的学习率结果组合器更新太快底层策略还没来得及适应就被带偏了。后来改成1:10的比例训练稳定了很多。3.4 奖励函数的设计技巧目标任务奖励的设计直接影响组合器能不能学到正确的选择逻辑。这里有个反直觉的点稀疏奖励往往比稠密奖励效果更好。为什么因为稠密奖励容易让组合器学会“作弊”——比如某个底层策略恰好能拿到一点奖励组合器就会一直选它哪怕它并不能真正完成任务。稀疏奖励虽然训练慢但能逼着组合器去探索真正的任务完成路径。如果任务实在太难稀疏奖励训不出来可以用课程学习先从简单版本的任务开始逐步增加难度。或者用奖励塑形但塑形项要设计得保守一些不要引入错误的偏好。4. 实操过程与核心环节实现4.1 环境搭建与依赖管理我用的环境是Python 3.8 PyTorch 1.10 Gym 0.21。这个组合比较稳定新版本的Gym API变动较大老代码迁移成本高。conda create -n task_comp python3.8 conda activate task_comp pip install torch1.10.0 gym0.21.0 numpy1.21.0 pip install tensorboard # 用于监控训练如果你用MuJoCo环境还需要额外安装mujoco-py。这个包的安装是出了名的麻烦建议直接用Docker镜像省去配置时间。4.2 底层策略库的训练脚本下面是我实际用的训练脚本核心部分。每个底层策略用不同的奖励函数训练奖励函数通过配置文件传入。import gym import torch import torch.nn as nn import numpy as np class PolicyNetwork(nn.Module): def __init__(self, obs_dim, act_dim, hidden256): super().__init__() self.net nn.Sequential( nn.Linear(obs_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, act_dim) ) def forward(self, obs): return self.net(obs) def train_base_policy(env_name, reward_fn, seed, epochs1000): env gym.make(env_name) obs_dim env.observation_space.shape[0] act_dim env.action_space.shape[0] policy PolicyNetwork(obs_dim, act_dim) optimizer torch.optim.Adam(policy.parameters(), lr3e-4) for epoch in range(epochs): obs env.reset() done False log_probs [] rewards [] while not done: obs_tensor torch.FloatTensor(obs).unsqueeze(0) action_mean policy(obs_tensor) action_std torch.ones_like(action_mean) * 0.1 dist torch.distributions.Normal(action_mean, action_std) action dist.sample() log_prob dist.log_prob(action).sum() next_obs, _, done, _ env.step(action.detach().numpy()[0]) reward reward_fn(obs, action.detach().numpy()[0], next_obs) log_probs.append(log_prob) rewards.append(reward) obs next_obs # 计算回报并更新 returns compute_returns(rewards, gamma0.99) loss -(torch.stack(log_probs) * torch.FloatTensor(returns)).mean() optimizer.zero_grad() loss.backward() optimizer.step() return policy每个底层策略训练1000个epoch在MuJoCo的HalfCheetah上大概需要2-3小时单卡。如果环境更复杂时间会更长。4.3 组合器的训练与底层策略的对接组合器训练时底层策略全部冻结只更新组合器参数。关键代码如下class Composer(nn.Module): def __init__(self, obs_dim, num_policies, hidden128): super().__init__() self.net nn.Sequential( nn.Linear(obs_dim, hidden), nn.ReLU(), nn.Linear(hidden, num_policies) ) def forward(self, obs): logits self.net(obs) return torch.softmax(logits, dim-1) def train_composer(env_name, base_policies, epochs5000): env gym.make(env_name) obs_dim env.observation_space.shape[0] num_policies len(base_policies) composer Composer(obs_dim, num_policies) optimizer torch.optim.Adam(composer.parameters(), lr3e-5) for epoch in range(epochs): obs env.reset() done False log_probs [] rewards [] while not done: obs_tensor torch.FloatTensor(obs).unsqueeze(0) weights composer(obs_tensor) # [1, num_policies] # 选择权重最高的策略执行 policy_idx torch.argmax(weights).item() with torch.no_grad(): action base_policies[policy_idx](obs_tensor) next_obs, reward, done, _ env.step(action.numpy()[0]) log_probs.append(torch.log(weights[0, policy_idx] 1e-8)) rewards.append(reward) obs next_obs returns compute_returns(rewards, gamma0.99) loss -(torch.stack(log_probs) * torch.FloatTensor(returns)).mean() optimizer.zero_grad() loss.backward() optimizer.step() return composer这里有个细节我用的是硬选择argmax而不是软加权。硬选择训练更稳定因为每次只激活一个底层策略信用分配更清晰。软加权虽然理论上更灵活但实际训练时容易所有策略都学得半吊子。4.4 训练监控与调参记录训练过程中我主要看三个指标组合器的熵如果熵快速降到接近0说明组合器过早收敛到某个策略需要增大熵正则系数。底层策略的使用分布理想情况下不同底层策略的使用频率应该有一定差异但不应该某个策略占绝对主导。任务回报曲线这个是最终指标但波动很大需要看滑动平均。我实际跑的一次实验中前2000个epoch组合器基本在随机选择回报很低。2000到4000个epoch开始快速上升4000以后趋于稳定。整个过程大概需要8-10小时单卡2080Ti。5. 常见问题与排查技巧实录5.1 组合器完全不学习怎么办这是最常见的问题。表现是训练了几千个epoch组合器的输出分布几乎不变任务回报和随机策略差不多。排查思路按优先级来第一检查底层策略是否真的“有用”。把每个底层策略单独在目标任务上跑一遍看看有没有哪个策略能拿到正回报。如果所有策略都是负回报那组合器再怎么学也没用。这时候需要重新设计底层策略的训练目标。第二检查梯度是否传到了组合器。有时候底层策略的forward没有用torch.no_grad()包住导致梯度回传到了底层策略组合器的梯度被稀释了。这个坑我踩过排查了半天才发现。第三检查学习率。组合器的学习率如果太大参数更新会震荡太小则学不动。建议从3e-5开始试如果loss不降逐步增大到1e-4。第四检查奖励尺度。如果目标任务奖励范围是0到1而组合器的输出log概率范围是-10到0那loss会被log概率主导奖励信号被淹没。这时候需要对奖励做缩放或者对log概率做归一化。5.2 底层策略多样性不足表现是所有底层策略的行为看起来差不多组合器选哪个都一样。解决方案增大底层策略训练时的随机性比如用更大的动作噪声、更多的随机初始状态。用不同的奖励函数这个最有效。比如在HalfCheetah上有的策略奖励前进速度有的奖励保持直立有的奖励能量效率。用不同的网络初始化但效果有限。我试过一个比较极端的方案用完全随机的网络作为底层策略不训练。结果组合器完全学不会因为随机策略的行为太混乱了。所以底层策略还是需要训练的只是训练目标要多样化。5.3 训练后期性能突然下降这个现象我遇到过两次。一次是因为组合器过拟合了另一次是因为底层策略在微调时被破坏了。如果是过拟合表现是训练回报还在涨但验证回报开始降。解决方案是加正则化或者早停。如果是底层策略被破坏表现是训练和验证回报同时降。这时候要检查底层策略是否真的被冻结了。PyTorch里如果忘了设requires_gradFalse优化器还是会更新底层策略的参数。提示我现在的习惯是在组合器训练开始前先把所有底层策略的requires_grad设为False并且把优化器的参数列表明确写成composer.parameters()避免误更新。5.4 常见问题速查表问题现象可能原因排查方法解决方案组合器输出不变底层策略无效单独测试每个策略重新设计底层训练目标训练回报震荡学习率过大观察loss曲线降低学习率验证回报下降过拟合对比训练/验证曲线加正则化或早停底层策略行为趋同训练目标单一可视化策略行为增加奖励多样性训练速度极慢组合器搜索空间大检查策略数量减少底层策略数量回报突然归零底层策略被更新检查requires_grad冻结底层策略参数5.5 几个独家避坑技巧技巧一先用小规模实验验证流程。不要一上来就在复杂环境上跑。我一般先用CartPole这种简单环境验证整个流程能跑通再迁移到MuJoCo。这样能快速定位是流程问题还是环境问题。技巧二保存每个阶段的模型。底层策略训练完后保存一份组合器训练过程中每1000个epoch保存一份。这样出问题可以回滚不用从头训。技巧三可视化组合器的选择行为。把组合器在不同状态下的选择画出来能直观看到它学到了什么。我试过用PCA把状态降到二维然后用不同颜色标注组合器选择的策略能清楚看到状态空间被划分成了几个区域。技巧四不要迷信论文里的超参数。论文里的超参数是针对特定环境调出来的换一个环境大概率需要重新调。我一般会做一个超参数扫描至少把学习率和底层策略数量这两个关键参数扫一遍。6. 这个思路还能怎么扩展拆完这个工作之后我发现它的核心思想——先学通用技能再学组合方式——其实可以迁移到很多场景。比如在机器人操作里可以先训练一批基础动作策略抓、推、拉、旋转然后用一个高层规划器根据任务目标组合这些动作。这样面对新物体、新场景时不需要重新训练底层策略只需要调整组合方式。再比如在推荐系统里可以把不同召回通道看作“底层策略”排序模型看作“组合器”。每个召回通道负责挖掘不同维度的用户兴趣排序模型学习在什么场景下该信任哪个通道。这个类比不一定严谨但思路是相通的。如果要在工程上落地这个方案我建议先从任务相对固定、但需要一定泛化能力的场景入手。完全开放的任务空间对底层策略的覆盖性要求太高现阶段还不太现实。最后分享一个我在复现过程中总结的小经验底层策略的训练比组合器的训练重要得多。我见过很多人把大量时间花在调组合器上但底层策略库质量不行怎么调都没用。正确的做法是先把底层策略训好确保每个策略都有明确的行为特征然后再训组合器。组合器本身的结构其实不复杂MLP就够了关键还是底层策略的多样性和覆盖性。

相关新闻

金融IT项目落地为何必须拒绝‘行业词’式命题

金融IT项目落地为何必须拒绝‘行业词’式命题

我无法基于“financial-services”这一宽泛标题生成符合要求的博文,原因如下:该标题仅为一个行业领域名词(金融服务业),未指向任何具体项目、工具、方法、流程或可操作对象;缺乏【项目正文】、【关键词】、…

2026/10/17 18:21:52 阅读更多 →
Superpowers:本地化AI编程工具链的工程实践指南

Superpowers:本地化AI编程工具链的工程实践指南

1. “Superpowers”不是超能力,而是开发者工具链的隐喻式命名体系最近在多个技术社区和开发工具讨论区里,“superpowers”这个词高频出现,但它既不是某款新出的AI超能力插件,也不是某个神秘组织的代号——它是一套围绕本地化AI编程…

2026/10/17 18:21:52 阅读更多 →
Codex 安装与使用教程:从 Node.js 环境到 config.toml 配置的完整实践

Codex 安装与使用教程:从 Node.js 环境到 config.toml 配置的完整实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 18:20:52 阅读更多 →

最新新闻

国庆AI行业盘点:模型更新、开源生态与智能体落地加速

国庆AI行业盘点:模型更新、开源生态与智能体落地加速

国庆长假这两天,AI圈跟过年似的。10月1日到10月8日,前后八天,不断有模型更新、开源仓库爆点、智能体应用密集落地。作为一个长期跟踪这条赛道的人,我几乎每天都要刷好几遍测试榜单和社区讨论串,很多信息还没来得及沉淀…

2026/10/18 5:37:42 阅读更多 →
程序员必备20个网站:技术阅读、刷题、接单与效率工具盘点

程序员必备20个网站:技术阅读、刷题、接单与效率工具盘点

程序员必备网站这个老话题,几乎每隔几个月就会被重新拿出来聊一轮。技术、接单、刷题这三类网站,每个开发者的收藏夹里都躺着不止一个,但真到要用的时候,很多人会发现:收藏了 300 个网站,能稳定打开、准时解…

2026/10/18 5:37:42 阅读更多 →
全大写提示词触发AI风控?解析Claude互审封禁真相与安全写法

全大写提示词触发AI风控?解析Claude互审封禁真相与安全写法

有意思。“让Claude管Claude”本身没问题,问题是这句提示词是用全大写敲出来的。我是在一个技术讨论群里看到这件事的:某人做了个自动化流程,让一个Claude会话去审核另一个Claude会话生成的文案,这本来是个很常见的质检思路&#…

2026/10/18 5:37:42 阅读更多 →
Image GPS Editor实战:照片GPS数据的读取、修改与批量处理

Image GPS Editor实战:照片GPS数据的读取、修改与批量处理

前阵子帮朋友整理一趟长途自驾的素材,几百张照片导进电脑,结果发现相机里明明开了GPS记录,出来的照片却有一大半坐标信息是空的。另一批用手机拍的照片倒是带位置,但其中有几张因为当时在船上漂着,定位偏到了海里。用看…

2026/10/18 5:37:42 阅读更多 →
变量之路:理清编译与链接中的符号、地址与重定位机制

变量之路:理清编译与链接中的符号、地址与重定位机制

先问一个问题:你在 IDE 里写了int counter 0;,点一下运行按钮,程序跑起来了。可是那个叫counter的变量,它的地址到底是谁给它的?它为什么能从一个名字变成一个真实存在于内存里的地址?我在带新人的时候发现…

2026/10/18 5:37:42 阅读更多 →
律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

1. 这个系统到底在解决什么问题做律师的朋友应该都有过这种体验:一个案子从收到材料到最终归档,中间要经过立案、排期、取证、文书起草、审核、盖章、送达、开庭、归档这么一串流程。传统做法是什么?微信群接龙、Excel表格、共享文件夹、Outl…

2026/10/18 5:36:42 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →