【PyTorch】现代卷积神经网络

news2024/12/22 23:54:21

文章目录

  • 1. 理论介绍
    • 1.1. 深度卷积神经网络(AlexNet)
      • 1.1.1. 概述
      • 1.1.2. 模型设计
    • 1.2. 使用块的网络(VGG)
    • 1.3. 网络中的网络(NiN)
    • 1.4. 含并行连结的网络(GoogLeNet)
  • 2. 实例解析
    • 2.1. 实例描述
    • 2.2. 代码实现
      • 2.2.1. 在FashionMNIST数据集上训练AlexNet
        • 2.2.1.1. 主要代码
        • 2.2.1.2. 完整代码
        • 2.2.1.3. 输出结果
      • 2.2.2. 在FashionMNIST数据集上训练VGG-11
        • 2.2.2.1. 主要代码
        • 2.2.2.2. 完整代码
        • 2.2.2.3. 输出结果
      • 2.2.3. 在FashionMNIST数据集上训练NiN
        • 2.2.3.1. 主要代码
        • 2.2.3.2. 完整代码
        • 2.2.3.3. 输出结果
      • 2.2.4. 在FashionMNIST数据集上训练GoogLeNet
        • 2.2.4.1. 主要代码
        • 2.2.4.2. 完整代码
        • 2.2.4.3. 输出结果

1. 理论介绍

1.1. 深度卷积神经网络(AlexNet)

1.1.1. 概述

  • 特征本身应该被学习,而且在合理地复杂性前提下,特征应该由多个共同学习的神经网络层组成,每个层都有可学习的参数。在机器视觉中,最底层可能检测边缘、颜色和纹理,更高层建立在这些底层表示的基础上,以表示更大的特征。
  • 包含许多特征的深度模型需要大量的有标签数据,才能显著优于基于凸优化的传统方法(如线性方法和核方法)。ImageNet挑战赛为研究人员提高超大规模的数据集。
  • 深度学习对计算资源要求很高,训练可能需要数百个迭代轮数,每次迭代都需要通过代价高昂的许多线性代数层传递数据。用GPU训练神经网络大大提高了训练速度,相比于CPU,GPU由100~1000个小的处理单元(核心)组成,庞大的核心数量使GPU比CPU快几个数量级;GPU核心更简单,功耗更低;GPU拥有更高的内存带宽;卷积和矩阵乘法,都是可以在GPU上并行化的操作。
  • AlexNet首次证明了学习到的特征可以超越手工设计的特征。

1.1.2. 模型设计

模型设计

  • AlexNet使用ReLU而不是sigmoid作为其激活函数。
  • 在最后一个卷积层后有两个全连接层,分别有4096个输出。 这两个巨大的全连接层拥有将近1GB的模型参数。 由于早期GPU显存有限,原版的AlexNet采用了双数据流设计,使得每个GPU只负责存储和计算模型的一半参数。
  • AlexNet通过暂退法控制全连接层的模型复杂度。
  • 为了进一步扩充数据,AlexNet在训练时增加了大量的图像增强数据,如翻转、裁切和变色。 这使得模型更健壮,更大的样本量有效地减少了过拟合。

1.2. 使用块的网络(VGG)

  • 经典卷积神经网络的基本组成部分
    • 带填充以保持分辨率的卷积层
    • 非线性激活函数
    • 池化层
  • VGG块由一系列卷积层组成,后面再加上用于空间下采样的最大池化层。深层且窄的卷积(即 3 × 3 3\times3 3×3)比较浅层且宽的卷积更有效。不同的VGG模型可通过每个VGG块中卷积层数量和输出通道数量的差异来定义。
  • VGG网络由几个VGG块和全连接层组成。超参数变量conv_arch指定了每个VGG块里卷积层个数和输出通道数。全连接模块则与AlexNet中的相同。
  • VGG-11有5个VGG块,其中前两个块各有一个卷积层,后三个块各包含两个卷积层,共8个卷积层。 第一个模块有64个输出通道,每个后续模块将输出通道数量翻倍,直到该数字达到512。

