当前位置: 首页 > news >正文

PyTorch深度学习快速入门--B站小土堆笔记

Pytorch工具箱

dir():打开工具箱,看见工具箱以及工具箱分隔区中都有什么工具

help():解释工具的用途以及使用方法

打开jupyter

开始菜单-->Anaconda

对比三种敲Python代码的方式

处理数据

# 读取数据
from torch.utils.data import Dataset
from PIL import Image
# 可以获取所有图片的地址并通过编号形成列表
import osclass MyData(Dataset):# 初始化类,为整个class提供一个全局变量(self.?? = ??)def __init__(self,root_dir,label_dir):self.root_dir = root_dirself.label_dir = label_dir# os.path.join():将root_dir和label_dir路径加起来self.path = os.path.join(self.root_dir,self.label_dir)self.list = os.listdir(self.path)# idx:图片序号def __getitem__(self, idx):img_name = self.list[idx]# 定义每一个图片的地址img_item_path = os.path.join(self.root_dir,self.label_dir,img_name)# 读取图片img = Image.open(img_item_path)label = self.label_dirreturn img,labeldef __len__(self):return len(self.list)root_dir = "dataset/train"
ants_label_dir = "ants"
bees_label_dir = "bees"ants_dataset = MyData(root_dir,ants_label_dir)
bees_dataset = MyData(root_dir,bees_label_dir)
train_dataset = ants_dataset + bees_datasetimg, label = ants_dataset[1]
img.show()# img, label = bees_dataset[0]
# img.show()

读官方文档解释

方法一:

在代码里按住Ctrl + 鼠标点击具体的方法/类,查看解释

方法二:在jupyter中查看

tensorboard可视化

相关指令:

# 下载tensorboard指令:
# pip install  tensorboard
# 进入tensorboard的事件文件:
# tensorboard --logdir=logs
# 改端口号为6007(默认为6006):
# tensorboard --logdir=logs --port=6007
# tensorboard:可视化
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image# 下载tensorboard指令:
# pip install  tensorboard
# 进入tensorboard的事件文件:
# tensorboard --logdir=logs
# 改端口号为6007(默认为6006):
# tensorboard --logdir=logs --port=6007# 创建tensorboard的事件文件
writer = SummaryWriter("logs")# # writer.add_scalar()的使用
# for i in range(100):
#     # 绘制 y=2x 函数图像
#     # writer.add_scalar(tag, scalar_value, global_step)
#     # tag表示图表名称 scalar_value表示y轴  global_step表示x轴
#     writer.add_scalar("y=2x", 2 * i, i)
#
# writer.close()# writer.add_image()的使用
# 改变1:换图片
image_path = "data/val/ants/800px-Meat_eater_ant_qeen_excavating_hole.jpg"
# 打开图片
img_PIL = Image.open(image_path)
# 将图片类型从PIL型转为numpy型
img_array = np.array(img_PIL)
# 输出图片类型
print(type(img_array))
# 输出图片格式:(H, W, C) = (512, 768, 3)
print(img_array.shape)
# writer.add_image(tag,img_tensor,global_step)
# tag:图片名称 img_tensor:图像的数据类型 global_step:步骤
# 将3通道调到前面 dataformats='HWC'
# 改变2:换步骤数
writer.add_image("test" , img_array , 2 , dataformats='HWC')
writer.close()

transforms对图片进行变换

# torchvision中的transforms:对图片进行变换
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms# 补充:
# PIL用Image.open()打开
# tensor用ToTensor()打开
# narrays用cv.imread()打开# 通过transforms.ToTensor解决:
# 1.transforms该如何使用(python)
# 2.为什么需要ToTensor数据类型# 绝对路径 D:\work\projects\PycharmProjects\learn_pytorch\data\train\ants_image\00130
# 相对路径 data/train/ants_image/0013035.jpg
img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)writer = SummaryWriter("logs")# 1.transforms该如何使用(python)
# 引入ToTensor对象  tensor数据类型:包装了反向神经网络所需要的一些理论基础的参数
tensor_transforms = transforms.ToTensor()
# 将img转化为tensor的数据类型
tensor_img = tensor_transforms(img)writer.add_image("Tensor_img",tensor_img)
writer.close()

