当前位置:   article > 正文

pytorch深度学习框架看着一篇就够了!_pytorch csdn

pytorch csdn

目录

1.安装—如何管理环境不同pytorch

1.创建虚拟环境

2.选择pytorch版本

2.在pytorch当中安装jupyter

3.学习pytorch必备两个函数

4.pytorch如何加载数据

5.tensorboard使用方法

add_scalar()使用方法

add_image()函数使用方法:

6.transform使用方法

Totensor

Normalize归一化

Resize

Compose用法

RandomCrop

7.数据集

8.DataLoader

9.神经网络基本骨架

10.卷积

11.卷积层

conv2d

12.最大池化使用

13.非线性激活

14.神经网络线性层

15.神经网络搭建-sequential

16.损失函数和反向传播

损失函数

平均绝对误差L1Loss

均方差MSELoss

交叉熵CrossEntropyLoss

反向传播backward

优化器optim

17现有神经网络的修改

VGG网络模型

18.网络模型的保存与读取

保存模型

如何加载模型

19.完整的模型训练

计算精确度

20.使用GPU进行训练

第一种训练方式

第二种训练方式

21完整的测试套路

附件:yolov5常见的注意事项和报错


 

部分内容参考pytorch中文教程

PyTorch 中文教程_w3cschoolPyTorch 是一个 Torch7 团队开源的 Python 优先的深度学习框架,提供两个高级功能:强大的 GPU 加速 Tensor 计算(类似 numpy)构建基于 tape 的自动升级系统上的深度神经网络 你可_来自PyTorch 中文教程,w3cschool编程狮。icon-default.png?t=N7T8https://www.w3cschool.cn/pytorch/

1.安装—如何管理环境不同pytorch

在做不同的项目需要使用不同版本的环境,比如有的项目需要pytorch0.4有的需要1.0版本,anaconda集成的conda包可以解决这个问题,它可以创建两个房间,一个房间放0.4版本,一个房子放1.0版本,需要哪个版本就进入哪个房间进行工作。

  1. 查看自己电脑驱动版本命令
  2. Win+R cmd 进入命令行
  3. cd C:\Program Files\NVIDIA Corporation\NVSMI
  4. nvidia-smi

 

1.创建虚拟环境

创建虚拟环境报错该如何解决:

Anaconda创建虚拟环境报错—UnavailableInvalidChannel: The channel is not accessible or is invalid_collecting package metadata (repodata.json): faile-CSDN博客报错Collecting package metadata (current_repodata.json): failedUnavailableInvalidChannel: The channel is not accessible or is invalid. channel name: simple channel url: https://pypi.tuna.tsinghua.edu.cn/simple error code: 404You will need to adjus_collecting package metadata (repodata.json): failed unavailableinvalidchannehttps://blog.csdn.net/weixin_45884316/article/details/113530349

安装pytorch的GPU版本但是显示的是CPU版本

conda安装GPU版pytorch,却是cpu版本的原因_pytorch-mutex_廿十七的博客-CSDN博客原因用官网的命令conda安装GPU版本pytorch,发现是安装的cpu版本。查看了下库的信息,发现有一个pytorch-mutex库,这个就是原因所在,将其卸载后,再重新安装GPU版本就解决了。卸载conda uninstall pytorch-mutex安装重新安装后,问题解决。conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch..._pytorch-mutexhttps://blog.csdn.net/qq_43550820/article/details/123708474

conda create -n pytorch python=3.6 #创建虚拟环境

创建成功之后输入conda activate pytorch激活pytorch环境

可以看见环境由base环境转换到pytorch环境当中。

使用pip list查看pytorch当中的包

2.选择pytorch版本

如果想在自己电脑(具有NVIDIA显卡)上跑通代码,就选CUDA,如果不需要在自己电脑上跑(在服务器上跑)或者没有独立显卡,就选CPU。查看自己的CUDA版本是11.6,所以选择比自己版本低的。

使用自动生成的命令:conda install pytorch torchvision torchaudio pytorch-cuda=11.6 -c pytorch -c nvidia来进行安装

安装9.2版本命令:conda install pytorch torchvision cudatoolkit=9.2 -c defaults -c numba/label/dev

安装完毕后可以进入python执行下面命令来测试torch是否安装成功:

写作pytorch命令为conda uninstall pytorch

pytorch查看版本和测试是否安装成功代码:

  1. import torch
  2. print(torch.__version__)
  3. print(torch.cuda.is_available())

2.在pytorch当中安装jupyter

在pytorch虚拟环境当中输入:conda install nb_conda命令

3.学习pytorch必备两个函数

dir():打开,看见:使用dir可以查看某一个工具箱里面有什么工具

dir(torch.cuda.is_available):可以查看torch工具箱里面的cuda工具里面的is_available工具

help():说明书 可以查看一个工具的用法

help(torch.cuda.is_available) 可以查看torch工具箱里面的cuda工具里面的is_available工具的用法

可以看出is_available返回的是一个bool类型的值

4.pytorch如何加载数据

需要理解两个类:Dataset Dataloader

Dataset :提供一种方式去获取数据及其label(如何获取每一个数据以及告诉我们有多少数据)

Dataloader:为后面的网络提供不同的数据形式

  1. from torch.utils.data import Dataset
  2. from PIL import Image
  3. import os
  4. # 使用图片操作等相关的功能
  5. class MyData(Dataset):
  6. def __init__(self, root_dir, label_dir):
  7. self.root_dir = root_dir # 将root_dir设置为这个类当中的全局变量
  8. self.label_dir = label_dir
  9. self.path = os.path.join(self.root_dir, self.label_dir)
  10. self.img_path = os.listdir(self.path) # 获取到路径下的所有图片 存储到list列表当中
  11. def __getitem__(self, item): # 获取到每一个图片的路径
  12. img_name = self.img_path[item]
  13. img_item_path = os.path.join(self.root_dir, self.label_dir, img_name)
  14. img = Image.open(img_item_path)
  15. label = self.label_dir
  16. return img, label
  17. def __len__(self): # 返回图片的数量
  18. return len(self.img_path)
  19. root_dir = 'dataset/train'
  20. ants_label_dir = 'ants'
  21. bees_label_dir = 'bees'
  22. ants_dataset = MyData(root_dir, ants_label_dir)
  23. bees_dataset = MyData(root_dir, bees_label_dir)
  24. train_dataset = ants_dataset + bees_dataset
  25. print(len(train_dataset))
  26. img, label = train_dataset[121]
  27. img.show()
  1. import os
  2. # 目的:将图像信息转换为txt文本信息进行存储
  3. root_dir = 'dataset/train'
  4. target_dir = 'ants_img'
  5. img_path = os.listdir(os.path.join(root_dir, target_dir))
  6. label = target_dir.split('_')[0]
  7. out_dir = 'ants_label'
  8. for i in img_path:
  9. file_name = i.split('.jpg')[0]
  10. with open(os.path.join(root_dir, out_dir, '{}.txt'.format(file_name)), 'w') as f:
  11. f.write(label)

