为何我的动态神经网络参数数量为0?如何注册与修复?
问题:自定义PyTorch神经网络无参数的原因及修复方案
我定义了如下PyTorch神经网络:
class Q_function(nn.Module): def __init__(self, input_size=3, hidden_size=5, num_layers=3, learning_rate=0.01): super(Q_function, self).__init__() self.input_size = input_size self.layers = [] for i in num_layers: self.layers.append(nn.Linear(input_size, hidden_size)) self.append(nn.ReLU()) self.layers.append(nn.Linear(hidden_size,1)) def forward(self, x): out = self.layers[0](x) for lay in range(1,len(self.layers)): out = self.layers[lay](out) return out
执行以下代码后,输出为空列表[]:
net = Q_function() list(net.parameters())
原因分析
- 模块未被注册:PyTorch的
nn.Module只会管理作为类实例属性直接挂载的子模块,你把所有层存在了普通Python列表self.layers里,这些模块没有被纳入nn.Module的参数追踪系统,所以parameters()方法找不到任何可训练参数。 - 代码存在语法/逻辑错误:
for i in num_layers:num_layers是整数3,直接遍历整数会触发TypeError,需改为for i in range(num_layers)。self.append(nn.ReLU()):nn.Module没有append方法,正确写法是self.layers.append(nn.ReLU())。- 循环中始终用
input_size作为线性层输入尺寸,会导致后续层输入输出不匹配,需将上一层的输出尺寸作为下一层的输入尺寸。
修复方案
方法1:使用nn.Sequential(最简洁推荐)
nn.Sequential会自动注册内部所有子模块,同时简化前向传播逻辑:
import torch.nn as nn class Q_function(nn.Module): def __init__(self, input_size=3, hidden_size=5, num_layers=3, learning_rate=0.01): super(Q_function, self).__init__() self.input_size = input_size layers = [] current_in_size = input_size # 构建隐藏层 for _ in range(num_layers): layers.append(nn.Linear(current_in_size, hidden_size)) layers.append(nn.ReLU()) current_in_size = hidden_size # 更新下一层的输入尺寸 # 输出层 layers.append(nn.Linear(hidden_size, 1)) # 用Sequential包裹所有层,自动注册参数 self.layers = nn.Sequential(*layers) def forward(self, x): # Sequential可直接调用,自动按顺序执行各层 return self.layers(x)
方法2:手动注册子模块
如果需要保留列表结构,可通过self.add_module()手动注册每个子模块:
import torch.nn as nn class Q_function(nn.Module): def __init__(self, input_size=3, hidden_size=5, num_layers=3, learning_rate=0.01): super(Q_function, self).__init__() self.input_size = input_size self.layers = [] current_in_size = input_size for i in range(num_layers): # 创建线性层并手动注册 linear_layer = nn.Linear(current_in_size, hidden_size) self.add_module(f"hidden_linear_{i}", linear_layer) self.layers.append(linear_layer) # 创建ReLU层并手动注册 relu_layer = nn.ReLU() self.add_module(f"hidden_relu_{i}", relu_layer) self.layers.append(relu_layer) current_in_size = hidden_size # 注册输出层 output_layer = nn.Linear(hidden_size, 1) self.add_module("output_linear", output_layer) self.layers.append(output_layer) def forward(self, x): out = x for layer in self.layers: out = layer(out) return out
验证
修复后执行以下代码,会返回所有可训练参数列表,不再是空值:
net = Q_function() print(list(net.parameters()))
内容的提问来源于stack exchange,提问作者A J
相关产品推荐
相关产品推荐