常用的transforms

ToTensor的使用:转换数据类型
# ToTensor的使用,作用是改变数据类型,PIL的数据类型无法在tensorboard中显示
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor",img_tensor)
Normalize的使用:归一化

# Normalize的使用(tensor类型),作用是归一化(归一化:改变模型参数,让模型呈现出不同状态)
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm)
Resize的使用(PIL类型):改变尺寸--等比例变化
# Resize的使用(PIL类型),作用是改变尺寸(等比例变化)
print(img.size)
trans_resize = transforms.Resize((50, 50))
# img PIL -> resize -> img_resize PIL
img_resize = trans_resize(img)
# img PIL -> totensor + resize -> img_tensor_resize tensor
img_tensor_resize = trans_totensor(img)
print(img_resize)
print(img_tensor_resize)
writer.add_image("Resize",img_tensor_resize,0)
Compose_resize的使用:改变尺寸--只改变最长边或最高边
# Compose_resize:只改变最长边或最高边
# Compose()中的参数需要是列表,数据需要是transforms类型,所以Compose([transforms参数1, transforms参数2], ...)
# Compose将几个操作合并到一起了
# eg:transforms.Compose([trans_resize_2, trans_totensor])
# 即将改变尺寸resize功能和改变数据类型totensor功能合并到了一起
# (要注意trans_resize_2输出的类型要与trans_totensor输入的类型相匹配,现在版本升级后忽略了这个限制)
# PIL -> PIL
trans_resize_2 = transforms.Resize(50)
# PIL -> tensor
# 正确
# trans_compose = transforms.Compose([trans_resize_2, trans_totensor])
# 新版本正确
trans_compose = transforms.Compose([trans_totensor, trans_resize_2])
img_resize_2 = trans_compose(img)
writer.add_image("Resize",img_resize_2,1)
RandomCrop:随机剪裁
# RandomCrop:随机剪裁
trans_random = transforms.RandomCrop(512)
trans_compose_random = transforms.Compose([trans_random, trans_totensor])
for i in range(10):img_cop = trans_compose_random(img)writer.add_image("RandomCrop", img_cop, i)writer.close()
总代码
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transformswriter = SummaryWriter("logs")  #创建tensorboard的事件文件
img = Image.open("images/pytorch.png")  #打开图片
print(img)# ToTensor的使用,作用是改变数据类型,PIL的数据类型无法在tensorboard中显示
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor",img_tensor)# Normalize的使用(tensor类型),作用是归一化(归一化:改变模型参数,让模型呈现出不同状态)
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([1, 1, 1, 7], [1, 9, 1, 9])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm,2)# Resize的使用(PIL类型),作用是改变尺寸(等比例变化)
print(img.size)
trans_resize = transforms.Resize((50, 50))
# img PIL -> resize -> img_resize PIL
img_resize = trans_resize(img)
# img PIL -> totensor + resize -> img_tensor_resize tensor
img_tensor_resize = trans_totensor(img)
print(img_resize)
print(img_tensor_resize)
writer.add_image("Resize",img_tensor_resize,0)# Compose_resize:只改变最长边或最高边
# Compose()中的参数需要是列表,数据需要是transforms类型,所以Compose([transforms参数1, transforms参数2], ...)
# Compose将几个操作合并到一起了
# eg:transforms.Compose([trans_resize_2, trans_totensor])
# 即将改变尺寸resize功能和改变数据类型totensor功能合并到了一起
# (要注意trans_resize_2输出的类型要与trans_totensor输入的类型相匹配,现在版本升级后忽略了这个限制)
# PIL -> PIL
trans_resize_2 = transforms.Resize(50)
# PIL -> tensor
# 正确
# trans_compose = transforms.Compose([trans_resize_2, trans_totensor])
# 新版本正确
trans_compose = transforms.Compose([trans_totensor, trans_resize_2])
img_resize_2 = trans_compose(img)
writer.add_image("Resize",img_resize_2,1)# RandomCrop:随机剪裁
trans_random = transforms.RandomCrop(512)
trans_compose_random = transforms.Compose([trans_random, trans_totensor])
for i in range(10):img_cop = trans_compose_random(img)writer.add_image("RandomCrop", img_cop, i)writer.close()

