pytorch深度学习笔记22

目录

摘要

1.池化层

2.深度卷积神经网络

3.​​​​​​​案例:服装分类


摘要

本篇文章继续学习尚硅谷深度学习教程,学习内容是卷积神经网络中的池化层和深度卷积网络相关知识,以及实际案例代码学习

1.池化层

池化层缩小长、宽方向上的空间来进行降 维,能够缩减模型的大小并提高计算速度。例如,对数据进行步幅为2的2×2的Max池化:

除了Max池化(计算窗口内的最大值),还有Average池化(平均池化,计算窗口内的平均值)等。一般会将池化的大小窗口和步幅设置为相同的值,比如2×2的窗口大小,步幅会设置为2。池化同样也可以设置填充。

和卷积层不同,池化层没有要学习的参数,并且池化运算按通道独立进行,经过池化运算后数据的通道数不会发生变化。

池化的另一个特点是对微小偏差具有鲁棒性,数据发生微小偏差时,池化可能会返回相同的结果。例如,数据在宽度方向上偏离1个元素,返回的结果不变。

API使用:

python 复制代码
# 最大池化
torch.nn.MaxPool2d(kernel_size, stride, padding)
# 平均池化
torch.nn.AvgPool2d(kernel_size, stride, padding)

import torch
import matplotlib.pyplot as plt

# 读取图片
img = plt.imread("data/duck.jpg")
print("图片数据形状:", img.shape)

# 将图片数据转换为张量并改变形状
input = torch.tensor(img).permute(2, 0, 1).float()
print("输入特征图形状:", input.shape)

# 初始化卷积核
conv = torch.nn.Conv2d(in_channels=3, out_channels=3, kernel_size=9, stride=3, padding=0, bias=False)

# 对输入特征图进行卷积操作
output1 = conv(input)
print("卷积后输出特征图形状:", output1.shape)

# 初始化池化层
pool = torch.nn.MaxPool2d(kernel_size=6, stride=6, padding=1)

# 进行池化操作
output2 = pool(output1)
print("池化后输出特征图形状:", output2.shape)

# 将输出特征图转换为图片
output1 = torch.clamp(output1.int(), 0, 255)  # 限制输出在0到255之间
output1 = output1.permute(1, 2, 0).detach().numpy()
output2 = torch.clamp(output2.int(), 0, 255)  # 限制输出在0到255之间
output2 = output2.permute(1, 2, 0).detach().numpy()

fig, ax = plt.subplots(1, 3, figsize=(15, 5))
ax[0].imshow(img)
ax[1].imshow(output1)
ax[2].imshow(output2)
plt.axis("off")    
plt.show()

2.​​​​​​​深度卷积神经网络

将神经网络的层数加深,可以更有效地提取层次信息,还可以减少参数数量,从而让学习更加高效。

基于CNN构建深度神经网络,可以提取出更多的图片信息,大幅提高图像识别精度。在人工智能的发展历程中,正是深度卷积神经网络,掀起了最近一轮深度学习的热潮。

AlexNet

2012年由Alex Krizhevsky、Ilya Sutskever与 Geoffrey Hinton合作提出,是一个基于CNN构建的神经网络模型,主要架构包含8层(5个卷积层+3个全连接层),激活函数使用 ReLU,最后经全连接层输出结果,并且使用了Dropout。

AlexNet在当年的ImageNet图像分类挑战赛中大幅刷新性能纪录,引发广泛关注;这被认为是深度学习兴起的标志。

VGG

2014年由牛津大学 Visual Geometry Group(视觉几何组)提出。VGG网络由多个卷积-池化层堆叠构成,将有权重的层(卷积层或全连接层)叠加至 16 或 19 层,也被称为VGG-16和VGG-19。

VGG结构简单,应用性强,因此得到了大量技术人员的青睐。

GoogleNet

2014年由Google团队提出的深度卷积神经网络架构。

整体上看,GoogleNet有更加复杂的网络结构,不过它的底层依然和CNN相同。它的特点是,引入了"Inception结构",使得网络不仅纵向上有深度,在横向上也有深度。

横向上使用多个大小不同的滤波器、最后再合并;有利于 减少参数数量、解决梯度消失问题。

  1. ResNet

2015年由微软团队(何恺明等人)提出,比之前的网络具有更深的结构。

为了解决深度网络的梯度消失问题,ResNet以 VGG 为基础,引入了"快捷结构"。这样一来,网络学习的目标就由原始的输出变为了,这被称为"残差学习";引入的这个恒等映射被称为"残差连接"(或者"跳跃连接"),这种网络结构也被称为"残差网络"(Residual Network,ResNet)。

ResNet有效地解决了深度网络中的梯度消失和梯度爆炸问题,在加深层的同时,提高了网络性能。

3.​​​​​​​案例:服装分类

使用Fashion MNIST数据集:https://www.kaggle.com/datasets/zalando-research/fashionmnist

数据集中每个样本都是28×28的灰度图像,与来自10个类别的标签相关联。标签对应如下:

  • 0:T恤/上衣
  • 1:裤子
  • 2:套头衫
  • 3:连衣裙
  • 4:外套
  • 5:凉鞋
  • 6:衬衫
  • 7:运动鞋
  • 8:包
  • 9:靴子

数据在csv文件中,每行数据为1个样本,第1列为标签,2到785列为784个像素。我们需要将其转换为28×28的形状:

python 复制代码
import torch
import pandas as pd
import torch.nn as nn
import matplotlib.pyplot as plt
from torch.utils.data import TensorDataset, DataLoader