5.tensorboard使用方法

tensorboard需要tensor数据类型才能进行显示。

TensorBoard简介    _DLANDML的博客-CSDN博客以前学习用的资料,整理电脑,放在这里,以备后续使用TensorBoard简介 TensorBoard是TensorFlow自带的一个强大的可视化工具,也是一个Web应用程序套件。TensorBoard目前支持7种可视化,Scalars,Images,Audio,Graphs,Distributions,Histograms和..._tensorboardhttps://blog.csdn.net/l641208111/article/details/112485884

add_scalar()使用方法

需要在tensorboard中调用SummaryWriter,使用SummaryWriter中的add_scalar方法:

  1. def add_scalar(self, tag, scalar_value, global_step=None, walltime=None):
  2. tag:数据标签,类似于图标的标题
  3. scalar_value:对应的y轴数据
  4. global_step:训练的步长

如果使用tensorboard报错:ImportError: TensorBoard logging requires TensorBoard with Python summary writer installed. This should be available in 1.14 or above.则需要进行安装tensorboard

运行结果:

  1. from torch.utils.tensorboard import SummaryWriter
  2. writer = SummaryWriter('logs') # 将数据保存到指定的文件夹当中
  3. # writer.add_image()
  4. # y=x
  5. for i in range(100):
  6. writer.add_scalar('y=x', i, i)
  7. writer.close()

代码运行结束之后会自动生成一个logs文件夹,在logs文件夹当中会有一个数据,如何打开该数据?在terminal窗口当中使用tensorboard --logdir=logs命令可以打开一个页面,这个就是上述代码的执行数据展示效果。

add_image()函数使用方法:

  1. def add_image(self, tag, img_tensor, global_step=None, walltime=None, dataformats='CHW'):
  2. Args:
  3. tag (string): Data identifier
  4. img_tensor (torch.Tensor, numpy.array, or string/blobname): Image data(必须是这几个类型)
  5. global_step (int): Global step value to record
  6. Shape:
  7. img_tensor: Default is :math:`(3, H, W)`. You can use ``torchvision.utils.make_grid()`` to
  8. convert a batch of tensor into 3xHxW format or call ``add_images`` and let us do the job.
  9. Tensor with :math:`(1, H, W)`, :math:`(H, W)`, :math:`(H, W, 3)` is also suitable as long as
  10. corresponding ``dataformats`` argument is passed, e.g. ``CHW``, ``HWC``, ``HW``.

当我们使用PIL中的方法打开图片时的类型如下:PIL不满足add_image函数要求的类型,可以使用opencv读取图片,获取numpy类型图片数据

转换之后会发现add_image()函数依旧会报错,因为该函数要求图片的格式是(3,H,W),但是使用numpy转换之后的图片(print(img_array.shape))的格式是(512, 768, 3),如果想要使用,则需要使用dataformats将图片格式进行转换。

  1. from torch.utils.tensorboard import SummaryWriter
  2. import numpy as np
  3. from PIL import Image
  4. writer = SummaryWriter('logs') # 将数据保存到指定的文件夹当中
  5. image_path = 'test_dataset/train/ants_image/0013035.jpg'
  6. img_PIL = Image.open(image_path)
  7. img_array = np.array(img_PIL)
  8. print(img_array.shape)
  9. writer.add_image('test_img', img_array, 1, dataformats='HWC')
  10. # y=x
  11. for i in range(100):
  12. writer.add_scalar('y=2x', 2 * i, i)
  13. writer.close()

结果:可以看见测试数据中生成一个图片

 读取一个新的图片,将add_image函数当中的步长设置为2,结果如下:

6.transform使用方法

Totensor

transform是torchvision中的一个python文件,可以比喻成一个工具箱,里面有很多工具,比如:ToTensor工具是用来把图片转换为tensor类型。

  1. from PIL import Image
  2. from torchvision import transforms
  3. # python用法 -》tensor数据类型
  4. # 通过transform.ToTensor解决两个问题
  5. # 1.transform该如何使用
  6. # 2.为什么需要tensor数据类型
  7. img_path = 'test_dataset/train/ants_image/9715481_b3cb4114ff.jpg'
  8. img = Image.open(img_path)
  9. tensor_train = transforms.ToTensor() # 创建一个对象 注意ToTensor是一个类,不能直接传入img参数
  10. tensor_img = tensor_train(img)
  11. print(tensor_img)

结果:

转换成tensor数据之后可以直接使用add_image函数

  1. from PIL import Image
  2. from torchvision import transforms
  3. import cv2
  4. from torch.utils.tensorboard import SummaryWriter
  5. # python用法 -》tensor数据类型
  6. # 通过transform.ToTensor解决两个问题
  7. # 1.transform该如何使用
  8. # 2.为什么需要tensor数据类型
  9. img_path = 'test_dataset/train/ants_image/9715481_b3cb4114ff.jpg'
  10. img = Image.open(img_path)
  11. tensor_train = transforms.ToTensor() # 创建一个对象 注意ToTensor是一个类,不能直接传入img参数
  12. tensor_img = tensor_train(img)
  13. cv_img = cv2.imread('test_dataset/train/ants_image/69639610_95e0de17aa.jpg') # 使用opencv生成的是numpy类型的数据
  14. writer = SummaryWriter('logs')
  15. writer.add_image('tensor_img', tensor_img)
  16. writer.close()

为什么要使用Tensor类型的数据,因为该类型里面包含了神经网络理论的一些参数,例如反向传播(backward_hook)、梯度(grad)、数据(data)等

Normalize归一化

原图和归一化的对比

归一化的公式:output[channel] = (input[channel] - mean[channel]) / std[channel])(输入值-平均值)/标准差

代码:

  1. from PIL import Image
  2. from torchvision import transforms
  3. from torch.utils.tensorboard import SummaryWriter
  4. writer = SummaryWriter('logs')
  5. img = Image.open("image/头像二.jpg")
  6. print(img)
  7. # 1.totensor方法使用
  8. train_totensor = transforms.ToTensor()
  9. img_tensor = train_totensor(img)
  10. writer.add_image('Totensor', img_tensor)
  11. # Normalize归一化
  12. print(img_tensor[0][0][0])
  13. trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) #两个[]里面分别表示平均值的标准差,因为图片是3通道的,所以每个[]里面有三个值。
  14. img_norm = trans_norm(img_tensor)
  15. print(img_norm[0][0][0])
  16. writer.add_image('Normalize',img_norm)
  17. writer.close()