torchvision中常见数据集的使用

CIFAR10
import torchvision
from torch.utils.tensorboard import SummaryWriter# 将数据集转化为tensor类型
dataset_transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()
])# 从Pytorch下载数据集,CIFAR10数据集一般用于物体识别
train_set = torchvision.datasets.CIFAR10(root="./P10_dataset_transform", train=True,transform=dataset_transform, download=True)
test_set = torchvision.datasets.CIFAR10(root="./P10_dataset_transform", train=False,transform=dataset_transform, download=True)# print(test_set[0])
# print(test_set.classes)
#
# img, target = test_set[0]
# print(img)
# print(target)
# print(test_set.classes[target])
# img.show()writer = SummaryWriter("P10")
for i in range(10):img, target = test_set[i]writer.add_image("test_set", img, i)writer.close()

DataLoader

dataset:管理数据,能给出数据信息

dataloader:决定如何取数据、取多少数据等

import torchvision# 准备的测试数据集
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWritertest_data = torchvision.datasets.CIFAR10(root="./P10_dataset_transform", train=False,transform=torchvision.transforms.ToTensor())
# batch_size=64即为DataLoader从一堆数据集中抓取batch_size=64个数据为一组
# drop_last=False即为最后不够的时候不舍去,True为舍去
# shuffle=False即为不洗牌,True为洗牌
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)# 测试数据集中第一张图片以及target
img, target = test_data[0]
print(img.shape)
print(target)writer = SummaryWriter("dataloader")
for epoch in range(2):step = 0for data in test_loader:imgs, targets = data# print(imgs.shape)# print(targets)writer.add_images("Epoch:{}".format(epoch), imgs, step)step = step + 1writer.close()

torch.nn.Module使用

初入门--使用神经网络(forward:output = input + 1)

# torch.nn.Module使用
import torch
from torch import nn# 神经网络模板Apple
class Apple(nn.Module):def __init__(self) -> None:super().__init__()def forward(self,input):output = input + 1return output# 用神经网络模板Apple创建出来的神经网络apple
apple = Apple()
x = torch.tensor(1.0)
output = apple(x)
print(output)

torch.nn.conv卷积使用

初步理解--自定义数据集
import torch
import torch.nn.functional as Finput = 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]])# print(input.shape)
# print(kernel.shape)
# 因为只有高和宽两个数据,而需要四个数据(minibatch,in_channnels,iH,iW)所以要reshape
# 5x5的平面->一个二维矩阵->channel通道为1v1;又因为只取一个样本(图片数量),所以batch_size=1
input = torch.reshape(input, (1, 1, 5, 5))
kernel = torch.reshape(kernel, (1, 1, 3, 3))print(input.shape)
print(kernel.shape)# 原数组input,比对数组kernel,移动步数stride,填充值padding
# 填充是为了更好地保留边缘特征,中间快会被卷积利用多次,而边缘块利用的少,会造成不均
output = F.conv2d(input, kernel, stride=1)
print(output)output2 = F.conv2d(input, kernel, stride=2)
print(output2)output3 = F.conv2d(input, kernel, stride=1, padding=1)
print(output3)
进阶理解--导入CIFAR10数据集+神经网络模型
# 卷积:提取图像特征;stride默认为1
# self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)
# in_channels:输入的通道数,彩色图片信道数为3;out_channels:输出的通道数,生成6个卷积核,卷积6次;
# kernel_size:卷积核大小,3x3;stride:一次走几步;padding:边缘部分填充几格
# 卷积改变channel数
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriterdataset = torchvision.datasets.CIFAR10("data_conv2d", train=False, transform=torchvision.transforms.ToTensor(), download=True)dataloader = DataLoader(dataset, batch_size=64)# 神经网络
class Apple(nn.Module):def __init__(self):super(Apple, self).__init__()
# in_channels:输入的通道数,彩色图片信道数为3;out_channels:输出的通道数,生成6个卷积核,卷积6次;
# kernel_size:卷积核大小,3x3;stride:一次走几步;padding:边缘部分填充几格self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)def forward(self, x):x = self.conv1(x)return xapple = Apple()
# print(apple)
writer = SummaryWriter("logs_conv2d")step = 0
for data in dataloader:imgs, targets = dataoutput = apple(imgs)print(imgs.shape)print(output.shape)# torch.Size([64, 3, 32, 32])writer.add_images("input", imgs, step)# torch.Size([64, 6, 30, 30]) ->[xxx, 3, 30, 30];将输出的6个信道的图片叠加到batch_size里导致扩大了# torch.reshape(output, (-1, 3, 30, 30));不知道xxx是多少时设置成-1,系统会自动计算该维度的大小以适应其他维度的要求output = torch.reshape(output, (-1, 3, 30, 30))writer.add_images("output", output, step)step = step + 1writer.close()