1.3. 网络中的网络(NiN)

  • 网络中的网络(NiN)在每个像素的通道上分别使用多层感知机
  • NiN块以一个普通卷积层开始,后面是两个 1 × 1 1\times1 1×1的卷积层。这两个 1 × 1 1\times1 1×1卷积层充当带有ReLU激活函数的逐像素全连接层。
  • NiN网络使用窗口形状为 11 × 11 11\times11 11×11 5 × 5 5\times5 5×5 3 × 3 3\times3 3×3的卷积层,输出通道数量与AlexNet中的相同。 每个NiN块后有一个最大池化层,池化窗口形状为 3 × 3 3\times3 3×3,步幅为2。 NiN和AlexNet之间的一个显著区别是NiN完全取消了全连接层。NiN使用一个NiN块,其输出通道数等于标签类别的数量。最后放一个全局平均池化层,生成一个对数几率 (logits)。
  • 移除全连接层可减少过拟合,同时显著减少NiN的参数。

1.4. 含并行连结的网络(GoogLeNet)

  • 使用不同大小的卷积核组合是有利的,因为可以有效地识别不同范围的图像细节。
  • Inception块由四条并行路径组成。四条路径都使用合适的填充来使输入与输出的高和宽一致。超参数是每层输出通道数
    Inception
  • GoogLeNet一共使用9个Inception块和全局平均汇聚层的堆叠来生成其估计值。Inception块之间的最大汇聚层可降低维度。
    GoogLeNet

2. 实例解析

2.1. 实例描述

  • 在FashionMNIST数据集上训练AlexNet。注:输入图像调整到 224 × 224 224\times224 224×224,不使用跨GPU分解模型。
  • 在FashionMNIST数据集上训练VGG-11。注:输入图像调整到 224 × 224 224\times224 224×224,可以按比例缩小通道数以减少参数量,学习率可以设置得略高。
  • 在FashionMNIST数据集上训练NiN。注:输入图像调整到 224 × 224 224\times224 224×224
  • 在FashionMNIST数据集上训练GoogLeNet。注:输入图像调整到 96 × 96 96\times96 96×96

2.2. 代码实现

2.2.1. 在FashionMNIST数据集上训练AlexNet

2.2.1.1. 主要代码
AlexNet = nn.Sequential(
        nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(),
        nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(),
        nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nn.Flatten(),
        nn.Linear(6400, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 10)
).to(device, non_blocking=True)
2.2.1.2. 完整代码
import os, torch
from tensorboardX import SummaryWriter
from rich.progress import track
from torchvision.datasets import FashionMNIST
from torchvision.transforms import Compose, ToTensor, Resize
from torch.utils.data import DataLoader
from torch import nn, optim

def load_dataset():
    """加载数据集"""
    root = "./dataset"
    transform = Compose([Resize(224), ToTensor()])
    mnist_train = FashionMNIST(root, True, transform, download=True)
    mnist_test = FashionMNIST(root, False, transform, download=True)

    dataloader_train = DataLoader(mnist_train, batch_size, shuffle=True, 
        num_workers=num_workers, pin_memory=True,
    )
    dataloader_test = DataLoader(mnist_test, batch_size, shuffle=False,
        num_workers=num_workers, pin_memory=True,
    )
    return dataloader_train, dataloader_test


if __name__ == "__main__":
    # 全局参数设置
    num_epochs = 10
    batch_size = 128
    num_workers = 3
    lr = 0.01
    device = torch.device('cuda')

    # 创建记录器
    def log_dir():
        root = "runs"
        if not os.path.exists(root):
            os.mkdir(root)
        order = len(os.listdir(root)) + 1
        return f'{root}/exp{order}'
    writer = SummaryWriter(log_dir=log_dir())

    # 数据集配置
    dataloader_train, dataloader_test = load_dataset()

    # 模型配置
    AlexNet = nn.Sequential(
        nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(),
        nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(),
        nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nn.Flatten(),
        nn.Linear(6400, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 10)
    ).to(device, non_blocking=True)
    criterion = nn.CrossEntropyLoss(reduction='none')
    optimizer = optim.SGD(AlexNet.parameters(), lr=lr)

    # 训练循环
    metrics_train = torch.zeros(3, device=device)  # 训练损失、训练准确度、样本数
    metrics_test = torch.zeros(2, device=device)   # 测试准确度、样本数
    for epoch in track(range(num_epochs), description='AlexNet'):
        AlexNet.train()
        for X, y in dataloader_train:
            X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
            loss = criterion(AlexNet(X), y)
            optimizer.zero_grad()
            loss.mean().backward()
            optimizer.step()

        AlexNet.eval()
        with torch.no_grad():
            metrics_train.zero_()
            for X, y in dataloader_train:
                X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                y_hat = AlexNet(X)
                loss = criterion(y_hat, y)
                metrics_train[0] += loss.sum()
                metrics_train[1] += (y_hat.argmax(dim=1) == y).sum()
                metrics_train[2] += y.numel()
            metrics_train[0] /= metrics_train[2]
            metrics_train[1] /= metrics_train[2]

            metrics_test.zero_()
            for X, y in dataloader_test:
                X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                y_hat = AlexNet(X)
                metrics_test[0] += (y_hat.argmax(dim=1) == y).sum()
                metrics_test[1] += y.numel()
            metrics_test[0] /= metrics_test[1]

            _metrics_train = metrics_train.cpu().numpy()
            _metrics_test = metrics_test.cpu().numpy()
            writer.add_scalars('metrics', {
                'train_loss': _metrics_train[0],
                'train_acc': _metrics_train[1],
                'test_acc': _metrics_test[0]
            }, epoch)

    writer.close()
