《PyTorch深度学习实践》课上代码笔记 五

自学笔记

课程老师:刘二大人 河北工业大学教师 https://liuii.github.io
课程来源:https://www.bilibili.com/video/BV1Y7411d7Ys

十二、Residual_Block(残差网络)

残差网络
为了防止梯度的消失,在一定次数的卷积操作后(一般为两次),将结果与输入进行相加后进行relu,这样后的梯度最小会在1左右,而不是0,能有效避免梯度消失。残差部分的代码如下:

#定义残差块
class ResidualBlock(nn.Module):
    def __init__(self, channels):
        super(ResidualBlock, self).__init__()
        #初始化属性
        self.channels = channels
        self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)

    #定义前馈函数
    def forward(self, x):
        y = F.relu(self.conv1(x))
        y = self.conv2(y)
        #返回值为输入x + y(经过处理的x)
        return F.relu(x + y)

将残差块按需要放在整个网络中,即可构成一个完整的网络。

#设计模型
class Net(nn.Module):
    #初始化属性
    def __init__(self):
        super(Net, self).__init__()
        #两个卷积
        self.conv1 = nn.Conv2d(1, 16, kernel_size=5)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=5)
        #最大池化
        self.mp = nn.MaxPool2d(2)
        #两个残差块
        self.rblock1 = ResidualBlock(16)
        self.rblock2 = ResidualBlock(32)
        #全连接
        self.fc = nn.Linear(512, 10)

    def forward(self, x):
        #这里是提取了x的行数,可以理解为输入数据的个数,x.size(1)为列,及数据维度
        in_size = x.size(0)
        x = self.mp(F.relu(self.conv1(x)))
        x = self.rblock1(x)
        x = self.mp(F.relu(self.conv2(x)))
        x = self.rblock2(x)
        #将x从(banch,32,4,4)变为(in_size,512),in_size即banch大小
        x = x.view(in_size, -1)
        x = self.fc(x)
        return x

整体代码如下:

#导入相应的包
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
import torch.nn as nn

#小训练集大小
batch_size = 64

#数据集的处理
#图片变换:转换成Tensor,标准化
transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize((0.1307,),(0.3081,))])
#创建训练数据集
train_dataset = datasets.MNIST(root='../dataset/mnist/',
                               train=True, download=True,
                               transform=transform)
#导入训练数据集
train_loader = DataLoader(train_dataset,
                          shuffle=True,
                          batch_size=batch_size)
#创建测试数据集
test_dataset = datasets.MNIST(root='../dataset/mnist/',
                              train=False,
                              download=True,
                              transform=transform)
#导入测试数据集
test_loader = DataLoader(test_dataset,
                          shuffle=False,
                          batch_size=batch_size)

#定义残差块
class ResidualBlock(nn.Module):
    def __init__(self, channels):
        super(ResidualBlock, self).__init__()
        #初始化属性
        self.channels = channels
        self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)

    #定义前馈函数
    def forward(self, x):
        y = F.relu(self.conv1(x))
        y = self.conv2(y)
        #返回值为输入x + y(经过处理的x)
        return F.relu(x + y)

#设计模型
class Net(nn.Module):
    #初始化属性
    def __init__(self):
        super(Net, self).__init__()
        #两个卷积
        self.conv1 = nn.Conv2d(1, 16, kernel_size=5)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=5)
        #最大池化
        self.mp = nn.MaxPool2d(2)
        #两个残差块
        self.rblock1 = ResidualBlock(16)
        self.rblock2 = ResidualBlock(32)
        #全连接
        self.fc = nn.Linear(512, 10)

    def forward(self, x):
        #这里是提取了x的行数,可以理解为输入数据的个数,x.size(1)为列,及数据维度
        in_size = x.size(0)
        x = self.mp(F.relu(self.conv1(x)))
        x = self.rblock1(x)
        x = self.mp(F.relu(self.conv2(x)))
        x = self.rblock2(x)
        #将x从(banch,32,4,4)变为(in_size,512),in_size即banch大小
        x = x.view(in_size, -1)
        x = self.fc(x)
        return x

#实例化
model = Net()

#损失函数及反馈
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

#训练
def train(epoch):
    running_loss = 0.0
    for batch_idx,data in enumerate(train_loader, 0):
        inputs, target = data
        optimizer.zero_grad()
        # forward + backward + update
        outputs = model(inputs)
        loss = criterion(outputs, target)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if batch_idx % 300 == 299:
            print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0

def test():
    correct = 0
    total = 0
    #不计算梯度,节省内存
    with torch.no_grad():
        for data in test_loader:
            #导入测试数据
            images, labels = data
            #带入模型,得到输出
            outputs = model(images)
            #找到输出中概率最大的下标及值
            _, predicted = torch.max(outputs.data, dim=1)
            #计算所有的测试个数
            total += labels.size(0)
            #计算正确的个数
            correct += (predicted == labels).sum().item()
    #输出准确率
    print('Accuracy on test set: %d %%' % (100 * correct / total))

if __name__ == '__main__':
    #训练10次
    for epoch in range(10):
        #训练
        train(epoch)
        #测试
        test()
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值