pytorch实现自定义网络层,并自设定前向传播路径-学习笔记
1. 不包含模型参数的自定义网络层
首先我们自定义一个网络层,
定义一个网络层,使其不包含模型参数,并在forward()函数中进行运算:
import torch
from torch import nnclass non_param_layer(nn.Module):def __init__(self, **kwargs):super(non_param_layer, self).__init__(**kwargs)def forward(self, x):return x - x.mean()
这个层中没有模型参数,只在forward中定义了计算:减去数据平均值
实例化该层并进行前向计算:
layer = non_param_layer()
layer(torch.tensor([1, 2, 3, 4, 5], dtype=troch.float))
输出:
tensor([-2., -1., 0., 1., 2.])
我们将该层网络加入网络中:
net = nn.Sequential(nn.Linear(8, 128), non_param_layer())
进行前向计算并输出自定义层的输出的均值:
y = net(torch.rand(4, 8))
y.mean().item() # 0
因为我们自定义的网络层所做的操作是:,每个输入减去所有数据的均值,所以其输出的各个数值取均值的结果为0
2. 含有模型参数的自定义层
与上面一节不同,我们要自定义一个含有模型参数的网络层:
之前的blog有讲过构造深度学习模型有很多种方法,其中,使用ParameterList和ParameterDict定以模型比较特别,接下来我们使用这两种方式自定义网络层。
class my_dense(nn.Module):def __init__(self):super(my_dense, self).__init__()self.params = nn.ParameterList([nn.Parameter(torch.randn(4, 4)) for i in range(3)])self.params.append(nn.Parameter(torch.randn(4, 1)))def forward(self, x):for i in range(len(self.params)):x = torch.mm(x, self.params[i])return x
net = my_dense()
print(net)
输出:
MyDense((params): ParameterList((0): Parameter containing: [torch.FloatTensor of size 4x4](1): Parameter containing: [torch.FloatTensor of size 4x4](2): Parameter containing: [torch.FloatTensor of size 4x4](3): Parameter containing: [torch.FloatTensor of size 4x1])
)
接下来使用ParameterDict网络模型并且自定义网络传播路径
class dict_dense(nn.Module):def __init__(self):super(dict_dense, self).__init()self.params = nn.ParameterDict({"liner1" : nn.Parameter(troch.randn(4, 4))"liner2" : nn.Parameter(torch.randn(4, 1))})self.params.update({"liner3 : nn.Parameter(torch.randn(4, 2))"})def forward(self, x, choice="liner1"):return torch.mm(x, self.params[choice])net = dict_dense()
pritn(net)
输出:
MyDictDense((params): ParameterDict((linear1): Parameter containing: [torch.FloatTensor of size 4x4](linear2): Parameter containing: [torch.FloatTensor of size 4x1](linear3): Parameter containing: [torch.FloatTensor of size 4x2])
)
然后可以自己指定网络训练的传播路径:
x = torch.ones(1, 4)
print(net(x, "liner1"))
同时,我们还可以使用Sequential将我们自定义的网络层加入到网络中:
mix_net = nn.Sequential(dict_dense(),my_dense() ,
)