应在统一预处理、同设备、同shape前提下,对各模型logits加权平均后softmax;须严格校验归一化参数、RGB顺序、输出维度等预处理一致性,避免因量级或分布差异导致集成失效。

怎么把多个 PyTorch 模型的输出加权平均
直接对每个模型的 logits 或 probs 张量按维度加权求和,再归一化(如需概率输出)。关键不是“怎么算”,而是“在哪算”——必须确保所有模型输出 shape 一致、设备一致、数据预处理一致。
- 先用
model.eval()和torch.no_grad()关掉梯度和训练模式 - 每个模型前向后立刻转到同一设备(比如都
.to('cpu')),避免RuntimeError: Expected all tensors to be on the same device - 检查输出 shape:二分类通常为
[N, 2],多分类为[N, C],若某模型输出是[N](单 logit),得先用torch.sigmoid或拼接成两维,否则加权会出错 - 权重用 Python list 或
torch.tensor都行,但要和模型顺序严格对应;例如权重[0.4, 0.35, 0.25]对应[model_a, model_b, model_c]
为什么不能直接对 softmax 后的概率加权平均
可以,但不推荐——它在数学上等价于对 logits 加权平均后再 softmax 的近似,且损失了 logits 的尺度信息。尤其当模型置信度差异大时(比如一个输出 [5.0, -1.2],另一个输出 [1.1, 0.9]),直接平均概率会模糊高置信预测的主导性。
- 更鲁棒的做法:对 logits 加权平均,再统一做
F.softmax(..., dim=1) - 如果某个模型只提供概率(比如封装好的 API),那就只能平均概率,但要注意它可能已做过温度缩放,和其他模型 logits 不在同一量级
- 验证方式:用同一张图喂两个模型,打印各自的
logits.max(),差距超 2 倍就说明量级不齐,硬平均会失真
如何避免模型间输入预处理不一致导致集成失效
这是最常被忽略的坑。不同模型训练时用的归一化参数(mean/std)、图像尺寸、插值方式、甚至 RGB/BGR 顺序,稍有差异,集成效果可能比单个模型还差。
- 必须复用同一套
transforms.Compose,而不是分别调各自的preprocess - 重点核对:
transforms.Normalize中的mean=[0.485, 0.456, 0.406]和std=[0.229, 0.224, 0.225]是否全部模型都用——ViT 可能用[0.5, 0.5, 0.5],ResNet 系列基本固定前者 - 如果模型来自不同代码库(比如一个用 OpenMMLab,一个用 TorchVision),手动检查其
__call__方法里是否隐式做了 BGR→RGB 转换 - 快速排查法:把同一张原始图送进各模型,打印输出的
logits[:3],如果数值分布完全不像(比如一个全在 [-2, 3],另一个在 [10, 35]),八成是预处理或模型 head 不匹配
PyTorch 多模型集成推理的性能瓶颈在哪
不是计算,是数据搬运和重复加载。GPU 显存带宽和 CPU→GPU 传输常成为拖慢吞吐的主因,尤其模型参数大、batch 小的时候。
- 别让每个模型单独做
input.to(device)—— 一次性把 input 放 GPU,再传给所有模型 - 避免反复
torch.load()加载模型权重;用torch.jit.script或torch.compile(2.0+)可提升单次前向 10%~30%,但注意compile对动态 control flow 支持有限 - 如果显存吃紧,考虑用
torch.cuda.amp.autocast(dtype=torch.float16),但得确认所有模型都兼容 FP16(有些自定义 op 会崩) - batch size 不是越大越好:实测中,对 3 个 ViT-B/16 模型集成,batch=16 比 batch=64 吞吐高 1.2 倍——因为后者触发了显存换页
真正麻烦的是模型结构异构带来的对齐成本:有的输出是 [N, C],有的带额外 token(如 CLS + patch),有的还带 dropout 随机性——这些细节不抠清楚,加权平均只是自我安慰。


