# 读取数据
fashion_mnist_train = pd.read_csv("data/fashion-mnist_train.csv")
fashion_mnist_test = pd.read_csv("data/fashion-mnist_test.csv")
# 将数据转换为张量,原数据形状为n×1×784,转换为n×1×28×28的张量
X_train = torch.tensor(fashion_mnist_train.iloc[:, 1:].values, dtype=torch.float32).reshape(-1, 1, 28, 28)
y_train = torch.tensor(fashion_mnist_train.iloc[:, 0].values, dtype=torch.int64)
X_test = torch.tensor(fashion_mnist_test.iloc[:, 1:].values, dtype=torch.float32).reshape(-1, 1, 28, 28)
y_test = torch.tensor(fashion_mnist_test.iloc[:, 0].values, dtype=torch.int64)
plt.imshow(X_train[12345, 0, :, :], cmap="gray")
plt.show()
# 构建数据集
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)

搭建如下结构的模型:

python 复制代码
# 搭建模型
model = nn.Sequential(
    nn.Conv2d(1, 6, kernel_size=5, padding=2),
    nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),
    nn.Conv2d(6, 16, kernel_size=5),
    nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2, stride=2),
    nn.Flatten(),  # 拉平
    nn.Linear(400, 120),
    nn.Sigmoid(),
    nn.Linear(120, 84),
    nn.Sigmoid(),
    nn.Linear(84, 10),
)
#给模型一个输入,测试各层输出值形状是否符合预期:
# 查看各层输出数据的形状
X = torch.rand(size=(1, 1, 28, 28), dtype=torch.float32)
for layer in model:
    X = layer(X)
    print(f"{layer.__class__.__name__:<12}output shape: {X.shape}")

先初始化线性层和卷积层的权重参数。使用交叉熵损失函数和SGD优化方法。每个epoch中在训练集上训练模型,并在验证集上验证模型的准确率。

python 复制代码
# 模型训练
def train(model, train_dataset, test_dataset, lr, epoch_num, batch_size, device):
    def init_weights(layer):
        # 对线性层和卷积层使用Xavier均匀分布初始化参数
        if type(layer) == nn.Linear or type(layer) == nn.Conv2d:
            nn.init.xavier_uniform_(layer.weight)

    model.apply(init_weights)  # 初始化参数
    model.to(device)  # 将模型加载到设备
    loss = nn.CrossEntropyLoss()  # 损失函数
    optimizer = torch.optim.SGD(model.parameters(), lr=lr)  # 优化器
    for epoch in range(epoch_num):

        # 训练过程
        model.train()  # 将模型设置为训练模式
        train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
        loss_accumulate = 0
        train_correct_accumulate = 0
        for batch_count, (X, y) in enumerate(train_loader):
            # 前向传播
            X, y = X.to(device), y.to(device)
            output = model(X)
            # 反向传播
            loss_value = loss(output, y)
            optimizer.zero_grad()
            loss_value.backward()
            optimizer.step()
            # 累加损失
            loss_accumulate += loss_value.item()
            # 累加正确输出的数量
            _, pred = output.max(1)
            train_correct_accumulate += pred.eq(y).sum()
            # 打印进度条
            print(f"\repoch:{epoch:0>2}[{'='*(int((batch_count+1) / len(train_loader) * 50)):<50}]", end="")
        this_loss = loss_accumulate / len(train_loader)  # 计算平均损失
        this_train_correct = train_correct_accumulate / len(train_dataset)  # 计算训练准确率

        # 验证过程
        model.eval()  # 将模型设置为评估模式
        test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True)
        test_correct_accumulate = 0
        with torch.no_grad():  # 关闭梯度计算
            for X, y in test_loader:
                # 前向传播
                X, y = X.to(device), y.to(device)
                output = model(X)
                # 累加正确输出的数量
                _, pred = output.max(1)
                test_correct_accumulate += pred.eq(y).sum()
        this_test_correct = test_correct_accumulate / len(test_dataset)  # 计算验证准确率

        # 打印损失,训练准确率,验证准确率
        print(f" loss:{this_loss:.6f}, train_acc:{this_train_correct:.6f}, test_acc:{this_test_correct:.6f}")

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  # 如果cude可用则使用cuda,否则使用cpu
train(model, train_dataset, test_dataset, lr=0.9, epoch_num=20, batch_size=256, device=device)
相关推荐
IT从业者张某某2 小时前
信奥赛-刷题笔记-栈篇-T3-P1318 积水面积
笔记
zhqh1002 小时前
openclaw+qwen(笔记,非教程)
笔记
JELEE.2 小时前
drf笔记与源码解析
笔记·python·django·drf
鄭郑2 小时前
STM32学习笔记--SPI初始化与数据收发(01)
笔记·stm32·学习
蒸蒸yyyyzwd2 小时前
强化学习学习笔记
深度学习
Shining05962 小时前
AI 编译器系列(三)《PyTorch 中图优化》
人工智能·pytorch·python·深度学习·学习·机器学习·infinitensor
wuxuand2 小时前
2026论文阅读——零日攻击无处遁形:一种用于网络入侵检测的新型对比损失函数
网络·人工智能·深度学习
花间相见2 小时前
【知识库笔记管理】—— 使用PARA方法高效建立自己个人知识库
大数据·笔记
浅念-2 小时前
C++11 核心知识点整理
开发语言·数据结构·c++·笔记·算法