Resize

用来改变图片的尺寸,参数是需要设置的图片大小

代码:

  1. # Resize 用来修改图片的尺寸
  2. print(img.size)
  3. trains_resize = transforms.Resize((500, 1000))
  4. # img PIL->resize->img_resize PIL
  5. img_resize1 = trains_resize(img)
  6. print(img_resize1)
  7. # img_resize PIL ->ToTensor->img_resize tensor
  8. img_resize2 = train_totensor(img_resize1)
  9. writer.add_image('Resize', img_resize2, 2)
  10. print(img_resize2)
  11. writer.close()

Compose用法

Compose()中的参数需要的是一个列表,在compose中,数据需要的是参数是transforms类型,所以可以得到compose([transforms1,transforms2])

代码:

  1. # Compose-resize -2
  2. trans_resize_2 = transforms.Resize(512)
  3. trans_compose = transforms.Compose([trans_resize_2, train_totensor]) # 传入的参数是一个Resize对象和一个ToTensor对象,注意两个对象不能交换位置
  4. #使用compose可以对同一个图片设置多个变换
  5. img_resize_2 = trans_compose(img)
  6. writer.add_image('Resize', img_resize_2, 1)
  7. writer.close()

compose类中__call__的作用:举例

  1. class Person:
  2. def __call__(self, name):
  3. print('__call__' + 'hello' + name)
  4. def hello(self, name):
  5. print('hello' + name)
  6. person = Person()
  7. person("li")
  8. person.hello('you')
  9. # call作用是对象不需要调用函数就能使用,不需要使用“.”来进行调用

RandomCrop

作用是对一个图像进行随机裁剪

代码:

  1. # RandomCrop 随机裁剪
  2. trans_random = transforms.RandomCrop(128)
  3. trans_compose_2 = transforms.Compose([trans_random, train_totensor])
  4. for i in range(10):
  5. img_crop = trans_compose_2(img)
  6. writer.add_image('RandomCrop', img_crop, i)

如果报错:raise ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width))那就是随机裁剪的时候设置参数设置太大,需要将参数减小。

7.数据集

pytorch当中有需要数据集这里以CIFAR10为例,看一些相关参数配置

  • root:必须要设置的一个参数
  • train:如果是ture创建的就是一个训练数据集,如果为false则创建的是一个测试数据集
  • transform:表示对图片进行什么操作放在这个里面
  • download:设置为true的时候可以自动从网上下载这些数据集

代码实现:

  1. import torchvision
  2. train_set = torchvision.datasets.CIFAR10(root='./CIFAR_dataset', train=True, download=True)
  3. test_set = torchvision.datasets.CIFAR10(root='./CIFAR_dataset', train=False, download=True)
  4. print(test_set[0]) # 查看第一个数据
  5. print(test_set.classes) # 查看classes类
  6. img, target = test_set[0] # target=3
  7. print(img)
  8. print(target)
  9. print(test_set.classes[target]) # 查看目标为3的类别是什么
  10. img.show()

运行结果:

将所有的图片转换为ToTensor:

  1. import torchvision
  2. from torch.utils.tensorboard import SummaryWriter
  3. dataset_transform = torchvision.transforms.Compose([
  4. torchvision.transforms.ToTensor()
  5. ]) # 使用compose方法将所有图片设置为ToTensor对象
  6. train_set = torchvision.datasets.CIFAR10(root='./CIFAR_dataset', train=True, transform=dataset_transform, download=True)
  7. test_set = torchvision.datasets.CIFAR10(root='./CIFAR_dataset', train=False, transform=dataset_transform, download=True)
  8. writer = SummaryWriter('CIFAR')
  9. for i in range(100):
  10. img, target = test_set[i]
  11. writer.add_image('test_set', img, i)
  12. writer.close()

8.DataLoader

DataLoader详解_dataloader函数-CSDN博客torchvision中datasets中所有封装的数据集都是torch.utils.data.Dataset的子类,它们都实现了__getitem__和__len__方法。因此,它们都可以用torch.utils.data.DataLoader进行数据加载。_dataloader函数https://blog.csdn.net/m0_74890428/article/details/127674386

运行报错:size of input tensor and input format are different. tensor shape: (64, 3, 32, 32), input_format: CHW 表示tensorboard 使用不当,自动补全是add_image,实际应该使用add_images

代码展示:

  1. import torchvision
  2. from torch.utils.data import DataLoader
  3. # 准备的测试数据集
  4. from torch.utils.tensorboard import SummaryWriter
  5. test_data = torchvision.datasets.CIFAR10(root="./CIFAR_dataset", train=False,
  6. transform=torchvision.transforms.ToTensor())
  7. test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True,
  8. num_workers=0, drop_last=True)
  9. # 测试数据集中的第一张图片
  10. img, target = test_data[0]
  11. print(img.shape)
  12. print(target)
  13. writer = SummaryWriter('dataloader')
  14. step = 0
  15. for data in test_loader:
  16. images, targets = data
  17. writer.add_images("test_data_drop_last", images, step)
  18. step += 1
  19. writer.close()
  • DataLoader里面参数设置:
  • dataset:需要加载的数据集
  • batch_size:每个批处理需要加载多少的样本
  • shuffle:设置为Ture的时候,每次运行都会重新清洗数据
  • num_workers:于数据加载的子进程数。0表示将在主进程中加载数据。
  • drop_last=True:会将不够batch_size的图片进行一个舍去,设置为false则会保留所有的图片

将dataloader中的batch_size设置为4代表将dataset数据集当中的4个数据中的img0-img3 4个数据封装到一起,同时将target0-target4也封装到一起。


9.神经网络基本骨架

pytorch中关于神经网络的操作都是在torch模块当中的torch.nn中

MODULE 模组:所有神经网络模块的基类,您的模型还应该继承这个类。

  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. class Model(nn.Module):
  4. def __init__(self):
  5. super().__init__()
  6. self.conv1 = nn.Conv2d(1, 20, 5)
  7. self.conv2 = nn.Conv2d(20, 20, 5)
  8. def forward(self, x):
  9. x = F.relu(self.conv1(x))
  10. return F.relu(self.conv2(x))
  11. # forward函数执行了4个步骤 卷积->非线性->卷积->非线性

10.卷积

使用torch.nn中的function