2.2.1.3. 输出结果

AlexNet

2.2.2. 在FashionMNIST数据集上训练VGG-11

2.2.2.1. 主要代码
def vgg_block(num_convs, in_channels, out_channels):
        """定义VGG块"""
        layers = []
        for _ in range(num_convs):
            layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
            layers.append(nn.ReLU())
            in_channels = out_channels
        layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
        return nn.Sequential(*layers)

def vgg(conv_arch):
    """定义VGG网络"""
    vgg_blocks = []
    in_channels = 1
    out_channels = 0

    for num_convs, out_channels in conv_arch:
        vgg_blocks.append(vgg_block(num_convs, in_channels, out_channels))
        in_channels = out_channels

    return nn.Sequential(
        *vgg_blocks, 
        nn.Flatten(),
        nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 10),
    )
2.2.2.2. 完整代码
import os
from tensorboardX import SummaryWriter
from rich.progress import track
import torch
from torch import nn, optim
from torch.utils.data import DataLoader
from torchvision.transforms import Compose, Resize, ToTensor
from torchvision.datasets import FashionMNIST

def load_dataset():
    """加载数据集"""
    root = "./dataset"
    transform = Compose([Resize(224), ToTensor()])
    mnist_train = FashionMNIST(root, True, transform, download=True)
    mnist_test = FashionMNIST(root, False, transform, download=True)

    dataloader_train = DataLoader(mnist_train, batch_size, shuffle=True, 
        num_workers=num_workers, pin_memory=True,
    )
    dataloader_test = DataLoader(mnist_test, batch_size, shuffle=False,
        num_workers=num_workers, pin_memory=True,
    )
    return dataloader_train, dataloader_test

