浅学 Pytorch

news2024/11/24 20:46:17

(一)Dataset

Dataset 是一个抽象类,用于表示数据集。它封装了数据的加载和预处理逻辑,使得数据的读取和处理更加灵活和易于管理。在PyTorch中,torch.utils.data.Dataset 是一个基类,用户可以继承并实现自己的数据集。

import os
from torch.utils.data import Dataset
from PIL import Image

class CustomDataset(Dataset):
    def __init__(self, root_dir, label_dir):
        self.root_dir = root_dir
        self.label_dir = label_dir
        self.path = os.path.join(self.root_dir, self.label_dir)
        self.img_path = os.listdir(self.path)

    def __len__(self):
        return len(self.img_path)

    def __getitem__(self, idx):
        img_name = self.img_path[idx]
        img_item_path = os.path.join(self.root_dir, self.label_dir, img_name)
        img = Image.open(img_item_path)
        label = self.label_dir
        return img, label


root_dir = 's-data/train'
ants_label_dir = 'ants_img'
bees_label_dir = 'bees_img'
ants_dataset = CustomDataset(root_dir, ants_label_dir)
bees_dataset = CustomDataset(root_dir, bees_label_dir)

img, label = bees_dataset[0]
img.show()

(二)TensorBoard

TensorBoard 是一个强大的可视化工具,它主要用于可视化和分析神经网络的训练过程,包括损失和准确率的变化、模型结构、图像数据、激活值等。

from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image

writer = SummaryWriter('logs')
img_path = 's-data/train/bees_img/16838648_415acd9e3f.jpg'
img_PIL = Image.open(img_path)
img_array = np.array(img_PIL)
# global_step 表示写入的步数(类似索引)
writer.add_image('test', img_array, 2, dataformats='HWC')

for i in range(100):
    writer.add_scalar('y=2x', 3 * i, i)

writer.close()

运行:

tensorboard --logdir=logs  --port=6007

(三)常见的 Transforms

1. ToTensor

它将形状为 (H, W, C) 且像素值在 [0, 255] 范围的 PIL 图像或 NumPy 数组转换为形状为 (C, H, W) 且像素值在 [0.0, 1.0] 范围的PyTorch张量。

from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('logs')
img = Image.open('data/train/bees/17209602_fe5a5a746f.jpg')

trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image('ToTensor', img_tensor)

writer.close()

在这里插入图片描述

2. Normalize

标准化的目的是使数据的各个特征具有相似的尺度,从而提高模型的训练效率和稳定性。用于标准化张量图像(tensor image)的每个通道。该变换接受两个参数:均值(mean)和标准差(std),并使用以下公式进行标准化:
output[channel] = (input[channel] - mean[channel]) / std[channel]

from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('logs')
img = Image.open('data/train/bees/17209602_fe5a5a746f.jpg')

trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
writer.add_image('Normalize', img_norm, 1)

writer.close()

在这里插入图片描述

3. Resize

用于将输入的PIL图像调整到模型所需的固定尺寸。
接受目标尺寸作为参数,可以是一个整数或一个二元元组:

  • 二元元组:如果提供一个二元元组,例如 (height, width),Resize 将图像调整为指定的高度和宽度。
  • 整数:如果提供一个整数,Resize 将保持图像的长宽比不变,并将图像的较短边调整为该整数长度,较长边则根据原始比例自动调整。
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('logs')
img = Image.open('data/train/bees/17209602_fe5a5a746f.jpg')

trans_resize = transforms.Resize((300, 300))
trans_resize2 = transforms.Resize(500)
img_resize = trans_resize(img)
img_resize2 = trans_resize2(img)
writer.add_image('Resize', trans_totensor(img_resize), 1)
writer.add_image('Resize', trans_totensor(img_resize2), 2)

writer.close()

4. RandomCrop、CenterCrop

RandomCrop 可以从输入图像中随机裁剪出一个指定大小的区域。
CenterCrop 可以 从图像中心裁剪出指定大小的区域。

trans_random = transforms.RandomCrop(200)
img_random = trans_random(img)
writer.add_image('RandomCrop', trans_totensor(img_random), 1)

