模型参数
nn.Parameter
在 PyTorch 中,nn.Parameter
是torch.nn.module.Parameter
类的一个实例,它用于自动跟踪模型参数在训练过程中的变化。nn.Parameter
是torch.Tensor
的一个子类,但与普通的Tensor
不同,nn.Parameter
会被添加到模型的parameters()
迭代器中,这样 PyTorch 的优化器就能找到并更新它们。
语法
CLASS torch.nn.parameter.Parameter(data=None, requires_grad=True) [SOURCE]
nn.Parameter
的主要参数是:
- data (torch.Tensor): 存储参数值的张量。这个张量包含了模型权重或偏置的数值。
- requires_grad (bool, optional): 一个布尔值,指定是否需要计算该参数的梯度。在大多数情况下,你会希望这个值为
True
,以便在训练过程中更新参数。默认值通常为True
。
使用nn.Parameter
的一个典型场景是在定义模型的__init__
方法时,将模型的层权重或偏置包装为nn.Parameter
对象。这样,当调用模型的parameters()
方法时,这些参数会被包含在返回的迭代器中,从而可以被优化器访问和更新。
以下是一个简单的例子,展示了如何在自定义模型中使用nn.Parameter
:
import torch
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
# 使用nn.Parameter定义权重和偏置
self.weight = nn.Parameter(torch.randn(2, 2))
self.bias = nn.Parameter(torch.zeros(2))
def forward(self, x):
# 在前向传播中使用定义的参数
x = torch.matmul(x, self.weight) + self.bias
return x
# 实例化模型
model = MyModel()
# 打印模型参数
for name, param in model.named_parameters():
print(name, param.size())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在这个例子中,MyModel
类定义了两个nn.Parameter
对象:weight
和bias
。这些参数在模型的前向传播方法forward
中被使用。当我们调用model.named_parameters()
时,这些参数会被包含在返回的迭代器中,我们可以遍历并打印它们的名称和大小。
注意,虽然nn.Parameter
是torch.Tensor
的一个子类,但你不应该直接对nn.Parameter
对象调用.backward()
或.grad
等方法。这些操作应该通过模型的输出和损失函数进行,然后使用优化器来更新参数。
小结
torch.nn.Parameter()
将一个不可训练的 tensor 转换成可以训练的类型 parameter,并将这个 parameter 绑定到这个 module 里面。即在定义网络时这个 tensor 就是一个可以训练的参数了。使用这个函数的目的也是想让某些变量在学习的过程中不断的修改其值以达到最优化。
1. model.modules()
- 功能:返回模型中所有模块(包括子模块)的迭代器,按深度优先顺序遍历。
- 返回值:所有模块(层)的无名迭代器。
- 应用场景:遍历整个模型及其子模块。
示例:
import torch.nn as nn
model = nn.Sequential(
nn.Linear(10, 20),
nn.ReLU(),
nn.Sequential(
nn.Conv2d(1, 3, 3),
nn.Sigmoid()
)
)
for module in model.modules():
print(module)
2
3
4
5
6
7
8
9
10
11
12
13
输出(显示所有模块,包括嵌套的子模块):
Sequential(
(0): Linear(in_features=10, out_features=20, bias=True)
(1): ReLU()
(2): Sequential(
(0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Sigmoid()
)
)
Linear(in_features=10, out_features=20, bias=True)
ReLU()
Sequential(
(0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Sigmoid()
)
Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
Sigmoid()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2. model.named_modules()
- 功能:返回模型中所有模块的迭代器(包括子模块),同时提供模块名称。
- 返回值:一个包含模块名称和模块本身的键值对的迭代器。
- 应用场景:需要知道模块的名称(键值)及其对应的层时使用。
示例:
for name, module in model.named_modules():
print(name, module)
2
输出:
Sequential(
(0): Linear(in_features=10, out_features=20, bias=True)
(1): ReLU()
(2): Sequential(
(0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Sigmoid()
)
)
0 Linear(in_features=10, out_features=20, bias=True)
1 ReLU()
2 Sequential(
(0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Sigmoid()
)
2.0 Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
2.1 Sigmoid()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
3. model.children()
- 功能:返回模型的直接子模块(不包括嵌套的子模块)。
- 返回值:直接子模块的无名迭代器。
- 应用场景:仅需遍历顶层模块时使用。
示例:
for child in model.children():
print(child)
2
输出(仅顶层模块):
Linear(in_features=10, out_features=20, bias=True)
ReLU()
Sequential(
(0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Sigmoid()
)
2
3
4
5
6
4. model.named_children()
- 功能:返回模型直接子模块及其名称的迭代器。
- 返回值:包含模块名称和直接子模块的键值对的迭代器。
- 应用场景:需要知道顶层模块的名称和内容时使用。
示例:
for name, child in model.named_children():
print(name, child)
2
输出:
0 Linear(in_features=10, out_features=20, bias=True)
1 ReLU()
2 Sequential(
(0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
(1): Sigmoid()
)
2
3
4
5
6
5. model.parameters()
model.parameters()
是 PyTorch 中 nn.Module
类的一个方法,用于返回模型中所有参数的迭代器。与 model.named_parameters()
不同,model.parameters()
仅返回参数本身,而不包括参数的名称。
返回值:
该方法返回一个迭代器,每次迭代返回一个 torch.nn.Parameter
对象,即模型中的参数。这些参数通常是模型的权重和偏置项。
示例:
import torch
import torch.nn as nn
# 定义一个简单的模型
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.fc1 = nn.Linear(320, 50)
def forward(self, x):
# 前向传播逻辑
pass
# 实例化模型
model = SimpleModel()
# 使用 parameters() 遍历模型参数
for param in model.parameters():
print(param.size())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
在这个例子中,model.parameters()
会遍历模型中的所有参数,并打印出每个参数的大小。输出:
torch.Size([10, 1, 5, 5])
torch.Size([10])
torch.Size([50, 320])
torch.Size([50])
2
3
4
每个卷积层(conv1
)和全连接层(fc1
)都有权重(weight
)和偏置(bias
)参数,这些参数都会被 model.parameters()
遍历到。
统计所有可训练参数:
total_trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
print("Total trainable parameters: ", total_trainable_params)
2
Total trainable parameters: 16310
注意事项
model.parameters()
返回的参数迭代器是按照它们在模型中被定义的顺序进行遍历的。- 由于
model.parameters()
不返回参数的名称,如果你需要参数的名称信息,应该使用model.named_parameters()
。 model.parameters()
返回的参数可以直接用于优化算法,如 SGD、Adam 等,因为这些算法通常只需要参数的数值而不需要它们的名称。
在训练神经网络时,我们通常会使用优化器(如 torch.optim.SGD
或 torch.optim.Adam
)来更新模型的参数。优化器内部会调用 model.parameters()
来获取模型参数的迭代器,并在每个训练步骤中更新这些参数。
6. model.named_parameters()
model.named_parameters()
是 PyTorch 中模型(通常是 nn.Module
的实例)的一个方法,用于返回模型中所有参数的迭代器,每个参数都以名称(字符串)和参数本身(torch.nn.Parameter
对象)的元组形式返回。
参数说明
model.named_parameters()
方法不接受任何参数。
返回值
该方法返回一个迭代器,每次迭代返回一个元组,元组的第一个元素是参数的名称(字符串),第二个元素是对应的参数(torch.nn.Parameter
对象)。
示例
下面是一个简单的示例,展示了如何使用 model.named_parameters()
:
import torch
import torch.nn as nn
# 定义一个简单的模型
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
self.fc1 = nn.Linear(320, 50)
self.fc2 = nn.Linear(50, 10)
def forward(self, x):
# 前向传播逻辑
pass
# 实例化模型
model = SimpleModel()
# 使用 named_parameters() 遍历模型参数
for name, param in model.named_parameters():
print(name, param.size())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在这个例子中,model.named_parameters()
会遍历模型中的所有参数,并打印出每个参数的名称和大小。输出:
conv1.weight torch.Size([10, 1, 5, 5])
conv1.bias torch.Size([10])
conv2.weight torch.Size([20, 10, 5, 5])
conv2.bias torch.Size([20])
fc1.weight torch.Size([50, 320])
fc1.bias torch.Size([50])
fc2.weight torch.Size([10, 50])
fc2.bias torch.Size([10])
2
3
4
5
6
7
8
每个卷积层(conv1
和 conv2
)都有权重(weight
)和偏置(bias
)参数,全连接层(fc1
和 fc2
)也是如此。注意,参数的名称是由层名称和参数类型(weight
或 bias
)组成的。
注意事项
named_parameters()
只返回模型中直接定义的参数,如果模型中有子模块(其他nn.Module
的实例),那么子模块中的参数也会被包括在内。- 如果你只想获取特定类型的参数(例如只获取权重或只获取偏置),你可以通过检查参数名称来实现。例如,你可以通过检查名称是否包含
weight
或bias
来过滤参数。 - 与
model.parameters()
不同,model.named_parameters()
返回的是名称和参数的元组,而model.parameters()
只返回参数的迭代器,不包含名称信息。
7. model.state_dict()
- 功能:返回模型的所有状态(参数和缓冲区)的字典。
- 返回值:
OrderedDict
,包含参数和持久化缓冲区的名称及值。 - 应用场景:保存模型状态或查看所有可训练参数和缓冲值时使用。
示例:
state_dict = model.state_dict()
for key, value in state_dict.items():
print(key, value.size())
2
3
输出:
conv1.weight torch.Size([10, 1, 5, 5])
conv1.bias torch.Size([10])
conv2.weight torch.Size([20, 10, 5, 5])
conv2.bias torch.Size([20])
fc1.weight torch.Size([50, 320])
fc1.bias torch.Size([50])
fc2.weight torch.Size([10, 50])
fc2.bias torch.Size([10])
2
3
4
5
6
7
8
总结
方法 | 返回内容 | 是否包含子模块 | 是否包含名称 |
---|---|---|---|
model.modules() | 所有模块 | 是 | 否 |
model.named_modules() | 所有模块及名称 | 是 | 是 |
model.children() | 直接子模块 | 否 | 否 |
model.named_children() | 直接子模块及名称 | 否 | 是 |
model.parameters() | 所有参数 | 是 | 否 |
model.named_parameters() | 所有参数及名称 | 是 | 是 |
model.state_dict() | 所有参数和缓冲区(字典形式) | 是 | 是 |
- 模块和参数:
modules
和children
提供层结构信息,而parameters
和state_dict
提供权重和偏置。 - 名称与无名:
named_*
方法更适合调试和命名层参数。