def vgg_block(num_convs, in_channels, out_channels):
        """定义VGG块"""
        layers = []
        for _ in range(num_convs):
            layers.append(nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
            layers.append(nn.ReLU())
            in_channels = out_channels
        layers.append(nn.MaxPool2d(kernel_size=2, stride=2))
        return nn.Sequential(*layers)

def vgg(conv_arch):
    """定义VGG网络"""
    vgg_blocks = []
    in_channels = 1
    out_channels = 0

    for num_convs, out_channels in conv_arch:
        vgg_blocks.append(vgg_block(num_convs, in_channels, out_channels))
        in_channels = out_channels

    return nn.Sequential(
        *vgg_blocks, 
        nn.Flatten(),
        nn.Linear(out_channels * 7 * 7, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 4096), nn.ReLU(),
        nn.Dropout(p=0.5),
        nn.Linear(4096, 10),
    )


if __name__ == '__main__':
    # 全局参数配置
    num_epochs = 10
    batch_size = 128
    num_workers = 3
    lr = 0.05
    device = torch.device('cuda')

    # 记录器配置
    def log_dir():
        root = "runs"
        if not os.path.exists(root):
            os.mkdir(root)
        order = len(os.listdir(root)) + 1
        return f'{root}/exp{order}'
    writer = SummaryWriter(log_dir=log_dir())

    # 数据集配置
    dataloader_train, dataloader_test = load_dataset()

    # 模型配置
    ratio = 4
    conv_arch = ((1, 64), (1, 128), (2, 256), (2, 512), (2, 512))
    small_conv_arch =  [(pair[0], pair[1] // ratio) for pair in conv_arch]
    net = vgg(small_conv_arch).to(device, non_blocking=True)
    criterion = nn.CrossEntropyLoss(reduction='none')
    optimizer = optim.SGD(net.parameters(), lr=lr)

    # 训练循环
    metrics_train = torch.zeros(3, device=device)  # 训练损失、训练准确度、样本数
    metrics_test = torch.zeros(2, device=device)   # 测试准确度、样本数
    for epoch in track(range(num_epochs), description='VGG'):
        net.train()
        for X, y in dataloader_train:
            X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
            loss = criterion(net(X), y)
            optimizer.zero_grad()
            loss.mean().backward()
            optimizer.step()
    
        net.eval()
        with torch.no_grad():
            metrics_train.zero_()
            for X, y in dataloader_train:
                X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                y_hat = net(X)
                loss = criterion(y_hat, y)
                metrics_train[0] += loss.sum()
                metrics_train[1] += (y_hat.argmax(dim=1) == y).sum()
                metrics_train[2] += y.numel()
            metrics_train[0] /= metrics_train[2]
            metrics_train[1] /= metrics_train[2]
    
            metrics_test.zero_()
            for X, y in dataloader_test:
                X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                y_hat = net(X)
                metrics_test[0] += (y_hat.argmax(dim=1) == y).sum()
                metrics_test[1] += y.numel()
            metrics_test[0] /= metrics_test[1]
    
            _metrics_train = metrics_train.cpu().numpy()
            _metrics_test = metrics_test.cpu().numpy()
            writer.add_scalars('metrics', {
                'train_loss': _metrics_train[0],
                'train_acc': _metrics_train[1],
                'test_acc': _metrics_test[0]
            }, epoch)
    
    writer.close()
2.2.2.3. 输出结果

VGG

2.2.3. 在FashionMNIST数据集上训练NiN

2.2.3.1. 主要代码
def nin_block(in_channels, out_channels, kernel_size, strides, padding):
    """定义NiN块"""
    return nn.Sequential(
        nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding), nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),
        nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU()
    )
net = nn.Sequential(
    nin_block(1, 96, kernel_size=11, strides=4, padding=0),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nin_block(96, 256, kernel_size=5, strides=1, padding=2),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nin_block(256, 384, kernel_size=3, strides=1, padding=1),
    nn.MaxPool2d(kernel_size=3, stride=2),
    nn.Dropout(0.5),
    nin_block(384, 10, kernel_size=3, strides=1, padding=1),
    nn.AdaptiveAvgPool2d((1, 1)),
    nn.Flatten()
).to(device, non_blocking=True)
2.2.3.2. 完整代码
import os
from tensorboardX import SummaryWriter
from alive_progress import alive_bar
import torch
from torch import nn, optim
from torch.utils.data import DataLoader
from torchvision.transforms import Compose, ToTensor, Resize
from torchvision.datasets import FashionMNIST

def load_dataset():
    """加载数据集"""
    root = "./dataset"
    transform = Compose([Resize(224), ToTensor()])
    mnist_train = FashionMNIST(root, True, transform, download=True)
    mnist_test = FashionMNIST(root, False, transform, download=True)

    dataloader_train = DataLoader(mnist_train, batch_size, shuffle=True, 
        num_workers=num_workers, pin_memory=True,
    )
    dataloader_test = DataLoader(mnist_test, batch_size, shuffle=False,
        num_workers=num_workers, pin_memory=True,
    )
    return dataloader_train, dataloader_test

def train_on_FashionMNIST(title):
    """在FashionMNIST数据集上训练指定模型"""
    # 创建记录器
    def log_dir():
        root = "runs"
        if not os.path.exists(root):
            os.mkdir(root)
        order = len(os.listdir(root)) + 1
        return f'{root}/exp{order}'
    writer = SummaryWriter(log_dir=log_dir())

    # 数据集配置
    dataloader_train, dataloader_test = load_dataset()

    # 模型配置
    criterion = nn.CrossEntropyLoss(reduction='none')
    optimizer = optim.SGD(net.parameters(), lr=lr)

    # 训练循环
    metrics_train = torch.zeros(3, device=device)  # 训练损失、训练准确度、样本数
    metrics_test = torch.zeros(2, device=device)   # 测试准确度、样本数
    with alive_bar(num_epochs, theme='classic', title=title) as bar:
        for epoch in range(num_epochs):
            net.train()
            for X, y in dataloader_train:
                X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                loss = criterion(net(X), y)
                optimizer.zero_grad()
                loss.mean().backward()
                optimizer.step()
        
            net.eval()
            with torch.no_grad():
                metrics_train.zero_()
                for X, y in dataloader_train:
                    X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                    y_hat = net(X)
                    loss = criterion(y_hat, y)
                    metrics_train[0] += loss.sum()
                    metrics_train[1] += (y_hat.argmax(dim=1) == y).sum()
                    metrics_train[2] += y.numel()
                metrics_train[0] /= metrics_train[2]
                metrics_train[1] /= metrics_train[2]
        
                metrics_test.zero_()
                for X, y in dataloader_test:
                    X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                    y_hat = net(X)
                    metrics_test[0] += (y_hat.argmax(dim=1) == y).sum()
                    metrics_test[1] += y.numel()
                metrics_test[0] /= metrics_test[1]
        
                _metrics_train = metrics_train.cpu().numpy()
                _metrics_test = metrics_test.cpu().numpy()
                writer.add_scalars('metrics', {
                    'train_loss': _metrics_train[0],
                    'train_acc': _metrics_train[1],
                    'test_acc': _metrics_test[0]
                }, epoch)
            bar()
    
    writer.close()

if __name__ == '__main__':
    # 全局参数配置
    num_epochs = 10
    batch_size = 128
    num_workers = 3
    lr = 0.1
    device = torch.device('cuda')

    # 模型配置
    def nin_block(in_channels, out_channels, kernel_size, strides, padding):
        """定义NiN块"""
        return nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding), nn.ReLU(),
            nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),
            nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU()
        )
    net = nn.Sequential(
        nin_block(1, 96, kernel_size=11, strides=4, padding=0),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nin_block(96, 256, kernel_size=5, strides=1, padding=2),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nin_block(256, 384, kernel_size=3, strides=1, padding=1),
        nn.MaxPool2d(kernel_size=3, stride=2),
        nn.Dropout(0.5),
        nin_block(384, 10, kernel_size=3, strides=1, padding=1),
        nn.AdaptiveAvgPool2d((1, 1)),
        nn.Flatten()
    ).to(device, non_blocking=True)
    def init_weights(m):
        if type(m) in [nn.Linear, nn.Conv2d]:
            nn.init.xavier_uniform_(m.weight)
            nn.init.zeros_(m.bias)
    net.apply(init_weights)
    
    # 在FashionMNIST数据集上训练模型
    train_on_FashionMNIST('NiN')
