Pytorch学习笔记(4):卷积神经网络

本博客基于github上某位大神的pytorch入门学习代码,在他的基础上加上了更详细的中文注释以及不懂的模块使用方法。github连接:https://github.com/yunjey/pytorch-tutorial

在运行代码之前,请确保当前环境已经安装torch、torchvision。

卷积神经网络

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms

# 指定运行的gpu设备
torch.cuda.set_device(0)
# 如果有cuda,使用cuda运行
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 超参数设置
num_epochs = 5
num_classes = 10
batch_size = 100
learning_rate = 0.001

# 下载训练数据集
train_dataset = torchvision.datasets.MNIST(root="../../data/minist", train=True, transform=transforms.ToTensor(), download=True)
# 下载测试数据集
test_dataset = torchvision.datasets.MNIST(root="../../data/minist", train=False, transform=transforms.ToTensor())

# 训练集和测试集数据加载器,设置批次输入大小以及乱序
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

# 定义卷积神经网络,这里有两个卷积层
class ConvNet(nn.Module):
    def __init__(self, num_classes=10):
        super(ConvNet, self).__init__()
        # 第一个卷积层
        self.layer1 = nn.Sequential(
            # 卷积层计算
            nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2),
            # 批归一化,防止因为数据过大导致RELU结果不稳定
            nn.BatchNorm2d(16),
            # 使用ReLU激活函数
            nn.ReLU(),
            # 最大池化层
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        # 第二个卷积层
        self.layer2 = nn.Sequential(
            # 卷积层计算
            nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2),
            # 批归一化
            nn.BatchNorm2d(32),
            # 使用ReLU激活函数
            nn.ReLU(),
            # 最大池化层
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        # 全连接层
        self.fc = nn.Linear(7*7*32, num_classes)
    
    # 前向传播
    def forward(self, x):
        out = self.layer1(x)
        out = self.layer2(out)
        # 转换成一维的向量(7*7*32)
        out = out.reshape(out.size(0), -1)
        print(out.size())
        out = self.fc(out)
        return out

# 创建模型,并在gpu上运行
model = ConvNet(num_classes).to(device)

# 交叉熵损失函数
criterion = nn.CrossEntropyLoss()
# 优化器,使用Adam优化算法
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

# 训练模型
total_step = len(train_loader)

for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # 将images和labels两个数据都搬到gpu上
        images = images.to(device)
        labels = labels.to(device)

        # 前向传播计算
        outputs = model(images)
        # 计算损失
        loss = criterion(outputs, labels)

        # 清空梯度缓存
        optimizer.zero_grad()
        # 反向传播
        loss.backward()
        # 更新梯度
        optimizer.step()

        if (i+1) % 100 == 0:
            print("Epoch [{}/{}], Step[{}/{}], loss:{:.4f}".format(epoch+1, num_epochs, i+1, total_step, loss.item()))

# 切换成评估模式,测试和训练时的操作不一样
model.eval()

# 测试模型
# 不用计算梯度
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
    print("Test accuracy of the model on the 10000 test images: {} %".format(100 * correct/total))

# 保存模型
torch.save(model.state_dict(), "./model/convModel.ckpt")

运行过程:
在这里插入图片描述

方法解释

nn.Sequential()

一个顺序容器,传入的神经网络模块将按顺序执行

nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

2维卷积,一般用于图像的卷积。

参数:

  • in_channels:输入图像的通道数
  • out_channels:输出的通道数
  • kernel_size:卷积核尺寸,可以设为一个整数或(int,int)类型的元组
  • stride:卷积步长,可以设为一个整数或(int,int)类型的元组
  • padding:填充操作
  • dilation:扩张操作,控制卷积核点的间距(默认为1)
  • groups:控制分组卷积,默认不分组(1组)
  • bias:是否将bias作为可学习的参数,默认为True

nn.BatchNorm2d()

常用于卷积网络中进行归一化处理,防止梯度爆炸。一般来说设置的参数就是卷积网络的通道数。

nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

对于输入的通道进行2维最大池化操作。

参数:

  • kernel_size:max_pooling的窗口大小
  • stride:窗口移动的步长,默认值等于kernel_size
  • padding:填充操作
  • dilation:扩张操作,控制窗口中元素步幅的参数
  • return_indices:如果设置为True,会返回最大值的下标
  • ceil_mode:如果设置为True,计算输出信号的时候,会向上取整

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值