代码实现:

  1. import torch
  2. import torch.nn.functional as F
  3. x = torch.tensor([[1, 2, 0, 3, 1],
  4. [0, 1, 2, 3, 1],
  5. [1, 2, 1, 0, 0],
  6. [5, 2, 3, 1, 1],
  7. [2, 1, 0, 1, 1]])
  8. kernel = torch.tensor([[1, 2, 1],
  9. [0, 1, 0],
  10. [2, 1, 0]])
  11. x = torch.reshape(x, (1, 1, 5, 5))
  12. kernel = torch.reshape(kernel, (1, 1, 3, 3))
  13. print(x.shape)
  14. print(kernel.shape)
  15. output = F.conv2d(x, kernel, stride=1)
  16. print(output)
  17. output2 = F.conv2d(x, kernel, stride=2) # 每次移动两步
  18. print(output2)
  19. output3 = F.conv2d(x, kernel, stride=1, padding=1)
  20. print(output3)

运行结果:

11.卷积层

conv2d

  1. CLASS torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0,
  2. dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)

相关参数介绍:


  • In _ channel (int)-输入图像中的通道数
  • Out _ channel (int)-卷积产生的通道数

当In _ channel =1并且out _ channel=1的时候,卷积核为1,如下图:

当当In _ channel =1并且out _ channel=2的时候,会产生两个卷积核来进行计算,如下:


  • Kernel _ Size (int 或 tuple)-卷积内核的大小
  • Stride (int 或 tuple,可选)-卷积的大步。默认值: 1
  • 填充(int、 tuple 或 str,可选)-将填充添加到输入的所有四边。默认值: 0
  • Pding _ mode (str,可选)-‘ zeros’,‘ response’,‘ copy’或‘ circulal’。默认值: ‘ zeros’
  • Dilation (int 或 tuple,可选)-内核元素之间的间距。默认值: 1
  • Group (int,可选)-从输入通道到输出通道的阻塞连接数
  • bias(bool,可选)-如果为真,则在输出中添加一个可学习的偏见

计算公式:

代码实现卷积层:

  1. import torch
  2. import torchvision
  3. from torch import nn
  4. from torch.utils.data import DataLoader
  5. from torch.utils.tensorboard import SummaryWriter
  6. dataset = torchvision.datasets.CIFAR10(root="./data", train=False, transform=torchvision.transforms.ToTensor(),
  7. download=True) # 下载测试数据集
  8. dataloader = DataLoader(dataset, batch_size=64)
  9. class Model(torch.nn.Module):
  10. def __init__(self):
  11. super(Model, self).__init__()
  12. self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1,
  13. padding=0)
  14. #彩色图片的通道都为3
  15. def forward(self, x):
  16. x = self.conv1(x)
  17. return x
  18. model = Model()
  19. writer = SummaryWriter('logs')
  20. step = 0
  21. for data in dataloader:
  22. images, targets = data
  23. output = model(images)
  24. # print(images.shape)
  25. # torch.Size([64, 3, 32, 32])
  26. # print('----')
  27. # print(output.shape)
  28. # torch.Size([64, 6, 30, 30])
  29. # print('****')
  30. writer.add_images('input', images, step)
  31. output = torch.reshape(output, (-1, 3, 30, 30)) #将6个通道变成3个通道,这个时候
  32. #batch_size会增加,这里不缺定batch_size是多少所以设置为-1,batch_size会自动进行计算.
  33. writer.add_images('output', output, step)
  34. step += 1
  35. writer.close()
  36. # 通过输出可以看见原来图片的大小是3个in_channels,经过卷积后变成6个in_channels,
  37. 图片大小由原来的32变成30

注意点:彩色图像需要3个channel才能显示,但是这个图片经过卷积层之后变成了6个channel,所以需要使用reshape对图像进行一个转换。

代码运行结果:

12.最大池化使用

最大池化得作用是保留数据得特征,同时将数据量减小,这样训练的参数就会减少,训练的速度就会加快.一般在经过卷积层之后都会再进行一层池化.

池化层的作用_池化层作用-CSDN博客max pooling是CNN当中的最大值池化操作,其实用法和卷积很类似tf.nn.max_pool(value, ksize, strides, padding, name=None)参数是四个,和卷积很类似:第一个参数value:需要池化的输入,一般池化层接在卷积层后面,所以输入通常是feature map,依然是[batch, height, width, channels]这样的shape第二个参数ksize:池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],_池化层作用https://blog.csdn.net/qq_28949847/article/details/106241442

  1. torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False,
  2. ceil_mode=False)

参数设置:

  • kernel_size:窗口的大小
  • stride:窗口的跨度(注意:这里的默认值大小为kernel_size大小)
  • padding:填充大小
  • ceil_mode:当为 True 时,将使用 ceil 而不是 floor 来计算输出形状(2者的区别:2.31这个数,使用floor的话就是向下取整取的是2,如果使用ceiling向上取整的话取得就是3)

dilation:一个控制窗口中元素步幅的参数,如下图每个核当中的元素会和另外一个元素之间差1.


最大池化得操作:

将步长设置为3的时候,当ceil_model设置为true的时候可以得到4个输出值,设置为False只有一个输出.ceil_model可以保留当前卷积图中最大的数据

代码实现:

  1. import torch
  2. import torchvision
  3. from torch import nn
  4. x = torch.tensor([[1, 2, 0, 3, 1],
  5. [0, 1, 2, 3, 1],
  6. [1, 2, 1, 0, 0],
  7. [5, 2, 3, 1, 1],
  8. [2, 1, 0, 1, 1]], dtype=torch.float32) # 这里需要将数据设置成浮点型
  9. x = torch.reshape(x, (-1, 1, 5, 5))
  10. print(x.shape)
  11. class Model(nn.Module):
  12. def __init__(self):
  13. super(Model, self).__init__()
  14. self.maxpool1 = nn.MaxPool2d(kernel_size=3, ceil_mode=True)
  15. def forward(self, x):
  16. output = self.maxpool1(x)
  17. return output
  18. model = Model()
  19. output = model(x)
  20. print(output)

实现效果:

