优先用 pip install git+https://github.com/sksq96/pytorch-summary;若不兼容则手动遍历 model.parameters() 计算 total=sum(p.numel() for p in model.parameters()),trainable=sum(p.numel() for p in model.parameters() if p.requires_grad)。

用 torchsummary 看模型参数量,但别直接 pip install torchsummary
torchsummary 是最常用的快捷方案,但它不支持新版 PyTorch(≥2.0)的某些模型结构(比如带 torch.compile 或含动态 shape 的模块),且对自定义 forward 中有控制流的模型会报错或漏统计。
实操建议:
- 优先安装兼容性更好的分支:
pip install git+https://github.com/sksq96/pytorch-summary(原 repo 已归档,这个 fork 支持到 PyTorch 2.3) - 调用时必须传入一个真实 batch 的输入张量,shape 要匹配模型期望(例如
summary(model, (3, 224, 224))表示单张 RGB 图像),否则会触发RuntimeError: Input type mismatch - 若模型含
nn.DataParallel或DistributedDataParallel,需传model.module,否则会统计重复或报错
手动遍历 model.named_parameters() 才真正可靠
所有 PyTorch 模型都支持该接口,不受封装方式、编译状态或动态图影响,是唯一能 100% 覆盖的方案。
关键点:
-
named_parameters()返回的是(name, param)元组,param.numel()给出该参数总元素数(即标量个数),不是内存字节数 - 注意区分
param.requires_grad == False的参数(如冻结的 BN weight/bias),它们仍计入总参数量,除非你明确只统计可训练参数 - 常见误算:把
param.shape当成维度数,实际要调用param.numel();例如torch.randn(2, 3, 4).numel() == 24,不是len(param.shape) == 3
最小可用示例:
total = sum(p.numel() for p in model.parameters())
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
print(f"Total params: {total:,} | Trainable: {trainable:,}")
按层/模块分组统计,快速定位大参数块
当总参数量异常高或想优化某部分时,光看总数没用,得知道谁在“吃内存”。
做法很简单:
- 用
model.named_children()或model.named_modules()遍历子模块,再对每个子模块调用.parameters() - 避免统计重复:只对“叶子模块”(即不含子模块的模块)统计,可用
list(module.children()) == []判断 - 典型陷阱:
nn.Sequential里嵌套的层名默认为空字符串,容易漏统计,建议统一用named_modules()并过滤掉空名
精简版分层统计逻辑:
for name, module in model.named_modules():
if list(module.children()) == []: # 叶子模块
params = sum(p.numel() for p in module.parameters())
if params > 0:
print(f"{name:30s}: {params:>10,}")
summary 输出里的“Trainable params”和实际不符?检查是否启用了梯度裁剪或 no_grad
torchsummary 的 trainable 参数计数依赖于 p.requires_grad 当前值。但如果你在统计前执行过 torch.no_grad() 上下文,或模型刚从 checkpoint 加载且未调用 model.train(),部分 BN 层的 weight/bias 可能被设为不可训练——这会导致 summary 显示的 trainable 数偏小,而手动遍历结果才反映真实状态。
更隐蔽的问题:某些模型(如 Hugging Face Transformers)在 from_pretrained(..., ignore_mismatched_sizes=True) 后,新增参数默认 requires_grad=True,但旧参数保持原状,summary 容易误判“可训练比例”。此时务必以手动遍历为准。
复杂点在于:参数量本身不等于显存占用,因为还有梯度、优化器状态、激活值等开销。但参数统计这一步,只要不用错 API,就没什么好商量的——model.parameters() 是唯一真相源。