2.2.3.3. 输出结果

NiN

2.2.4. 在FashionMNIST数据集上训练GoogLeNet

2.2.4.1. 主要代码
class Inception(nn.Module):
    # c1--c4是每条路径的输出通道数
    def __init__(self, in_channels, c1, c2, c3, c4, **kwargs):
        super(Inception, self).__init__(**kwargs)
        # 线路1,单1x1卷积层
        self.p1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)
        # 线路2,1x1卷积层后接3x3卷积层
        self.p2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)
        self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
        # 线路3,1x1卷积层后接5x5卷积层
        self.p3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)
        self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
        # 线路4,3x3最大汇聚层后接1x1卷积层
        self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
        self.p4_2 = nn.Conv2d(in_channels, c4, kernel_size=1)

    def forward(self, x):
        p1 = F.relu(self.p1_1(x))
        p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))
        p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))
        p4 = F.relu(self.p4_2(self.p4_1(x)))
        # 在通道维度上连结输出
        return torch.cat((p1, p2, p3, p4), dim=1)
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
               nn.ReLU(),
               nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
b2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),
               nn.ReLU(),
               nn.Conv2d(64, 192, kernel_size=3, padding=1),
               nn.ReLU(),
               nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
b3 = nn.Sequential(Inception(192, 64, (96, 128), (16, 32), 32),
               Inception(256, 128, (128, 192), (32, 96), 64),
               nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
b4 = nn.Sequential(Inception(480, 192, (96, 208), (16, 48), 64),
               Inception(512, 160, (112, 224), (24, 64), 64),
               Inception(512, 128, (128, 256), (24, 64), 64),
               Inception(512, 112, (144, 288), (32, 64), 64),
               Inception(528, 256, (160, 320), (32, 128), 128),
               nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),
               Inception(832, 384, (192, 384), (48, 128), 128),
               nn.AdaptiveAvgPool2d((1,1)),
               nn.Flatten())