使用图片数据集进行最大池化:

  1. import torch
  2. import torchvision
  3. from torch import nn
  4. from torch.utils.data import DataLoader
  5. from torch.utils.tensorboard import SummaryWriter
  6. dataset = torchvision.datasets.CIFAR10(root="./data", train=False, download=True,
  7. transform=torchvision.transforms.ToTensor())
  8. dataloader = DataLoader(dataset, batch_size=64)
  9. # x = torch.tensor([[1, 2, 0, 3, 1],
  10. # [0, 1, 2, 3, 1],
  11. # [1, 2, 1, 0, 0],
  12. # [5, 2, 3, 1, 1],
  13. # [2, 1, 0, 1, 1]], dtype=torch.float32) # 这里需要将数据设置成浮点型
  14. # x = torch.reshape(x, (-1, 1, 5, 5))
  15. # print(x.shape)
  16. class Model(nn.Module):
  17. def __init__(self):
  18. super(Model, self).__init__()
  19. self.maxpool1 = nn.MaxPool2d(kernel_size=3, ceil_mode=True)
  20. def forward(self, x):
  21. output = self.maxpool1(x)
  22. return output
  23. model = Model()
  24. writer = SummaryWriter('log_maxpool')
  25. step = 0
  26. for data in dataloader:
  27. images, targets = data
  28. writer.add_images('input', images, step)
  29. output = model(images)
  30. writer.add_images('output', output, step)
  31. step += 1
  32. writer.close()

池化之后得图片:

13.非线性激活

非线性激活函数有很多,有RELU,sigmoid等函数.

以ReLU函数举例

  1. torch.nn.ReLU(inplace=False)
  2. #Inplace (bool)-可以选择就地执行操作

inplace:

当inplace设置为ture的时候,可以在原来的变量上进行操作,为false的时候需要有一个新的变量接收返回值.一般采用false来保存原始数据.

代码实现:

  1. import torch
  2. from torch import nn
  3. x = torch.tensor([[1, -0.5],
  4. [-1, 3]])
  5. x = torch.reshape(x, (-1, 1, 2, 2)) # relu函数输入需要设置batch_size
  6. print(x.shape)
  7. class Model(nn.Module):
  8. def __init__(self):
  9. super(Model, self).__init__()
  10. self.relu = nn.ReLU()
  11. def forward(self, x):
  12. y = self.relu(x)
  13. return y
  14. model = Model()
  15. y = model(x)
  16. print(y)

实现效果:

代码转换图片:

  1. import torch
  2. from torch import nn
  3. import torchvision
  4. from torch.utils.data import DataLoader
  5. from torch.utils.tensorboard import SummaryWriter
  6. # x = torch.tensor([[1, -0.5],
  7. # [-1, 3]])
  8. #
  9. # x = torch.reshape(x, (-1, 1, 2, 2)) # relu函数输入需要设置batch_size
  10. # print(x.shape)
  11. dataset = torchvision.datasets.CIFAR10('./CIFAR_dataset', train=False, download=True,
  12. transform=torchvision.transforms.ToTensor())
  13. dataloader = DataLoader(dataset, batch_size=64)
  14. class Model(nn.Module):
  15. def __init__(self):
  16. super(Model, self).__init__()
  17. self.relu = nn.ReLU()
  18. self.sigmoid = nn.Sigmoid()
  19. def forward(self, x):
  20. y = self.sigmoid(x)
  21. return y
  22. model = Model()
  23. writer = SummaryWriter('log_nn_relu')
  24. step = 0
  25. for data in dataloader:
  26. images, targets = data
  27. writer.add_images('input', images, step)
  28. output = model(images)
  29. writer.add_images('output', output, step)
  30. step += 1
  31. writer.close()

转化结果:

14.神经网络线性层

如上图,线形层就是将展开后的25个数据变成3个,类似于这样的操作

线性回归:

  1. torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None)
  2. output=input*w+b(偏置)

flatten函数:

  1. torch.flatten(input, start_dim=0, end_dim=- 1)
  2. #input (Tensor) – the input tensor.
  3. #start_dim (int) – the first dim to flatten
  4. #end_dim (int) – the last dim to flatten
  5. Example:
  6. >>> t = torch.tensor([[[1, 2],
  7. ... [3, 4]],
  8. ... [[5, 6],
  9. ... [7, 8]]])
  10. >>> torch.flatten(t)
  11. tensor([1, 2, 3, 4, 5, 6, 7, 8])
  12. >>> torch.flatten(t, start_dim=1)
  13. tensor([[1, 2, 3, 4],
  14. [5, 6, 7, 8]])

线性层代码实现:

  1. import torchvision
  2. import torch
  3. from torch import nn
  4. from torch.utils.data import DataLoader
  5. dataset = torchvision.datasets.CIFAR10(root="./CIFAR_dataset", train=False, transform=torchvision.transforms.ToTensor(),
  6. download=True)
  7. dataloader = DataLoader(dataset, batch_size=64)
  8. class Model(nn.Module):
  9. def __init__(self):
  10. super(Model, self).__init__()
  11. self.linear1 = nn.Linear(196608, 10)
  12. def forward(self, x):
  13. y = self.linear1(x)
  14. return y
  15. model = Model()
  16. for data in dataloader:
  17. images, targets = data
  18. # print(images.shape) torch.Size([64, 3, 32, 32])
  19. # output = torch.reshape(images, (1, 1, 1, -1)) torch.Size([1, 1, 1, 196608])
  20. output = torch.flatten(images) # 将图片进行扁平化操作 可以代替上一行reshape操作
  21. print(output.shape)
  22. output = model(output)
  23. print(output.shape)

运行效果:

15.神经网络搭建-sequential

sequential:

  1. torch.nn.Sequential(*args: Module)
  2. Example:
  3. # Using Sequential to create a small model. When `model` is run,
  4. # input will first be passed to `Conv2d(1,20,5)`. The output of
  5. # `Conv2d(1,20,5)` will be used as the input to the first
  6. # `ReLU`; the output of the first `ReLU` will become the input
  7. # for `Conv2d(20,64,5)`. Finally, the output of
  8. # `Conv2d(20,64,5)` will be used as input to the second `ReLU`
  9. model = nn.Sequential(
  10. nn.Conv2d(1,20,5),
  11. nn.ReLU(),
  12. nn.Conv2d(20,64,5),
  13. nn.ReLU()
  14. )
  15. # Using Sequential with OrderedDict. This is functionally the
  16. # same as the above code
  17. model = nn.Sequential(OrderedDict([
  18. ('conv1', nn.Conv2d(1,20,5)),
  19. ('relu1', nn.ReLU()),
  20. ('conv2', nn.Conv2d(20,64,5)),
  21. ('relu2', nn.ReLU())
  22. ]))

cifar10的模型结构:

如何实现上述cifar10模型结构,需要使用下面函数来进行相关参数推导:

dilation一般默认为1,stride默认为1

