ValueError: optimizer got an empty parameter list:Linear 放在普通 list 里为什么找不到参数

简介: PyTorch中`ValueError: optimizer got an empty parameter list`常因将`nn.Linear`等层存于普通Python列表(如`self.layers = []`)所致——虽能前向传播,但未被父`nn.Module`注册,故`model.parameters()`为空。正确做法是使用`nn.ModuleList`管理动态层,确保参数自动注册、可被优化器识别和设备迁移。(239字)

明明写了多个 nn.Linear,前向也能得到结果,但创建 Adam 或 SGD 时却报参数列表为空:

ValueError: optimizer got an empty parameter list

这条消息说的是“传给优化器的可训练对象为空”,并不等于程序里完全没有权重。对应原始问题把各层放在 self.nn_layers = [] 中,恰好需要区分“层已经创建”和“层已被父模块注册”。

先观察:有 Linear,为什么 parameters() 还是空的

下面保留原帖动态建层的写法,缩成两层小网络。可以在已有 PyTorch 的环境直接运行,不需要数据集:

import torch
from torch import nn

class PlainListActor(nn.Module):
    def __init__(self):
        super().__init__()
        self.layers = [nn.Linear(4, 8), nn.Linear(8, 2)]

    def forward(self, x):
        x = torch.relu(self.layers[0](x))
        return self.layers[1](x).softmax(dim=-1)

bad_model = PlainListActor()
print("josh050608")
print("registered parameters:", [name for name, _ in bad_model.named_parameters()])
print("inner Linear parameters:", [name for name, _ in bad_model.layers[0].named_parameters()])
print("forward shape:", bad_model(torch.ones(3, 4)).shape)
try:
    torch.optim.Adam(bad_model.parameters(), lr=0.001)
except ValueError as exc:
    print("optimizer error:", exc)

关键检查会显示:父模型的注册参数列表为空,第一层 Linear 自己却有 weight、bias,前向仍可输出 [3,2]。所以“能调用 forward”不能证明 model.parameters() 已经找到了这些层。

父模块会管理作为子模块注册的层;普通 Python list 只是一个普通容器。放在里面的 Linear 不会因此自动出现在父模块的 parameters、state_dict 或递归设备迁移中。

修复:动态层列表使用 ModuleList

对原帖,最小修改是把 self.nn_layers = [] 改成 self.nn_layers = nn.ModuleList(),随后继续 append。无需把整个动态网络改写成另一套固定结构。

下面是保留原帖 4→128→2 配置的完整版本。构造时先复制调用方传入的列表,避免添加输出层时把原列表也改掉:

class NetActor(nn.Module):
    def __init__(self, state_size, action_size, hidden_sizes):
        super().__init__()
        sizes = [state_size, *list(hidden_sizes), action_size]
        self.nn_layers = nn.ModuleList([
            nn.Linear(source, target)
            for source, target in zip(sizes[:-1], sizes[1:])
        ])

    def forward(self, x):
        for layer in self.nn_layers[:-1]:
            x = torch.relu(layer(x))
        return self.nn_layers[-1](x).softmax(dim=-1)

model = NetActor(4, 2, [128])
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
print("registered shapes:", [(n, tuple(p.shape)) for n, p in model.named_parameters()])
print("parameter elements:", sum(p.numel() for p in model.parameters()))

这里应注册四个参数张量:第一层 weight、bias 和第二层 weight、bias,元素总数为 898。ModuleList 本身不定义 forward,上面的循环仍负责实际计算,这也是它与 Sequential 的区别。

如果层已存在于列表中,也可以用 nn.ModuleList(existing_layers) 保留这些层对象。对于刚开始构建的模型,直接在构造函数使用 ModuleList 更清楚。改完类后要重新创建实例和优化器;Notebook 里只重新运行类定义,不会自动改变旧对象。

不仅看参数非空,还要检查它真的更新了

继续运行下面代码。这里用三条合成输入和简单的概率损失检查梯度路径,不代表原 Actor 算法的完整训练目标:

inputs = torch.ones(3, 4)
before = model.nn_layers[0].weight.detach().clone()
optimizer.zero_grad()
probabilities = model(inputs)
assert probabilities.shape == (3, 2)
assert torch.allclose(probabilities.sum(dim=1), torch.ones(3))
loss = -probabilities[:, 0].log().mean()
loss.backward()
for name, parameter in model.named_parameters():
    assert parameter.grad is not None, name
    assert torch.isfinite(parameter.grad).all(), name
optimizer.step()
assert not torch.equal(before, model.nn_layers[0].weight)
assert "nn_layers.0.weight" in model.state_dict()
print("registered parameters:", len(list(model.parameters())))
print("first weight updated:", not torch.equal(before, model.nn_layers[0].weight))

这样能同时验证三件事:优化器拿到了参数、反向能到达各层、step 后权重发生变化。真实工程再把示例损失换回自己的策略目标。

如果改成 ModuleList 仍然为空

先确认创建优化器时传入的是新模型,而不是旧实例。然后直接打印 list(model.named_parameters()),区分下面几类情况:

观察 下一步检查
没有注册参数,层只在普通 list/dict 中 使用 ModuleList/ModuleDict,或把层直接挂到模型属性
构造函数里的定义没有执行 核对 __init__ 拼写、父类初始化与构造分支
named_parameters 非空,传给优化器的对象却空 检查筛选条件、生成器是否已经被遍历耗尽
自定义“权重”只是普通 Tensor 根据设计注册为 nn.Parameter,而不只是设置 requires_grad

同名 CSDN 案例里确实有 __init__ 下划线写错的情况,但它不能解释原帖已经正确初始化父类、却使用普通列表的代码。相同报错要根据模型定义与注册参数列表判断,不能把某一篇帖子的根因当成通用答案。

参考:原始问题;同报错的 CSDN 拼写错误案例、ModuleList(2.5)、nn.Module(2.5)、优化器(2.5)。

相关文章
|
10天前
|
Linux 开发工具 iOS开发
Codex保姆级教程(下载+安装+登录+使用,含所有版本,2026最新)
Codex是OpenAI推出的开源AI编程智能体,本地运行,可理解整个代码库,支持自然语言指令改代码、执行命令、跑测试、修Bug,兼容Win/macOS/Linux。(239字)
3995 19
|
11天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
4135 49
|
11天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
1976 7
|
6天前
|
云安全 人工智能 安全
|
6天前
|
存储 弹性计算 人工智能
2026 年阿里云双十一活动入口攻略,新客服务器优惠通道、三大会场入口梳理
综合来看,2026年阿里云双十一活动入口清晰: 阿里云轻量应用服务器、阿里云ECS云服务器、阿里云GPU云服务器、阿里云百炼大模型服务平台 活动会场、综合权益中心、99计划专场三大入口覆盖服务器、AI权益与续费特价;新用户通过控制台首页banner、权益中心、产品页三处路径进入专属专场,老用户通过控制台弹窗和费用中心权益中心进入老客专区,企业用户做企业实名后解锁专属满减与阶梯折扣。
819 0
|
5天前
|
Linux 开发工具 iOS开发
2026最新codex下载安装保姆级使用教程(下载+安装+登录+使用,含所有历史版本)
本文详解OpenAI Codex国内快速上手指南:提供Win/macOS/Linux全平台免安装包、npm/Homebrew等多方式安装、账号/API Key双登录、简体中文切换,覆盖下载、安装、汉化、使用及高频避坑(如微软商店失败、npm超时等),10分钟即可跑通。
1087 2
|
12天前
|
安全 算法 定位技术
《高性价比人生指南》完整原版:普通人用最少的资源,过好这一生的底层逻辑~How To Live Better
📖《高性价比人生指南》是一份基于实证、拒绝焦虑的生存手册,倡导以“人生时薪”为视角,重新计算时间、金钱与精力的成本与收益。它不承诺逆袭,只教人算清账:省下的钱若耗掉时间便亏;买体验比买物品更值;睡眠是最高杠杆的健康投资;关系贵在情绪价值而非表面热络;学习重在改变行为而非自我安慰。核心理念:用低成本、高回报的微小行动,换取长期的选择权——不是成为谁,而是掌控自己人生的主动权。
2144 6
|
云安全 安全 网络安全
|
24天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
4337 58