torch.nn.MaxPool2d最大池化

# 池化:相当于采样,保留数据特征的同时压缩数据量,提高模型能力
# 最大池化:找出被选择区域的最大值输出,即:马赛克
# stride默认为池化核kernel_size大小;dilation=1核中每一个元素和另一个元素之间会插入1个空格
# ceil_mode:ceil向上取整,floor向下取整。默认为False,如果有空数据(边缘)就放弃;True,有空数据在存在的数据内取最大值
# 池化不改变channel数
import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriterdataset = torchvision.datasets.CIFAR10("data_maxpool", train=False, transform=torchvision.transforms.ToTensor(), download=True)dataloader = DataLoader(dataset, batch_size=64)# 神经网络
class Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=False)# 重写forward函数def forward(self, input):output = self.maxpool1(input)return outputapple = Apple()writer = SummaryWriter("logs_maxpool")step = 0
for data in dataloader:imgs, targets = datawriter.add_images("input", imgs, step)output = apple(imgs)writer.add_images("output", output, step)step = step + 1writer.close()

torch.nn.ReLU、Sigmoid--非线性激活

# 非线性激活:向神经网络中引入一些非线性的特质
# ReLU:0及负数均为0,正数y=x
# Sigmoid:官网上有定义具体的函数
import torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriterinput = torch.tensor([[1, -0.5],[-1, 3]])input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)dataset = torchvision.datasets.CIFAR10("data_sigmoid", train=False, transform=torchvision.transforms.ToTensor(), download=True)dataloader = DataLoader(dataset, batch_size=64)# 神经网络
class Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()# inplace = True/False是否进行原地变换,默认为Falseself.relu1 = ReLU(inplace=False)# 修改神经网络为Sigmoidself.sigmoid1 = Sigmoid()# 重写forward函数def forward(self, input):output = self.sigmoid1(input)return outputapple = Apple()writer = SummaryWriter("logs_sigmoid")step = 0
for data in dataloader:imgs, targets = datawriter.add_images("input", imgs, global_step=step)output = apple(imgs)writer.add_images("output", output, global_step=step)step = step + 1writer.close()

torch.nn.Linear线性层

目标:将 5 x 5 的图片转化为 1 x 25 ,再通过线性层转化为 1 x 3

# 线性层
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoaderdataset = torchvision.datasets.CIFAR10("data_linear", train=False, transform=torchvision.transforms.ToTensor(), download=True)dataloader = DataLoader(dataset, batch_size=64, drop_last=True)# 神经网络
class Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()# 将torch.Size([1, 1, 1, 196608])格式通过线性网络层self.linear1 = Linear(in_features=196608, out_features=10)变成torch.Size([1, 1, 1, 10])格式self.linear1 = Linear(in_features=196608, out_features=10)# 重写forward函数def forward(self, input):output = self.linear1(input)return outputapple = Apple()for data in dataloader:imgs, targets = dataprint(imgs.shape)# 将torch.Size([64, 3, 32, 32])格式通过output = torch.reshape(imgs, (1, 1, 1, -1))展平成torch.Size([1, 1, 1, 196608])格式# output = torch.reshape(imgs, (1, 1, 1, -1))# flatten:将nxn展平成1x1,即为执行(1, 1, 1, -1)展开操作output = torch.flatten(imgs)print(output.shape)output = apple(output)print(output.shape)

