Эта статья является исследованием некоторых функций. Функция в основном включает в себя следующие четыре удобства:
- Функции для построения модели:
add_module
,add_module
,add_module
- Подмодули доступа:
add_module
,add_module
,add_module
,add_module
- Обход сети:
add_module
,add_module
- Сохранение и загрузка модели:
add_module
,add_module
,add_module
1 Функции построения модели
torch.nn.Module
Это базовый класс всех сетей, и этот класс должен быть унаследован в классе, реализующем модель в PyTorch (об этом говорилось в предыдущем курсе). При построении модуля модуль — это модуль, который содержит другие модули.Точно так же вы можете сначала определить небольшой сетевой модуль, а затем использовать этот небольшой модуль как компонент другой сети.Следовательно, структура сети представляет собой древовидную структуру..
Сначала мы просто определяем сеть:
import torch.nn as nn
import torch
class MyNet(nn.Module):
def __init__(self):
super(MyNet,self).__init__()
self.conv1 = nn.Conv2d(3,64,3)
self.conv2 = nn.Conv2d(64,64,3)
def forward(self,x):
x = self.conv1(x)
x = self.conv2(x)
return x
net = MyNet()
print(net)
Выходной результат:
MyNet
имеет два свойстваconv1
иconv2
два сверточных слоя при прямом распространенииforward
При этом два сверточных слоя по очереди вызываются для реализации функции сети.
1.1 add_module
Это самая распространенная функция для определения сети, в некоторых проектах вы увидите такой методadd_module
. Мы используем этот метод, чтобы переписать приведенную выше сеть:
class MyNet(nn.Module):
def __init__(self):
super(MyNet,self).__init__()
self.add_module('conv1',nn.Conv2d(3,64,3))
self.add_module('conv2',nn.Conv2d(64,64,3))
def forward(self,x):
x = self.conv1(x)
x = self.conv2(x)
return x
фактическиadd_module(name,layer)
иself.name=layer
выполняет ту же функцию,Лично, может быть, это потому, что add_module может использовать строки для определения имен переменных, поэтому его можно поместить в цикл? Во всяком случае, это сначала понимает знакомство.
Вышеупомянутые два метода состоят в том, чтобы добавлять слои слой за слоем.Если сеть сложная, ей нужно написать много повторяющегося кода. Итак, давайте поговорим о построении сетевого модуля,torch.nn.ModuleList
иtorch.nn.Sequential
1.2 ModuleList
ModuleList
буквально использоватьlist
Форма сетевого слоя сохраняется. Таким образом, слои, требуемые сетью, могут быть сначала созданы, сохранены в списке, а затем пропущены черезModuleList
метод добавления в сеть.
class MyNet(nn.Module):
def __init__(self):
super(MyNet,self).__init__()
self.linears = nn.ModuleList(
[nn.Linear(10,10) for i in range(5)]
)
def forward(self,x):
for l in self.linears:
x = l(x)
return x
net = MyNet()
print(net)
Результат:
Этот ModuleList в основном используется для чтения файла конфигурации для построения модели сети.В следующем примере используется построение модели VGG:
vgg_cfg = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'C', 512, 512, 512, 'M',
512, 512, 512, 'M']
def vgg(cfg, i, batch_norm=False):
layers = []
in_channels = i
for v in cfg:
if v == 'M':
layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
elif v == 'C':
layers += [nn.MaxPool2d(kernel_size=2, stride=2, ceil_mode=True)]
else:
conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
if batch_norm:
layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)]
else:
layers += [conv2d, nn.ReLU(inplace=True)]
in_channels = v
return layers
class Model1(nn.Module):
def __init__(self):
super(Model1,self).__init__()
self.vgg = nn.ModuleList(vgg(vgg_cfg,3))
def forward(self,x):
for l in self.vgg:
x = l(x)
m1 = Model1()
print(m1)
Сначала прочтите файл конфигурации сетевой структурыvgg_cfg
Затем создайте соответствующий список слоев на основе этого файла, а затем используйтеModuleList
добавлены в сеть, чтобы можно было быстро создавать разные сети (Используя приведенное выше в качестве примера, вы можете быстро изменить структуру сети, изменив файл конфигурации)
1.3 Sequential
В некоторых небольших проектах, сделанных мной,Sequential
Он используется чаще.
Все еще переписывая исходный простейший пример:
class MyNet(nn.Module):
def __init__(self):
super(MyNet,self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(3,64,3),
nn.Conv2d(64,64,3)
)
def forward(self,x):
x = self.conv(x)
return x
net = MyNet()
print(net)
результат операции:
Друзья, кто дотошно наблюдает, могут найти эту проблему, сетевой слой в Seqential по умолчанию отмечен цифрами, и в начале мы используемself.conv1
иself.conv2
При использовании conv1 и conv2 в качестве меток.
как мы модифицируемSequential
А как насчет имени сетевого уровня? Здесь нужно использоватьcollections.OrderedDict
заказанный словарь.Sequential
заключается в поддержке построения упорядоченного словаря.
from collections import OrderedDict
class MyNet(nn.Module):
def __init__(self):
super(MyNet,self).__init__()
self.conv = nn.Sequential(OrderedDict([
('conv1',nn.Conv2d(3,64,3)),
('conv2',nn.Conv2d(64,64,3))
]))
def forward(self,x):
x = self.conv(x)
return x
net = MyNet()
print(net)
Выходной результат:
1.4 Небольшое резюме
- Чтобы добавить только сетевой слой или подмодуль, вы можете использовать
add_module
Или напрямую назначать атрибуты; -
ModuleList
Список модулей может быть добавлен в сеть с более высокой степенью свободы. -
Sequential
Генерирует модуль Module по порядку.Для построения рекомендуется использовать метод OrderedDict. Добавьте к сетевому слою каноническое имя, которое полезно для последующего поиска и обхода.