【2022-6-19 PyTorch模型定义】

学习目标:

PyTorch模型定义
1.1PyTorch模型定义的方式

Module 类是 torch.nn 模块里提供的一个模型构造类 (nn.Module),是所有神经⽹网络模块的基类,我们可以继承它来定义我们想要的模型;

PyTorch模型定义应包括两个主要部分:各个部分的初始化(init);数据流向定义(forward)

基于nn.Module,我们可以通过Sequential,ModuleList和ModuleDict三种方式定义PyTorch模型。

from collections import OrderedDict

import torch.nn as nn
class MySequential(nn.Module):
    from collections import OrderedDict
    def __init__(self, *args):
        super(MySequential, self).__init__()
        if len(args) == 1 and isinstance(args[0], OrderedDict): # 如果传入的是一个OrderedDict
            for key, module in args[0].items():
                self.add_module(key, module)  # add_module方法会将module添加进self._modules(一个OrderedDict)
        else:  # 传入的是一些Module
            for idx, module in enumerate(args):
                self.add_module(str(idx), module)
    def forward(self, input):
        # self._modules返回一个 OrderedDict,保证会按照成员添加时的顺序遍历成
        for module in self._modules.values():
            input = module(input)
        return input

import torch.nn as nn
net = nn.Sequential(
        nn.Linear(784, 256),
        nn.ReLU(),
        nn.Linear(256, 10),
        )
print(net)

import collections
import torch.nn as nn
net2 = nn.Sequential(collections.OrderedDict([
          ('fc1', nn.Linear(784, 256)),
          ('relu1', nn.ReLU()),
          ('fc2', nn.Linear(256, 10))
          ]))
print(net2)

net = nn.ModuleList([nn.Linear(784, 256), nn.ReLU()])
net.append(nn.Linear(256, 10)) # # 类似List的append操作
print(net[-1])  # 类似List的索引访问
print(net)

net = nn.ModuleDict({
    'linear': nn.Linear(784, 256),
    'act': nn.ReLU(),
})
net['output'] = nn.Linear(256, 10) # 添加
print(net['linear']) # 访问
print(net.output)
print(net)

1.2 利用模型块快速搭建复杂网络

import torch
import torch.nn as nn
import torch.nn.functional as F
class DoubleConv(nn.Module):
    """(convolution => [BN] => ReLU) * 2"""

    def __init__(self, in_channels, out_channels, mid_channels=None):
        super().__init__()
        if not mid_channels:
            mid_channels = out_channels
        self.double_conv = nn.Sequential(
            nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False),
            nn.BatchNorm2d(mid_channels),
            nn.ReLU(inplace=True),
            nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(inplace=True)
        )

    def forward(self, x):
        return self.double_conv(x)
class Down(nn.Module):
    """Downscaling with maxpool then double conv"""

    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.maxpool_conv = nn.Sequential(
            nn.MaxPool2d(2),
            DoubleConv(in_channels, out_channels)
        )

    def forward(self, x):
        return self.maxpool_conv(x)
class Up(nn.Module):
    """Upscaling then double conv"""

    def __init__(self, in_channels, out_channels, bilinear=True):
        super().__init__()

        # if bilinear, use the normal convolutions to reduce the number of channels
        if bilinear:
            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
            self.conv = DoubleConv(in_channels, out_channels, in_channels // 2)
        else:
            self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2)
            self.conv = DoubleConv(in_channels, out_channels)

    def forward(self, x1, x2):
        x1 = self.up(x1)
        # input is CHW
        diffY = x2.size()[2] - x1.size()[2]
        diffX = x2.size()[3] - x1.size()[3]

        x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2,
                        diffY // 2, diffY - diffY // 2])
        # if you have padding issues, see
        # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a
        # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd
        x = torch.cat([x2, x1], dim=1)
        return self.conv(x)


class UNet:
        pass


class OutConv(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(OutConv, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)

    def forward(self, x):
        return self.conv(x)

    class UNet(nn.Module):
            def __init__(self, n_channels, n_classes, bilinear=True):
                    super(UNet, self).__init__()
                    self.n_channels = n_channels
                    self.n_classes = n_classes
                    self.bilinear = bilinear

                    self.inc = DoubleConv(n_channels, 64)
                    self.down1 = Down(64, 128)
                    self.down2 = Down(128, 256)
                    self.down3 = Down(256, 512)
                    factor = 2 if bilinear else 1
                    self.down4 = Down(512, 1024 // factor)
                    self.up1 = Up(1024, 512 // factor, bilinear)
                    self.up2 = Up(512, 256 // factor, bilinear)
                    self.up3 = Up(256, 128 // factor, bilinear)
                    self.up4 = Up(128, 64, bilinear)
                    self.outc = OutConv(64, n_classes)

            def forward(self, x):
                    x1 = self.inc(x)
                    x2 = self.down1(x1)
                    x3 = self.down2(x2)
                    x4 = self.down3(x3)
                    x5 = self.down4(x4)
                    x = self.up1(x5, x4)
                    x = self.up2(x, x3)
                    x = self.up3(x, x2)
                    x = self.up4(x, x1)
                    logits = self.outc(x)
                    return logits

1.3 PyTorch修改模型

from collections import OrderedDict

classifier = nn.Sequential(OrderedDict([('fc1', nn.Linear(2048, 128)),
                                        ('relu1', nn.ReLU()),
                                        ('dropout1', nn.Dropout(0.5)),
                                        ('fc2', nn.Linear(128, 10)),
                                        ('output', nn.Softmax(dim=1))
                                        ]))

net.fc = classifier


class Model(nn.Module):
        def __init__(self, net):
                super(Model, self).__init__()
                self.net = net
                self.relu = nn.ReLU()
                self.dropout = nn.Dropout(0.5)
                self.fc_add = nn.Linear(1001, 10, bias=True)
                self.output = nn.Softmax(dim=1)

        def forward(self, x, add_variable):
                x = self.net(x)
                x = torch.cat((self.dropout(self.relu(x)), add_variable.unsqueeze(1)), 1)
                x = self.fc_add(x)
                x = self.output(x)
                return x
import torchvision.models as models
net = models.resnet50()
model = Model(net).cuda()

outputs = model(inputs, add_var)


class Model(nn.Module):
        def __init__(self, net):
                super(Model, self).__init__()
                self.net = net
                self.relu = nn.ReLU()
                self.dropout = nn.Dropout(0.5)
                self.fc1 = nn.Linear(1000, 10, bias=True)
                self.output = nn.Softmax(dim=1)

        def forward(self, x, add_variable):
                x1000 = self.net(x)
                x10 = self.dropout(self.relu(x1000))
                x10 = self.fc1(x10)
                x10 = self.output(x10)
                return x10, x1000

        import torchvision.models as models
        net = models.resnet50()
        model = Model(net).cuda()
        out10, out1000 = model(inputs, add_var)

        from torchvision import models
        model = models.resnet152(pretrained=True)

        # 保存整个模型
        torch.save(model, save_dir)
        # 保存模型权重
        torch.save(model.state_dict, save_dir)
        os.environ['CUDA_VISIBLE_DEVICES'] = '0'  # 如果是多卡改成类似0,1,2
        model = model.cuda()  # 单卡
        model = torch.nn.DataParallel(model).cuda()  # 多卡

1.4 PyTorch模型保存与读取


学习内容:


学习时间:

2小时


学习产出:

`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值