神经网络搭建小实战+Sequential的使用

import torch
from torch import nn# 神经网络搭建小实战+Sequential的使用
# 神经网络搭建小实战模型在nn_seq.png
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriterclass Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()# padding:把卷积核中心放在顶角看多出多少行就行了,在默认stride为1,通道数不改变的情况下的情况下# 如果前后卷积核尺寸不变的话,那么padding =(f - 1) / 2,f是卷积核的尺寸,也就是5,所以padding = (5 - 1) / 2 = 2# self.conv1 = Conv2d(in_channels=3, out_channels=32,kernel_size=5, padding=2, stride=1)# self.maxpool1 = MaxPool2d(kernel_size=2)# self.conv2 = Conv2d(in_channels=32, out_channels=32,kernel_size=5, padding=2, stride=1)# self.maxpool2 = MaxPool2d(kernel_size=2)# self.conv3 = Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2, stride=1)# self.maxpool3 = MaxPool2d(kernel_size=2)# self.flatten = Flatten()# self.linear1 = Linear(in_features=1024, out_features=64)# self.linear2 = Linear(in_features=64, out_features=10)# Sequential:整合上面的步骤,且代码和输出更加简洁self.module1 = Sequential(Conv2d(in_channels=3, out_channels=32,kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Flatten(),Linear(in_features=1024, out_features=64),Linear(in_features=64, out_features=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.module1(x)return xapple = Apple()
print(apple)# 对网络结构进行检验
input = torch.ones((64, 3, 32, 32))
output = apple(input)
print(output.shape)writer = SummaryWriter("logs_seq")
# add_graph:计算图
writer.add_graph(apple, input,)
writer.close()

损失函数和反向传播

简义

损失函数

量化模型预测结果与真实标签之间的 “误差大小”(模型训练的核心目标,就是通过优化算法(如梯度下降)最小化这个误差,让模型的预测尽可能接近真实情况。)

反向传播

当模型做出错误预测时,它能计算出每个参数对错误的 "贡献度"(以grad作为依据),然后按贡献度大小调整参数,让模型下次预测更准确。

torch.nn.LinearCrossEntropyLoss交叉熵(分类问题)

