import torch import torch.nn as nn import torch.nn.functional as F from collections import OrderedDict
""" 使用 PyTorch 构建模型的方法大致有 3 种: 1) 继承 nn.Module 基类构建模型 2) 使用 nn.Sequential 容器按层顺序构建模型 3) 继承 nn.Module 基类构建模型,再使用相关容器(如 nn.Sequential、nn.ModuleList、nn.ModuleDict 等)进行封装 """
class Model_Seq(nn.Module): """ 通过继承基类 nn.Module 来构建模型 """
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim): super(Model_Seq, self).__init__() self.flatten = nn.Flatten() self.linear1 = nn.Linear(in_dim, n_hidden_1) self.bn1 = nn.BatchNorm1d(n_hidden_1) self.linear2 = nn.Linear(n_hidden_1, n_hidden_2) self.bn2 = nn.BatchNorm1d(n_hidden_2) self.out = nn.Linear(n_hidden_2, out_dim)
def forward(self, x): x = self.flatten(x) x = self.linear1(x) x = self.bn1(x) x = F.relu(x) x = self.linear2(x) x = self.bn2(x) x = F.relu(x) x = self.out(x) x = F.softmax(x, dim=1) return x
in_dim, n_hidden_1, n_hidden_2, out_dim = 28 * 28, 300, 100, 10 model_seq = Model_Seq(in_dim, n_hidden_1, n_hidden_2, out_dim) print(model_seq)
Seq_arg = nn.Sequential( nn.Flatten(), nn.Linear(in_dim, n_hidden_1), nn.BatchNorm1d(n_hidden_1), nn.ReLU(), nn.Linear(n_hidden_1, n_hidden_2), nn.BatchNorm1d(n_hidden_2), nn.ReLU(), nn.Linear(n_hidden_2, out_dim), nn.Softmax(dim=1) ) print(Seq_arg)
in_dim, n_hidden_1, n_hidden_2, out_dim = 25 * 25, 300, 100, 10 Seq_module = nn.Sequential() Seq_module.add_module('flatten', nn.Flatten()) Seq_module.add_module('linear1', nn.Linear(in_dim, n_hidden_1)) Seq_module.add_module('bn1', nn.BatchNorm1d(n_hidden_1)) Seq_module.add_module('relu1', nn.ReLU()) Seq_module.add_module('linear2', nn.Linear(n_hidden_1, n_hidden_2)) Seq_module.add_module('bn2', nn.BatchNorm1d(n_hidden_2)) Seq_module.add_module('relu2', nn.ReLU()) Seq_module.add_module('out', nn.Linear(n_hidden_2, out_dim)) Seq_module.add_module('softmax', nn.Softmax(dim=1)) print(Seq_module)
Seq_dict = nn.Sequential( OrderedDict( [ ('flatten', nn.Flatten()), ('linear1', nn.Linear(in_dim, n_hidden_1)), ('bn1', nn.BatchNorm1d(n_hidden_1)), ('relu1', nn.ReLU()), ('linear2', nn.Linear(n_hidden_1, n_hidden_2)), ('bn2', nn.BatchNorm1d(n_hidden_2)), ('relu2', nn.ReLU()), ('out', nn.Linear(n_hidden_2, out_dim)), ('softmax', nn.Softmax(dim=1)) ] ) ) print(Seq_dict)
class Model_lay(nn.Module): """ 使用 nn.Sequential 模型容器来构建模型,Sequential 函数的功能是将网络的层组合到一起。 """
def __init__(self, in_dim, n_hidden1, n_hidden2, out_dim): super(Model_lay, self).__init__() self.flatten = nn.Flatten() self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden1), nn.BatchNorm1d(n_hidden1), nn.ReLU()) self.layer2 = nn.Sequential(nn.Linear(n_hidden1, n_hidden2), nn.BatchNorm1d(n_hidden2), nn.ReLU()) self.out = nn.Linear(n_hidden2, out_dim)
def forward(self, x): x = self.flatten(x) x = self.layer1(x) x = self.layer2(x) x = self.out(x) x = F.softmax(x, dim=1) return x
print(Model_lay)
class Model_lst(nn.Module): """ 使用 nn.ModuleList 模型容器来构建模型,ModuleList 可以存储任意数量的 nn.Module 子类。 """ def __init__(self, in_dim, n_hidden1, n_hidden2, out_dim): super(Model_lst, self).__init__() self.layers = nn.ModuleList([ nn.Flatten(), nn.Linear(in_dim, n_hidden1), nn.BatchNorm1d(n_hidden1), nn.ReLU(), nn.Linear(n_hidden1, n_hidden2), nn.BatchNorm1d(n_hidden2), nn.ReLU(), nn.Linear(n_hidden2, out_dim), nn.Softmax(dim=1) ])
def forward(self, x): for index, layer in enumerate(self.layers): print(f'第 {index} 层: {layer}') x = layer(x) return x
data = torch.randn(32, 25, 25) model_lst = Model_lst(25 * 25, 300, 100, 10) out = model_lst(data)
class Model_dict(nn.Module): def __init__(self, in_dim, n_hidden1, n_hidden2, out_dim): super(Model_dict, self).__init__() self.layers_dict = nn.ModuleDict({ 'flatten': nn.Flatten(), 'linear1': nn.Linear(in_dim, n_hidden1), 'bn1': nn.BatchNorm1d(n_hidden1), 'relu': nn.ReLU(), 'linear2': nn.Linear(n_hidden1, n_hidden2), 'bn2': nn.BatchNorm1d(n_hidden2), 'out': nn.Linear(n_hidden2, out_dim), 'softmax': nn.Softmax(dim=1) })
def forward(self, x): layers = ['flatten', 'linear1', 'bn1', 'relu', 'linear2', 'bn2', 'relu', 'out', 'softmax'] for layer in layers: x = self.layers_dict[layer](x) return x
class ResNetBasicBlock(nn.Module): def __init__(self, in_channels, out_channels, stride=1, downsample=None): super(ResNetBasicBlock, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1) self.bn1 = nn.BatchNorm2d(out_channels) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=stride, padding=1) self.bn2 = nn.BatchNorm2d(out_channels)
def forward(self, x): output = self.conv1(x) output = self.bn1(output) output = F.relu(output) output = self.conv2(output) output = self.bn2(output) return F.relu(output + x)
class ResNetDownBlock(nn.Module): def __init__(self, in_channels, out_channels, stride, downsample=None): super(ResNetDownBlock, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride[0], padding=1) self.bn1 = nn.BatchNorm2d(out_channels) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=stride[1], padding=1) self.bn2 = nn.BatchNorm2d(out_channels) self.extra = nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride[0], padding=0), nn.BatchNorm2d(out_channels) )
def forward(self, x): extra_x = self.extra(x)
output = self.conv1(x) output = self.bn1(output) output = F.relu(output) output = self.conv2(output) output = self.bn2(output) return F.relu(output + extra_x)
class ResNet18(nn.Module): def __init__(self): super(ResNet18, self).__init__() self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3) self.bn1 = nn.BatchNorm2d(64) self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) self.layer1 = nn.Sequential( ResNetBasicBlock(64, 64, 1), ResNetBasicBlock(64, 64, 1) ) self.layer2 = nn.Sequential( ResNetDownBlock(64, 128, [2, 1]), ResNetBasicBlock(128, 128, 1) ) self.layer3 = nn.Sequential( ResNetDownBlock(128, 256, [2, 1]), ResNetBasicBlock(256, 256, 1) ) self.layer4 = nn.Sequential( ResNetDownBlock(256, 512, [2, 1]), ResNetBasicBlock(512, 512, 1) ) self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1, 1)) self.fc = nn.Linear(512, 10)
def forward(self, x): out = self.conv1(x) out = self.layer1(out) out = self.layer2(out) out = self.layer3(out) out = self.layer4(out) out = self.avgpool(out) out = out.reshape(x.shape[0], -1) out = self.fc(out) return out
model_resnet18 = ResNet18() print(model_resnet18) data = torch.randn(32, 3, 224, 224) result = model_resnet18(data) print(result.shape)
|