简介本资源是一套面向深度强化学习研究者与进阶开发者的模仿学习算法开源实现聚焦于在PPO策略框架下对比分析主流逆强化学习与行为克隆方法。涵盖AIRL、BC、DRIL、FAIRL、GAIL、GMMIL、nn-PUGAIL、RED等8种核心算法并支持状态-only模仿、吸收态建模及R1梯度正则化等关键实验配置适用于机器人控制、自动驾驶策略迁移等典型场景。压缩包共27个文件含6个核心Python脚本如main.py、training.py、evaluation.py、2个说明文档README.md、LICENSE.md、17张训练/测试结果可视化图表PNG格式及1个预训练专家轨迹模型.pth整体仅999KB轻量易部署。已有1068人学习下载提供开箱即用的完整实验流程从环境构建、算法调用、训练日志记录到多维度性能评估所有图表均按算法分类命名目录结构清晰便于复现实验、横向对比收敛性与泛化能力。1. 模仿学习不是“抄作业”而是让模型学会“看人做事”从人类示范中提取策略的完整闭环你有没有试过训练一个机械臂抓取杯子结果强化学习跑了三天奖励曲线像心电图一样乱跳最后只学会疯狂撞桌角某高校实验室去年就卡在这个点上——他们手头有200段专家操作视频、带力反馈的手套轨迹、甚至还有多视角同步录像但硬是没用上。直到把整套数据喂进一个轻量级模仿学习 pipeline3 小时内就跑出了可部署的策略模型。这不是玄学是模仿学习Imitation Learning在真实场景下的典型价值它绕开稀疏奖励、避免探索风险、直接复用人类先验知识。这个imitation-learning开源项目就是一套端到端可复现的 PyTorch 实现覆盖行为克隆Behavior Cloning、DAgger、GAIL 三大主流范式所有代码都经过 CUDA 11.3 PyTorch 1.12 环境实测支持从.npy轨迹文件一键加载、自动划分训练/验证集、内置 CarRacing-v0 和 PandaReach-v3 两个仿真环境接口。适合刚跑通第一个 DQN 的强化学习新手也适合需要快速落地机器人策略迁移的工程团队——只要你手里有“人怎么做”的数据它就能告诉你“模型该怎么学”。2. 行为克隆BC最朴素却最常被低估的起点从轨迹加载到损失函数定制行为克隆是模仿学习的基石原理极简把人类示范当作监督信号用标准的监督学习方式训练策略网络。但它绝不是“随便写个 MSE 就完事”。这个项目里 BC 模块的设计恰恰暴露了多数初学者踩坑的第一道坎输入状态与输出动作的时空对齐是否严格动作标签是否做了域内归一化损失函数是否适配动作空间类型下面我们拆解从原始轨迹到可训练模型的每一步。2.1 轨迹数据格式规范与预处理脚本项目默认接受两种轨迹格式demo_{env_name}.npy三维 NumPy 数组(N, T, D)其中N是轨迹数量T是每条轨迹步数需统一D是状态动作拼接维度demo_{env_name}_split/目录内含states.npy(N*T, S)、actions.npy(N*T, A)、dones.npy(N*T,)三个文件支持变长轨迹。提示若你的数据是 ROS bag 或 CSV 导出务必先用scripts/convert_to_npy.py转换。该脚本强制校验states与actions行数一致并对actions执行np.clip(action, env.action_space.low, env.action_space.high)—— 这步能避免后续训练因越界动作导致梯度爆炸。# scripts/convert_to_npy.py 关键逻辑 import numpy as np from gym import spaces def load_csv_traj(csv_path: str, state_cols: list, action_cols: list): df pd.read_csv(csv_path) states df[state_cols].values.astype(np.float32) actions df[action_cols].values.astype(np.float32) # 关键按环境动作空间裁剪非简单归一化 if hasattr(env, action_space) and isinstance(env.action_space, spaces.Box): actions np.clip(actions, env.action_space.low, env.action_space.high) return states, actions # 输出为 (N*T, S) 和 (N*T, A)供 BC DataLoader 直接读取 np.save(states.npy, states) np.save(actions.npy, actions)这段代码后必须做两件事① 确认state_cols顺序与env.observation_space.shape严格一致例如 PandaReach 的qpos必须在前7维qvel在后7维②action_cols维度必须等于env.action_space.shape[0]。我曾见过某团队因 CSV 中混入时间戳列导致动作维度错位模型收敛后输出全是nan查了两天才发现是action_cols多写了一列。2.2 BC 模型结构与损失函数可配置化设计项目中的BCPolicy类采用模块化设计核心在于forward()与compute_loss()分离# models/bc_policy.py class BCPolicy(nn.Module): def __init__(self, state_dim: int, action_dim: int, hidden_dims: list [256, 256]): super().__init__() self.net MLP(state_dim, hidden_dims, action_dim) # 标准MLP self.action_space None # 后续由env注入 def forward(self, obs: torch.Tensor) - torch.Tensor: return self.net(obs) # 输出原始logits或未裁剪动作 def compute_loss(self, obs: torch.Tensor, actions: torch.Tensor) - torch.Tensor: pred_actions self(obs) # 关键根据动作空间类型自动选择损失函数 if isinstance(self.action_space, spaces.Box): # 连续动作使用MSE但加权处理高斯噪声项 loss F.mse_loss(pred_actions, actions, reductionnone) # 对每个动作维度加权力控任务中 torque 维度权重应高于 position if hasattr(self, action_weights) and self.action_weights is not None: loss (loss * torch.tensor(self.action_weights, deviceloss.device)).mean() else: loss loss.mean() elif isinstance(self.action_space, spaces.Discrete): # 离散动作CrossEntropy需将actions转为long loss F.cross_entropy(pred_actions, actions.long()) else: raise NotImplementedError(fUnsupported action space: {self.action_space}) return loss参数说明hidden_dims[256, 256]是经验性起点对于高自由度机械臂如 Panda 7-DoF建议升至[512, 512, 256]action_weights是字典形参数例如{torque: 2.0, position: 1.0}在train_bc.py中通过--action-weight-torque 2.0注入若你的环境动作含物理约束如关节限位切勿在forward()中直接torch.clamp()—— 这会截断梯度应在compute_loss()前用env.action_space裁剪标签而非预测值。2.3 训练脚本参数详解与硬件适配技巧train_bc.py支持全参数命令行注入以下是最常调优的 5 个参数及其物理意义参数默认值推荐值CarRacing推荐值PandaReach说明--batch-size12825664轨迹短100步用小 batch 防过拟合轨迹长500步可用大 batch 加速--lr3e-41e-45e-5连续控制任务对学习率更敏感Panda 的 torque 控制需更低 lr 避免抖动--weight-decay1e-501e-4动作含高频噪声时加 weight decay 可抑制过拟合尤其对 force/torque 维度--num-epochs10520CarRacing 示范质量高5轮足够Panda 数据少且含误差需更多 epoch--eval-freq115Panda 每次仿真耗时高降低评估频率防拖慢训练执行命令示例PandaReach 场景python train_bc.py \ --env-name PandaReach-v3 \ --demo-path ./data/panda_reach_demos/ \ --batch-size 64 \ --lr 5e-5 \ --weight-decay 1e-4 \ --num-epochs 20 \ --action-weight-torque 3.0 \ --action-weight-position 1.0 \ --device cuda:0注意--device必须显式指定项目不自动 fallback 到 CPU。若cuda:0显存不足可改用cuda:1并在train_bc.py第 89 行添加torch.cuda.set_device(args.device)—— 这是 PyTorch 1.12 的已知行为变更不加会导致RuntimeError: Expected all tensors to be on the same device。3. DAgger解决行为克隆泛化灾难的迭代修正机制如何让模型在“犯错”中持续进化行为克隆最大的硬伤是训练时看到的全是专家状态而部署时模型会进入自己生成的、分布偏移的状态distributional shift。DAggerDataset Aggregation正是为此而生它不追求一步到位而是让模型边执行、边收集“自己搞砸时的状态”再请专家标注这些状态下的正确动作从而把训练分布逐步拉回真实 rollout 轨迹。这个项目里的 DAgger 实现关键在于三阶段闭环控制模型 rollout → 状态采样 → 专家标注 → 数据融合。下面拆解其工程实现细节。3.1 DAgger 的三阶段数据流与rollout_buffer设计DAgger 的核心数据结构是RolloutBuffer它并非简单存储(s,a)对而是维护三个独立缓冲区expert_buffer: 存储原始专家轨迹只读永不更新model_buffer: 存储模型 rollout 产生的(s, a_pred, done)用于计算当前策略性能query_buffer: 存储待专家标注的状态s_query按uncertainty_score排序默认用动作方差。# buffers/dagger_buffer.py class RolloutBuffer: def __init__(self, state_dim: int, action_dim: int, max_size: int 10000): self.states np.empty((max_size, state_dim), dtypenp.float32) self.actions np.empty((max_size, action_dim), dtypenp.float32) self.dones np.empty(max_size, dtypebool) self.uncertainties np.empty(max_size, dtypenp.float32) # 用于排序 self.ptr 0 self.size 0 def add(self, state: np.ndarray, action: np.ndarray, done: bool, uncertainty: float): self.states[self.ptr] state self.actions[self.ptr] action self.dones[self.ptr] done self.uncertainties[self.ptr] uncertainty self.ptr (self.ptr 1) % self.max_size self.size min(self.size 1, self.max_size) def get_top_k_states(self, k: int) - np.ndarray: # 返回 uncertainty 最高的 k 个状态 idx np.argsort(self.uncertainties)[-k:] return self.states[idx]关键点uncertainty不是凭空计算的。项目中默认采用动作方差法对每个状态s让策略网络前向 5 次启用 dropout计算输出动作的方差var(a|s)。若方差 0.1说明模型对该状态决策信心低优先送入query_buffer。这比随机采样效率高 3.2 倍实测 CarRacing 数据。3.2 专家标注接口与human_in_the_loop模式项目提供两种专家标注方式离线模式default用预存的专家策略如expert_policies/car_racing_expert.pt自动标注在线模式--human-in-the-loop启动 PyGame 窗口由真人实时操作并记录动作。# trainers/dagger_trainer.py def collect_queries(self, policy: nn.Module, env, num_queries: int 100): query_states [] if self.args.human_in_the_loop: # 启动交互窗口监听键盘事件 pygame.init() screen pygame.display.set_mode((800, 600)) clock pygame.time.Clock() for _ in range(num_queries): obs env.reset() done False while not done: # 渲染环境 env.render() # 获取键盘动作WASD 控制 action self._get_human_action() obs, _, done, _ env.step(action) if self._is_uncertain(obs, policy): # 方差阈值判断 query_states.append(obs.copy()) clock.tick(30) else: # 离线模式用专家策略 rollout expert_policy torch.load(self.args.expert_policy_path) for _ in range(num_queries): obs env.reset() done False while not done and len(query_states) num_queries: with torch.no_grad(): action expert_policy(torch.from_numpy(obs).float().to(self.device)) obs, _, done, _ env.step(action.cpu().numpy()) if self._is_uncertain(obs, policy): query_states.append(obs.copy()) return np.array(query_states)注意在线模式下pygame依赖需单独安装pip install pygame且必须在 X11 环境运行WSL2 用户需配置export DISPLAY:0。若报pygame.error: No available video device请改用离线模式。3.3 数据融合策略与beta_schedule的物理含义DAgger 的灵魂在于beta参数它控制每轮迭代中新采集的专家数据占训练集的比例。beta1.0即完全用新数据纯行为克隆beta0.0即完全用旧数据无改进。项目采用线性衰减调度# trainers/dagger_trainer.py def get_beta(self, iteration: int, total_iters: int) - float: # beta_t 1 - t/T第1轮全用新数据最后一轮全用旧数据 return 1.0 - (iteration / total_iters)但实际调试发现固定线性衰减并不鲁棒。某跨平台系统项目中我们改为性能驱动调度当模型在验证集上的 rollout success rate 提升 2% 时beta重置为 0.8强制注入高质量新数据。这使 PandaReach 的抓取成功率从 63% 提升至 89%。执行 DAgger 训练的完整命令python train_dagger.py \ --env-name PandaReach-v3 \ --demo-path ./data/panda_reach_demos/ \ --expert-policy-path ./expert_policies/panda_expert.pt \ --num-iterations 5 \ --queries-per-iter 50 \ --bc-batch-size 64 \ --bc-lr 5e-5 \ --device cuda:0 \ --save-dir ./dagger_models/每轮迭代后脚本自动保存dagger_iter_{i}.pt并打印[DAgger Iter 3] Train Acc: 0.821 | Val Success Rate: 0.76 | New Queries Added: 47/50若New Queries Added长期低于 80%说明uncertainty_threshold设得太低需调小默认 0.1 → 0.05。4. GAIL用对抗思想解决奖励函数缺失难题判别器如何教会生成器“像人一样动”当你的任务没有明确奖励函数比如“写字要像人”“走路要自然”而只有专家演示时GAILGenerative Adversarial Imitation Learning就是终极答案。它把模仿学习转化为一个对抗游戏生成器策略网络试图骗过判别器区分专家 vs 模型轨迹判别器则努力分辨真假。这个项目中的 GAIL 实现避开了原论文中复杂的 TRPO 更新改用PPO 判别器联合训练大幅降低调参门槛。但它的陷阱恰恰藏在判别器的输入构造和梯度截断里。4.1 判别器输入构造为什么必须用(s,a,s)三元组GAIL 原论文用状态转移(s,a,s)作为判别器输入而非单纯(s,a)。原因很物理人类动作具有强时序依赖性。例如 CarRacing 中“向左打方向”在直道是危险动作在弯道却是必要操作。仅看(s,a)判别器无法判断合理性但加入s下一帧图像或状态它就能捕捉“打方向后车是否顺利入弯”这一因果链。项目中Discriminator输入为(s,a,s)拼接向量# models/gail_discriminator.py class Discriminator(nn.Module): def __init__(self, state_dim: int, action_dim: int, hidden_dims: list [256, 256]): super().__init__() # 输入维度 state_dim action_dim state_dim self.net MLP(state_dim action_dim state_dim, hidden_dims, 1) def forward(self, s: torch.Tensor, a: torch.Tensor, s_next: torch.Tensor) - torch.Tensor: x torch.cat([s, a, s_next], dim-1) # shape: (B, 2*SA) return torch.sigmoid(self.net(x)) # 输出 [0,1]表示“专家概率”关键参数state_dim必须与s_next维度严格一致。若你的环境s_next包含额外信息如s_next[achieved_goal]需在env.step()后手动提取s_next_vec np.concatenate([s_next[observation], s_next[achieved_goal]])否则判别器输入维度错位训练会静默失败loss 不下降但梯度正常。4.2 GAIL 损失函数与 PPO 的耦合更新机制GAIL 不直接优化策略而是将判别器输出D(s,a,s)视为伪奖励r(s,a,s) -log(D(s,a,s))再用 PPO 优化该奖励下的策略。项目中GAILTrainer的核心循环如下# trainers/gail_trainer.py for step in range(self.args.num_steps): # 1. 用当前策略 rollout收集 (s,a,s,done) batch self.rollout(policy, env) # 2. 判别器前向计算伪奖励 with torch.no_grad(): d_logits self.discriminator(batch.s, batch.a, batch.s_next) # 伪奖励 -log(D) for expert-like, log(1-D) for model-like rewards -torch.log(d_logits 1e-8) # 防止 log(0) # 3. PPO 更新策略标准PPO loss value loss ppo_loss self.ppo_update(policy, batch, rewards) # 4. 判别器更新专家数据 label1模型数据 label0 expert_batch self.sample_expert_batch() d_loss_expert F.binary_cross_entropy( self.discriminator(expert_batch.s, expert_batch.a, expert_batch.s_next), torch.ones_like(expert_batch.s[:, 0]) ) d_loss_model F.binary_cross_entropy( self.discriminator(batch.s, batch.a, batch.s_next), torch.zeros_like(batch.s[:, 0]) ) d_loss d_loss_expert d_loss_model self.discriminator_optim.zero_grad() d_loss.backward() self.discriminator_optim.step()这里有两个血泪经验梯度截断必须加在判别器更新后若d_loss过大5.0d_logits会饱和趋近 0 或 1导致伪奖励r爆炸。项目在d_loss.backward()后插入torch.nn.utils.clip_grad_norm_(self.discriminator.parameters(), max_norm0.5)PPO 的clip_epsilon需调小GAIL 中伪奖励方差极大标准 PPO 的clip_epsilon0.2会导致策略更新过于激进。实测0.1更稳定通过--ppo-clip-eps 0.1设置。4.3 GAIL 训练稳定性诊断表5 个关键指标与修复方案GAIL 是出了名的难训但问题总有迹可循。以下是我在某图像引导机器人项目中总结的GAIL 健康度诊断表每项指标对应具体修复动作指标健康值异常现象原因修复方案D_expert_mean0.85长期 0.7判别器欠拟合无法识别专家特征增加判别器层数--disc-hidden-dims 512 512或降低--disc-lr1e-4→5e-5D_model_mean0.3长期 0.5判别器过强策略无法欺骗减小判别器容量或增加--disc-update-ratio每轮 PPO 更新 1 次判别器更新 3 次reward_std2.0×reward_mean5.0×reward_mean伪奖励方差过大PPO 更新震荡启用--reward-normalize对每 batch reward 做 Z-score 归一化entropy_loss缓慢下降至 0.1~0.3持续 0.5 或 0.05策略过早收敛或发散调整--entropy-coef默认 0.01 → 0.005 或 0.02kl_div0.020.1PPO 更新步长过大降低--ppo-clip-eps0.1→0.05或增加--ppo-epochs10→20执行 GAIL 训练的推荐命令CarRacingpython train_gail.py \ --env-name CarRacing-v0 \ --demo-path ./data/car_racing_demos/ \ --disc-hidden-dims 512 512 \ --disc-lr 5e-5 \ --ppo-clip-eps 0.05 \ --entropy-coef 0.005 \ --reward-normalize \ --device cuda:0首次运行时务必打开--verbose观察前 100 步的D_expert_mean和D_model_mean是否快速分离目标前者 0.9后者 0.2。若 200 步后仍胶着立即停机检查demo_path是否误用了模型轨迹。5. 避坑指南模仿学习四大经典翻车现场与根因定位法模仿学习看似流程清晰实则处处是坑。这些坑往往不报错只让模型“安静地失败”——训练 loss 下降、验证 accuracy 达标但部署时动作诡异、策略崩溃。以下是我在多个机器人项目中踩过的4 个高频翻车现场每个都附带可复现的现象、底层根因和一行命令级修复方案。5.1 翻车现场一行为克隆训练 loss 降得飞快但 rollout 时模型疯狂抖动现象train_bc.py运行 10 分钟train_loss从 0.5 降到 0.02val_acc达 98%但eval_policy.py一运行机械臂关节像触电一样高频震颤torque输出在 ±50 N·m 间瞬时切换。根因动作标签未做物理域裁剪而是在forward()中用torch.clamp()截断。这导致反向传播时梯度在裁剪边界处突变为 0clipping gradient vanishing模型只学会在边界附近“试探”而非真正理解力控逻辑。修复✅ 正确做法在数据预处理阶段用env.action_space严格裁剪actions.npypython scripts/clip_actions.py --demo-path ./data/panda_demos/ --env-name PandaReach-v3❌ 错误做法在BCPolicy.forward()中写return torch.clamp(self.net(obs), -1.0, 1.0)。5.2 翻车现场二DAgger 迭代 5 轮Val Success Rate却从 72% 降到 58%现象train_dagger.py第 1 轮Val Success Rate0.72第 3 轮跌至0.65第 5 轮仅0.58New Queries Added却始终 45/50说明数据在持续注入。根因uncertainty_score计算错误。项目默认用动作方差但若你的策略网络未启用 dropoutmodel.eval()模式下 dropout 自动关闭方差恒为 0query_buffer实际填充的是随机状态专家标注的全是“简单样本”反而稀释了原始专家数据的高质量分布。修复✅ 强制在 rollout 时启用 dropout# trainers/dagger_trainer.py line 142 policy.train() # 关键必须设为 train 模式以启用 dropout with torch.no_grad(): action policy(obs_tensor) policy.eval() # 用完立刻切回 eval✅ 或改用更鲁棒的不确定性度量--uncertainty-method entropy对分类动作或--uncertainty-method ensemble需启动多模型。5.3 翻车现场三GAIL 训练中D_expert_mean一直为 0.5D_model_mean也是 0.5现象train_gail.py运行 1 小时判别器两个输出均值稳定在0.498±0.002伪奖励rewards全是-log(0.5)≈0.693策略更新等同于随机游走。根因判别器输入(s,a,s)的s_next维度与s不匹配。例如 CarRacing 的s是(96,96,3)图像而s_next被错误传入了(1,96,96,3)多了 batch 维torch.cat后维度混乱判别器根本学不到任何特征。修复✅ 在rollout函数中强制校验s_next形状# utils/rollout.py line 67 assert s_next.shape s.shape, fs_next shape {s_next.shape} ! s shape {s.shape}✅ 或使用项目内置的--debug-shape模式它会在每步打印所有张量形状。5.4 翻车现场四所有算法在 CarRacing 上表现良好但迁移到 PandaReach 时CUDA out of memory现象train_bc.py --env-name CarRacing-v0用--batch-size 256顺畅运行但换--env-name PandaReach-v3后即使--batch-size 16也报CUDA out of memorynvidia-smi显示显存占用从 2GB 飙到 12GB。根因PandaReach 的observation_space含高维图像Box(0,255,(128,128,3),uint8)而 CarRacing 是低维向量。项目默认对图像观测不做 resize导致s张量巨大128*128*349152维batch_size16时仅s就占16*49152*4≈3MB但实际因中间激活层爆炸显存飙升。修复✅ 强制图像预处理在env.reset()后插入cv2.resize# environments/panda_reach_env.py line 89 if isinstance(obs, dict) and image in obs: obs[image] cv2.resize(obs[image], (64, 64)) # 降采样到 64x64✅ 或启用项目全局开关--resize-image 64 64它会自动包装所有gym.Env的step()和reset()。6. 模型蒸馏与跨环境部署如何把 2GB 的 GAIL 策略压缩成 12MB 的 ONNX 模型当你在仿真环境里调通了 GAIL下一步必然是部署到真机。但真机资源有限Jetson AGX Orin 只有 32GB 内存ROS 2 节点要求模型加载 500ms而原生 PyTorch 模型动辄 1.8GB含优化器状态、历史 buffer。这个项目提供的export_onnx.py工具能把训练好的策略网络BC/GAIL/DAgger一键导出为 ONNX再经 TensorRT 加速实测推理延迟从 47ms 降至 3.2ms体积从 2.1GB 压缩至 11.7MB。下面是我压测 3 个真实场景后总结的蒸馏全流程。6.1 ONNX 导出必须冻结的 4 个动态节点ONNX 不支持 Python 控制流如if/else、动态张量形状如s.shape[0]、以及 PyTorch 特有算子如torch.nn.functional.interpolate。项目export_onnx.py的核心是构建一个纯前向、静态图、无副作用的封装类# exporters/export_onnx.py class PolicyWrapper(nn.Module): def __init__(self, policy: nn.Module, env_name: str): super().__init__() self.policy policy.eval() # 必须 eval 模式 self.env_name env_name # 关键预注册所有可能的输入 shape禁用动态推理 if CarRacing in env_name: self.input_shape (1, 96, 96, 3) # HWC 格式 elif PandaReach in env_name: self.input_shape (1, 64, 64, 3) # 已 resize def forward(self, obs: torch.Tensor) - torch.Tensor: # 强制 reshape消除动态 shape obs obs.view(self.input_shape) # 不用 obs.reshape(-1) # 移除所有非前向操作no dropout, no logging, no env.step with torch.no_grad(): action self.policy(obs) # 关键动作裁剪必须在 ONNX 外部做ONNX 不支持 clip # 所以这里只输出 raw action裁剪交给 C host 程序 return action # 导出命令 wrapper PolicyWrapper(trained_policy, args.env_name) dummy_input torch.randn(1, *wrapper.input_shape[1:], dtypetorch.float32) torch.onnx.export( wrapper, dummy_input, f{args.output_dir}/policy.onnx, input_names[obs], output_names[action], opset_version12, # 必须 ≤12TensorRT 8.4 不支持 14 dynamic_axes{obs: {0: batch}, action: {0: batch}} # 仅 batch 维动态 )注意opset_version12是硬性要求。若用14TensorRT 会报Unsupported ONNX data type。这是 NVIDIA 官方文档明确标注的兼容性限制。6.2 TensorRT 优化从 ONNX 到 INT8 量化引擎的 5 步编译ONNX 文件只是中间表示真正提速靠 TensorRT。项目compile_trt.py封装了完整的编译链# 编译命令Jetson 环境 python compile_trt.py \ --onnx-path ./exports/policy.onnx \ --engine-path ./exports/policy.engine \ --precision int8 \ --calibration-data ./data/calib_samples.npy \ # 用于 INT8 量化的 500 个样本 --workspace-size 2048 \ # MBOrin 至少 2048 --max-batch-size 16编译过程分 5 步每步都有失败风险点ONNX 解析检查opset_version和算子支持trtexec --onnxpolicy.onnx --verbose图优化合并 Conv-BN-Re本文还有配套的精品资源点击获取