torch.nn.L1Loss求平均
torch.nn.MSELoss求平方差
入门代码
# 损失函数和反向传播
# 损失函数Loss:算网络与标准之间的差距
# 反向传播:尝试如何调整网络过程中的参数才会导致最终的loss变小(因为是从loss开始推导参数,和网络的顺序相反,所以叫反向传播),以及梯度的理解可以直接当成“斜率”
import torch
from torch.nn import L1Loss, MSELoss
from torch import nn# RuntimeError: mean(): could not infer output dtype. Input dtype must be either a floating point or complex dtype. Got: Long
# 改整型为浮点型dtype=torch.float32
inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)# batch_size=1, channel=1, 1行, 3列
inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))loss = L1Loss()
# loss = L1Loss(reduction='sum')  #求平均--L1Loss
result = loss(inputs, targets)loss_mse = nn.MSELoss()  #求平方差--MSELoss
result_mse = loss_mse(inputs, targets)
print(result)
print(result_mse)x = torch.tensor([0.1, 0.2, 0.3])
y = torch.tensor([1])
x = torch.reshape(x, (1, 3))
loss_cross = nn.CrossEntropyLoss()  #交叉熵--分类问题
result_cross = loss_cross(x, y)
print(result_cross)
结合数据库和神经网络模型代码
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoaderdataset = torchvision.datasets.CIFAR10("data_loss_network", train=False, transform=torchvision.transforms.ToTensor(), download=True)dataloader = DataLoader(dataset, batch_size=1, drop_last=True)class Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()self.module1 = Sequential(Conv2d(in_channels=3, out_channels=32,kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Flatten(),Linear(in_features=1024, out_features=64),Linear(in_features=64, out_features=10))def forward(self, x):x = self.module1(x)return xloss = nn.CrossEntropyLoss()  #交叉熵--分类问题
apple = Apple()
for data in dataloader:imgs, targets = dataoutputs = apple(imgs)result_loss = loss(outputs, targets)result_loss.backward()  #反向传播print("ok")

优化器

通过调整模型参数(如权重、偏置),最小化 / 最大化目标函数(通常是损失函数,如 MSE、交叉熵),最终让模型逼近 “最优性能”(如预测更准确、误差更小)。

# 优化器optim:通过梯度grad自动调节loss
import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader# 加载数据集
dataset = torchvision.datasets.CIFAR10("data_optim", train=False, transform=torchvision.transforms.ToTensor(), download=True)dataloader = DataLoader(dataset, batch_size=1, drop_last=True)# 构建神经网络模型
class Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()self.module1 = Sequential(Conv2d(in_channels=3, out_channels=32,kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2, stride=1),MaxPool2d(kernel_size=2),Flatten(),Linear(in_features=1024, out_features=64),Linear(in_features=64, out_features=10))def forward(self, x):x = self.module1(x)return x# 计算损失
loss = nn.CrossEntropyLoss()
apple = Apple()
# 设置优化器用于降低损失函数值
optim = torch.optim.SGD(apple.parameters(), lr=0.01)
for epoch in range(20):running_loss = 0.0for data in dataloader:imgs, targets = dataoutputs = apple(imgs)result_loss = loss(outputs, targets)  #计算出经过神经网络模型后的输出值与真实值之间的差距optim.zero_grad()  #将梯度清0result_loss.backward()  #反向传播求梯度optim.step()  #使用优化器对模型进行调优running_loss = running_loss + result_lossprint(running_loss)

使用torchvision中现有的网络模型

import torchvision# 这个数据集140+G太大了
# train_data = torchvision.datasets.ImageNet("data_ImageNet", split='train', download=True,
#                                            transform=torchvision.transforms.ToTensor())
from torch import nn
from torchvision.models import VGG16_Weights# False:默认参数,没训练
vgg16_false = torchvision.models.vgg16(weights=None)
# vgg16_false = torchvision.models.vgg16(pretrained=False)
# True:训练好的参数
vgg16_true = torchvision.models.vgg16(weights=VGG16_Weights.DEFAULT)
# vgg16_false = torchvision.models.vgg16(pretrained=True)
print(vgg16_true)train_data = torchvision.datasets.CIFAR10("data_pretrained", train=True, transform=torchvision.transforms.ToTensor(), download=True)# 在VGG16_Weights网络模型中加模型
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
print(vgg16_true)# 修改VGG16_Weights网络模型中的in_features、out_features
print(vgg16_false)
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)

输出结果--在VGG16_Weights网络模型中加模型

输出结果--修改VGG16_Weights网络模型中的in_features、out_features

保存&&加载模型

保存模型

import torch
import torchvision# pretrained=False:未经过训练的数据集=weights=None
from torch import nnvgg16 = torchvision.models.vgg16(weights=None)# 保存方式1:保存了模型的结构+模型的参数
torch.save(vgg16, "vgg16_method1.pth")# 保存方式2:保存了模型参数(官方推荐)--把vgg的状态保存成一种字典型数据格式
torch.save(vgg16.state_dict(), "vgg16_method2.pth")# 陷阱
class Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3)def forward(self, x):x = self.module1(x)return xapple = Apple()
torch.save(apple, "apple_method1.pth")

加载模型