代码实现上述cifar10模型结构:

  1. import torch
  2. from torch import nn
  3. class Model(nn.Module):
  4. def __init__(self):
  5. super(Model, self).__init__()
  6. # in_channels开始为3,out_channels为32,卷积核kernel_size为5,通过conv2d公式进行计算可以求出padding=2
  7. self.conv1 = nn.Conv2d(3, 32, 5, padding=2)
  8. self.maxpool1 = nn.MaxPool2d(2)
  9. self.conv2 = nn.Conv2d(32, 32, 5, padding=2)
  10. self.maxpool2 = nn.MaxPool2d(2)
  11. self.conv3 = nn.Conv2d(32, 64, 5, padding=2)
  12. self.maxpool3 = nn.MaxPool2d(2)
  13. self.flatten = nn.Flatten()
  14. self.linear1 = nn.Linear(1024, 64)
  15. self.linear2 = nn.Linear(64, 10)
  16. def forward(self, x):
  17. x = self.conv1(x)
  18. x = self.maxpool1(x)
  19. x = self.conv2(x)
  20. x = self.maxpool2(x)
  21. x = self.conv3(x)
  22. x = self.maxpool3(x)
  23. x = self.flatten(x)
  24. x = self.linear1(x)
  25. x = self.linear2(x)
  26. return x
  27. model = Model()
  28. print(model)
  29. input = torch.ones((64, 3, 32, 32))
  30. output = model(input)
  31. print(output.shape)

代码运行效果:


使用sequential优化之后的代码:

  1. import torch
  2. from torch import nn
  3. from torch.nn import Conv2d, MaxPool2d, Linear, Sequential, Flatten
  4. from torch.utils.tensorboard import SummaryWriter
  5. class Model(nn.Module):
  6. def __init__(self):
  7. super(Model, self).__init__()
  8. self.model1 = Sequential(
  9. # in_channels开始为3,out_channels为32,卷积核kernel_size为5,通过conv2d公式进行计算可以求出padding=2
  10. Conv2d(3, 32, 5, padding=2),
  11. MaxPool2d(2),
  12. Conv2d(32, 32, 5, padding=2),
  13. MaxPool2d(2),
  14. Conv2d(32, 64, 5, padding=2),
  15. MaxPool2d(2),
  16. Flatten(),
  17. Linear(1024, 64),
  18. Linear(64, 10)
  19. )
  20. def forward(self, x):
  21. x = self.model1(x)
  22. return x
  23. model = Model()
  24. print(model)
  25. x = torch.ones((64, 3, 32, 32))
  26. y = model(x)
  27. # y=torch.unsqueeze(y, dim=0)
  28. print(y.shape)
  29. writer = SummaryWriter('log_seq')
  30. writer.add_graph(model, x)
  31. writer.close()

通过tensorboard打开一个可视化界面可以看到代码的

16.损失函数和反向传播

损失函数

损失函数的作用:

1.计算实际输出和目标输出之间的差距

2.为我们更新输出提供一定的依据(反向传播),grad梯度

平均绝对误差L1Loss

对应项相减,然后求平均值

  1. torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')
  2. #reduction默认为求平均,也可以改成sum

实现代码:

  1. import torch
  2. from torch.nn import L1Loss
  3. inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
  4. targets = torch.tensor([1, 2, 5], dtype=torch.float32)
  5. inputs = torch.reshape(inputs, (1, 1, 1, 3,))
  6. targets = torch.reshape(targets, (1, 1, 1, 3))
  7. loss = L1Loss()
  8. result = loss(inputs, targets)
  9. #L1oss=(1-1+2-2+5-3)/3
  10. print(result)

实现结果:

均方差MSELoss

创建一个标准,测量输入xx和目标yy中每个元素之间的均方误差(L2范数的平方)。

torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')

代码实现:

  1. loss_mse = MSELoss()
  2. result2 = loss_mse(inputs, targets)
  3. # MSELoss=(0+0+2^2)/3

交叉熵CrossEntropyLoss

(本质上是交叉熵公式+softmax公式)

当训练一个有C类的分类问题时,它很有用。如果提供的话,可选的参数weight应该是一个1D张量,为每个类分配权重。当你有一个不平衡的训练集时,这特别有用。

pytorch中交叉熵损失(nn.CrossEntropyLoss())的计算过程_pytorch 计算熵-CSDN博客公式首先需要了解CrossEntropyLoss的计算过程,交叉熵的函数是这样的: 其中,其中yi表示真实的分类结果。这里只给出公式,关于CrossEntropyLoss的其他详细细节请参照其他博文。测试代码(一维)import torchimport torch.nn as nnimport mathcriterion = nn.CrossEntropyLos..._pytorch 计算熵https://blog.csdn.net/ft_sunshine/article/details/92074842

公式:

公式详解如下图:

我们需要预测一个图片是狗种类的概率,假设输出层设置输出人的概率为0.1,狗的概率为0.2,猫的概率为0.3,我们设置预测对象target=1,也就是预测狗的概率,这个时候x=[0.1,0.2,0.3],class=1,代入公式即可。

交叉熵对于形状的要求:

N=batch_size,C代表分类问题,之前的cifar10就是分了10类,这里的C就是10

反向传播backward

当我们使用损失函数的时候,我们可以调用损失函数的一个backward函数,得到一个反向传播,反向传播可以调节每一步我们需要的参数,这个参数对应的一个梯度,有了这个梯度可以利用优化器,可以调剂我们的梯度,这样就可以达到一个降低误差的目的。

优化器optim

  1. import torch
  2. from torch import nn
  3. import torchvision
  4. from torch.nn import Conv2d, MaxPool2d, Linear, Sequential, Flatten, CrossEntropyLoss
  5. from torch.utils.data import DataLoader
  6. from torch.utils.tensorboard import SummaryWriter
  7. from nn_lose import loss
  8. dataset = torchvision.datasets.CIFAR10('./data', train=False, transform=torchvision.transforms.ToTensor(),
  9. download=True)
  10. dataloader = DataLoader(dataset, batch_size=1)
  11. class Model(nn.Module):
  12. def __init__(self):
  13. super(Model, self).__init__()
  14. self.model1 = Sequential(
  15. # in_channels开始为3,out_channels为32,卷积核kernel_size为5,通过conv2d公式进行计算可以求出padding=2
  16. Conv2d(3, 32, 5, padding=2),
  17. MaxPool2d(2),
  18. Conv2d(32, 32, 5, padding=2),
  19. MaxPool2d(2),
  20. Conv2d(32, 64, 5, padding=2),
  21. MaxPool2d(2),
  22. Flatten(),
  23. Linear(1024, 64),
  24. Linear(64, 10)
  25. )
  26. def forward(self, x):
  27. x = self.model1(x)
  28. return x
  29. loss = CrossEntropyLoss()
  30. model = Model()
  31. optim = torch.optim.SGD(model.parameters(), lr=0.01, ) # lr是学习速率 (优化器)
  32. for epoch in range(20): # 设置进行多轮学习
  33. running_loss = 0
  34. for data in dataloader:
  35. images, targets = data
  36. outputs = model(images)
  37. result_loss = loss(outputs, targets)
  38. optim.zero_grad() # 将每一个可以调节梯度的参数调节为0
  39. result_loss.backward() # 计算每一个参数对应的梯度
  40. optim.step() # 对每一个参数进行一个调优
  41. running_loss = running_loss + result_loss
  42. print(1)

