深度之眼 PyTorch 训练营第 4 期(5):构建模型 torch.nn.Module
本文中,我們看一看如何構建模型。
創造一個模型分兩步:構建模型和權值初始化。而構建模型又有“定義單獨的網絡層”和“把它們拼在一起”兩步。
1. torch.nn.Module
torch.nn.Module 是所有 torch.nn 中的類的父類。我們來看一個非常簡單的神經網絡:
class SimpleNet(nn.Module):def __init__(self, x):super(SimpleNet,self).__init__()self.fc = nn.Linear(x.shape[0], 1)def forward(self, x):x = self.fc(x)return x我們隨便喂給它一個張量,打印它的網絡:
>>> simpleNet = SimpleNet(torch.tensor((10, 2))) >>> print(simpleNet) SimpleNet((fc): Linear(in_features=2, out_features=1, bias=True) )所有自定義的神經網絡都要繼承 torch.nn.Module。定義單獨的網絡層在 __init__ 函數中實現,把定義好的網絡層拼接在一起在 forward 函數中實現。網絡類有兩個重要的函數:parameters 存儲了模型的權重;modules 存儲了模型的結構。
>>> list(simpleNet.modules()) [SimpleNet((fc): Linear(in_features=2, out_features=1, bias=True)),Linear(in_features=2, out_features=1, bias=True)]>>> list(simpleNet.parameters()) [Parameter containing:tensor([[ 0.1533, -0.2574]], requires_grad=True),Parameter containing:tensor([-0.1589], requires_grad=True)]2. torch.nn.Sequential
這是一個序列容器,既可以放在模型外面單獨構建一個模型,也可以放在模型里面成為模型的一部分。
# 單獨成為一個模型 model1 = nn.Sequential(nn.Conv2d(1,20,5),nn.ReLU(),nn.Conv2d(20,64,5),nn.ReLU()) # 成為模型的一部分 class LeNetSequential(nn.Module):def __init__(self, classes):super(LeNetSequential, self).__init__()self.features = nn.Sequential(nn.Conv2d(3, 6, 5),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(6, 16, 5),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),)self.classifier = nn.Sequential(nn.Linear(16*5*5, 120),nn.ReLU(),nn.Linear(120, 84),nn.ReLU(),nn.Linear(84, classes),)def forward(self, x):x = self.features(x)x = x.view(x.size()[0], -1)x = self.classifier(x)return x放在模型里面的話,模型還是需要 __init__ 和 forward 函數。
這樣構建出來的模型的層沒有名字:
>>> model2 = nn.Sequential( ... nn.Conv2d(1,20,5), ... nn.ReLU(), ... nn.Conv2d(20,64,5), ... nn.ReLU() ... ) >>> model2 Sequential((0): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))(1): ReLU()(2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))(3): ReLU() )為了方便區分不同的層,我們可以使用 collections 里的 OrderedDict 函數:
>>> from collections import OrderedDict >>> model3 = nn.Sequential(OrderedDict([ ... ('conv1', nn.Conv2d(1,20,5)), ... ('relu1', nn.ReLU()), ... ('conv2', nn.Conv2d(20,64,5)), ... ('relu2', nn.ReLU()) ... ])) >>> model3 Sequential((conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))(relu1): ReLU()(conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))(relu2): ReLU() )3. torch.nn.ModuleList
將網絡層存儲進一個列表,可以使用列表生成式快速生成網絡,生成的網絡層可以被索引,也擁有列表的方法 append,extend 或 insert。
>>> class MyModule(nn.Module): ... def __init__(self): ... super(MyModule, self).__init__() ... self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)]) ... self.linears.append(nn.Linear(10, 1)) # append ... def forward(self, x): ... for i, l in enumerate(self.linears): ... x = self.linears[i // 2](x) + l(x) ... return x>>> myModeul = MyModule() >>> myModeul MyModule((linears): ModuleList((0): Linear(in_features=10, out_features=10, bias=True)(1): Linear(in_features=10, out_features=10, bias=True)(2): Linear(in_features=10, out_features=10, bias=True)(3): Linear(in_features=10, out_features=10, bias=True)(4): Linear(in_features=10, out_features=10, bias=True)(5): Linear(in_features=10, out_features=10, bias=True)(6): Linear(in_features=10, out_features=10, bias=True)(7): Linear(in_features=10, out_features=10, bias=True)(8): Linear(in_features=10, out_features=10, bias=True)(9): Linear(in_features=10, out_features=10, bias=True)(10): Linear(in_features=10, out_features=1, bias=True) # append 進的層) )4. torch.nn.ModuleDict
這個函數與上面的 torch.nn.Sequential(OrderedDict(...)) 的行為非常類似,并且擁有 keys,values,items,pop,update 等詞典的方法:
>>> class MyDictDense(nn.Module): ... def __init__(self): ... super(MyDictDense, self).__init__() ... self.params = nn.ModuleDict({ ... 'linear1': nn.Linear(512, 128), ... 'linear2': nn.Linear(128, 32) ... }) ... self.params.update({'linear3': nn.Linear(32, 10)}) # 添加層... def forward(self, x, choice='linear1'): ... return torch.mm(x, self.params[choice])>>> net = MyDictDense() >>> print(net) MyDictDense((params): ModuleDict((linear1): Linear(in_features=512, out_features=128, bias=True)(linear2): Linear(in_features=128, out_features=32, bias=True)(linear3): Linear(in_features=32, out_features=10, bias=True)) )>>> print(net.params.keys()) odict_keys(['linear1', 'linear2', 'linear3'])>>> print(net.params.items()) odict_items([('linear1', Linear(in_features=512, out_features=128, bias=True)), ('linear2', Linear(in_features=128, out_features=32, bias=True)), ('linear3', Linear(in_features=32, out_features=10, bias=True))])歡迎關注我的微信公眾號“花解語 NLP”:
總結
以上是生活随笔為你收集整理的深度之眼 PyTorch 训练营第 4 期(5):构建模型 torch.nn.Module的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS2022安装教程(超详细)
- 下一篇: 计算阶乘的位数