net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(1024, 10)).to(device, non_blocking=True)
2.2.4.2. 完整代码
import os
from tensorboardX import SummaryWriter
from alive_progress import alive_bar
import torch
from torch import nn, optim
from torch.nn import functional as F
from torch.utils.data import DataLoader
from torchvision.transforms import Compose, ToTensor, Resize
from torchvision.datasets import FashionMNIST

def load_dataset():
    """加载数据集"""
    root = "./dataset"
    transform = Compose([Resize(96), ToTensor()])
    mnist_train = FashionMNIST(root, True, transform, download=True)
    mnist_test = FashionMNIST(root, False, transform, download=True)

    dataloader_train = DataLoader(mnist_train, batch_size, shuffle=True, 
        num_workers=num_workers, pin_memory=True,
    )
    dataloader_test = DataLoader(mnist_test, batch_size, shuffle=False,
        num_workers=num_workers, pin_memory=True,
    )
    return dataloader_train, dataloader_test

def train_on_FashionMNIST(title):
    """在FashionMNIST数据集上训练指定模型"""
    # 创建记录器
    def log_dir():
        root = "runs"
        if not os.path.exists(root):
            os.mkdir(root)
        order = len(os.listdir(root)) + 1
        return f'{root}/exp{order}'
    writer = SummaryWriter(log_dir=log_dir())

    # 数据集配置
    dataloader_train, dataloader_test = load_dataset()

    # 模型配置
    criterion = nn.CrossEntropyLoss(reduction='none')
    optimizer = optim.SGD(net.parameters(), lr=lr)

    # 训练循环
    metrics_train = torch.zeros(3, device=device)  # 训练损失、训练准确度、样本数
    metrics_test = torch.zeros(2, device=device)   # 测试准确度、样本数
    with alive_bar(num_epochs, theme='classic', title=title) as bar:
        for epoch in range(num_epochs):
            net.train()
            for X, y in dataloader_train:
                X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                loss = criterion(net(X), y)
                optimizer.zero_grad()
                loss.mean().backward()
                optimizer.step()
        
            net.eval()
            with torch.no_grad():
                metrics_train.zero_()
                for X, y in dataloader_train:
                    X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                    y_hat = net(X)
                    loss = criterion(y_hat, y)
                    metrics_train[0] += loss.sum()
                    metrics_train[1] += (y_hat.argmax(dim=1) == y).sum()
                    metrics_train[2] += y.numel()
                metrics_train[0] /= metrics_train[2]
                metrics_train[1] /= metrics_train[2]
        
                metrics_test.zero_()
                for X, y in dataloader_test:
                    X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
                    y_hat = net(X)
                    metrics_test[0] += (y_hat.argmax(dim=1) == y).sum()
                    metrics_test[1] += y.numel()
                metrics_test[0] /= metrics_test[1]
        
                _metrics_train = metrics_train.cpu().numpy()
                _metrics_test = metrics_test.cpu().numpy()
                writer.add_scalars('metrics', {
                    'train_loss': _metrics_train[0],
                    'train_acc': _metrics_train[1],
                    'test_acc': _metrics_test[0]
                }, epoch)
            bar()
    
    writer.close()