trans_center = transforms.CenterCrop(200)
img_center = trans_center(img)
writer.add_image('CenterCrop', trans_totensor(img_center), 1)

5. ToPILImage

用于将 tensor 张量或 NumPy 数组转换为 PIL 图像。

trans_pil = transforms.ToPILImage()
img_pil = trans_pil(img_tensor)
print(type(img_pil))  # <class 'PIL.Image.Image'>

6. Compose

它将一系列图像变换按顺序应用于输入图像,形成一个统一的变换流水线。

from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('logs')
img = Image.open('data/train/bees/17209602_fe5a5a746f.jpg')

transform = transforms.Compose([
    transforms.Resize((300, 300)),
    transforms.CenterCrop(200), 
    transforms.ToTensor(),
    transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])
img_compose = transform(img)
writer.add_image('Compose', img_compose, 2)

writer.close()

7. ColorJitter

随机更改图像的亮度、对比度、饱和度和色调。

trans_color = transforms.ColorJitter(brightness=1, contrast=1, saturation=1, hue=0.5)
img_color = trans_color(img)
writer.add_image('ColorJitter', trans_totensor(img_color), 1)

8. Grayscale

将图像转换为灰度。默认是1

trans_gray = transforms.Grayscale(3)
img_gray = trans_gray(img)
writer.add_image('Grayscale', trans_totensor(img_gray), 1)

(四)DataLoader

用于加载和批量处理数据集。它提供了常见的数据操作功能,如批量加载、数据洗牌、并行数据加载等,从而简化了数据预处理和模型训练流程。
dataloader = DataLoader(dataset, batch_size=64, shuffle=True, num_workers=4)

  • batch_size:每个批次的数据量大小。比如batch_size=64 表示每次从数据集中取 64 个样本。
  • shuffle:在每个 epoch 结束后,是否对数据进行洗牌。shuffle=True 可以打乱数据的顺序,有助于提高模型的泛化能力。
  • num_workers:用于数据加载的子进程数。比如 num_workers=4 表示使用 4 个子进程加载数据。增加 num_workers 数量可以加速数据加载过程,尤其是在数据预处理复杂或数据集较大时。
  • drop_last:如果数据集大小不能被批量大小整除,drop_last=True 则会丢弃最后一个不完整的批次。
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10(root='./CIFA10', train=False, download=True,
                                         transform=torchvision.transforms.ToTensor())

test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)

writer = SummaryWriter('CIFA-logs')

step = 0
for data in test_loader:
    imgs, targets = data
    writer.add_images('testdata_loader', imgs, step)
    step = step + 1

writer.close()

在这里插入图片描述

(五)神经网络

1. 基本骨架 — nn.Module的使用

在 PyTorch 中,nn.Module 是构建神经网络的基础类。所有的神经网络模块都应继承自 nn.Module,并实现 forward 方法。在该类中,定义了网络的层以及前向传播的方式。

  • 继承 nn.Module:定义一个类来表示你的神经网络,并使它继承 nn.Module。
  • 定义网络层:在 __init__ 方法中定义网络的各个层,并使用 nn.Module 的子模块(如 nn.Linear,nn.Conv2d 等)。
  • 实现前向传播:在 forward 方法中定义输入数据如何通过网络层计算输出。这是网络前向传播的逻辑。
import torch
from torch import nn


class Module(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, input):
        output = input + 1
        return output


x = torch.tensor(1.0)
model = Module()
output = model(x)
print(output)  # tensor(2.)

2. 卷积操作 — nn.functional.conv

