Pytorch深度学习笔记(十一)卷积神经网络CNN

目录

1.概述

2.单通道卷积

3.多通道卷积

4.卷积层常见的参数

5.代码实现(卷积神经网络训练MNIST数据集)


推荐课程:10.卷积神经网络(基础篇)_哔哩哔哩_bilibili

1.概述

全连接神经网络:完全由线性层串行连接起来的网络。在全连接神经网络中,我们会把图像像素映射为一个较长的张量,这样会丧失图像像素之间原始的空间结构

卷积神经网络:保留图像像素之间原始的空间结构的神经网络。

convolution卷积:会保留图像像素之间原始的空间结构

subsampling下采样:缩小图像,提取特征值。

卷积神经网络分为feature extraction特征提取和classification分类两部分。

卷积层每次需要拿出一块像素块进行操作:

Input Channel输入通道数、Output Channel输出通道数、卷积核的大小(长和宽)

2.单通道卷积

可以把卷积核以及卷积核扫描到图像的区域当作两个矩阵,卷积核依次与扫描到的区域做数乘

单通道卷积运算的过程: 

1.将对应位置的元素相乘

2.将得到的所有乘积做一个求和

3.放到输出矩阵的对应位置

3.多通道卷积

有多少个输入通道,卷积核就要有多少个通道数,数乘后,将所有得到的输出矩阵(张量)相加,得到最终的输出矩阵(张量)。

三个卷积核通道构成一个卷积核。

在RGB模型上的表现:

如果有n个输入通道m个输出通道:

1.卷积核的通道数输入通道数一致

2.卷积核的总个数输出通道数一致,输出张量的通道数输出通道数一致

3.注意:输出张量的长和宽与卷积核的长和宽一定相同

(牢记这三条卷积规则)

最后将输出的张量摞叠起来。

一个卷积核的大小 = n*卷积核的宽度*卷积核的高度

卷积核总的大小 = m*n*卷积核的宽度*卷积核的高度 

卷积网络的权重为(输出通道数m, 输入通道数n, 卷积核的宽度, 卷积核的高度 )

import torch
# 输入、输出通道数
in_channels, out_channels = 5, 10
# 图像的宽高
width, height = 100, 100
# 卷积核大小
kernel_size = 3
# batch大小
batch_size = 1

# 设置输入张量
input = torch.randn(batch_size,
                    in_channels,
                    width,
                    height)
# 卷积层
# 设置卷积核,kernel_size则默认卷积核为3*3
conv_layer = torch.nn.Conv2d(in_channels,
                             out_channels,
                             kernel_size=kernel_size)

# 返回输出
output = conv_layer(input)

print(input.shape)
print(output.shape)
print(conv_layer.weight.shape)

4.卷积层常见的参数

padding(填充):在某些情况下,我们希望输出的张量变得更大一些,由于输出张量的大小与卷积核在输入图像上的扫描面积有关,因此我们只需在输入图像外围填充0即可。padding=1,等于在输入矩阵(张量)外围扩张一层,则长/宽+2。padding=n,长/宽+2*n。

stride(步长)卷积核在输入图像上的扫描间隔。可以有效降低输出张量的大小。Max pooling默认stride = 2。stride = 2意味着输出张量长和宽各减小一半。

注:输出矩阵的长/宽 = 输入矩阵的长/宽 - 卷积核长/宽 + 1

5.代码实现(卷积神经网络训练MNIST数据集)

Conv2d Layer为卷积层。Pooling Layer为最大池层,输出张量缩小一半。ReLU Layer为激活层。

参考之前的标黄的卷积规则,思考(1,28,28)—Conv2d(in = 1,out = 10,size = 5)—>(10,24,24)。

import torch
# 用于图像映射到矩阵中
from matplotlib import pyplot as plt
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

batch_size = 64

#…1.准备数据………………………………………………………………………………………………………………………………………#
# 把像素值0-255转化为图像张量0-1
transform = transforms.Compose([
    # transforms.ToTensor()转化张量,Normalize映射到[0,1]之间
    transforms.ToTensor(),
    # (均值,标准差)
    transforms.Normalize((0.1307, ), (0.381, ))
])

# 训练集
train_dataset = datasets.MNIST(root="../dataset/mnist",
                           train=True,
                           download=False,
                           transform=transform)

train_loader = DataLoader(train_dataset,
                          batch_size=batch_size,
                          shuffle=True)

test_dataset = datasets.MNIST(root="../dataset/mnist",
                           train=False,
                           download=False,
                           transform=transform)

test_loader = DataLoader(test_dataset,
                          batch_size=batch_size,
                          shuffle=False)


#…2.设计模型………………………………………………………………………………………………………………………………………#
# 继承torch.nn.Module,定义自己的计算模块,neural network
class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 卷积层(输入通道数,输出通道数,卷积核大小(长/宽))
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=5)
        # 最大池层,池化,卷积核大小(长/宽)减小一半
        self.pooling = torch.nn.MaxPool2d(2)
        # 从320维降到10维
        self.fc = torch.nn.Linear(320, 10)

    def forward(self, x):
        # flatten data from (n,1,28,28) to (n, 784)
        batch_size = x.size(0)
        # 激活
        x = F.relu(self.pooling(self.conv1(x)))
        x = F.relu(self.pooling(self.conv2(x)))
        # 调整张量维度为320
        x = x.view(batch_size, -1)  # -1 此处自动算出的是320
        # 降维
        x = self.fc(x)

        return x

#……3.构造损失函数和优化器………………………………………………………………………………………………………#
model = Net()
# 实例化损失函数,返回损失值
criterion = torch.nn.CrossEntropyLoss()
# 优化器,momentum冲量
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

#……4.训练和测试……………………………………………………………………………………………………………………………#
def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        # 1.准备数据
        inputs, labels = data
        optimizer.zero_grad()
        # 2.正向传播
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        # 3.反向传播
        loss.backward()
        # 4.更新权重w
        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():内部代码不会再计算梯度
    with torch.no_grad():
        for data in test_loader:
            images, labels = data
            # 内部权重已更新完毕,测试时直接使用即可
            outputs = model(images)
            # dim沿着第一个纬度(行)找最大值,返回(最大值,最大值下标)
            _, predicted = torch.max(outputs.data, dim=1)
            total += labels.size(0)
            # 预测值与标签对比,正确则加1
            correct += (predicted == labels).sum().item()
    # 输出精确率
    print('Accuracy on test set: %d %%' % (100 * correct / total))
    return correct / total


if __name__ == '__main__':
    epoch_list = []
    acc_list = []

    for epoch in range(10):
        train(epoch)
        acc = test()
        epoch_list.append(epoch)
        acc_list.append(acc)

#…………5.绘图……………………………………………………………………#
    plt.plot(epoch_list, acc_list)
    plt.ylabel('accuracy')
    plt.xlabel('epoch')
    plt.show()

 训练结果:

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向岸看

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值