if __name__ == '__main__':
    # 全局参数配置
    num_epochs = 10
    batch_size = 128
    num_workers = 3
    lr = 0.1
    device = torch.device('cuda')

    # 模型配置
    class Inception(nn.Module):
        # c1--c4是每条路径的输出通道数
        def __init__(self, in_channels, c1, c2, c3, c4, **kwargs):
            super(Inception, self).__init__(**kwargs)
            # 线路1,单1x1卷积层
            self.p1_1 = nn.Conv2d(in_channels, c1, kernel_size=1)
            # 线路2,1x1卷积层后接3x3卷积层
            self.p2_1 = nn.Conv2d(in_channels, c2[0], kernel_size=1)
            self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)
            # 线路3,1x1卷积层后接5x5卷积层
            self.p3_1 = nn.Conv2d(in_channels, c3[0], kernel_size=1)
            self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)
            # 线路4,3x3最大汇聚层后接1x1卷积层
            self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)
            self.p4_2 = nn.Conv2d(in_channels, c4, kernel_size=1)

        def forward(self, x):
            p1 = F.relu(self.p1_1(x))
            p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))
            p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))
            p4 = F.relu(self.p4_2(self.p4_1(x)))
            # 在通道维度上连结输出
            return torch.cat((p1, p2, p3, p4), dim=1)
    b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
                   nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
    b2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),
                   nn.ReLU(),
                   nn.Conv2d(64, 192, kernel_size=3, padding=1),
                   nn.ReLU(),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
    b3 = nn.Sequential(Inception(192, 64, (96, 128), (16, 32), 32),
                   Inception(256, 128, (128, 192), (32, 96), 64),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
    b4 = nn.Sequential(Inception(480, 192, (96, 208), (16, 48), 64),
                   Inception(512, 160, (112, 224), (24, 64), 64),
                   Inception(512, 128, (128, 256), (24, 64), 64),
                   Inception(512, 112, (144, 288), (32, 64), 64),
                   Inception(528, 256, (160, 320), (32, 128), 128),
                   nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
    b5 = nn.Sequential(Inception(832, 256, (160, 320), (32, 128), 128),
                   Inception(832, 384, (192, 384), (48, 128), 128),
                   nn.AdaptiveAvgPool2d((1,1)),
                   nn.Flatten())

    net = nn.Sequential(b1, b2, b3, b4, b5, nn.Linear(1024, 10)).to(device, non_blocking=True)
    def init_weights(m):
        if type(m) in [nn.Linear, nn.Conv2d]:
            nn.init.xavier_uniform_(m.weight)
            nn.init.zeros_(m.bias)
    net.apply(init_weights)

    # 在FashionMNIST数据集上训练模型
    train_on_FashionMNIST('GoogLeNet')
2.2.4.3. 输出结果

GoogLeNet

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1303429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能科技企业网站搭建的作用是什么

随着科学技术快速提升,各种智能产品随之而来,每个赛道里都涌入了大量企业商家,有些热门产品更是广受关注,对企业来说,形象、品牌、信息等方面需要完美呈现到用户眼前,而网站无疑是很好的工具。 企业通过【…

新增模板中心和系统设置模块,支持飞书平台对接,DataEase开源数据可视化分析平台v2.1.0发布

这一版本的功能升级包括:新增模板中心,用户可以通过模板中心的模板快速创建仪表板和数据大屏;新增“系统设置”功能模块,该模块包含系统参数、认证设置、嵌入式管理、平台对接四个子模块。在“系统参数”子模块中,用户…

OpenCV-opencv下载安装和基本操作

文章目录 一、实验目的二、实验内容三、实验过程OpenCV-python的安装与配置python下载和环境配置PIP镜像安装Numpy安装openCV-python检验opencv安装是否成功 openCV-python的基本操作图像输入和展示以及写出openCV界面编程单窗口显示多图片鼠标事件键盘事件滑动条事件 四、实验…

LeetCode 279完全平方数 139单词拆分 卡码网 56携带矿石资源(多重背包) | 代码随想录25期训练营day45

动态规划算法6 LeetCode 279 完全平方数 2023.12.11 题目链接代码随想录讲解[链接] int numSquares(int n) {//1确定dp数组,其下标表示j的完全平方数的最少数量//3初始化,将dp[0]初始化为0,用于计算,其他值设为INT_MAX用于递推…

Django系列之Celery异步框架+RabbitMQ使用

在Django项目中,如何集成使用Celery框架来完成一些异步任务以及定时任务呢? 1. 安装 pip install celery # celery框架 pip install django-celery-beat # celery定时任务使用 pip install django-celery-results # celery存储结果使用2. Django集成…

WebRTC AEC回声消除算法拆解

WebRTC AEC算法流程分析——时延估计(一) 其实,网上有很多类似资料,各个大厂研发不同应用场景设备的音频工程师基本都对其进行了拆解,有些闪烁其词,有些却很深奥,笔者随着对WebRTC了解的深入&a…

修改汽车的控制系统实现自动驾驶,基于一个开源的汽车驾驶辅助系统实现全自动驾驶

修改汽车的控制系统实现自动驾驶,基于一个开源的汽车驾驶辅助系统实现全自动驾驶。 自动驾驶汽车依靠人工智能、视觉计算、雷达、监控装置和全球定位系统协同合作,让电脑可以在没有任何人类主动的操作下,自动安全地操作机动车辆。 演示视频: Openpilot :一个开源的汽车驾…

2020年第九届数学建模国际赛小美赛C题亚马逊野火解题全过程文档及程序

2020年第九届数学建模国际赛小美赛 C题 亚马逊野火 原题再现: 野火是指发生在乡村或荒野地区的可燃植被中的任何不受控制的火灾。这样的环境过程对人类生活有着重大的影响。因此,对这一现象进行建模,特别是对其空间发生和扩展进行建模&…

[算法基础 ~排序] Golang 实现

文章目录 排序什么是排序排序的分类1. 冒泡1.1 冒泡排序1.2. 快速排序 2. 选择2.1 简单选择排序2.2 堆排序 3. 插入3.1 直接插入3.2 折半插入3.3 希尔排序 4. 归并排序代码实现 5. 基数排序 排序图片就不贴了吧 排序 什么是排序 以下部分动图来自CSDN ::: tip 稳定性的概念 …

网络测试工具:tcping-测试端口连接

网络测试工具:tcping-测试端口连接 平常使用的ping,是通过icmp协议去测试网络连通性的,tcping是通过tcp三次握手测试端口的连通性。总的来说,ping测试的是L3的连通性,tcping测试的是L4的连通性。 tcping工具下载 htt…

Go语言学习:第1天

一、为什么开始学go语言 我自己是做测试的,所测试项目使用的是go语言。开始学习go语言的原因有两个:一方面,为了更好的做好工作; 另一方面,为了提高自己的核心竞争力。 二、第1天学习到的内容 2.1 Go是怎么解决包依…

打包less

接HTML和css之后对less进行打包 1.在之前的文件夹里的src文件夹创建一个less文件 2.打开webpack——>中文文档——>Loader——>less—loader 3.复制下图代码到终端 4.复制下图内容到webpack.config.js脚本 5.在src里的js文件年引入less文件 6.在终端运行 npm run te…

[原创]如何正确的部署R语言开发环境(含动图演示).

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…

arm-linux设备fsck命令移植

arm-linux设备fsck命令移植 文章目录 **arm-linux设备fsck命令移植**1、下载e2fsprogs-源码2、解压3、进入源码目录4、配置编译环境:使用以下命令配置交叉编译环境5、测试 1、下载e2fsprogs-源码 首先要确定自己的文件系统格式,IG2000的文件系统是ext4&…

基于OpenCV+CNN+IOT+微信小程序智能果实采摘指导系统——深度学习算法应用(含python、JS工程源码)+数据集+模型(四)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境TensorFlow 环境Jupyter Notebook环境Pycharm 环境微信开发者工具OneNET云平台 模块实现1. 数据预处理2. 创建模型并编译3. 模型训练及保存1)模型训练2)模型保存 4. 上传结果1)…