torch.nn.functional.conv 是 PyTorch 中用于直接调用卷积操作的函数。它有多个变体,如 conv1d、conv2d、conv3d,分别对应一维、二维和三维卷积。与 nn.Conv2d 等模块化接口不同,nn.functional.conv 需要手动指定所有的参数,包括权重和偏置,因此更灵活,但也需要更多手动管理。

  • input:输入张量,形状为(minibatch, in_channels, iH, iW),其中minibatch是批量大小,in_channels是输入通道数,iHiW是输入的高度和宽度。
  • weight:卷积核的权重张量,形状为(out_channels, in_channels/groups, kH, kW),其中out_channels是输出通道数,in_channels/groups是每组的输入通道数,kHkW是卷积核的高度和宽度。
  • bias:偏置项,形状为(out_channels)
  • stride:卷积操作的步幅,默认值为1。可以是一个整数或一个元组(sH, sW)
  • padding:输入的填充大小,默认值为0。可以是一个整数或一个元组(padH, padW),用于控制输出的空间维度。
  • dilation:卷积核元素之间的间距,默认值为1。可以是一个整数或一个元组(dH, dW)
  • groups:控制输入和输出的连接方式,默认值为1。groups=1表示标准卷积,groups=in_channels表示深度卷积,每个输入通道有一个单独的滤波器。