import torchfrom model_save import *
# 方式1 -> 保存方式1,加载模型
import torchvision
from torch import nnmodel = torch.load("vgg16_method1.pth")
# print(model)# 方式2 -> 保存方式2,加载模型
# 变字典型为网络模型:vgg16 = torchvision.models.vgg16(weights=None)和vgg16.load_state_dict()
vgg16 = torchvision.models.vgg16(weights=None)
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
# model = torch.load("vgg16_method2.pth")
# print(vgg16)# # 陷阱
# model = torch.load('apple_method1.pth')
# print(model)# # 改正陷阱的方式1:把模型写过来
# class Apple(nn.Module):
#     # 初始化方法,继承父类
#     def __init__(self):
#         super(Apple, self).__init__()
#         self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3)
#
#     def forward(self, x):
#         x = self.module1(x)
#         return x
#
# # 但是不需要写:apple = Apple()
# model = torch.load('apple_method1.pth')
# print(model)# 改正陷阱的方式2
# 最上边导入model_save:  from model_save import *
model = torch.load('apple_method1.pth')
print(model)

模型训练

# 搭建神经网络模型
import torch
from torch import nnclass Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()# Sequential:整合上面的步骤,且代码和输出更加简洁self.model = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=32,kernel_size=5, padding=2, stride=1),nn.MaxPool2d(kernel_size=2),nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2, stride=1),nn.MaxPool2d(kernel_size=2),nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2, stride=1),nn.MaxPool2d(kernel_size=2),nn.Flatten(),nn.Linear(in_features=1024, out_features=64),nn.Linear(in_features=64, out_features=10))# 正向传播def forward(self, x):x = self.model(x)return x# 测试本模型
if __name__ == '__main__':apple = Apple()# batch_size=64(64张图片) channel=3 32*32input = torch.ones((64, 3, 32, 32))output = apple(input)print(output.shape)
# 模型训练
import torchvision
import time
from torch.utils.tensorboard import SummaryWriter
from model import *
from torch import nn
from torch.utils.data import DataLoader# 准备数据集
train_data = torchvision.datasets.CIFAR10(root="data_train", transform=torchvision.transforms.ToTensor(),train=True, download=True)
test_data = torchvision.datasets.CIFAR10(root="data_train", transform=torchvision.transforms.ToTensor(),train=False, download=True)# length 长度。本次表示的是有几张图片
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10,训练数据集长度为:10
print("训练数据集长度为:{}".format(train_data_size))
print("测试数据集长度为:{}".format(test_data_size))# 利用DataLoader来加载数据集
# 这里的batch_size=64表示的是一次训练64张图片
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)# # 搭建神经网络->model.py
# class Apple(nn.Module):
#     # 初始化方法,继承父类
#     def __init__(self):
#         super(Apple, self).__init__()
#         # Sequential:整合上面的步骤,且代码和输出更加简洁
#         self.model = nn.Sequential(
#             nn.Conv2d(in_channels=3, out_channels=32,kernel_size=5, padding=2, stride=1),
#             nn.MaxPool2d(kernel_size=2),
#             nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2, stride=1),
#             nn.MaxPool2d(kernel_size=2),
#             nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2, stride=1),
#             nn.MaxPool2d(kernel_size=2),
#             nn.Flatten(),
#             nn.Linear(in_features=1024, out_features=64),
#             nn.Linear(in_features=64, out_features=10)
#         )
#
#     def forward(self, x):
#         x = self.model(x)
#         return x# 创建网络模型
apple = Apple()# 损失函数
loss_fn = nn.CrossEntropyLoss()# 优化器SGD:随机梯度下降
# learning_rate = 0.01=1x(10)^(-2)=1e-2
learning_rate = 1e-2
optimizer = torch.optim.SGD(apple.parameters(), lr=learning_rate)# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10# 添加tensorboard
writer = SummaryWriter("logs_train")# 计时:CPU
start_time = time.time()for i in range(epoch):print("----------第{}轮训练开始----------".format(i+1))# 训练步骤开始# apple.train()for data in train_dataloader:imgs, targets = dataoutputs = apple(imgs)loss = loss_fn(outputs, targets)# 优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()total_train_step = total_train_step + 1# 逢百打印+记录if total_train_step % 100 == 0:end_time = time.time()print(end_time - start_time)print("训练次数:{}, loss:{} ".format(total_train_step, loss.item()))writer.add_scalar("train_loss", loss.item(), total_train_step)# 测试步骤开始,即为不进行优化只计算差距loss# apple.eval()total_test_loss = 0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs, targets = dataoutputs = apple(imgs)loss = loss_fn(outputs, targets)total_test_loss = total_test_loss + loss.item()accuracy = (outputs.argmax(1) == targets).sum()total_accuracy = total_accuracy + accuracyprint("整体测试集上的loss:{}".format(total_test_loss))print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss", total_test_loss, total_test_step)writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)total_test_step = total_test_step + 1torch.save(apple, "apple_{}.pth".format(i))# torch.save(apple.state_dict(), "apple_{}.pth".format(i))print("模型已保存")writer.close()
import torch
import torchvision
from PIL import Image
from torch import nn# 采用模型apple_0.pth时此行需要注释掉
device = torch.device("cuda:0")
image_path = "images/dog.png"
image = Image.open(image_path)
print(image)image = image.convert('RGB')transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),torchvision.transforms.ToTensor()])image = transform(image)
print(image.shape)# 创建网络模型
class Apple(nn.Module):# 初始化方法,继承父类def __init__(self):super(Apple, self).__init__()# Sequential:整合上面的步骤,且代码和输出更加简洁self.model = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=32,kernel_size=5, padding=2, stride=1),nn.MaxPool2d(kernel_size=2),nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2, stride=1),nn.MaxPool2d(kernel_size=2),nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2, stride=1),nn.MaxPool2d(kernel_size=2),nn.Flatten(),nn.Linear(in_features=1024, out_features=64),nn.Linear(in_features=64, out_features=10))def forward(self, x):x = self.model(x)return x# 加载网络模型。因为加载的模型apple_9.pth是用GPU训练保存的,所以输入的图片也得送给GPU测试
# model = torch.load("apple_0.pth")
model = torch.load("apple_9.pth")
print(model)
image = torch.reshape(image, (1, 3, 32, 32))
# 采用模型apple_0.pth时此行需要注释掉
image = image.to(device)
model.eval()
with torch.no_grad():output = model(image)
print(output)
print(output.argmax(1))
http://www.dtcms.com/a/411121.html

