本系列文章配套代码获取有以下两种途径:
-
通过百度网盘获取:
链接:https://pan.baidu.com/s/1XuxKa9_G00NznvSK0cr5qw?pwd=mnsj
提取码:mnsj
-
前往GitHub获取:
https://github.com/returu/PyTorch
-
getattr:
# 等价于object.name
getattr(object, name[, default])
-
setattr:
# 等价于object.name = value
setattr(object, name, value)
class CustomLinearLayer(nn.Module):
def __init__(self, input_features, output_features):
super().__init__()
self.name = 'CustomLinearLayer'
# nn.Parameter()内的参数是网络中可学习的参数
self.weight = nn.Parameter(torch.Tensor(output_features, input_features))
self.bias = nn.Parameter(torch.Tensor(output_features))
self.submodel_1 = nn.Linear(5,4)
self.submodel_2 = nn.Linear(4,2)
self.submodel_3 = nn.Sequential(nn.Linear(2,3),nn.Linear(3,5))
def forward(self, x):
out = torch.mm(x, self.weight.t()) + self.bias
out = self.submodel_1(out)
out = self.submodel_2(out)
out = self.submodel_3(out)
return out
# 实例化网络
custom_linear = CustomLinearLayer(input_features=10, output_features=5)
__getattr__:
custom_linear.__dict__
linear = nn.Linear(10, 5)
print(linear.weight)
-
Parameter对象:
# 以下三种方式均可
custom_linear.bias
getattr(custom_linear , 'bias')
custom_linear.__getattr__('bias')
# 以下两种方式均可
custom_linear.name
getattr(custom_linear , 'name')
# 该方式会报错:AttributeError
custom_linear.__getattr__('name')
# 以下两种方式均可
custom_linear._parameters
getattr(custom_linear , '_parameters')
# 该方式会报错:AttributeError
custom_linear.__getattr__('_parameters')
-
nn.Module对象:
与Parameter对象类似,可以用过以下三种方式访问子module。
# 以下三种方式均可
custom_linear.submodel_3
getattr(custom_linear , 'submodel_3')
custom_linear.__getattr__('submodel_3')
对于_modules 来说,它是 torch.nn.Module 类中的一个实例变量,存储了所有子模块的信息。并且它被存储在 __dict__ 中。当尝试访问 _modules 时,会直接从 custom_linear 实例的 __dict__ 中找到 _modules,因此不会触发 __getattr__ 方法的执行而导致错误。
# 以下两种方式均可
custom_linear._modules
getattr(custom_linear , '_modules')
# 该方式会报错:AttributeError
custom_linear.__getattr__('_modules')
-
train属性:
# 以下两种方式均可
custom_linear.training , custom_linear.submodel_1.training # (True, True)
custom_linear.eval()
getattr(custom_linear , 'training') , getattr(custom_linear.submodel_1 , # (False, False)'training')
# 该方式会报错:AttributeError
custom_linear.__getattr__('training')
__setattr__:
__setattr__ 方法在设置对象的属性时被调用。在 torch.nn.Module 中,__setattr__ 方法同样被重写以支持参数、缓冲区和子模块的正确管理。当你添加一个新的子模块到 Module 实例中,例如:
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.linear = nn.Linear(10, 5)
在 MyModule 的构造函数中,self.linear = nn.Linear(10, 5) 调用了 __setattr__ 方法。这个方法不仅将 linear 添加到了 __dict__ 中,还将其添加到了 _modules 字典中,以便于后续的访问和序列化。
-
Parameter对象:
custom_linear.bias = nn.Parameter(torch.ones(5).float())
custom_linear.bias
# 输出结果:
# Parameter containing:
# tensor([1., 1., 1., 1., 1.], requires_grad=True)
-
nn.Module对象:
可以使用 __setattr__() 方法来动态地修改模型结构,需要注意的是,这种方式通常是不推荐的,因为它可能导致不可预测的行为,特别是在使用优化器和调度器时。然而,在某些特定场景下,如微调模型、添加适配器层或进行特定的模型修改时,这可能是有用的。
class DynamicModel(nn.Module):
def __init__(self):
super(DynamicModel, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1)
def forward(self, x):
x = self.conv1(x)
return x
# 创建模型实例
model = DynamicModel()
# 使用setattr()动态添加一个线性层
new_layer = nn.Linear(64*14*14, 10)
setattr(model, 'fc_layer', new_layer)
# 直接替换 forward 方法
def updated_forward(self, x):
x = self.conv1(x)
x = x.view(x.size(0), -1) # 展平操作
x = self.fc_layer(x) # 使用动态添加的线性层
return x
# 更新模型的前向传播方法以使用新的线性层
model.forward = updated_forward.__get__(model, DynamicModel)
# 现在可以使用更新后的模型进行前向传播
input_tensor = torch.rand(1,3,14,14)
output = model(input_tensor)
output.shape
# 输出结果:torch.Size([1, 10])
更多内容可以前往官网查看:
https://pytorch.org/
本篇文章来源于微信公众号: 码农设计师