`在这里插入图片描述

import torch
import torch.nn.functional as F

# 输入 5x5 图像
input = torch.tensor([[1, 2, 0, 3, 1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 3, 1, 1],
                      [2, 1, 0, 1, 1]])

# 卷积核
kernel = torch.tensor([[1, 2, 1],
                       [0, 1, 0],
                       [2, 1, 0]])

# input – input tensor of shape(batch_size, in_channels, 𝑖𝐻, 𝑖𝑊)
# 转成四维张量
input = torch.reshape(input, (1, 1, 5, 5))
kernel = torch.reshape(kernel, (1, 1, 3, 3))

output = F.conv2d(input, kernel, stride=1)
print(output)

output2 = F.conv2d(input, kernel, padding=1)
print(output2)

在这里插入图片描述

3. 卷积层 — nn.Conv2d

在 PyTorch 中,卷积层可以通过 torch.nn.Conv 模块实现。根据不同的卷积类型,PyTorch 提供了多个类,包括 nn.Conv1d、nn.Conv2d 和nn.Conv3d,分别用于一维、二维和三维卷积操作。最常用的是 nn.Conv2d,用于处理二维图像数据。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils import tensorboard
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10('./CIFA10', train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=64)

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = Conv2d(3, 3, 3, 1, 0)

    def forward(self, x):
        x = self.conv1(x)
        return x


cnn = CNN()

writer = tensorboard.SummaryWriter('CIFA-logs')
step = 0
for data in dataloader:
    imgs, targets = data
    output = cnn(imgs)
    writer.add_images('input', imgs, step)
    writer.add_images('output', output, step)
    step += 1
    
writer.close()

在这里插入图片描述

4. 池化层 — 最大池化 nn.MaxPool2d 的使用

nn.MaxPool2d 是 PyTorch 中的一个池化层,用于在卷积神经网络(CNN)中执行二维的最大池化操作。最大池化的目的是通过取局部窗口的最大值来减小特征图的尺寸,从而减少计算量、参数数量和过拟合的风险,同时保留重要的特征信息。

  • kernel_size:窗口的大小,可以是单个整数(表示高度和宽度相同)或元组(分别指定高度和宽度)。
  • stride:步幅,指定窗口移动的步长。可以是单个整数或元组。默认情况下等于 kernel_size。
  • padding:填充,指定在输入张量的边缘填充的大小。默认值为 0。
  • dilaton:控制窗口中元素的间距。默认值为 1。
  • ceil_mode:为 True 时数据不够就取,为 False 数据不够就丢弃。

在这里插入图片描述

import torch
from torch import nn
from torch.nn import MaxPool2d

input = torch.tensor([[1, 2, 0, 3, 1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 3, 1, 1],
                      [2, 1, 0, 1, 1]])

input = torch.reshape(input, (1, 5, 5))

class MaxPool(nn.Module):
    def __init__(self):
        super(MaxPool, self).__init__()
        self.maxpool1 = MaxPool2d(3, ceil_mode=True)
        self.maxpool2 = MaxPool2d(3, ceil_mode=False)

    def forward(self, x):
        output1 = self.maxpool1(x)
        output2 = self.maxpool2(x)
        return output1, output2


model = MaxPool()
output1, output2 = model(input)
print(output1)
print(output2)

在这里插入图片描述

import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils import tensorboard
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10('CIFA10', train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=64)

class MaxPool(nn.Module):
    def __init__(self):
        super(MaxPool, self).__init__()
        self.maxpool = MaxPool2d(3, ceil_mode=True)

    def forward(self, x):
        output = self.maxpool(x)
        return output


model = MaxPool()
writer = tensorboard.SummaryWriter('CIFA-logs')
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images('input', imgs, step)
    output = model(imgs)
    writer.add_images('maxpool_output', output, step)
    step += 1

writer.close()

在这里插入图片描述

5. 非线性激活函数

用于在神经网络中引入非线性特性。它们的作用是在输入数据经过线性变换后,施加一个非线性的映射,从而使得神经网络能够学习到复杂的模式和特征。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils import tensorboard
from torch.utils.data import DataLoader

input = torch.tensor([[1, -0.5],
                      [-1, 3]])

dataset = torchvision.datasets.CIFAR10('CIFA10', train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=64)

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.relu = ReLU()
        self.sigmoid = Sigmoid()

    def forward(self, x):
        output1 = self.relu(x)
        output2 = self.sigmoid(x)
        return output1, output2


model = Model()
output1, output2 = model(input)
print(output1)
print(output2)

writer = tensorboard.SummaryWriter('CIFA-logs')
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images('非线性-input', imgs, step)
    ouput1 = model(imgs)[0]
    writer.add_images('relu', ouput1, step)
    output2 = model(imgs)[1]
    writer.add_images('sigmoid', output2, step)
    step += 1

writer.close()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6. 线性层 — nn.linear

nn.Linear 是 PyTorch 中用于实现线性变换的层,通常用于全连接神经网络(也称为前馈神经网络)的隐藏层和输出层。它执行的操作是对输入数据进行线性变换,即输入向量乘以权重矩阵并加上偏置项。

import torch
from torch import nn
from torch.nn import Linear

class LinearLayer(nn.Module):
    def __init__(self):
        super(LinearLayer, self).__init__()
        self.linear = Linear(4, 3, bias=True)
        # 随机初始化
        print('weights:', self.linear.weight)
        print('Bias:', self.linear.bias)

    def forward(self, x):
        return self.linear(x)


model = LinearLayer()
input = torch.tensor([[1.0, 2.0, 3.0, 4.0]])
output = model(input)
print(output)

在这里插入图片描述

7. 搭建小实战和Sequential的使用

在这里插入图片描述

import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils import tensorboard


class CIFAR(nn.Module):
    def __init__(self):
        super(CIFAR, self).__init__()
        # self.conv1 = Conv2d(3, 32, 5, padding=2)
        # self.maxpool1 = MaxPool2d(2)
        # self.conv2 = Conv2d(32, 32, 5, padding=2)
        # self.maxpool2 = MaxPool2d(2)
        # self.conv3 = Conv2d(32, 64, 5, padding=2)
        # self.maxpool3 = MaxPool2d(2)
        # # 它的作用是将多维的输入数据展平成一维。通常在卷积神经网络(CNN)中使用,用于将卷积层或池化层的输出转换为全连接层的输入格式。
        # self.flatten = Flatten()
        # # 全连接层
        # self.linear1 = Linear(64 * 4 * 4, 64)
        # self.linear2 = Linear(64, 10)
        # 第二种写法:
        self.model = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(64 * 4 * 4, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        # x = self.conv1(x)
        # x = self.maxpool1(x)
        # x = self.conv2(x)
        # x = self.maxpool2(x)
        # x = self.conv3(x)
        # x = self.maxpool3(x)
        # x = self.flatten(x)
        # x = self.linear1(x)
        # x = self.linear2(x)
        x = self.model(x)
        return x


cifar = CIFAR()
print(cifar)

input = torch.ones((64, 3, 32, 32))
output = cifar(input)
print(output.shape)

writer = tensorboard.SummaryWriter("CIFA-logs")
writer.add_graph(cifar, input)
writer.close()

在这里插入图片描述

在这里插入图片描述

8. 损失函数与反向传播

损失函数是一个函数,用于衡量模型的预测输出与实际目标之间的差距。它的值越小,表示模型的预测越接近真实值。损失函数的选择取决于具体的任务类型,如回归、分类等。

L1Loss(也称为 绝对值损失 或 平均绝对误差,MAE):它用于测量预测值和真实值之间的差异,通过计算预测值与真实值之差的绝对值来量化这种差异。
在这里插入图片描述
MSELoss(Mean Squared Error Loss,均方误差损失):特别是在回归任务中。它通过计算预测值和真实值之间差异的平方来量化预测误差,并取所有样本误差的平均值。
在这里插入图片描述
CrossEntropyLoss(交叉熵损失): 是深度学习中常用于分类任务的一种损失函数。它结合了 softmax 激活函数和负对数似然损失,用于衡量模型的预测概率分布与真实标签分布之间的差异。
在这里插入图片描述

import torch
from torch.nn import L1Loss, MSELoss, CrossEntropyLoss

inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)

# L1Loss
loss_fn1 = L1Loss()  # 默认是mean,求均值损失
res1 = loss_fn1(inputs, targets)
print(res1)  # tensor(0.6667)

loss_fn2 = L1Loss(reduction='sum')
res2 = loss_fn2(inputs, targets)
print(res2)  # tensor(2.)

# MSELoss
loss_fn3 = MSELoss()
res3 = loss_fn3(inputs, targets)
print(res3)  # tensor(1.3333)

loss_fn4 = MSELoss(reduction='sum')
res4 = loss_fn4(inputs, targets)
print(res4)  # tensor(4.)

# CrossEntropyLoss
loss_fn5 = CrossEntropyLoss()
# 未经过 softmax 的原始分数(logits)
# CrossEntropyLoss 自动将 y_pred 经过 softmax 后计算负对数似然损失,因此不需要手动应用 softmax 函数
y_pred = torch.tensor([[2.0, 1.0, 0.1]])
y_true = torch.tensor([0])
res5 = loss_fn5(y_pred, y_true)
print(res5)  # tensor(0.4170)

反向传播(Backpropagation)是神经网络训练过程中用于计算和更新模型参数的算法。它基于梯度下降的思想,通过计算损失函数关于模型参数的梯度来更新参数,使损失函数的值最小化。
在这里插入图片描述

(六)优化器

torch.optim 是 PyTorch 中用于实现各种优化算法的模块。优化器的作用是更新模型参数,以最小化损失函数。它们基于梯度下降法,但每种优化器有不同的更新策略。

1. SGD (随机梯度下降)

基本的优化算法,逐步更新参数。支持动量项来加速收敛。

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential, CrossEntropyLoss
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10('CIFA10', train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=64)

class CIFAR(nn.Module):
    def __init__(self):
        super(CIFAR, self).__init__()
        self.model = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(64 * 4 * 4, 64),
            Linear(64, 10)
        )

    def forward(self, x):
        x = self.model(x)
        return x


loss = CrossEntropyLoss()
cifar = CIFAR()
optimizer = torch.optim.SGD(cifar.parameters(), lr=0.001)
for epoch in range(20):
    running_loss = 0
    for data in dataloader:
        imgs, targets = data
        outputs = cifar(imgs)
        res = loss(outputs, targets)
        optimizer.zero_grad()
        res.backward()
        optimizer.step()
        running_loss += res

    print(running_loss)

在这里插入图片描述

(七)现有网络模型的使用及修改

import torchvision
from torch import nn
from torchvision.models import VGG16_Weights, vgg16

vgg16_false = vgg16(weights=None)
vgg16_true = vgg16(weights=VGG16_Weights.DEFAULT)


train_data = torchvision.datasets.CIFAR10('CIFA10', train=True, download=True,
                                          transform=torchvision.transforms.ToTensor())

# 添加一个线性层
vgg16_true.classifier.add_module('7', nn.Linear(1000, 10))
print(vgg16_true)
# 修改一个线性层
vgg16_true.classifier[6] = nn.Linear(4096, 10)
print(vgg16_true)

(八)模型的保存与读取

1. 保存整个模型

import torch
import torchvision

vgg16 = torchvision.models.vgg16(weights=torchvision.models.VGG16_Weights.DEFAULT)
# 保存方式1(保存模型结构 + 参数)
torch.save(vgg16, 'vgg16.pth')
import torch

model = torch.load('vgg16.pth')
print(model)

2. 保存模型的参数(推荐)

import torch
import torch.nn as nn

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.fc = nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)


model = Model()
torch.save(model.state_dict(), 'myModel_path')  # 假设保存的是已经训练好的参数

model = Model()  # 重新实例化(参数是随机初始化的)
model.load_state_dict(torch.load('myModel_path'))  # 将训练好的参数加载进来
print(model)

(九)完整的模型训练套路

model:

import torch
from torch import nn

class CIFAR_Net(nn.Module):
    def __init__(self):
        super(CIFAR_Net, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64 * 4 * 4, 64),
            nn.Linear(64, 10)
        )

    def forward(self, x):
        return self.model(x)


if __name__ == '__main__':
    cifar = CIFAR_Net()
    input = torch.ones((64, 3, 32, 32))
    output = cifar(input)
    print(output.shape)
import torch
import torchvision
from torch.nn import CrossEntropyLoss
from torch.utils import tensorboard
from torch.utils.data import DataLoader
from model import *

# 准备数据集
train_data = torchvision.datasets.CIFAR10('CIFA10', train=True, download=True,
                                          transform=torchvision.transforms.ToTensor())

test_data = torchvision.datasets.CIFAR10('CIFA10', train=False, download=True,
                                         transform=torchvision.transforms.ToTensor())

# 数据集大小
train_data_size = len(train_data)
test_data_size = len(test_data)
print(f"train_data_size: {train_data_size}, test_data_size: {test_data_size}")

# 加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_loader = DataLoader(test_data, batch_size=64)

# 创建网络模型
cifar = CIFAR_Net()

# 损失函数
loss_fn = CrossEntropyLoss()

# 优化器
learning_rate = 0.01  # 也可以写成 1e-2 = 1 * 10的-2次方
optimizer = torch.optim.SGD(cifar.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 设置训练的次数
total_train_step = 0
# 设置测试的次数
total_test_step = 0
# 设置训练的轮数
epoch = 10

writer = tensorboard.SummaryWriter('CIFA-logs')

for i in range(epoch):
    print(f'第{i + 1}轮训练开始')
    # 训练步骤开始
    cifar.train()
    total_train_loss = 0
    for data in train_dataloader:
        imgs, targets = data
        outputs = cifar(imgs)
        loss = loss_fn(outputs, targets)
        total_train_loss += loss.item()
        # 反向传播
        optimizer.zero_grad()
        loss.backward()
        # 更新权重
        optimizer.step()
        # 记录训练的次数
        total_train_step += 1
        if total_train_step % 100 == 0:
            print(f'第{total_train_step}步训练,loss为{loss.item()}')
            # 添加到tensorboard
            writer.add_scalar('train_loss', loss.item(), total_train_step)
    print(f'第{i + 1}轮训练结束,loss为{total_train_loss}')

    # 测试步骤开始
    cifar.eval()
    total_test_loss = 0
    total_accuracy = 0
    # 上下文管理器,用于在不需要计算梯度的情况下运行PyTorch张量。
    with torch.no_grad():
        for data in test_loader:
            imgs, targets = data
            outputs = cifar(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy += accuracy.item()
            # 记录测试的次数
            total_test_step += 1
            if total_test_step % 100 == 0:
                print(f'第{total_test_step}步测试,loss为{loss.item()}')
                # 添加到tensorboard
                writer.add_scalar('test_loss', loss.item(), total_test_step)
        print(f'第{i + 1}轮测试结束,loss为{total_test_loss}')
    print(f'第{i + 1}轮测试结束,accuracy为{total_accuracy / test_data_size}')
    writer.add_scalar('test_accuracy', total_accuracy / test_data_size, i + 1)

    torch.save(cifar, f'cifar_{i + 1}.pth')

writer.close()

在这里插入图片描述

(十)利用GPU训练

1. 第一种方法

在下方三处加入 cuda()

  • 网络模型
  • 数据(输入、标注)
  • 损失函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 第二种方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(十一)完整的模型验证套路

import torch
import torchvision
from PIL import Image

img_path = 'imgs/cat5.png'
image = Image.open(img_path)

transform = torchvision.transforms.Compose([
    torchvision.transforms.Resize((32, 32)),
    torchvision.transforms.ToTensor()
])
image = transform(image)

model = torch.load('cifar_30.pth', weights_only=False, map_location=torch.device('cpu'))

image = torch.reshape(image, (1, 3, 32, 32))
model.eval()
with torch.no_grad():
    output = model(image)

idx = output.argmax(dim=1)
classes = ('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
print(classes[idx])

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

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

相关文章

软件渗透测试详细介绍,专业软件测评机构分享

随着信息技术的飞速发展&#xff0c;软件应用已成为我们生活和工作中不可或缺的一部分。然而&#xff0c;与此&#xff0c;信息安全问题也日益凸显&#xff0c;网络攻击的频繁发生让企业和用户面临前所未有的风险。为了更好地保护软件产品的安全性&#xff0c;渗透测试应运而生…

Mysql执行计划(上)

1、执行计划的概念 执行计划是什么&#xff1a;使用EXPLAIN关键字可以模拟优化器执行SQL查询语句&#xff0c;从而知道MySQL是如何处理你的SQL语句的。 作用&#xff1a;分析你的查询语句或是表结构的性能瓶颈 语法&#xff1a;Explain SQL语句 执行计划输出内容介绍&#…

记录一次网关无响应的排查

1. 使用jstack pid > thread.txt 打印进 thread.txt 文件里 去观察线程的状态。 我发现&#xff0c;一个线程在经过 rateliter的prefilter后, 先是调用 consume方法&#xff0c;获取到锁。 接着在执行 jedis的 evalsha命令时 一直卡在socket.read()的状态。 发现jedis官…

【iOS】OC关键字总结及底层原理(上)

目录 线程安全相关的关键字atomic&nonatomic 作用域相关的关键字static、extern、const&auto 读写权限相关和指定方法名的关键字内存管理相关的关键字&#xff08;或方法&#xff09;1. 引用计数的存储SideTableretain方法源码分析release方法源码分析dealloc方法源码分…

无缝融入,即刻智能[4]:MaxKB知识库问答系统[进一步深度开发调试,完成基于API对话,基于ollama大模型本地部署等]

无缝融入,即刻智能[4]:MaxKB知识库问答系统[进一步深度开发调试,完成基于API对话,基于ollama大模型本地部署等] 1.简介 MaxKB(Max Knowledge Base)是一款基于 LLM 大语言模型的开源知识库问答系统, 1.1 产品优势 开箱即用:支持直接上传文档、自动爬取在线文档,支持文本…

计算机网络 6.3Internet组成6.4Internet地址

第三节 Internet组成 一、基本结构及特点 1.Internet结构类型&#xff1a;分层网络互联群体。 2.主要构成&#xff1a;①主干网&#xff1b;②中间层网&#xff1b;③底层网。 3.结构特点&#xff1a; ①对用户隐藏网间连接的底层节点。 ②不指定网络互联的拓扑结构。 ③…

【时时三省】(C语言基础)数组作为函数参数

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ——csdn时时三省 排序为升序-冒泡排序 冒泡排序的思想: 两两相邻的元素进行比较。并且可能得话需要交换 示例: 数组名 数组名是数组首元素的地址 但是有两个例外 1.sizeof(数组名)-数组名表示整个数组-计…

VMware虚拟机上网

一、VMware Network Adapter VMnet8配置 ①打开VMware软件&#xff1a;点击菜单栏→编辑→虚拟网络编辑器 ②点击NAT模式&#xff0c;使用管理员权限对子网IP和网关进行配置 ③子网IP和掩码就是这样&#xff0c;这里可以自行配置 ④点击上图中的NAT设置&#xff0c;配置网关 …

Rider中修改默认文件关联,自定义打开方式

问题描述 想用Qt designer打开.ui文件&#xff0c;但是在Rider中&#xff0c;IDE会默认通过text进行打开 解决方法 1&#xff0c;允许用户将特定的文件类型与一个应用程序关联起来 File -> Settings -> Editor -> File Types -> Recognized File Types下&…

uniapp微信小程序 canvas绘制圆形半透明阴影 createCircularGradient函数不支持透明度部分解决方案

背景 我需要在微信小程序中&#xff0c;用canvas绘制一个圆形钟表&#xff0c;在ui设计图中&#xff0c;有一部分阴影&#xff0c;这里我节选一下&#xff1a; 即深色发黑的部分 canvas通用阴影绘制 由于canvas中并不支持css那样简单的方式为圆形添加阴影或高光&#xff0c…

Spring Boot 默认可以同时处理多少个请求?

微信中阅读&#xff0c;欢迎关注 CodeFit。 创作不易&#xff0c;如果你觉得这篇文章对您有帮助&#xff0c;请不要忘了 点赞、分享 和 关注&#xff0c;为我的 持续创作 提供 动力! 解析 Spring Boot 的请求处理能力 目前&#xff0c;Spring Boot 是 Java 开发中不可或缺的框…

【大模型从入门到精通9】openAI API 提升机器推理:高级策略3

这里写目录标题 理论问题实践问题理论实践实践 理论问题 什么是链式思考推理&#xff08;Chain of Thought Reasoning&#xff09;&#xff0c;它是如何增强人工智能模型在解决问题任务中的表现的&#xff1f; 链式思考推理提供的透明度如何使用户受益并建立对AI模型的信任&am…

基于python和aiohttp实现的web请求管理分发服务

想实现一个web请求管理分发服务&#xff0c;需要有如下功能&#xff1a; 1、第三方服务上报心跳&#xff0c;管理服务能监控第三方服务是否存活 2、管理服务支持http和ws服务的转发 3、管理服务支持最基础的转发策略&#xff0c;比方说轮询 直接上代码 一、网络和路由接口…

用AI助手写程序

用AI帮助写程序究竟靠不靠谱&#xff0c;下面来测试一下&#xff1a; 在文心一言中输入&#xff1a;写一个C Windows API串口通信程序。结果如下&#xff1a; #include <windows.h> #include <iostream> // 串口配置 void ConfigureCommPort(HANDLE hComm) {…

Linux系统的ARM边缘计算网关在纸张处理机械中的应用

数字化时代纸张处理机械行业也在不断追求智能化和高效化。ARM 边缘计算网关作为一种关键技术&#xff0c;为纸张处理机械的智能化提供了强大的支持。结合 Linux 系统的二次开发&#xff0c;它能够加速生产流程&#xff0c;提高生产效率和质量。 ARM 边缘计算网关具有强大的计算…

Python学习笔记50:游戏篇之外星人入侵(十一)

前言 本篇文章接着之前的内容&#xff0c;继续对游戏功能进行优化&#xff0c;主要是优化游戏状态以及对应的处理。 状态 一个游戏包含多种状态&#xff0c;这个状态是一个可以很复杂也可以很简单的内容。条件所限&#xff0c;我们这个游戏的状态就比较简单&#xff1a; 未…

log4j反序列化-流程分析

分析版本 JDK8u141 依赖 <dependencies><!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><ve…

三、1 一维数组的创建和初始化

数组是一组相同类型元素的集合 1、数组的创建 2、数组的初始化 在创建数组的同时&#xff0c;给数组内容一些合理的值 3、一维数组的使用 4、一维数组在内存中的存储 数组的内容在内存中连续存放

sqli靶场复现(1-8关)

目录 1.sqli-labs第二关 1.判断是否存在sql注入 1.1你输入数字值的ID作为参数&#xff0c;我们输入?id1 1.2在数据库可以查看到users下的对应内容 2.联合注入 2.1首先知道表格有几列&#xff0c;如果报错就是超过列数&#xff0c;如果显示正常就是没有超出列数。 2.2得…

模拟一次XFS故障,分析原因并进行修复

模拟一次XFS故障 在平常处理问题时经常会遇到文件系统损坏的问题&#xff0c;有时候是日志里面出现了报错但文件系统还是可以读写&#xff0c;有时候是文件系统已经无法读写了 分析下不同现象的原因和一些可能出现的情况。 通过直接修改块存储损坏文件系统 1、制作一个xfs文…