17现有神经网络的修改

VGG网络模型

VGG——CNN经典网络模型(pytorch实现)-CSDN博客一、LeNet-5这个是n多年前就有的一个CNN的经典结构,主要是用于手写字体的识别,也是刚入门需要学习熟悉的一个网络。原论文地址输入:32*32的手写字体图片,这些手写字体包含0~9数字,也就是相当于10个类别的图片输出:分类结果,0~9之间的一个数因此我们可以知道,这是一个多分类问题,总共有十个类,因此神经网络的最后输出层必然是SoftMax问题,然后神经元的个数是10个。LeNet...https://blog.csdn.net/weixin_44023658/article/details/105707969

VGG网络模型是在ImageNET上面进行训练的,一共有1000个种类,可以用来提取一些特殊的特征

网络结构:

  1. VGG(
  2. (features): Sequential(
  3. (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  4. (1): ReLU(inplace=True)
  5. (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  6. (3): ReLU(inplace=True)
  7. (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  8. (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  9. (6): ReLU(inplace=True)
  10. (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  11. (8): ReLU(inplace=True)
  12. (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  13. (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  14. (11): ReLU(inplace=True)
  15. (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  16. (13): ReLU(inplace=True)
  17. (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  18. (15): ReLU(inplace=True)
  19. (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  20. (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  21. (18): ReLU(inplace=True)
  22. (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  23. (20): ReLU(inplace=True)
  24. (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  25. (22): ReLU(inplace=True)
  26. (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  27. (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  28. (25): ReLU(inplace=True)
  29. (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  30. (27): ReLU(inplace=True)
  31. (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  32. (29): ReLU(inplace=True)
  33. (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  34. )
  35. (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  36. (classifier): Sequential(
  37. (0): Linear(in_features=25088, out_features=4096, bias=True)
  38. (1): ReLU(inplace=True)
  39. (2): Dropout(p=0.5, inplace=False)
  40. (3): Linear(in_features=4096, out_features=4096, bias=True)
  41. (4): ReLU(inplace=True)
  42. (5): Dropout(p=0.5, inplace=False)
  43. (6): Linear(in_features=4096, out_features=1000, bias=True)
  44. )
  45. )

对vgg网络中的一些结构进行修改(模型的保存和加载以及修改和增加)

  1. import torchvision
  2. from torch import nn
  3. vgg16_false = torchvision.models.vgg16(pretrained=False)
  4. # 参数:当pretrained=false的时候 只是进行加载数据;为true的时候就是下载数据
  5. vgg16_true = torchvision.models.vgg16(pretrained=True)
  6. vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
  7. # 在原有的vgg网络中classifier中增加一个线性层,设置输入为1000输出为10
  8. print(vgg16_true)
  9. print('---------------')
  10. print(vgg16_false)
  11. vgg16_false.classifier[6] = nn.Linear(4096, 10) # 改变classifier中线性层的输出值
  12. print(vgg16_false)

 vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10)):

vgg16_false.classifier[6] = nn.Linear(4096, 10)

18.网络模型的保存与读取

完整的模型验证套路

保存模型

  1. import torch
  2. import torchvision
  3. from torch import nn
  4. vgg16 = torchvision.models.vgg16(pretrained=False)
  5. # 网络模型保存
  6. # 方式1
  7. torch.save(vgg16, 'vgg16_method1.pth')
  8. # 保存方式2 将vgg16中的参数保存为一个字典的一个格式(官方推荐的一个保存格式)
  9. torch.save(vgg16.state_dict(), 'vgg16_method2.pth')
  10. # 自己定义网络模型
  11. class Model(nn.Module):
  12. def __init__(self):
  13. super(Model, self).__init__()
  14. self.conv1 = nn.Conv2d(3, 64, kernel_size=3)
  15. def forward(self, x):
  16. x = self.conv1(x)
  17. return x
  18. model = Model()
  19. torch.save(model, 'model.pth')

使用方式2要比方式1内存小

使用方式2是以字典的格式进行一个保存

如何加载模型

  1. # 方式1 加载方式1的模型
  2. import torch
  3. import torchvision
  4. from model_save import *
  5. model = torch.load('vgg16_method1.pth')
  6. # print(model)
  7. print('------------')
  8. # 方式2加载模型
  9. model2 = torch.load('vgg16_method2.pth')
  10. # print(model2)
  11. print('************')
  12. # 如何加载以网络的格式已经保存为字典类型的模型
  13. vgg16 = torchvision.models.vgg16(pretrained=False)
  14. vgg16.load_state_dict(torch.load('vgg16_method2.pth'))
  15. # print(vgg16)
  16. # 当我们调用自己写好的网络时候,一定要把该网络代码所有内容导入进来
  17. model = torch.load('model.pth')
  18. print(model)

19.完整的模型训练

  1. import torch
  2. import torchvision
  3. from torch.utils.data import DataLoader
  4. from torch.nn import CrossEntropyLoss
  5. from torch.utils.tensorboard import SummaryWriter
  6. from model import *
  7. # 1.获取训练和测试数据集
  8. train_data = torchvision.datasets.CIFAR10(root="./data", train=True, transform=torchvision.transforms.ToTensor(),
  9. download=True)
  10. test_data = torchvision.datasets.CIFAR10(root="./data", train=False, transform=torchvision.transforms.ToTensor(),
  11. download=True)
  12. # 求数据集的大小
  13. train_data_size = len(train_data)
  14. test_data_size = len(test_data)
  15. # python当中字符串格式化方法,使用format可以将{}替换成format里面的内容
  16. print('训练数据集的大小为:{}'.format(train_data_size))
  17. print('训练数据集的大小为:{}'.format(test_data_size))
  18. # 2、使用Dataloader来加载数据集
  19. train_dataloader = DataLoader(train_data, batch_size=64)
  20. test_dataloader = DataLoader(test_data, batch_size=64)
  21. # 4.创建网络模型
  22. network = Network()
  23. # 5.创建损失函数
  24. loss_fn = CrossEntropyLoss()
  25. # 6.创建优化器
  26. # learning_rate = 0.01
  27. learning_rate = 1e-2
  28. optimizer = torch.optim.SGD(network.parameters(), lr=learning_rate)
  29. # 7.设置网络训练过程中的参数
  30. # 记录训练的次数
  31. total_train_steps = 0
  32. # 记录测试次数
  33. total_test_steps = 0
  34. # 训练的轮数
  35. epochs = 10
  36. # 添加tensorboard
  37. writer = SummaryWriter('log_train')
  38. for i in range(10):
  39. print('-----第{}轮训练开始-----'.format(i + 1))
  40. # 8.训练步骤开始
  41. network.train() # 这行代码是为了应对神经网络中的一些特殊的层
  42. for data in train_dataloader:
  43. images, targets = data
  44. outputs = network(images)
  45. loss = loss_fn(outputs, targets) # 计算误差
  46. # 放入优化器模型当中进行优化
  47. optimizer.zero_grad() # 使用优化器清零
  48. loss.backward() # 使用反向传播
  49. optimizer.step()
  50. total_train_steps += 1
  51. # 展示输出结果
  52. if total_train_steps % 100 == 0:
  53. print("训练次数:{},损失值为:{}".format(total_train_steps, loss.item()))
  54. writer.add_scalar("train_loss", loss.item(), total_train_steps)
  55. # 9、进行检测
  56. network.eval() # 这行代码是为了应对神经网络中的一些特殊的层
  57. total_test_loss = 0 # 统计整体测试损失
  58. total_accuracy = 0 # 统计整体精确度
  59. with torch.no_grad(): # 消除网络模型当中的梯度
  60. for data in test_dataloader:
  61. images, targets = data
  62. outputs = network(images)
  63. loss = loss_fn(outputs, targets)
  64. total_test_loss += loss.item()
  65. accuracy = (outputs.argmax(1) == targets).sum()
  66. total_accuracy += accuracy
  67. print('整体测试集上面的loss:{}'.format(total_test_loss))
  68. print('整体测试集上面的准确率:{}'.format(total_accuracy / test_data_size))
  69. writer.add_scalar("test_loss", total_test_loss, total_test_steps)
  70. writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_steps)
  71. total_test_steps += 1
  72. # 10.保存模型
  73. torch.save(network, 'network_{}.pth'.format(i))
  74. # 官方推荐保存模式 torch.save(network.state_dict(),'network_{}.pth'.format(i))
  75. print('模型已经保存')
  76. writer.close()

第4步的神经网络层

  1. from torch.nn import Module, Sequential, Conv2d, MaxPool2d, Flatten, Linear
  2. import torch
  3. # 3.来搭建神经网络
  4. class Network(Module):
  5. def __init__(self):
  6. super(Network, self).__init__()
  7. self.model = Sequential(
  8. Conv2d(3, 32, 5, 1, 2),
  9. MaxPool2d(2),
  10. Conv2d(32, 32, 5, 1, 2),
  11. MaxPool2d(2),
  12. Conv2d(32, 64, 5, 1, 2),
  13. MaxPool2d(2),
  14. Flatten(),
  15. Linear(64 * 4 * 4, 64),
  16. Linear(64, 10)
  17. )
  18. def forward(self, x):
  19. x = self.model(x)
  20. return x
  21. if __name__ == '__main__':
  22. network = Network()
  23. inputs = torch.ones((64, 3, 32, 32))
  24. print(inputs.shape)
  25. outputs = network(inputs)
  26. print(outputs.shape)

计算精确度

  1. import torch
  2. print(torch.__version__)
  3. print(torch.cuda.is_available())
  4. outputs = torch.tensor([[0.1, 0.2],
  5. [0.3, 0.4]])
  6. print(outputs.argmax(1))
  7. preds = outputs.argmax(1)
  8. targets = torch.tensor([0, 1])
  9. print((preds == targets).sum())
  10. """
  11. argmax用法
  12. 当参数设置为1的时候,横向进行对比,0.1<0.2 返回0.2的位置1 同理0.05<0.4 返回0.4的位置1
  13. 当参数设置为0的时候,纵向进行对比,0.1>0.005 返回0.1的位置0 同理0.2<0.4 返回0.4的位置1
  14. """

20.使用GPU进行训练

第一种训练方式

需要找到以下三个地方,使用.cuda(),就可以实现GPU训练

  1. 网络模型
  2. 数据(输入,标注)
  3. 损失函数

第二种训练方式

  1. 定义device=torch.device('cpu') 或者 torch.device('cuda') 同时可以使用torch.device('cuda:?')来指定使用第几个显卡
  2. 使用.to(device)来进行调用

21完整的测试套路

  1. from PIL import Image
  2. import torchvision
  3. import torch
  4. from torch.nn import Module, Sequential, Conv2d, MaxPool2d, Flatten, Linear
  5. image_path = "image/img_2.png"
  6. image = Image.open(image_path)
  7. print(image)
  8. '''
  9. 使用convert的原因:因为png是4个通道,除了RGB通道以外还有一个透明的通道
  10. 所以调用image.convert('RGB')来保留原来的通道,可以更好的适应jpd和png格式
  11. '''
  12. image = image.convert('RGB')
  13. transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)), torchvision.transforms.ToTensor()])
  14. image = transform(image)
  15. print(image.shape)
  16. class Network(Module):
  17. def __init__(self):
  18. super(Network, self).__init__()
  19. self.model = Sequential(
  20. Conv2d(3, 32, 5, 1, 2),
  21. MaxPool2d(2),
  22. Conv2d(32, 32, 5, 1, 2),
  23. MaxPool2d(2),
  24. Conv2d(32, 64, 5, 1, 2),
  25. MaxPool2d(2),
  26. Flatten(),
  27. Linear(64 * 4 * 4, 64),
  28. Linear(64, 10)
  29. )
  30. def forward(self, x):
  31. x = self.model(x)
  32. return x
  33. # 加载cpu训练的模型需要加上map_location=torch.device('cpu')
  34. network = torch.load('network_9.pth', map_location=torch.device('cpu'))
  35. image = torch.reshape(image, (1, 3, 32, 32))
  36. network.eval()
  37. with torch.no_grad():
  38. output = network(image)
  39. print(output)
  40. print(output.argmax(1))

附件:yolov5常见的注意事项和报错

注意1:不要在.yaml中添加任何中文注释,这样会报‘gbk’的错误

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/360141
推荐阅读
相关标签
  

闽ICP备14008679号