# learn **Repository Path**: li-zen/learn ## Basic Information - **Project Name**: learn - **Description**: pytorch学习笔记 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 1 - **Created**: 2024-09-19 - **Last Updated**: 2025-08-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: PyTorch, Python, Deep-learning ## README # pytorch笔记 ### Dataset类 用途:设置数据集 导入需要的库 ```python from torch.utils.data import Dataset #本小节的主角 from PIL import Image # 用于处理图片,也可以用cv2 import os # 处理文件路径 ``` 继承Dataset类,需要获取图片位置,标签 ```python class MyData(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 __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 def __len__(self): return len(self.img_path) ``` 调用 ```python root_dir = "dataset/train" ants_label_dir = "ants" ants_dataset = MyData(root_dir, ants_label_dir) ``` 读取 ```python img, label = ants_dataset[1] #获取图片和标签 ``` ### TensorBoard使用 用途:绘制图像 导入对应库 ```python from torch.utils.tensorboard import SummaryWriter ``` 启动服务 ``` tensorboard --logdir=logs --port=6006 ``` 绘制图像 ```python writer = SummaryWriter('logs') # 写入目标文件夹 writer.add_image("test", img_arr, 2, dataformats='HWC') # 标题,(torch.tensor或者numpy), 阶段,通道,展示图片 for i in range(100): writer.add_scalar("y=2x", 2*i, i)#分别是标题,x轴,y轴,绘制曲线 ``` ### Transforms使用 类似一个处理图片的工具箱,resize改变图片形状,toTensor改变图片格式 Tensor数据类型:包装了一些神经网络常用的参数 如何使用transforms ``` from torchvision import transforms from PIL import Image image_path = "dataset/train/ants/0013035.jpg" img = Image.open(image_path) tensor_trans = transforms.ToTensor() tensor_img = tensor_trans(img) print(tensor_img) ``` ![transforms介绍](./pytorch学习/transforms介绍.jpg) ### transforms的一些方法 ```python from PIL import Image from torchvision import transforms from torch.utils.tensorboard import SummaryWriter writer = SummaryWriter("logs") img = Image.open("111.jpg") print(img) # ToTensor修改图片为Tensor格式 trans_totensor = transforms.ToTensor() img_tensor = trans_totensor(img) writer.add_image("ToTensor", img_tensor, 0) # Normalize 标准化方法 # output[channel] = (input[channel] - mean[channel]) / std[channel] print(img_tensor[0][0][0]) # 将[0,1]->[-1,1] 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("norm", img_norm, 0) # Resize 缩放,输入PIL格式,输出PIL格式,元组强制缩放,一个值等比缩放 print(img.size) trans_resize = transforms.Resize((512, 512)) img_resize = trans_resize(img) print(img_resize.size) img_resize = trans_totensor(img_resize) writer.add_image("resize", img_resize, 0) print(img_resize) # Compose 将多个transforms结合,一次完成多个变换 trans_resize_2 = transforms.Resize(512) trans_compose = transforms.Compose([trans_resize_2, trans_totensor]) img_resize_2 = trans_compose(img) writer.add_image("resize", img_resize_2, 1) # RandomCrop 随机裁切,元组则裁切定义大小,一个值裁切正方形 trans_rand = transforms.RandomCrop(512) trans_compose_2 = transforms.Compose([trans_rand, trans_totensor]) for i in range(10): img_rand = trans_compose_2(img) writer.add_image("rand", img_rand, i) writer.close() ``` ### 使用官方的数据集 打开官网,里面有数据集相关讲解,以cifar10为例,设定对应参数,root:下载位置,train:是否为训练集,transform:设置变换器,download:是否下载; ```python train_srt = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_trans, download=True) test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=dataset_trans, download=True) ``` 内部数据结构为每一项的数据为:图片信息,分类;总信息包含分类名等信息 ```python import torchvision from torch.utils.tensorboard import SummaryWriter dataset_trans = torchvision.transforms.Compose([ torchvision.transforms.ToTensor() ]) train_srt = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_trans, download=True) test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=dataset_trans, download=True) print(test_set) # 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 参数: batch_size:int,每次取样数目 shuffle:bool,是否打乱 num_workers:int,进程数 drop_last:bool,尾部是否舍去 ```python import torchvision from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter dataset_trans = torchvision.transforms.Compose([ torchvision.transforms.ToTensor() ]) # train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_trans, download=True) test_data = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=dataset_trans, download=True) test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=False) img, target = test_data[0] print(img.shape) print(target) writer = SummaryWriter("dataloader") for epoch in range(2): step = 0 for data in test_loader: imgs, targets = data # print(imgs.shape) # print(targets) writer.add_images("Epoch: {}".format(epoch), imgs, step) step += 1 writer.close() ``` ### nn.Module nn — Neural Network 包含内容: Containers:容器,神经网络的骨架 Convolution Layers:卷积层 Poolng layers:池化层 Padding Layers: Non-linear Activation:非线性激活 Normalization Layers:正则化层 ##### Containers包含以下模块 Module:为所有神经网络提供基本骨架 ```python class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() 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 x ``` ##### F conv2d 二维卷积 参数: input:输入图像 weight:权重,卷积核 bias:偏置,卷积结束后进行偏置计算(加减乘除) stride:步长 padding:对输入图像四周填充0 dilation卷积核对应位 groups:分组卷积 padding_mode:填充形式 ##### nn conv2d 参数: in_chsnnels:int 输入通道数 out_channels:int 输出通道数 kernel_size:int or tuple 卷积核大小 stride:int or tuple 步长 padding:int or tuple 填充 dilation:int or tuple 卷积对应位 group:int 分组卷积 bias:bool 偏置 padding_mode:string 填充模式 **公式** ![Conv2d公式](./pytorch学习/Conv2d公式.png) **案例** ```python import torch from torch import nn from torch.nn import Conv2d import torchvision from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) dataloader = DataLoader(dataset, batch_size=64) class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() 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 x tudui = Tudui() print(tudui) step = 0 writer = SummaryWriter("logs") for data in dataloader: imgs, targets = data output = tudui(imgs) print(imgs.shape) print(output.shape) output = torch.reshape(output, (-1, 3, 30, 30)) writer.add_images("aa", imgs, step) # writer.add_images("Epoch: {}".format(1), imgs, step) writer.add_images("bb", output, step) step = step + 1 writer.close() ``` ### 池化层 ##### nn.MaxPool2d 参数: kernel_size:池化核 stride:步长 padding:填充 dilated:空洞 ![Dilated计算](./pytorch学习/Dilated计算.png) ceil_mode:多出是否保留 ![ceil_mode](.\pytorch学习\ceil_mode.png) ##### 应用案例 ```python 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]], dtype=torch.float32) input = torch.reshape(input, (-1, 1, 5, 5)) print(input.shape) class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True) def forward(self, input): output = self.maxpool1(input) return output tudui = Tudui() output = tudui(input) print(output) ``` 用途:减少输入数量 1080p->720p ##### 展示 ```python import torch import torchvision.datasets from torch import nn from torch.nn import MaxPool2d from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) dataloader = DataLoader(dataset, batch_size=64) class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.maxpool1 = MaxPool2d(kernel_size=2, ceil_mode=False) def forward(self, input): output = self.maxpool1(input) return output tudui = Tudui() print(tudui) step = 0 writer = SummaryWriter("logs_POOL") for data in dataloader: imgs, targets = data output = tudui(imgs) writer.add_images("aa", imgs, step) # writer.add_images("Epoch: {}".format(1), imgs, step) writer.add_images("bb", output, step) step = step + 1 writer.close() ``` ### 非线性激活 ##### RELU ##### Sigmoid ```python import torch from torch import nn from torch.nn import ReLU input = torch.tensor([[1, -0.5], [-1, 3]]) output = torch.reshape(input, (-1,1,2,2)) print(output.shape) class TD(nn.Module): def __init__(self): super(TD, self).__init__() self.relu1 = ReLU() def forward(self, input): output = self.relu1(input) return output td = TD() output = td(input) print(output) ``` 用途:引入非线性特征,提升泛化能力 ### 线性层和其他层 ##### 正则化层 加快训练速度 参数:num_features:通道 ##### Recurrent层 RNN,LSTM,多用于文字识别 ##### Transformer层 特定的网络结构,不常用 ##### Linear层(线性层,全连接层) **常用** ![linear层](./pytorch学习/linear层.png) 将多组数据不断学习减少数据量,如下图vgg最后一部分4096个参数学习到1000个参数 ![vgg](./pytorch学习/vgg.jpg) ```python import torch from torch import nn from torch.nn import Linear import torchvision from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) dataloader = DataLoader(dataset, batch_size=64) class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.linear = Linear(196608, 10) def forward(self, x): x = self.linear(x) return x tudui = Tudui() print(tudui) step = 0 writer = SummaryWriter("logs_li") for data in dataloader: imgs, targets = data print(imgs.shape) output = torch.flatten(imgs) print(output.shape) output = tudui(output) print(output.shape) step = step + 1 writer.close() ``` ##### Dropout层 随机将一些输入的元素变为0,变异概率设置p值 防止一些过拟合 ##### Sparse层 多用于自然语言处理 ### 自行搭建网络架构 ``` import torch from torch import nn from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential from torch.utils.tensorboard import SummaryWriter class TD(nn.Module): def __init__(self): super(TD, self).__init__() # 方法1,使用Sequential,将所有操作放到一个model里, 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(1024, 64), Linear(64, 10), ) # 方法2,自己定义每一层,在forward里自行调用 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) self.flaten = Flatten() self.linear1 = Linear(1024, 64) self.linear2 = Linear(64, 10) def forward(self, x): # 方法1,直接调用即可 x = self.model(x) # 方法2,每一层都需要自行调用 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.flaten(x) x = self.linear1(x) x = self.linear2(x) return x td = TD() # 生成input input = torch.ones((64, 3, 32, 32)) output = td(input) print(output.shape) # 网络模型图 writer = SummaryWriter("logs_seq") writer.add_graph(td, input) writer.close() ``` 图片 ![网络图](.\pytorch学习\网络图.png) ### 损失函数和反向传播 loss函数功能 计算实际输出和目标的差距 为我们更新输出提供一定依据(反向传播) 为每个卷积核设置了一个grad,即梯度,根据梯度进行参数更新 常用loss:MSELoss,CrossEntopyLoss(交叉熵,分类用) ```python import torchvision.datasets from torch.nn import CrossEntropyLoss, Sequential, Conv2d, MaxPool2d, Flatten, Linear from torch.utils.data import DataLoader from torch import nn dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) dataloader = DataLoader(dataset, batch_size=1) class TD(nn.Module): def __init__(self): super(TD, 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(1024, 64), Linear(64, 10), ) def forward(self, x): x = Sequential(x) return x loss = CrossEntropyLoss() td = TD() for data in dataloader: imgs, targets = data outputs = td(imgs) res_loss = loss(outputs, targets) # 反向传播 res_loss.backward() print(outputs) print(targets) print() ``` ### 优化器 ```python import torch.optim import torchvision.datasets from torch.nn import CrossEntropyLoss, Sequential, Conv2d, MaxPool2d, Flatten, Linear from torch.utils.data import DataLoader from torch import nn dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) dataloader = DataLoader(dataset, batch_size=1) class TD(nn.Module): def __init__(self): super(TD, self).__init__() # 方法1,使用Sequential,将所有操作放到一个model里, 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(1024, 64), Linear(64, 10) ) def forward(self, x): x = self.model(x) return x loss = CrossEntropyLoss() td = TD() # 定义优化器 optim = torch.optim.SGD(td.parameters(), lr=0.01) for epoch in range(20): running_loss = 0.0 for data in dataloader: imgs, targets = data outputs = td(imgs) res_loss = loss(outputs, targets) # 清除上一轮训练留下的残留 optim.zero_grad() # 反向传播 res_loss.backward() # 优化器进行参数优化 optim.step() running_loss += res_loss print(running_loss) ``` ### 修改和使用现有模型 ```python import torchvision import torch from torch import nn # train_data = torchvision.datasets.ImageNet("./data_image_net", split="train", download=True, # transform=torchvision.transforms.ToTensor) from torch.utils.data import DataLoader # 下载模型,true是预训练过有更好权重的的模型,false则没有 vgg16_false = torchvision.models.vgg16(pretrained=False) vgg16_true = torchvision.models.vgg16(pretrained=True) print(vgg16_false) print("——————————————————————") print(vgg16_true) dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(),download=True) # 添加新层 vgg16_true.add_module("add_linear", nn.Linear(1000, 10)) # 修改层 vgg16_false.classifier[6] = nn.Linear(4096, 10) ``` ### 模型的加载与保存 保存 ```python import torchvision import torch vgg16 = torchvision.models.vgg16(pretrained=False) # 保存方式1,模型结构+参数 torch.save(vgg16, "vgg16_method1.pth") # 保存方式2,模型参数(官方推荐) torch.save(vgg16.state_dict(), "vgg16_method2.pth") ``` 加载 ```python import torch import torchvision.models # 方式1 加载,如果是自己定义的模型,需要让方法访问到你的模型,需要import model = torch.load("vgg16_method1.pth") print(model) # 方式2 加载 vgg16 = torchvision.models.vgg16(pretrained=False) vgg16.load_state_dict(torch.load("vgg16_method2.pth")) print(vgg16) ``` ### 完整模型训练 需要两个文件,一个专门存放Model文件,另一个存放训练 train ```python import torch.optim import torchvision from torch import nn # 引入自己的模型 import model from model import Tudui from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter train_data = torchvision.datasets.CIFAR10("./data", train=True, transform=torchvision.transforms.ToTensor(), download=True) test_data = torchvision.datasets.CIFAR10("./data", train=False, transform=torchvision.transforms.ToTensor(), download=True) train_data_size = len(train_data) test_data_size = len(test_data) print("训练数据集长度:{}".format(train_data_size)) print("测试数据集长度:{}".format(test_data_size)) train_dataloader = DataLoader(train_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) tudui = Tudui() # 损失函数 loss_fn = nn.CrossEntropyLoss() # 优化器 lr = 0.01 optimizer = torch.optim.SGD(tudui.parameters(), lr=lr) # 设置训练网络的参数 # 训练次数 total_train_step = 0 # 测试次数 total_test_step = 0 # 训练轮数 epoch = 10 writer = SummaryWriter('./logs') for i in range(epoch): print("--------第{}轮--------".format(i+1)) # 训练模式 tudui.train() for data in train_dataloader: imgs, targets = data outputs = tudui(imgs) loss = loss_fn(outputs, targets) # 优化器 optimizer.zero_grad() loss.backward() optimizer.step() total_train_step += 1 if total_train_step % 100 == 0: print("loss:{}".format(loss.item())) writer.add_scalar("train_loss", loss.item(), total_train_step) total_test_loss = 0 total_acc = 0 # 测试模式 tudui.eval() with torch.no_grad(): for data in test_dataloader: imgs, targets = data outputs = tudui(imgs) accuracy = (outputs.argmax(1) == targets).sum() # 计算本次测试正确的数量 total_acc += accuracy loss = loss_fn(outputs, targets) total_test_loss += loss print(total_test_loss) print(total_acc/test_data_size) writer.add_scalar("test_loss", total_test_loss, total_test_step) writer.add_scalar("test_acc", total_acc/test_data_size, total_test_step) total_test_step += 1 torch.save(tudui, "tudui_{}.pth".format(i)) ``` model ```python import torch from torch import nn # 模型文件 class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.model = nn.Sequential( nn.Conv2d(3, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, 1, 2), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(64*4*4, 64), nn.Linear(64, 10) ) def forward(self, x): x = self.model(x) return x if __name__ == '__main__': tudui = Tudui() input = torch.ones((64, 3, 32, 32)) output = tudui(input) print(output.shape) ``` ### 使用GPU训练 需要在网络模型,数据,损失函数加上.cuda ```python import torchvision from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter import torch from torch import nn # 模型文件 class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.model = nn.Sequential( nn.Conv2d(3, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, 1, 2), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(64*4*4, 64), nn.Linear(64, 10) ) def forward(self, x): x = self.model(x) return x train_data = torchvision.datasets.CIFAR10("./dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True) test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) train_data_size = len(train_data) test_data_size = len(test_data) print("训练数据集长度:{}".format(train_data_size)) print("测试数据集长度:{}".format(test_data_size)) train_dataloader = DataLoader(train_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) if torch.cuda.is_available(): tudui = Tudui().cuda() else: tudui = Tudui() # 损失函数 if torch.cuda.is_available(): loss_fn = nn.CrossEntropyLoss().cuda() else: loss_fn = nn.CrossEntropyLoss() # 优化器 lr = 0.01 optimizer = torch.optim.SGD(tudui.parameters(), lr=lr) # 设置训练网络的参数 # 训练次数 total_train_step = 0 # 测试次数 total_test_step = 0 # 训练轮数 epoch = 10 writer = SummaryWriter('./logs') for i in range(epoch): print("--------第{}轮--------".format(i + 1)) # 训练模式 tudui.train() for data in train_dataloader: imgs, targets = data if torch.cuda.is_available(): imgs = imgs.cuda() targets = targets.cuda() outputs = tudui(imgs) loss = loss_fn(outputs, targets) # 优化器 optimizer.zero_grad() loss.backward() optimizer.step() total_train_step += 1 if total_train_step % 100 == 0: print("loss:{}".format(loss.item())) writer.add_scalar("train_loss", loss.item(), total_train_step) total_test_loss = 0 total_acc = 0 # 测试模式 tudui.eval() with torch.no_grad(): for data in test_dataloader: imgs, targets = data if torch.cuda.is_available(): imgs = imgs.cuda() targets = targets.cuda() outputs = tudui(imgs) accuracy = (outputs.argmax(1) == targets).sum() total_acc += accuracy loss = loss_fn(outputs, targets) total_test_loss += loss print(total_test_loss) print(total_acc / test_data_size) writer.add_scalar("test_loss", total_test_loss, total_test_step) writer.add_scalar("test_acc", total_acc / test_data_size, total_test_step) total_test_step += 1 torch.save(tudui, "tudui_{}.pth".format(i)) ``` 方法2:首先定义device,后面将网络模型,数据,损失函数加上to(device) ```python import torchvision from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter import torch from torch import nn # 定义设备 device = torch.device("cuda") # 模型文件 class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.model = nn.Sequential( nn.Conv2d(3, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, 1, 2), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(64*4*4, 64), nn.Linear(64, 10) ) def forward(self, x): x = self.model(x) return x train_data = torchvision.datasets.CIFAR10("./dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True) test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True) train_data_size = len(train_data) test_data_size = len(test_data) print("训练数据集长度:{}".format(train_data_size)) print("测试数据集长度:{}".format(test_data_size)) train_dataloader = DataLoader(train_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) tudui = Tudui() tudui = tudui.to(device) # 损失函数 loss_fn = nn.CrossEntropyLoss() loss_fn = loss_fn.to(device) # 优化器 lr = 0.01 optimizer = torch.optim.SGD(tudui.parameters(), lr=lr) # 设置训练网络的参数 # 训练次数 total_train_step = 0 # 测试次数 total_test_step = 0 # 训练轮数 epoch = 10 writer = SummaryWriter('./logs') for i in range(epoch): print("--------第{}轮--------".format(i + 1)) # 训练模式 tudui.train() for data in train_dataloader: imgs, targets = data imgs = imgs.to(device) targets = targets.to(device) outputs = tudui(imgs) loss = loss_fn(outputs, targets) # 优化器 optimizer.zero_grad() loss.backward() optimizer.step() total_train_step += 1 if total_train_step % 100 == 0: print("loss:{}".format(loss.item())) writer.add_scalar("train_loss", loss.item(), total_train_step) total_test_loss = 0 total_acc = 0 # 测试模式 tudui.eval() with torch.no_grad(): for data in test_dataloader: imgs, targets = data imgs = imgs.to(device) targets = targets.to(device) outputs = tudui(imgs) accuracy = (outputs.argmax(1) == targets).sum() total_acc += accuracy loss = loss_fn(outputs, targets) total_test_loss += loss print(total_test_loss) print(total_acc / test_data_size) writer.add_scalar("test_loss", total_test_loss, total_test_step) writer.add_scalar("test_acc", total_acc / test_data_size, total_test_step) total_test_step += 1 torch.save(tudui, "tudui_{}.pth".format(i)) ``` 不知道有没有cuda ``` device = torch.device("cuda" if torch.cuda.is_available() else "cpu") ``` ### 完整模型测试验证套路 使用已有模型 ```python import torch import torchvision from PIL import Image from torch import nn img_path = "./imgs/dog.jpg" img = Image.open(img_path) transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)), torchvision.transforms.ToTensor()]) img = transform(img) # 模型文件 class Tudui(nn.Module): def __init__(self): super(Tudui, self).__init__() self.model = nn.Sequential( nn.Conv2d(3, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, 1, 2), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, 1, 2), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(64*4*4, 64), nn.Linear(64, 10) ) def forward(self, x): x = self.model(x) return x # 训练模型用的设备与自身机子配套 # model = torch.load("./tudui_44.pth", map_location=torch.device("cuda")) model = torch.load("./tudui_44.pth") model.to("cpu") print(model) img = torch.reshape(img, (1, 3, 32, 32)) model.eval() with torch.no_grad(): output = model(img) print(output) print(output.argmax(1)) ```