相关文章:

  • 【论文阅读笔记】VeloCycle
  • OpenSpeedy简介
  • 【论文阅读 | IF 2025 | LFDT-Fusion:潜在特征引导的扩散 Transformer 模型在通用图像融合中的应用】
  • 网网站建设站建设做推广优化的网站有哪些
  • 企业建设网站个人总结网站内容与目录结构图
  • 软考中级习题与解答——第十三章_数据库分析与设计(1)
  • 2025 PHP7/8 实战入门:15 天精通现代 Web 开发——第 15 课:项目实战与部署
  • RNA甲基化技术如何选择?
  • 网站建设与运营实验上海环球金融中心
  • 高斯分布及其线性变换
  • silverlight做的网站英文网站做百度权重有意义吗
  • 宁波网站推广报价南京网站定制
  • Linux开发工具入门:零基础到熟练使用(二)
  • kafka-日志收集平台部署项目
  • 郑州建站推广公司太原市制作网站
  • 学习:uniapp全栈微信小程序vue3后台(28)
  • 如何提高网站流量公众号推广代理
  • 怎么自己做淘宝客网站吗.net响应式网站模板
  • AI投资决策Agent系列——沃伦·巴菲特Agent
  • 网站开发流程知乎深圳线上注册公司
  • PSG数据集概述
  • 《考研408数据结构》第二章《线性表(顺序表、链表)》复习笔记
  • 网站程序语言那个好网页设计的就业和发展前景
  • SpringBoot 日志报错 No static resource favicon.ico
  • TOGAF® 与新兴技术:区块链、物联网与量子计算
  • 提升网站访问量wordpress %postname%
  • 环评登记表在哪个网站做做网站和淘宝美工 最低电脑
  • C++ QT 实现自定义事件
  • 郑州做网站的企业wordpress插件内链
  • 安卓接入Kwai广告源