【AI】ChatGLM3-6B上手体验

之前写过ChatGLM2-6B大语言模型的部署安装文档,现在ChatGLM模型已经更新迭代到第三代了,从官方公布的数据来看,模型的能力是得到了进一步的增强。 这次写文章主要是来记录一下使用过程,方便回头查看。 ChatGLM3-6B官方的视频教程…

VSCode中如何查看EDI报文?

VSCode是开发人员常用的一款软件,为了降低EDI报文的阅读门槛,知行的开发人员设计了EDI插件,可以在VSCode中下载使用。 如何打开一个EDI报文——VSCode EDI插件介绍 EDI插件下载流程 进入VSCode,打开Extensions,在搜索…

STM32-01-认识单片机

文章目录 一、单片机简介二、Cortex-M系列介绍三、初识STM32四、STM32原理图设计五、搭建开发环境六、STM32初体验七、MDK5使用技巧 一、单片机简介 单片机是什么? 单片机:Single-Chip Microcomputer,单片微型计算机,是一种集成电…

Keepalived+Nginx实现高可用(上)

一、背景与简介 为了服务的高可用性,避免单点故障问题,通常我们使用"冗余设计思想"进行架构设计。冗余设计思想,本质就是将同一个应用或者服务放置在多台不同的服务器上[鸡蛋不放在同一个篮子里],这样减少整体服务宕机的…

2023 年山东省职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题

2023 年山东省职业院校技能大赛(高等职业教育) “信息安全管理与评估”样题 目录 任务 1 网络平台搭建(50 分) 任务 2 网络安全设备配置与防护(250 分) 模块二 网络安全事件响应、数字取证调查、应用程序安…