【我是土堆 - PyTorch教程】学习随手记(已更新 | 已完结 | 10w字超详细版)

这篇具有很好参考价值的文章主要介绍了【我是土堆 - PyTorch教程】学习随手记(已更新 | 已完结 | 10w字超详细版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. Pytorch环境的配置及安装

如何管理项目环境?

如何看自己电脑cuda版本?

安装Pytorch 

2. Python编辑器的选择、安装及配置

PyCharm 

PyCharm神器

Jupyter(可交互) 

3. Python学习中的两大法宝函数

说明 

实战操作

总结

4. Pycharm及Jupyter使用及对比

如何在PyCharm中新建项目?

Python控制台​编辑

如何在Jupyter中新建项目?

三种运行方式(PyCharm、PyCharm的Python控制台、Jupyter Notebook)的适用场景:

5. PyTorch加载数据初认识

PyTorch 读取数据涉及两个类:Dataset & Dataloader

数据集的几种组织形式

Dataset类 

6. Dataset类代码实战

两种方法读图片

控制台读取&可视化图片

(一)数据格式1 

读数据

(二)数据格式2

7. TensorBoard的使用

SummaryWriter类

安装TensorBoard

add_scalar() 方法的使用

add_image() 的使用

利用numpy.array(),对PIL图片进行转换

8. 图像变换,torchvision中transforms的使用

transforms的结构及用法

结构

一些类

使用

两个问题

1、transforms 该如何使用(python)

2、为什么我们需要 Tensor 数据类型

两种读取图片的方式

9. 常见的Transforms的使用

Compose 的使用

Python中 __call__ 的用法

ToTensor 的使用

ToPILImage 的使用

Normalize 的使用

Resize() 的使用

Compose() 的使用

RandomCrop() 的使用

总结使用方法

10. torchvision 中的数据集使用

CIFAR10数据集

标准数据集如何下载、查看、使用

如何把数据集(多张图片)和 transforms 结合在一起

11. DataLoader 的使用

参数介绍 

示例 

batch_size

drop_last

shuffle

12. 神经网络的基本骨架 - nn.Module 的使用

Containers

debug看流程 

13. 土堆说卷积操作

stride(步进)

要求输入的维度 & reshape函数

padding(填充)

14. 神经网络 - 卷积层

kernel_size

in_channels & out_channels

CIFAR10数据集实例 

卷积层 vgg16

卷积前后维度计算公式

15. 神经网络 - 最大池化的使用

参数 

ceil_mode参数

输入输出维度计算公式

代码实现 

为什么要进行最大池化?最大池化的作用是什么?

用数据集 CIFAR10 实现最大池化

16. 神经网络 - 非线性激活 

最常见:RELU   

代码举例:RELU

Sigmoid

代码举例:Sigmoid(数据集CIFAR10)

关于inplace

17. 神经网络 - 线性层及其他层介绍 

批标准化层(不难,自学)   

Recurrent Layers(特定网络中使用,自学)

Transformer Layers(特定网络中使用,自学)

Linear Layers(本节讲解)

代码实例

flatten 摊平

Dropout Layers(不难,自学)

Sparse Layers(特定网络中使用,自学)

Embedding

Distance Functions

Loss Functions

pytorch提供的一些网络模型

18. 神经网络 - 搭建小实战和 Sequential 的使用

对 CIFAR10 进行分类的简单神经网络

直接搭建,实现上图 CIFAR10 model 的代码

实际过程中如何检查网络的正确性?

若不知道flatten之后的维度是多少该怎么办?

用 Sequential 搭建,实现上图 CIFAR10 model 的代码

引入 tensorboard 可视化模型结构

19. 损失函数与反向传播

L1LOSS

代码

MSELOSS(均方误差)

代码

CROSSENTROPYLOSS(交叉熵)

如何在之前写的神经网络中用到 Loss Function(损失函数)

backward  反向传播

20. 优化器

如何使用优化器?

算法

SGD为例 

完整代码

21. 现有网络模型的使用及修改

数据集 ImageNet

参数及下载 

VGG16 模型

参数 pretrained=True/False 

vgg16 网络架构 

如何利用现有网络去改动它的结构?

添加 

修改 

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

两种方式保存模型

两种方式加载模型

方式1 有陷阱(自己定义网络结构,没有用 vgg16 时)

问题描述 

解决

解决另法:

23. 完整的模型训练套路

model.py 文件代码

train.py 文件代码

如何知道模型是否训练好,或达到需求?

完整代码

与 TensorBoard 结合

保存每一轮训练的模型 

正确率的实现(对分类问题) 

train.py 完整代码

model.train() 和 model.eval()

作用 

回顾案例

24. 利用GPU训练

第一种使用GPU训练的方式

比较CPU/GPU训练时间 

对于CPU

对于GPU

查看GPU信息 

Google Colab

如何使用GPU?

查看GPU配置 

第二种使用GPU训练的方式(更常用)

25. 完整的模型验证(测试、demo)套路

示例 

test.py(把训练模型运用到实际环境中)完整代码

示例二

26. 看看开源项目

README.md 

train.py

训练参数设置


1. Pytorch环境的配置及安装

首先需要下载Anaconda(包含了大量的package/工具包)

深度学习离不开显卡(TensorFlow/Pytorch支持英伟达的显卡),起到训练加速的作用

  • 显卡的配置:驱动 + CUDA Toolkit(CUDA工具包)
  • CUDA Toolkit 会跟随Pytorch一键安装
  • 主要检查显卡的驱动是否正确安装:任务管理器—性能—GPU,若能看到GPU的型号,即意味着显卡的驱动已经正确安装

如何管理项目环境?

一个package相当于一个工具包,把环境理解成一个房子,初始环境base,不同环境可以有不同版本的工具包,切换环境即可

conda指令创建pytorch环境如果开了代理服务器,务必关闭!!!

以下命令在 Anaconda Prompt 中输入:

conda create -n pytorch python=3.8   # -n是name的意思
conda activate pytorch  # 激活环境

notimplementederror: module [vgg16] is missing the required

左边括号里的环境由base变成了pytorch(环境名称)

看一下环境中的工具包:

pip list

 notimplementederror: module [vgg16] is missing the required

并没有pytorch,接下来:安装pytorch

网址:PyTorch

如何看自己电脑cuda版本?

  • 任务管理器—性能—GPU
    notimplementederror: module [vgg16] is missing the required
  • 或:设备管理器—显示适配器
    notimplementederror: module [vgg16] is missing the required
    独立显卡

在cmd里输入:

nvidia-smi

notimplementederror: module [vgg16] is missing the required

安装Pytorch 

找到自己适合的版本,复制命令: 

  • Stable 稳定版:1.1版本以后加入了TensorBoard,可以看到训练过程中的数据,如损失函数的变化
  • Package:一般Windows下推荐使用Conda,Linux下推荐使用pip
  • Compute Platform:
    • 无英伟达显卡或只有集显:CPU
    • 有英伟达显卡:30系列显卡不支持11.1以下的CUDA

notimplementederror: module [vgg16] is missing the required

在刚刚激活了pytorch环境的窗口里输入: 

conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch

 等待安装成功之后,再

pip list

notimplementederror: module [vgg16] is missing the required

可以看到已经安装成功

检验安装是否成功:先输入

python

再输入

import torch

若没有报错则安装成功,如图

notimplementederror: module [vgg16] is missing the required

检验pytorch是否可以用GPU:

 torch.cuda.is_available()

返回True即可


2. Python编辑器的选择、安装及配置

PyCharm 

PyCharm: the Python IDE for Professional Developers by JetBrains

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

在Python工作台/控制台验证:

notimplementederror: module [vgg16] is missing the required

 先输入

import torch

再输入

 torch.cuda.is_available()

返回True即可,如上图

PyCharm神器

notimplementederror: module [vgg16] is missing the required

在左边输入,右边有变量的属性,很直观 

---------------------------------------------------------------------------------------------------------------------------------

Jupyter(可交互) 

Project Jupyter | Home

建议直接安装Anaconda,Jupyter会随着Anaconda一起安装

Jupyter 默认安装在 base 环境中,但是base环境中没有安装 Pytorch,导致Jupyter无法使用Pytorch,两种解决方式:

  • 在base环境中再安装一遍Pytorch
  • 在Pytorch环境中安装Jupyter(选择这种)

打开Anaconda Prompt是base环境,从base环境启用Jupyter需要一个package:ipykernel,如图:

输入

conda list

notimplementederror: module [vgg16] is missing the required

可以看到要用到的 package是 ipykernel

进入Pytorch环境中:

conda activate pytorch

再输入

conda list

notimplementederror: module [vgg16] is missing the required

可以发现没有 ipykernel ,安装这个 package(同样需要关闭代理服务器!!!

conda install nb_conda

等到done之后,再输入

jupyter notebook

 等到页面跳转到浏览器,New — Python[conda env:pytorch]*

notimplementederror: module [vgg16] is missing the required

 同样,先输入

import torch

再输入

 torch.cuda.is_available()

返回True即可,如下图

notimplementederror: module [vgg16] is missing the required

意外插曲:

网页可以正常跳转,但是会有这个窗口弹出:

notimplementederror: module [vgg16] is missing the required

解决方式:按照地址删去 pythoncom38.dll 文件即可(可能需要删多个 pythoncom38.dll 文件)


3. Python学习中的两大法宝函数

说明 

package(名称为 pytorch)就像一个工具箱,有不同的分隔区,分隔区里有不同的工具

探索工具箱,两个道具:

  • dir() 函数:能让我们知道工具箱以及工具箱中的分隔区有什么东西(打开,看见)
  • help() 函数:能让我们知道每个工具是如何使用的,工具的使用方法(说明书)

例:

notimplementederror: module [vgg16] is missing the required

dir(pytorch),就能看到输出1、2、3、4等分隔区;想继续探索第3个分隔区里有什么的话,dir(pytorch.3),输出会是a,b,c(3号分隔区里有a,b,c等工具),如何使用?

help(pytorch.3.a)  输出:将此扳手放在特定地方,然后拧动

---------------------------------------------------------------------------------------------------------------------------------

实战操作

打开PyCharm,输入

dir(torch)

notimplementederror: module [vgg16] is missing the required

 可以看到输出了大量的分隔区(或理解为更小的工具箱),ctrl+F找到cuda

notimplementederror: module [vgg16] is missing the required

看cuda分隔区里有什么,输入

dir(torch.cuda)

可以看到又输出了大量的分隔区

notimplementederror: module [vgg16] is missing the required

继续输入:

dir(torch.cuda.is_available)

可以看到输出的前后都带有双下划线__,这是一种规范,说明这个变量不容许篡改,即它不再是一个分隔区,而是一个确确实实的函数(相当于工具,可以用help()函数

notimplementederror: module [vgg16] is missing the required

 对工具使用 help():

help(torch.cuda.is_available)

注意 is_available 不带括号

notimplementederror: module [vgg16] is missing the required

 返回一个布尔值(True或False),表明cuda是否可用

总结

  • dir() 函数:打开package
  • help() 函数:官方的解释文档,看函数怎么用

    4. Pycharm及Jupyter使用及对比

如何在PyCharm中新建项目?

(1)新建文件夹 Learn_torch(右键:New Folder)
notimplementederror: module [vgg16] is missing the required
notimplementederror: module [vgg16] is missing the required

File —> Settings

notimplementederror: module [vgg16] is missing the required

(2)新建 Python文件,命名 first_demo
notimplementederror: module [vgg16] is missing the required
 

(3)运行程序:为该Python文件设置相应的Python解释器后,点击绿色的运行符号即可
notimplementederror: module [vgg16] is missing the required

或直接右键:
notimplementederror: module [vgg16] is missing the required
 

Python控制台

Python控制台(Python Console)是以每一行作为一个块进行执行 

---------------------------------------------------------------------------------------------------------------------------------

如何在Jupyter中新建项目?

 首先在开始菜单打开anaconda的命令行,进入pytorch的conda环境,再打开Jupyter

notimplementederror: module [vgg16] is missing the required

 notimplementederror: module [vgg16] is missing the required

以每一个为一个运行整体

---------------------------------------------------------------------------------------------------------------------------------

三种运行方式(PyCharm、PyCharm的Python控制台、Jupyter Notebook)的适用场景:

代码是以块为一个整体运行的话,Python文件的块是所有行的代码,即在PyCharm运行时出现错误时,修改后要从头开始运行

PyCharm的Python控制台是一行一行代码运行的,即以每一行为一个块来运行的(也可以以任意行为块运行,按Shift+回车,输入下一行代码,再按回车运行)

  • 优点:Python控制台可以看到每个变量的属性
  • 缺点:出现错误后代码的可阅读性大大降低
  • 一般调试时使用

Jupyter以任意行为块运行

Python控制台和Jupyter的好处是:某一块发生错误时,修改这一块时不会影响前面已经运行的块

PyCharm 从头开始运行 通用,传播方便,适用于大型项目 需要从头运行
PyCharm的Python控制台 一行一行运行(也可以以任意行) 可以显示每个变量的属性,一般调试时使用 出错时会破坏整体阅读性,不利于代码阅读及修改
Jupyter Notebook 以任意行为块运行 代码阅读性较高,利于代码的阅读及修改 环境需要配置

5. PyTorch加载数据初认识

对于神经网络训练,要从数据海洋里找到有用的数据

PyTorch 读取数据涉及两个类:Dataset & Dataloader

Dataset:提供一种方式,获取其中需要的数据及其对应的真实的 label 值,并完成编号。主要实现以下两个功能:

  • 如何获取每一个数据及其label
  • 告诉我们总共有多少的数据

Dataloader:打包(batch_size),为后面的神经网络提供不同的数据形式

---------------------------------------------------------------------------------------------------------------------------------

数据集的几种组织形式

数据集 hymenoptera_data(识别蚂蚁和蜜蜂的数据集,二分类)

notimplementederror: module [vgg16] is missing the required

  1. train 里有两个文件夹:ants 和 bees,其中分别都是一些蚂蚁和蜜蜂的图片
  2. train_images是一个文件夹,train_labels是另一个文件夹,如OCR数据集
  3. label直接为图片的名称

---------------------------------------------------------------------------------------------------------------------------------

Dataset类 

from torch.utils.data import Dataset

查看Dataset类的介绍:

help(Dataset)

或者:

Dataset??

Dataset 是一个抽象类,所有数据集都需要继承这个类,所有子类都需要重写 __getitem__ 的方法,这个方法主要是获取每个数据集及其对应 label,还可以重写长度类 __len__

def __getitem__(self, index):
    raise NotImplementedError

def __add__(self, other):
    return ConcatDataset([self, other])

6. Dataset类代码实战

两种方法读图片

# 法1
from PIL import Image
img_path = "xxx"
img = Image.open(img_path)
img.show()

# 法2:利用opencv读取图片,获得numpy型图片数据
import cv2
cv_img=cv2.imread(img_path)

安装opencv: 

在 PyCharm的 Terminal 里输入(关闭代理服务器!!!

pip install opencv-python

import cv2

---------------------------------------------------------------------------------------------------------------------------------

控制台读取&可视化图片

(一)数据格式1 

notimplementederror: module [vgg16] is missing the required

  • 绝对路径:E:\学完了学完了\PyTorch\土堆-Pytorch\Learn_torch\dataset\train\ants
  • 相对路径:dataset/train/ants 

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

注意,路径引号前加 r 可以防止转义,或使用双斜杠  

在Python控制台读取数据,可以看到图片的属性:

from PIL import Image
img_path = r"E:\学完了学完了\PyTorch\土堆-Pytorch\Learn_torch\dataset\train\ants\0013035.jpg"
img = Image.open(img_path)

 notimplementederror: module [vgg16] is missing the required

输入 img.size 就可以返回属性的数值

notimplementederror: module [vgg16] is missing the required

可视化图片输入:img.show()

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

读数据

想要获取图片地址(通过索引),需要os库

import os
dir_path = "dataset/train/ants"
img_path_list = os.listdir(dir_path)  # 将文件夹下的东西变成一个列表

notimplementederror: module [vgg16] is missing the required    

import os 
root_dir = "dataset/train"
label_dir = "ants"

path = os.path.join(root_dir, label_dir)  # 把两个路径拼接在一起

notimplementederror: module [vgg16] is missing the required

完整代码: 

from torch.utils.data import Dataset
from PIL import Image   #读取图片
import os   #想要获得所有图片的地址,需要导入os(系统库)

#创建一个class,继承Dataset类
class MyData(Dataset):
  def __init__(self,root_dir,label_dir):   #创建初始化类,即根据这个类去创建一个实例时需要运行的函数
    #通过索引获取图片的地址,需要先创建图片地址的list
    #self可以把其指定的变量给后面的函数使用,相当于为整个class提供全局变量
    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):   #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)


#用类创建实例
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)

img, label = ants_dataset[0]
img.show()   # 可视化第一张图片

#将ants(124张)和bees(121张)两个数据集进行拼接
train_dataset=ants_dataset+bees_dataset

(二)数据格式2

当label比较复杂,存储数据比较多时,不可能以文件夹命名的方式,而是以每张图片对应一个txt文件,txt里存储label信息的方式

notimplementederror: module [vgg16] is missing the required

rename_dataset.py代码如下: 

notimplementederror: module [vgg16] is missing the required

import os

root_dir=r"E:\学完了学完了\PyTorch\土堆-Pytorch\Learn_torch\dataset\train"
# 把原来的ants重命名为ants_image
target_dir="ants_image"
img_path=os.listdir(os.path.join(root_dir,target_dir))
label=target_dir.split('_')[0]   # ants
out_dir="ants_label"

for i in img_path:
    file_name=i.split('.jpg')[0]
    with open(os.path.join(root_dir,out_dir,"{}.txt".format(file_name)),'w') as f:
        f.write(label)

运行效果如图: 

notimplementederror: module [vgg16] is missing the required


7. TensorBoard的使用

  • 安装
  • add_scalar() 的使用(常用来绘制 train/val loss)
  • add_image() 的使用(常用来观察训练结果)

transforms 在 Dataset 类中很常用,对图像进行变换,如图像要统一到某一个尺寸,或图像中的每一个数据进行类的转换

学 TensorBoard 探究:

  • 训练过程中loss是如何变化的
  • 模型在不同阶段的输出

---------------------------------------------------------------------------------------------------------------------------------

SummaryWriter类

from torch.utils.tensorboard import SummaryWriter

查看一个类如何使用:在PyCharm中,按住Ctrl键,把鼠标移到类上

是一个直接向 log_dir 文件夹写入的事件文件,可以被 TensorBoard 进行解析

初始化函数:

def __init__(self, log_dir=None):

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

# 实例化SummaryWriter类
writer = SummaryWriter("logs")   # 把对应的事件文件存储到logs文件夹下

主要用到两个方法:

writer.add_image()
writer.add_scalar()

writer.close()

---------------------------------------------------------------------------------------------------------------------------------

安装TensorBoard

在 Anaconda 命令行中激活 pytorch 环境,或直接在 PyCharm 的 Terminal 的 pytorch 环境中安装

输入:

pip install tensorboard

即可安装成功

---------------------------------------------------------------------------------------------------------------------------------

Ctrl + /    注释

add_scalar() 方法的使用

def add_scalar(
        self,
        tag,
        scalar_value,
        global_step=None,
        walltime=None,
        new_style=False,
        double_precision=False,
    ):

添加一个标量数据到 Summary 当中,需要参数

  • tag:Data指定方式,类似于图表的title
  • scalar_value:需要保存的数值(y轴)
  • global_step:训练到多少步(x轴)

例:y=x

from torch.utils.tensorboard import SummaryWriter   #导入SummaryWriter类

#创建实例
writer=SummaryWriter("logs")   #把对应的事件文件存储到logs文件夹下

#两个方法
# writer.add_image()
# y=x
for i in range(100):
    writer.add_scalar("y=x",i,i)

writer.close()

运行后多了一个logs文件夹,下面是TensorBoard的一些事件文件,如图:

notimplementederror: module [vgg16] is missing the required

如何打开事件文件?

在 Terminal 里输入:

tensorboard --logdir=logs  # logdir=事件文件所在文件夹名

结果如图:

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

为了防止和别人冲突(一台服务器上有好几个人训练,默认打开的都是6006端口),也可以指定端口,命令如下:

​tensorboard --logdir=logs --port=6007

例:y=2x

from torch.utils.tensorboard import SummaryWriter   #导入SummaryWriter类

#创建实例
writer=SummaryWriter("logs")   #把对应的事件文件存储到logs文件夹下

#两个方法
# writer.add_image()
# y=2x
for i in range(100):
    writer.add_scalar("y=2x",2*i,i)  # 标题、y轴、x轴

writer.close()

 notimplementederror: module [vgg16] is missing the required

title 和 y 不一致的情况:

 notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required
过程中会发生拟合

每向 writer 中写入新的事件,也记录了上一个事件

如何解决?

把logs文件夹下的所有文件删掉,程序删掉,重新开始

或:重新写一个子文件,即创建新的 SummaryWriter("新文件夹")

删掉logs下的文件,重新运行代码,在 Terminal 里按 Ctrl+C ,再输入命令:

​tensorboard --logdir=logs --port=6007

就可以出现名字为y=2x,但实际纵坐标是y=3x数值的图像

以上即是显示 train_loss 的一个方式

---------------------------------------------------------------------------------------------------------------------------------

add_image() 的使用

def add_image(self, tag, img_tensor, global_step=None):
  • tag:对应图像的title
  • img_tensor:图像的数据类型,只能是torch.Tensor、numpy.array、string/blobname
  • global_step:训练步骤,int 类型

notimplementederror: module [vgg16] is missing the required notimplementederror: module [vgg16] is missing the required

例子:

notimplementederror: module [vgg16] is missing the required

在Python控制台输入:notimplementederror: module [vgg16] is missing the required

# 打开控制台,其位置就是项目文件夹所在的位置
# 故只需复制相对地址

image_path = "data/train/ants_image/0013035.jpg"

from PIL import Image
img = Image.open(image_path)
print(type(img))

---------------------------------------------------------------------------------------------------------------------------------

利用numpy.array(),对PIL图片进行转换

在Python控制台,把PIL类型的img变量转换为numpy类型(add_image() 函数所需要的图像的数据类型),重新赋值给img_array:

import numpy as np
img_array=np.array(img)
print(type(img_array))   # numpy.ndarray

从PIL到numpy,需要在add_image()中指定shape中每一个数字/维表示的含义 

step1:蚂蚁为例 

from torch.utils.tensorboard import SummaryWriter   #导入SummaryWriter类
import numpy as np
from PIL import Image

#创建实例
writer=SummaryWriter("logs")   #把对应的事件文件存储到logs文件夹下
image_path="data/train/ants_image/0013035.jpg"
img_PIL=Image.open(image_path)
img_array=np.array(img_PIL)
print(type(img_array))
print(img_array.shape)   #(512,768,3)  即(H,W,C)(高度,宽度,通道)

writer.add_image("test",img_array,1, dataformats='HWC')  # 第1步

writer.close()

结果:

notimplementederror: module [vgg16] is missing the required

step2:蜜蜂为例 

from torch.utils.tensorboard import SummaryWriter   #导入SummaryWriter类
import numpy as np
from PIL import Image

#创建实例
writer=SummaryWriter("logs")   #把对应的事件文件存储到logs文件夹下
image_path="data/train/bees_image/16838648_415acd9e3f.jpg"
img_PIL=Image.open(image_path)
img_array=np.array(img_PIL)
print(type(img_array))
print(img_array.shape)   #(512,768,3)  即(H,W,C)(高度,宽度,通道)

writer.add_image("test",img_array,2, dataformats='HWC')   # 第2步

writer.close()

结果:

notimplementederror: module [vgg16] is missing the required

在一个title下,通过滑块显示每一步的图形,可以直观地观察训练中给model提供了哪些数据,或者想对model进行测试时,可以看到每个阶段的输出结果

如果想要单独显示,重命名一下title即可,即 writer.add_image() 的第一个字符串类型的参数


8. 图像变换,torchvision中transforms的使用

对图片进行一些变换

transforms的结构及用法

from torchvision import transforms

结构

按住Ctrl,看 transforms.py文件(工具箱),它定义了很多 class文件(工具)

notimplementederror: module [vgg16] is missing the required

搜索快捷键:

File—> Settings—> Keymap—> 搜索 structure(快捷键 Alt+7)

一些类

  • Compose类:结合不同的transforms
    notimplementederror: module [vgg16] is missing the required
     图片先经过中心裁剪,再变成Tensor返回
  • ToTensor类:把一个PIL的Image或者numpy数据类型的图片转换成 tensor 的数据类型
  • ToPILImage类:把一个图片转换成PIL Image
  • Normalize类:归一化
  • Resize类:尺寸变换
  • CenterCrop类:中心裁剪

使用

  • transforms.py   工具箱
  • totensor / resize等类   工具

拿一些特定格式的图片,经过工具(class文件)后,就会输出我们想要的图片变换的结果

---------------------------------------------------------------------------------------------------------------------------------

两个问题

python的用法 ——> tensor数据类型
通过 transforms.ToTensor去解决两个问题

  1. Transforms该如何使用
  2. Tensor数据类型与其他图片数据类型有什么区别?为什么需要Tensor数据类型 
from PIL import Image
from torchvision import transforms

# 绝对路径 C:\Users\11842\Desktop\Learn_torch\data\train\ants_image\0013035.jpg
# 相对路径 data/train/ants_image/0013035.jpg
img_path="data/train/ants_image/0013035.jpg"   #用相对路径,绝对路径里的\在Windows系统下会被当做转义符
# img_path_abs="C:\Users\11842\Desktop\Learn_torch\data\train\ants_image\0013035.jpg",双引号前加r表示转义

img = Image.open(img_path)   #Image是Python中内置的图片的库
print(img)  # PIL类型

1、transforms 该如何使用(python)

从transforms中选择一个class,对它进行创建,对创建的对象传入图片,即可返回出结果 

ToTensor将一个 PIL Image 或 numpy.ndarray 转换为 tensor的数据类型 

notimplementederror: module [vgg16] is missing the required

# 1、Transforms该如何使用
tensor_trans = transforms.ToTensor()  #从工具箱transforms里取出ToTensor类,返回tensor_trans对象
tensor_img=tensor_trans(img)   #创建出tensor_trans后,传入其需要的参数,即可返回结果
print(tensor_img)

Ctrl+P可以提示函数里需要填什么参数 

notimplementederror: module [vgg16] is missing the required

2、为什么我们需要 Tensor 数据类型

在Python Console输入:

from PIL import Image
from torchvision import transforms

img_path= "data/train/ants_image/0013035.jpg"  
img = Image.open(img_path)   

tensor_trans = transforms.ToTensor() 
tensor_img = tensor_trans(img)  

notimplementederror: module [vgg16] is missing the required

打开img,即用Python内置的函数读取的图片,具有的参数有:

notimplementederror: module [vgg16] is missing the required

再打开tensor_img,看一下它有哪些参数:

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

Tensor 数据类型包装了反向神经网络所需要的一些理论基础的参数,如:_backward_hooks、_grad等(先转换成Tensor数据类型,再训练)

---------------------------------------------------------------------------------------------------------------------------------

两种读取图片的方式

  • PIL Image
    from PIL import Image
    img_path = "xxx"
    img = Image.open(img_path)
    img.show()
  • numpy.ndarray(通过opencv)
    import cv2
    cv_img=cv2.imread(img_path)

上节课以 numpy.array 类型为例,这节课使用 torch.Tensor 类型:

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

# python的用法 ——> tensor数据类型
# 通过 transforms.ToTensor去解决两个问题
# 1、Transforms该如何使用
# 2、Tensor数据类型与其他图片数据类型有什么区别?为什么需要Tensor数据类型

# 绝对路径 C:\Users\11842\Desktop\Learn_torch\data\train\ants_image\0013035.jpg
# 相对路径 data/train/ants_image/0013035.jpg
img_path="data/train/ants_image/0013035.jpg"   #用相对路径,绝对路径里的\在Windows系统下会被当做转义符
# img_path_abs="C:\Users\11842\Desktop\Learn_torch\data\train\ants_image\0013035.jpg",双引号前加r表示转义
img = Image.open(img_path)   #Image是Python中内置的图片的库
#print(img)

writer = SummaryWriter("logs")

# 1、Transforms该如何使用
tensor_trans = transforms.ToTensor()  #从工具箱transforms里取出ToTensor类,返回tensor_trans对象
tensor_img = tensor_trans(img)   #创建出tensor_trans后,传入其需要的参数,即可返回结果
#print(tensor_img)

writer.add_image("Tensor_img",tensor_img)  # .add_image(tag, img_tensor, global_step)
# tag即名称
# img_tensor的类型为torch.Tensor/numpy.array/string/blobname
# global_step为int类型

writer.close()

运行后,在 Terminal 里输入:

tensorboard --logdir=logs

notimplementederror: module [vgg16] is missing the required

进入网址后可以看到图片:

notimplementederror: module [vgg16] is missing the required


9. 常见的Transforms的使用

  • 输入
  • 输出
  • 作用

图片有不同的格式,打开方式也不同

图片格式 打开方式
PIL Image.open()   ——Python自带的图片打开方式
tensor ToTensor()
narrays cv.imread()   ——Opencv

---------------------------------------------------------------------------------------------------------------------------------

Compose 的使用

把不同的 transforms 结合在一起,后面接一个数组,里面是不同的transforms

Example:图片首先要经过中心裁剪,再转换成Tensor数据类型
        >>> transforms.Compose([
        >>>     transforms.CenterCrop(10),
        >>>     transforms.PILToTensor(),
        >>>     transforms.ConvertImageDtype(torch.float),
        >>> ])

---------------------------------------------------------------------------------------------------------------------------------

Python中 __call__ 的用法

内置函数 __call__ ,不用.的方式调用方法,可以直接拿对象名,加上需要的参数,即可调用方法

按 Ctrl+p,会提示需要什么参数

class Person:
    def __call__(self, name):   #下划线__表示为内置函数
        print("__call__"+"Hello "+name)

    def hello(self,name):
        print("hello"+name)

person = Person()
person("zhangsan")
person.hello("lisi")

输出结果如下:

__call__Hello zhangsan
hellolisi

---------------------------------------------------------------------------------------------------------------------------------

ToTensor 的使用

把 PIL Image 或 numpy.ndarray 类型转换为 tensor 类型(TensorBoard 必须是 tensor 的数据类型)

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

writer = SummaryWriter("logs")
img=Image.open("images/people.jpg")
print(img)  #可以看到类型是PIL

#ToTensor的使用
trans_totensor = transforms.ToTensor()  #将类型转换为tensor
img_tensor = trans_totensor(img)   #img变为tensor类型后,就可以放入TensorBoard当中
writer.add_image("ToTensor",img_tensor)
writer.close()

(运行前要先把之前的logs进行删除)运行后,在 Terminal 里输入:

tensorboard --logdir=logs

notimplementederror: module [vgg16] is missing the required

进入网址后可以看到图片:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

ToPILImage 的使用

把 tensor 数据类型或 ndarray 类型转换成 PIL Image

---------------------------------------------------------------------------------------------------------------------------------

Normalize 的使用

用平均值/标准差归一化 tensor 类型的 image(输入)

图片RGB三个信道,将每个信道中的输入进行归一化

output[channel] = (input[channel] - mean[channel]) / std[channel]

设置 mean 和 std 都为0.5,则 output= 2*input -1。如果 input 图片像素值为0~1范围内,那么结果就是 -1~1之间

#Normalize的使用
print(img_tensor[0][0][0])  # 第0层第0行第0列
trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])  # mean,std,因为图片是RGB三信道,故传入三个数
img_norm = trans_norm(img_tensor)  # 输入的类型要是tensor
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm)

输出结果: 

tensor(0.6549)
tensor(0.3098)

 刷新网页:

 notimplementederror: module [vgg16] is missing the required

加入step值:

#Normalize的使用
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([6,3,2],[9,3,5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm,2)  # 第二步

writer.close()

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Resize() 的使用

输入:PIL Image      将输入转变到给定尺寸

  • 序列:(h,w)高度,宽度
  • 一个整数:不改变高和宽的比例,只单纯改变最小边和最长边之间的大小关系。之前图里最小的边将会匹配这个数(等比缩放)

PyCharm小技巧设置:忽略大小写,进行提示匹配

  • 一般情况下,你需要输入R,才能提示出Resize
  • 我们想设置,即便你输入的是r,也能提示出Resize,也就是忽略了大小写进行匹配提示

File—> Settings—> 搜索case—> Editor-General-Code Completion-去掉Match case前的√

—>Apply—>OK

返回值还是 PIL Image

#Resize的使用
print(img.size)  # 输入是PIL.Image

trans_resize = transforms.Resize((512,512))
#img:PIL --> resize --> img_resize:PIL
img_resize = trans_resize(img)  #输出还是PIL Image

#img_resize:PIL --> totensor --> img_resize:tensor(同名,覆盖)
img_resize = trans_totensor(img_resize)

writer.add_image("Resize",img_resize,0)
print(img_resize)

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Compose() 的使用

Compose() 中的参数需要是一个列表,Python中列表的表示形式为[数据1,数据2,...]

在Compose中,数据需要是transforms类型,所以得到Compose([transforms参数1,transforms参数2,...])

#Compose的使用(将输出类型从PIL变为tensor类型,第二种方法)

trans_resize_2 = transforms.Resize(512)  # 将图片短边缩放至512,长宽比保持不变

# PIL --> resize --> PIL --> totensor --> tensor
#compose()就是把两个参数功能整合,第一个参数是改变图像大小,第二个参数是转换类型,前者的输出类型与后者的输入类型必须匹配

trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
img_resize_2 = trans_compose(img)   # 输入需要是PIL Image
writer.add_image("Resize",img_resize_2,1)
notimplementederror: module [vgg16] is missing the required
长方形

---------------------------------------------------------------------------------------------------------------------------------

RandomCrop() 的使用

随机裁剪,输入PIL Image

参数size:

  • sequence:(h,w) 高,宽
  • int:裁剪一个该整数×该整数的图像

(1)以 int 为例: 

#RandomCrop()的使用
trans_random = transforms.RandomCrop(512)
trans_compose_2 = transforms.Compose([trans_random,trans_totensor])
for i in range(10):  #裁剪10个
    img_crop = trans_compose_2(img)  # 输入需要是PIL Image
    writer.add_image("RandomCrop",img_crop,i)

notimplementederror: module [vgg16] is missing the required

(2)以 sequence 为例:

#RandomCrop()的使用
trans_random = transforms.RandomCrop((500,1000))
trans_compose_2 = transforms.Compose([trans_random,trans_totensor])
for i in range(10):  #裁剪10个
    img_crop = trans_compose_2(img)
    writer.add_image("RandomCropHW",img_crop,i)

 notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

总结使用方法

  • 关注输入和输出类型
  • 多看官方文档
  • 关注方法需要什么参数:参数如果设置了默认值,保留默认值即可,没有默认值的需要指定(看一下要求传入什么类型的参数)
  • 不知道变量的输出类型可以
    • 直接print该变量
    • print(type()),看结果里显示什么类型
    • 断点调试 dubug
  • 最后要 totensor,在 tensorboard 看一下结果(tensorboard需要tensor数据类型进行显示)

    10. torchvision 中的数据集使用

  • 如何把数据集(多张图片)和 transforms 结合在一起
  • 标准数据集如何下载、查看、使用
notimplementederror: module [vgg16] is missing the required
Pytorch官网

 torchvision — Torchvision 0.11.0 documentation

(1)torchvision.datasets

如:COCO 目标检测、语义分割;MNIST 手写文字;CIFAR 物体识别

(2)torchvision.io

 输入输出模块,不常用

(3)torchvision.models

提供一些比较常见的神经网络,有的已经预训练好,如分类、语义分割、目标检测、视频分类

(4)torchvision.ops

torchvision提供的一些比较少见的特殊的操作,不常用

(5)torchvision.transforms

(6)torchvision.utils

提供一些常用的小工具,如TensorBoard

---------------------------------------------------------------------------------------------------------------------------------

本节主要讲解torchvision.datasets,以及它如何跟transforms联合使用 

CIFAR10数据集

notimplementederror: module [vgg16] is missing the required
train参数默认为True

CIFAR10 数据集包含了6万张32×32像素的彩色图片,图片有10个类别,每个类别有6千张图像,其中有5万张图像为训练图片,1万张为测试图片

notimplementederror: module [vgg16] is missing the required

标准数据集如何下载、查看、使用

#如何使用torchvision提供的标准数据集
import torchvision

train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True) #root使用相对路径,会在该.py所在位置创建一个叫dataset的文件夹,同时把数据保存进去
test_set=torchvision.datasets.CIFAR10(root="./dataset",train=False,download=True)

print(test_set[0])  # 查看测试集中的第一个数据,是一个元组:(img, target)
print(test_set.classes)  # 列表

img,target = test_set[0]
print(img)
print(target)  # 3
print(test_set.classes[target])  # cat
img.show()

数据集下载过慢时:

获得下载链接后,把下载链接放到迅雷中,会首先下载压缩文件tar.gz,之后会对该压缩文件进行解压,里面会有相应的数据集

采用迅雷下载完毕后,在PyCharm里新建directory,名字也叫dataset,再将下载好的压缩包复制进去,download依然为True,运行后,会自动解压该数据

没有显示下载地址时:

按住Ctrl键,查看数据集的源代码,若其中有 url地址,可直接复制到迅雷中进行下载

-------------------------------------------------------------------------------------------------------------------------------- 

如何把数据集(多张图片)和 transforms 结合在一起

CIFAR10数据集原始图片是PIL Image,如果要给pytorch使用,需要转为tensor数据类型(转成tensor后,就可以用tensorboard了)

transforms 更多地是用在 datasets 里 transform 的选项中

import torchvision
from torch.utils.tensorboard import SummaryWriter

#把dataset_transform运用到数据集中的每一张图片,都转为tensor数据类型
dataset_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])

train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=dataset_transform,download=True) #root使用相对路径,会在该.py所在位置创建一个叫dataset的文件夹,同时把数据保存进去
test_set=torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=dataset_transform,download=True)

# print(test_set[0])

writer = SummaryWriter("p10")
#显示测试数据集中的前10张图片
for i in range(10):
    img,target = test_set[i]
    writer.add_image("test_set",img,i)  # img已经转成了tensor类型

writer.close()

运行后在 terminal 里输入

tensorboard --logdir="p10"

notimplementederror: module [vgg16] is missing the required


11. DataLoader 的使用

  • dataset:告诉程序中数据集的位置,数据集中索引,数据集中有多少数据(想象成一叠扑克牌)
  • dataloader:将数据加载到神经网络中,每次从dataset中取数据,通过dataloader中的参数可以设置如何取数据(想象成抓的一组牌)

torch.utils.data — PyTorch 1.10 documentation

参数介绍 

参数如下(大部分有默认值,实际中只需要设置少量的参数即可):

  • dataset:只有dataset没有默认值,只需要将之前自定义的dataset实例化,再放到dataloader中即可 

notimplementederror: module [vgg16] is missing the required

  • batch_size:每次抓牌抓几张
  • shuffle:打乱与否,值为True的话两次打牌时牌的顺序是不一样。默认为False,但一般用True
  • num_workers:加载数据时采用单个进程还是多个进程,多进程的话速度相对较快,默认为0(主进程加载)。Windows系统下该值>0会有问题(报错提示:BrokenPipeError)
  • drop_last:100张牌每次取3张,最后会余下1张,这时剩下的这张牌是舍去还是不舍去。值为True代表舍去这张牌、不取出,False代表要取出该张牌

---------------------------------------------------------------------------------------------------------------------------------

示例 

# 测试数据集中第一张图片及target
img,target = test_data[0]
print(img.shape)
print(target)

输出结果:

torch.Size([3, 32, 32])   #三通道,32×32大小
3   #类别为3

dataset 

  • __getitem()__:return img,target

dataloader(batch_size=4):从dataset中取4个数据

  • img0,target0 = dataset[0]
  • img1,target1 = dataset[1]
  • img2,target2 = dataset[2]
  • img3,target3 = dataset[3]

把 img 0-3 进行打包,记为imgs;target 0-3 进行打包,记为targets;作为dataloader中的返回

for data in test_loader:
    imgs,targets = data
    print(imgs.shape)
    print(targets)

输出结果:

torch.Size([4, 3, 32, 32])   #4张图片,三通道,32×32
tensor([0, 4, 4, 8])  #4个target进行一个打包

数据是随机取的(断点debug一下,可以看到采样器sampler是随机采样的),所以两次的 target 0 并不一样

---------------------------------------------------------------------------------------------------------------------------------

batch_size

# 用上节课torchvision提供的自定义的数据集
# CIFAR10原本是PIL Image,需要转换成tensor

import torchvision.datasets
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

# 准备的测试数据集
test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor())

# 加载测试集
test_loader = DataLoader(dataset=test_data,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
#batch_size=4,意味着每次从test_data中取4个数据进行打包

writer = SummaryWriter("dataloader")
step=0
for data in test_loader:
    imgs,targets = data  #imgs是tensor数据类型
    writer.add_images("test_data",imgs,step)
    step=step+1

writer.close()

运行后在 terminal 里输入:

 tensorboard --logdir="dataloader"

运行结果如图,滑动滑块即是每一次取数据时的batch_size张图片:

notimplementederror: module [vgg16] is missing the required

由于 drop_last 设置为 False,所以最后16张图片(没有凑齐64张)显示如下:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

drop_last

若将 drop_last 设置为 True,最后16张图片(step 156)会被舍去,结果如图:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

shuffle

一个 for data in test_loader 循环,就意味着打完一轮牌(抓完一轮数据),在下一轮再进行抓取时,第二次数据是否与第一次数据一样。值为True的话,会重新洗牌(一般都设置为True)

shuffle为False的话两轮取的图片是一样的

在外面再套一层 for epoch in range(2) 的循环

# shuffle为True
for epoch in range(2):
    step=0
    for data in test_loader:
        imgs,targets = data  #imgs是tensor数据类型
        writer.add_images("Epoch:{}".format(epoch),imgs,step)
        step=step+1

结果如下:

可以看出两次 step 155 的图片不一样

notimplementederror: module [vgg16] is missing the required


12. 神经网络的基本骨架 - nn.Module 的使用

Pytorch官网左侧:Python API(相当于package,提供了一些不同的工具)

关于神经网络的工具主要在torch.nn里 

torch.nn — PyTorch 1.10 documentation

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Containers

包含6个模块:

  • Module
  • Sequential
  • ModuleList
  • ModuleDict
  • ParameterList
  • ParameterDict

其中最常用的是 Module 模块(为所有神经网络提供基本骨架)

CLASS torch.nn.Module  #搭建的 Model都必须继承该类

模板: 

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):   #搭建的神经网络 Model继承了 Module类(父类)
    def __init__(self):   #初始化函数
        super(Model, self).__init__()   #必须要这一步,调用父类的初始化函数
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):   #前向传播(为输入和输出中间的处理过程),x为输入
        x = F.relu(self.conv1(x))   #conv为卷积,relu为非线性处理
        return F.relu(self.conv2(x))
  • 前向传播 forward(在所有子类中进行重写)
    notimplementederror: module [vgg16] is missing the required
  • 反向传播 backward

---------------------------------------------------------------------------------------------------------------------------------

 notimplementederror: module [vgg16] is missing the required

Code —> Generate —> Override Methods  可以自动补全代码

notimplementederror: module [vgg16] is missing the required

 例子:

import torch
from torch import nn


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

    # def __init__(self):
    #     super(Tudui, self).__init__()

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

tudui = Tudui()   #拿Tudui模板创建出的神经网络
x = torch.tensor(1.0)  #将1.0这个数转换成tensor类型
output = tudui(x)
print(output)

结果如下:

tensor(2.)

debug看流程 

在下列语句前打断点:

tudui = Tudui()   #整个程序的开始

然后点击蜘蛛,点击 Step into My Code,可以看到代码每一步的执行过程

notimplementederror: module [vgg16] is missing the required


13. 土堆说卷积操作

torch.nn — PyTorch 1.10 documentation

Convolution Layers 

Conv2d — PyTorch 1.10 documentation

torch.nn 和 torch.nn.functional 的区别:前者是后者的封装,更利于使用

点击 torch.nn.functional - Convolution functions - conv2d 

notimplementederror: module [vgg16] is missing the required

stride(步进)

可以是单个数,或元组(sH,sW) — 控制横向步进和纵向步进

notimplementederror: module [vgg16] is missing the required

当 stride = 2 时,横向和纵向都是2,输出是一个2×2的矩阵

--------------------------------------------------------------------------------------------------------------------------------

要求输入的维度 & reshape函数

notimplementederror: module [vgg16] is missing the required

  • input:尺寸要求是batch,几个通道,高,宽(4个参数)
  • weight:尺寸要求是输出,in_channels(groups一般为1),高,宽(4个参数)

使用 torch.reshape 函数,将输入改变为要求输入的维度

实现上图的代码:

import torch
import torch.nn.functional as F

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]])   #将二维矩阵转为tensor数据类型
# 卷积核kernel
kernel = torch.tensor([[1,2,1],
                       [0,1,0],
                       [2,1,0]])

# 尺寸只有高和宽,不符合要求
print(input.shape)  #5×5
print(kernel.shape)  #3×3

# 尺寸变换为四个数字
input = torch.reshape(input,(1,1,5,5))  #通道数为1,batch大小为1
kernel = torch.reshape(kernel,(1,1,3,3))
print(input.shape)
print(kernel.shape)

output = F.conv2d(input,kernel,stride=1)  # .conv2d(input:Tensor, weight:Tensor, stride)
print(output)

结果为:

notimplementederror: module [vgg16] is missing the required

当将步进 stride 改为 2 时:

output2 = F.conv2d(input,kernel,stride=2)
print(output2)

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

padding(填充)

在输入图像左右两边进行填充,决定填充有多大。可以为一个数或一个元组(分别指定高和宽,即纵向和横向每次填充的大小)。默认情况下不进行填充

padding=1:将输入图像左右上下两边都拓展一个像素,空的地方默认为0

notimplementederror: module [vgg16] is missing the required

代码实现: 

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

输出结果如下:可以看出输出尺寸变大 

notimplementederror: module [vgg16] is missing the required


14. 神经网络 - 卷积层

torch.nn — PyTorch 1.10 documentation

Convolution Layers

nn.Conv1d

一维卷积

Applies a 1D convolution over an input signal composed of several input planes.

nn.Conv2d

二维卷积

Applies a 2D convolution over an input signal composed of several input planes.

nn.Conv3d

三维卷积

Applies a 3D convolution over an input signal composed of several input planes.

图像为二维矩阵,所以讲解 nn.Conv2d

Conv2d — PyTorch 1.10 documentation

notimplementederror: module [vgg16] is missing the required

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

# in_channels 输入通道数
# out_channels 输出通道数
# kernel_size 卷积核大小 
#以上参数需要设置

#以下参数提供了默认值
# stride=1 卷积过程中的步进大小
# padding=0 卷积过程中对原始图像进行padding的选项
# dilation=1 每一个卷积核对应位的距离
# groups=1 一般设置为1,很少改动,改动的话为分组卷积
# bias=True 通常为True,对卷积后的结果是否加减一个常数的偏置
# padding_mode='zeros' 选择padding填充的模式
notimplementederror: module [vgg16] is missing the required
dilation 叫空洞卷积

动图: 

conv_arithmetic/README.md at master · vdumoulin/conv_arithmetic · GitHub

notimplementederror: module [vgg16] is missing the required

kernel_size

定义了一个卷积核的大小,若为3则生成一个3×3的卷积核

  • 卷积核的参数是从一些分布中进行采样得到的
  • 实际训练过程中,卷积核中的值会不断进行调整

in_channels & out_channels

  • in_channels:输入图片的channel数(彩色图像 in_channels 值为3)
  • out_channels:输出图片的channel数

in_channels 和 out_channels 都为 1 时,拿一个卷积核在输入图像中进行卷积

out_channels 为 2 时,卷积层会生成两个卷积核(不一定一样),得到两个输出,叠加后作为最后输出

---------------------------------------------------------------------------------------------------------------------------------

CIFAR10数据集实例 

# CIFAR10数据集
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)  # 这里用测试数据集,因为训练数据集太大了
dataloader = DataLoader(dataset,batch_size=64)

# 搭建神经网络Tudui
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 因为是彩色图片,所以in_channels=3
        self.conv1 = Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)   #卷积层conv1
    def forward(self,x):  #输出为x
        x = self.conv1(x)
        return x

tudui = Tudui()  # 初始化网络
# 打印一下网络结构
print(tudui)   #Tudui((conv1): Conv2d(3, 6, kernel_size=(3, 3), stride=(1, 1)))

writer = SummaryWriter("../logs")
step = 0
for data in dataloader:
    imgs,targets = data  #经过ToTensor转换,成为tensor数据类型,可以直接送到网络中
    output = tudui(imgs)
    print(imgs.shape)     #输入大小 torch.Size([64, 3, 32, 32])  batch_size=64,in_channels=3(彩色图像),每张图片是32×32的
    print(output.shape)   #经过卷积后的输出大小 torch.Size([64, 6, 30, 30])  卷积后变成6个channels,但原始图像减小,所以是30×30的
    writer.add_images("input",imgs,step)
    
    # 6个channel无法显示。torch.Size([64, 6, 30, 30]) ——> [xxx,3,30,30] 第一个值不知道为多少时写-1,会根据后面值的大小进行计算
    output = torch.reshape(output,(-1,3,30,30))
    writer.add_images("output",output,step)
    step = step + 1

运行后,在 Terminal 里启动 pytorch 环境:

conda activate pytorch

打开 tensorboard:

tensorboard --logdir=logs

打开网址 http://localhost:6006/:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

卷积层 vgg16

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

卷积前后维度计算公式

notimplementederror: module [vgg16] is missing the required


15. 神经网络 - 最大池化的使用

torch.nn — PyTorch 1.10 documentation

Pooling layers

  • MaxPool:最大池化(下采样)
  • MaxUnpool:上采样
  • AvgPool:平均池化
  • AdaptiveMaxPool2d:自适应最大池化

最常用:MaxPool2d — PyTorch 1.10 documentation

参数 

CLASS torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
# kernel_size 池化核

notimplementederror: module [vgg16] is missing the required

注意,卷积中stride默认为1,而池化中stride默认为kernel_size 

notimplementederror: module [vgg16] is missing the required

--------------------------------------------------------------------------------------------------------------------------------

ceil_mode参数

notimplementederror: module [vgg16] is missing the required

Ceil_mode 默认情况下为 False,对于最大池化一般只需设置 kernel_size 即可 

--------------------------------------------------------------------------------------------------------------------------------

输入输出维度计算公式

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

代码实现 

要求的 input 必须是四维的,参数依次是:batch_size、channel、高、宽 

上述图用代码实现:(以 Ceil_mode = True 为例)

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)  #最大池化无法对long数据类型进行实现,将input变成浮点数的tensor数据类型
input = torch.reshape(input,(-1,1,5,5))  #-1表示torch计算batch_size
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)

运行结果如下:

 notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

为什么要进行最大池化?最大池化的作用是什么?

最大池化的目的是保留输入的特征,同时把数据量减小(数据维度变小),对于整个网络来说,进行计算的参数变少,会训练地更快

  • 如上面案例中输入是5x5的,但输出是3x3的,甚至可以是1x1的
  • 类比:1080p的视频为输入图像,经过池化可以得到720p,也能满足绝大多数需求,传达视频内容的同时,文件尺寸会大大缩小

池化一般跟在卷积后,卷积层是用来提取特征的,一般有相应特征的位置是比较大的数字,最大池化可以提取出这一部分有相应特征的信息

池化不影响通道数

池化后一般再进行非线性激活

-------------------------------------------------------------------------------------------------------------------------------- 

用数据集 CIFAR10 实现最大池化

import torch
import torchvision
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("../data",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset,batch_size=64)

# 搭建神经网络
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()

writer = SummaryWriter("../logs_maxpool")
step = 0
for data in dataloader:
    imgs,targets = data
    writer.add_images("input",imgs,step)
    output = tudui(imgs)  #output尺寸池化后不会有多个channel,原来是3维的图片,经过最大池化后还是3维的,不需要像卷积一样还要reshape操作(影响通道数的是卷积核个数)
    writer.add_images("output",output,step)
    step = step + 1

writer.close()

运行后在 terminal 里输入(注意是在pytorch环境下):

tensorboard --logdir=logs_maxpool

打开网址:

notimplementederror: module [vgg16] is missing the required


16. 神经网络 - 非线性激活 

  • Padding Layers(对输入图像进行填充的各种方式)
    几乎用不到,nn.ZeroPad2d(在输入tensor数据类型周围用0填充)
    nn.ConstantPad2d(用常数填充)
    在 Conv2d 中可以实现,故不常用

  • Non-linear Activations (weighted sum, nonlinearity)

  • Non-linear Activations (other)

非线性激活:给神经网络引入一些非线性的特征

非线性越多,才能训练出符合各种曲线或特征的模型(提高泛化能力)

-------------------------------------------------------------------------------------------------------------------------------- 

最常见:RELU   

ReLU — PyTorch 1.10 documentation

notimplementederror: module [vgg16] is missing the required

输入:(N,*)    N 为 batch_size,*不限制

代码举例:RELU

import torch
from torch import nn
from torch.nn import ReLU

input = torch.tensor([[1,-0.5],
                      [-1,3]])
input = torch.reshape(input,(-1,1,2,2))  #input必须要指定batch_size,-1表示batch_size自己算,1表示是1维的
print(input.shape)   #torch.Size([1, 1, 2, 2])

# 搭建神经网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.relu1 = ReLU()  #inplace默认为False
    def forward(self,input):
        output = self.relu1(input)
        return output

# 创建网络
tudui = Tudui()
output = tudui(input)
print(output)

运行结果:

notimplementederror: module [vgg16] is missing the required

跟输入对比可以看到:小于0的值被0截断,大于0的值仍然保留

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

Sigmoid

Sigmoid — PyTorch 1.10 documentation

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

 输入:(N,*)    N 为 batch_size,*不限制

代码举例:Sigmoid(数据集CIFAR10)

import torch
import torchvision.datasets
from torch import nn
from torch.nn import Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

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

# 搭建神经网络
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.sigmoid1 = Sigmoid()  #inplace默认为False
    def forward(self,input):
        output = self.sigmoid1(input)
        return output

# 创建网络
tudui = Tudui()

writer = SummaryWriter("../logs_sigmoid")
step = 0
for data in dataloader:
    imgs,targets = data
    writer.add_images("input",imgs,global_step=step)
    output = tudui(imgs)
    writer.add_images("output",output,step)
    step = step + 1

writer.close()

运行后在 terminal 里输入:

tensorboard --logdir=logs_sigmoid

打开网址:

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

关于inplace

notimplementederror: module [vgg16] is missing the required


17. 神经网络 - 线性层及其他层介绍 

批标准化层(不难,自学)   

Normalization Layers

torch.nn — PyTorch 1.10 documentation

BatchNorm2d — PyTorch 1.10 documentation

对输入采用Batch Normalization,可以加快神经网络的训练速度

CLASS torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
# num_features C-输入的channel
# With Learnable Parameters
m = nn.BatchNorm2d(100)
# Without Learnable Parameters
m = nn.BatchNorm2d(100, affine=False)  # 正则化层num_feature等于channel,即100
input = torch.randn(20, 100, 35, 45)   #batch_size=20,100个channel,35x45的输入
output = m(input)

---------------------------------------------------------------------------------------------------------------------------------

Recurrent Layers(特定网络中使用,自学)

RNN、LSTM等,用于文字识别中,特定的网络结构

torch.nn — PyTorch 1.13 documentation

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Transformer Layers(特定网络中使用,自学)

特定网络结构

torch.nn — PyTorch 1.13 documentation

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Linear Layers(本节讲解)

Linear — PyTorch 1.10 documentation

notimplementederror: module [vgg16] is missing the required
d代表特征数,L代表神经元个数     K和b在训练过程中神经网络会自行调整,以达到比较合理的预测

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

代码实例

vgg16 model

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

flatten 摊平

torch.flatten — PyTorch 1.10 documentation

# Example
>>> t = torch.tensor([[[1, 2],
                   [3, 4]],
                  [[5, 6],
                   [7, 8]]])   #3个中括号,所以是3维的
>>> torch.flatten(t)  #摊平
tensor([1, 2, 3, 4, 5, 6, 7, 8])
>>> torch.flatten(t, start_dim=1)  #变为1行
tensor([[1, 2, 3, 4],
        [5, 6, 7, 8]])
  • reshape():可以指定尺寸进行变换
  • flatten():变成1行,摊平
output = torch.flatten(imgs)
# 等价于
output = torch.reshape(imgs,(1,1,1,-1))


for data in dataloader:
    imgs,targets = data
    print(imgs.shape)  #torch.Size([64, 3, 32, 32])
    output = torch.reshape(imgs,(1,1,1,-1))  # 想把图片展平
    print(output.shape)  # torch.Size([1, 1, 1, 196608])
    output = tudui(output)
    print(output.shape)  # torch.Size([1, 1, 1, 10])

for data in dataloader:
    imgs,targets = data
    print(imgs.shape)  #torch.Size([64, 3, 32, 32])
    output = torch.flatten(imgs)   #摊平
    print(output.shape)   #torch.Size([196608])
    output = tudui(output)
    print(output.shape)   #torch.Size([10])

 --------------------------------------------------------------------------------------------------------------------------------

notimplementederror: module [vgg16] is missing the required

import torch
import torchvision.datasets
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

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

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.linear1 = Linear(196608,10)
    def forward(self,input):
        output = self.linear1(input)
        return output

tudui = Tudui()

for data in dataloader:
    imgs,targets = data
    print(imgs.shape)  #torch.Size([64, 3, 32, 32])
    # output = torch.reshape(imgs,(1,1,1,-1))  # 想把图片展平
    # print(output.shape)  # torch.Size([1, 1, 1, 196608])
    # output = tudui(output)
    # print(output.shape)  # torch.Size([1, 1, 1, 10])
    output = torch.flatten(imgs)   #摊平
    print(output.shape)   #torch.Size([196608])
    output = tudui(output)
    print(output.shape)   #torch.Size([10])

 运行结果如下:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Dropout Layers(不难,自学)

Dropout — PyTorch 1.10 documentation

在训练过程中,随机把一些 input(输入的tensor数据类型)中的一些元素变为0,变为0的概率为p

目的:防止过拟合

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Sparse Layers(特定网络中使用,自学)

Embedding

Embedding — PyTorch 1.10 documentation

用于自然语言处理 

-------------------------------------------------------------------------------------------------------------------------------- 

Distance Functions

计算两个值之间的误差

torch.nn — PyTorch 1.13 documentation

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

Loss Functions

loss 误差大小

torch.nn — PyTorch 1.13 documentation

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

pytorch提供的一些网络模型

  • 图片相关:torchvision   torchvision.models — Torchvision 0.11.0 documentation
    分类、语义分割、目标检测、实例分割、人体关键节点识别(姿态估计)等等
  • 文本相关:torchtext   无
  • 语音相关:torchaudio  torchaudio.models — Torchaudio 0.10.0 documentation

下一节:Container ——> Sequential(序列)


18. 神经网络 - 搭建小实战和 Sequential 的使用

Containers中有Module、Sequential等 

Sequential — PyTorch 1.10 documentation

Example:

# Using Sequential to create a small model. When `model` is run,
# input will first be passed to `Conv2d(1,20,5)`. The output of
# `Conv2d(1,20,5)` will be used as the input to the first
# `ReLU`; the output of the first `ReLU` will become the input
# for `Conv2d(20,64,5)`. Finally, the output of
# `Conv2d(20,64,5)` will be used as input to the second `ReLU`
model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

# Using Sequential with OrderedDict. This is functionally the
# same as the above code
model = nn.Sequential(OrderedDict([
          ('conv1', nn.Conv2d(1,20,5)),
          ('relu1', nn.ReLU()),
          ('conv2', nn.Conv2d(20,64,5)),
          ('relu2', nn.ReLU())
        ]))

好处:代码简洁易懂

---------------------------------------------------------------------------------------------------------------------------------

对 CIFAR10 进行分类的简单神经网络

CIFAR 10:根据图片内容,识别其究竟属于哪一类(10代表有10个类别)

CIFAR-10 and CIFAR-100 datasets

notimplementederror: module [vgg16] is missing the required

第一次卷积:首先加了几圈 padding(图像大小不变,还是32x32),然后卷积了32次

  • Conv2d — PyTorch 1.10 documentation
  • 输入尺寸是32x32,经过卷积后尺寸不变,如何设置参数?  —— padding=2,stride=1
  • 计算公式:notimplementederror: module [vgg16] is missing the required

几个卷积核就是几通道的,一个卷积核作用于RGB三个通道后会把得到的三个矩阵的对应值相加,也就是说会合并,所以一个卷积核会产生一个通道

任何卷积核在设置padding的时候为保持输出尺寸不变都是卷积核大小的一半

通道变化时通过调整卷积核的个数(即输出通道)来实现的,在 nn.conv2d 的参数中有 out_channel 这个参数,就是对应输出通道

kernel 的内容是不一样的,可以理解为不同的特征抓取,因此一个核会产生一个channel

直接搭建,实现上图 CIFAR10 model 的代码

from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2)  #第一个卷积
        self.maxpool1 = MaxPool2d(kernel_size=2)   #池化
        self.conv2 = Conv2d(32,32,5,padding=2)  #维持尺寸不变,所以padding仍为2
        self.maxpool2 = MaxPool2d(2)
        self.conv3 = Conv2d(32,64,5,padding=2)
        self.maxpool3 = MaxPool2d(2)
        self.flatten = Flatten()  #展平为64x4x4=1024个数据
        # 经过两个线性层:第一个线性层(1024为in_features,64为out_features)、第二个线性层(64为in_features,10为out_features)
        self.linear1 = Linear(1024,64)
        self.linear2 = Linear(64,10)  #10为10个类别,若预测的是概率,则取最大概率对应的类别,为该图片网络预测到的类别
    def forward(self,x):   #x为input
        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)
        return x

tudui = Tudui()
print(tudui)

可以看到网络结构:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

实际过程中如何检查网络的正确性?

核心:一定尺寸的数据经过网络后,能够得到我们想要的输出

对网络结构进行检验的代码: 

input = torch.ones((64,3,32,32))  #全是1,batch_size=64,3通道,32x32
output = tudui(input)
print(output.shape)

运行结果:

torch.Size([64, 10])

-------------------------------------------------------------------------------------------------------------------------------- 

若不知道flatten之后的维度是多少该怎么办?

from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2)  #第一个卷积
        self.maxpool1 = MaxPool2d(kernel_size=2)   #池化
        self.conv2 = Conv2d(32,32,5,padding=2)  #维持尺寸不变,所以padding仍为2
        self.maxpool2 = MaxPool2d(2)
        self.conv3 = Conv2d(32,64,5,padding=2)
        self.maxpool3 = MaxPool2d(2)
        self.flatten = Flatten()  #展平为64x4x4=1024个数据
        # 经过两个线性层:第一个线性层(1024为in_features,64为out_features)、第二个线性层(64为in_features,10为out_features)
        self.linear1 = Linear(1024,64)
        self.linear2 = Linear(64,10)  #10为10个类别,若预测的是概率,则取最大概率对应的类别,为该图片网络预测到的类别
    def forward(self,x):   #x为input
        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)
        return x

tudui = Tudui()
print(tudui)

input = torch.ones((64,3,32,32))  #全是1,batch_size=64(64张图片),3通道,32x32
output = tudui(input)
print(output.shape)  # torch.Size([64,1024])

 看到输出的维度是(64,1024),64可以理解为64张图片,1024就是flatten之后的维度了

---------------------------------------------------------------------------------------------------------------------------------

用 Sequential 搭建,实现上图 CIFAR10 model 的代码

作用:代码更加简洁

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


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = 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为input
        x = self.model1(x)
        return x

tudui = Tudui()
print(tudui)

input = torch.ones((64,3,32,32))  #全是1,batch_size=64,3通道,32x32
output = tudui(input)
print(output.shape)

运行结果:

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

引入 tensorboard 可视化模型结构

在上述代码后面加上以下代码:

from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("../logs_seq")
writer.add_graph(tudui,input)   # add_graph 计算图
writer.close()

运行后在 terminal 里输入:

 tensorboard --logdir=logs_seq

 打开网址,双击图片中的矩形,可以放大每个部分:

notimplementederror: module [vgg16] is missing the required


19. 损失函数与反向传播

torch.nn 里的 loss function 衡量误差,在使用过程中根据需求使用,注意输入形状和输出形状即可

loss 衡量实际神经网络输出 output 与真实想要结果 target 的差距,越小越好

作用:

  • 计算实际输出和目标之间的差距
  • 为我们更新输出提供一定的依据(反向传播):给每一个卷积核中的参数提供了梯度 grad,采用反向传播时,每一个要更新的参数都会计算出对应的梯度,优化过程中根据梯度对参数进行优化,最终达到整个 loss 进行降低的目的

梯度下降法:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

L1LOSS

notimplementederror: module [vgg16] is missing the required

input:(N,*)    N是batch_size,即有多少个数据;*可以是任意维度 

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

代码

  • 取平均的方式: 
import torch
from torch.nn import L1Loss

# 实际数据或网络默认情况下就是float类型,不写测试案例的话一般不需要加dtype
inputs = torch.tensor([1,2,3],dtype=torch.float32)   # 计算时要求数据类型为浮点数,不能是整型的long
targets = torch.tensor([1,2,5],dtype=torch.float32)

inputs = torch.reshape(inputs,(1,1,1,3))   # 1 batch_size, 1 channel, 1行3列
targets = torch.reshape(targets,(1,1,1,3))

loss = L1Loss()
result = loss(inputs,targets)
print(result)

运行结果:

tensor(0.6667)
  • 求和的方式:

修改上述代码中的一句即可

loss = L1Loss(reduction='sum')

运行结果:

tensor(2.)

---------------------------------------------------------------------------------------------------------------------------------

MSELOSS(均方误差)

input:(N,*)    N是batch_size,即有多少个数据;*可以是任意维度 

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

notimplementederror: module [vgg16] is missing the required

代码

import torch
from torch import nn

# 实际数据或网络默认情况下就是float类型,不写测试案例的话一般不需要加dtype
inputs = torch.tensor([1,2,3],dtype=torch.float32)   # 计算时要求数据类型为浮点数,不能是整型的long
targets = torch.tensor([1,2,5],dtype=torch.float32)

inputs = torch.reshape(inputs,(1,1,1,3))   # 1 batch_size, 1 channel, 1行3列
targets = torch.reshape(targets,(1,1,1,3))

loss_mse = nn.MSELoss()
result_mse = loss_mse(inputs,targets)

print(result_mse)

结果:

tensor(1.3333)

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

CROSSENTROPYLOSS(交叉熵)

适用于训练分类问题,有C个类别

例:三分类问题,person,dog,cat

notimplementederror: module [vgg16] is missing the required
公式中的 log 可以按 ln 算

这里的output不是概率,是评估分数

notimplementederror: module [vgg16] is missing the required input 为没有进行处理过的对每一类的得分

代码:

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)

结果:

tensor(1.1019)

---------------------------------------------------------------------------------------------------------------------------------

如何在之前写的神经网络中用到 Loss Function(损失函数)

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

dataset = torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=1)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = 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为input
        x = self.model1(x)
        return x

loss = nn.CrossEntropyLoss()

tudui = Tudui()

for data in dataloader:
    imgs,targets = data  # imgs为输入,放入神经网络中
    outputs = tudui(imgs)  # outputs为输入通过神经网络得到的输出,targets为实际输出
    result_loss = loss(outputs,targets)
    print(result_loss)  # 神经网络输出与真实输出的误差

结果:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

backward  反向传播

计算出每一个节点参数的梯度

在上述代码后加一行:

result_loss.backward()  # backward反向传播,是对result_loss,而不是对loss

在这一句代码前打上断点(运行到该行代码的前一行,该行不运行),debug 后:notimplementederror: module [vgg16] is missing the required

 tudui ——> model 1 ——> Protected Attributes ——> _modules ——> '0' ——> bias / weight——> grad(是None)

点击Step into My Code,运行完该行后,可以发现刚刚的None有值了(损失函数一定要经过 .backward() 后才能反向传播,才能有每个需要调节的参数的grad的值

下一节:选择合适的优化器,利用梯度对网络中的参数进行优化更新,以达到整个 loss最低的目的


20. 优化器

当使用损失函数时,可以调用损失函数的 backward,得到反向传播,反向传播可以求出每个需要调节的参数对应的梯度,有了梯度就可以利用优化器,优化器根据梯度对参数进行调整,以达到整体误差降低的目的

torch.optim — PyTorch 1.10 documentation

---------------------------------------------------------------------------------------------------------------------------------

如何使用优化器?

(1)构造

# Example:
# SGD为构造优化器的算法,Stochastic Gradient Descent 随机梯度下降
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)  #模型参数、学习速率、特定优化器算法中需要设定的参数
optimizer = optim.Adam([var1, var2], lr=0.0001)

(2)调用优化器的step方法

利用之前得到的梯度对参数进行更新

for input, target in dataset:
    optimizer.zero_grad() #把上一步训练的每个参数的梯度清零
    output = model(input)
    loss = loss_fn(output, target)  # 输出跟真实的target计算loss
    loss.backward() #调用反向传播得到每个要更新参数的梯度
    optimizer.step() #每个参数根据上一步得到的梯度进行优化

---------------------------------------------------------------------------------------------------------------------------------

算法

如Adadelta、Adagrad、Adam、RMSProp、SGD等等,不同算法前两个参数:params、lr 都是一致的,后面的参数不同

CLASS torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)
# params为模型的参数、lr为学习速率(learning rate)
# 后续参数都是特定算法中需要设置的

学习速率不能太大(太大模型训练不稳定)也不能太小(太小模型训练慢),一般建议先采用较大学习速率,后采用较小学习速率

-------------------------------------------------------------------------------------------------------------------------------- 

SGD为例 

SGD(随机梯度下降法)为例进行说明: 

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

# 加载数据集并转为tensor数据类型
dataset = torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
# 加载数据集
dataloader = DataLoader(dataset,batch_size=1)

# 创建网络名叫Tudui
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = 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为input,forward前向传播
        x = self.model1(x)
        return x

# 计算loss
loss = nn.CrossEntropyLoss()

# 搭建网络
tudui = Tudui()

# 设置优化器
optim = torch.optim.SGD(tudui.parameters(),lr=0.01)  # SGD随机梯度下降法

for data in dataloader:
    imgs,targets = data  # imgs为输入,放入神经网络中
    outputs = tudui(imgs)  # outputs为输入通过神经网络得到的输出,targets为实际输出
    result_loss = loss(outputs,targets)
    optim.zero_grad()  # 把网络模型中每一个可以调节的参数对应梯度设置为0
    result_loss.backward()  # backward反向传播求出每一个节点的梯度,是对result_loss,而不是对loss
    optim.step()  # 对每个参数进行调优

可以在以下地方打断点,debug:

notimplementederror: module [vgg16] is missing the required

tudui ——> Protected Attributes ——> _modules ——> 'model1' ——> Protected Attributes ——> _modules ——> '0' ——> weight ——> data 或 grad

通过每次按箭头所指的按钮(点一次运行一行),观察 data 和 grad 值的变化

  • 第一行 optim.zero_grad() 是让grad清零
  • 第三行 optim.step() 会通过grad更新data

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

完整代码

在 data 循环外又套一层 epoch 循环,一次 data 循环相当于对数据训练一次,加了 epoch 循环相当于对数据训练 20 次

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

# 加载数据集并转为tensor数据类型
dataset = torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=1)

# 创建网络名叫Tudui
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = 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为input,forward前向传播
        x = self.model1(x)
        return x

# 计算loss
loss = nn.CrossEntropyLoss()

# 搭建网络
tudui = Tudui()

# 设置优化器
optim = torch.optim.SGD(tudui.parameters(),lr=0.01)  # SGD随机梯度下降法
for epoch in range(20):
    running_loss = 0.0  # 在每一轮开始前将loss设置为0
    for data in dataloader:  # 该循环相当于只对数据进行了一轮学习
        imgs,targets = data  # imgs为输入,放入神经网络中
        outputs = tudui(imgs)  # outputs为输入通过神经网络得到的输出,targets为实际输出
        result_loss = loss(outputs,targets)
        optim.zero_grad()  # 把网络模型中每一个可以调节的参数对应梯度设置为0
        result_loss.backward()  # backward反向传播求出每一个节点的梯度,是对result_loss,而不是对loss
        optim.step()  # 对每个参数进行调优
        running_loss = running_loss + result_loss  # 每一轮所有loss的和
    print(running_loss)

部分运行结果:

notimplementederror: module [vgg16] is missing the required

优化器对模型参数不断进行优化,每一轮的 loss 在不断减小

实际过程中模型在整个数据集上的训练次数(即最外层的循环)都是成百上千/万的,本例仅以 20 次为例


21. 现有网络模型的使用及修改

notimplementederror: module [vgg16] is missing the required

本节主要讲解 torchvision

notimplementederror: module [vgg16] is missing the required

本节主要讲解 Classification 里的 VGG 模型,数据集仍为 CIFAR10 数据集(主要用于分类)

torchvision.models — Torchvision 0.11.0 documentation

---------------------------------------------------------------------------------------------------------------------------------

数据集 ImageNet

注意:必须要先有 package scipy

在 Terminal 里输入

pip list

寻找是否有 scipy,若没有的话输入

pip install scipy

(注意关闭代理!!!)

---------------------------------------------------------------------------------------------------------------------------------

参数及下载 

notimplementederror: module [vgg16] is missing the required

下载 ImageNet 数据集:

import torchvision.datasets
train_data = torchvision.datasets.ImageNet("../data_image_net",split='train',download=True,
                                           transform=torchvision.transforms.ToTensor())

./xxx表示当前路径下,../xxx表示返回上一级目录 

多行注释快捷键:ctrl+/

运行后会报错:

RuntimeError: The dataset is no longer publicly accessible. You need to download the archives externally and place them in the root directory.
notimplementederror: module [vgg16] is missing the required
数据集不再可以公开访问,必须手动下载压缩文件,放在目录中

下载地址:

Imagenet 完整数据集下载_wendell 的博客-CSDN博客_imagenet下载

100 多个G,太大... 放弃

按住 Ctrl 键,点击 ImageNet,查看其源码:

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

VGG16 模型

VGG 11/13/16/19  常用16和19

参数 pretrained=True/False 

notimplementederror: module [vgg16] is missing the required

  • pretrained 为 False 的情况下,只是加载网络模型,参数都为默认参数,不需要下载
  • 为 True 时需要从网络中下载,卷积层、池化层对应的参数等等(在ImageNet数据集中训练好的)
import torchvision.models

vgg16_false = torchvision.models.vgg16(pretrained=False)  # 另一个参数progress显示进度条,默认为True
vgg16_true = torchvision.models.vgg16(pretrained=True)
print('ok')

断点打在 print('ok') 前,debug 一下,结果如图:

 notimplementederror: module [vgg16] is missing the required

vgg16_true ——> classifier ——> Protected Attributes ——> modules ——> '0'(线性层) ——> weight

notimplementederror: module [vgg16] is missing the required

为 false 的情况,同理找到 weight 值:

notimplementederror: module [vgg16] is missing the required

总结: 

  • 设置为 False 的情况,相当于网络模型中的参数都是初始化的、默认的
  • 设置为 True 时,网络模型中的参数在数据集上是训练好的,能达到比较好的效果

---------------------------------------------------------------------------------------------------------------------------------

vgg16 网络架构 

import torchvision.models

vgg16_false = torchvision.models.vgg16(pretrained=False)  # 另一个参数progress显示进度条,默认为True
vgg16_true = torchvision.models.vgg16(pretrained=True)

print(vgg16_true)

输出:

VGG(
  (features): Sequential(
# 输入图片先经过卷积,输入是3通道的、输出是64通道的,卷积核大小是3×3的
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
# 非线性
    (1): ReLU(inplace=True)
# 卷积、非线性、池化...
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace=True)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace=True)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace=True)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace=True)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace=True)
    (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (18): ReLU(inplace=True)
    (19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace=True)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace=True)
    (23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (25): ReLU(inplace=True)
    (26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (27): ReLU(inplace=True)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace=True)
    (30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
# 最后线性层输出为1000(vgg16也是一个分类模型,能分出1000个类别)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

 ImageNet

notimplementederror: module [vgg16] is missing the required 所以 out_features = 1000

---------------------------------------------------------------------------------------------------------------------------------

如何利用现有网络去改动它的结构?

train_data = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)

CIFAR10 把数据分成了10类,而 vgg16 模型把数据分成了 1000 类,如何应用这个网络模型呢?

  • 把最后线性层的 out_features 从1000改为10
  • 在最后的线性层下面再加一层,in_features为1000,out_features为10

利用现有网络去改动它的结构,避免写 vgg16

很多框架会把 vgg16 当做前置的网络结构,提取一些特殊的特征,再在后面加一些网络结构,实现功能

-------------------------------------------------------------------------------------------------------------------------------- 

添加 

以 vgg16_true 为例讲解,实现上面的第二种思路:

# 给 vgg16 添加一个线性层,输入1000个类别,输出10个类别
vgg16_true.add_module('add_linear',nn.Linear(in_features=1000,out_features=10))
print(vgg16_true)

结果如图:

notimplementederror: module [vgg16] is missing the required

如果想将 module 添加至 classifier 里:

# 给 vgg16 添加一个线性层,输入1000个类别,输出10个类别
vgg16_true.classifier.add_module('add_linear',nn.Linear(in_features=1000,out_features=10))
print(vgg16_true)

 结果如图:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

修改 

以上为添加,那么如何修改呢?

以 vgg16_false 为例:

vgg16_false = torchvision.models.vgg16(pretrained=False)  # 另一个参数progress显示进度条,默认为True
print(vgg16_false)

结果如下:

  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace=True)
    (2): Dropout(p=0.5, inplace=False)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace=True)
    (5): Dropout(p=0.5, inplace=False)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

想将最后一层 Linear 的 out_features 改为10:

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

结果如下:

notimplementederror: module [vgg16] is missing the required

本节:

  • 如何加载现有的一些 pytorch 提供的网络模型
  • 如何对网络模型中的结构进行修改,包括添加自己想要的一些网络模型结构

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

后续内容:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

两种方式保存模型

import torch
import torchvision.models

vgg16 = torchvision.models.vgg16(pretrained=False)  # 网络中模型的参数是没有经过训练的、初始化的参数

方式1:不仅保存了网络模型的结构,也保存了网络模型的参数

# 保存方式1:模型结构+模型参数
torch.save(vgg16,"vgg16_method1.pth")

方式2:网络模型的参数保存为字典,不保存网络模型的结构(官方推荐的保存方式,用的空间小)

# 保存方式2:模型参数(官方推荐)
torch.save(vgg16.state_dict(),"vgg16_method2.pth")   
# 把vgg16的状态保存为字典形式(Python中的一种数据格式)

运行后 src 文件夹底下会多出以下两个文件:

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

两种方式加载模型

方式1:对应保存方式1,打印出的是网络模型的结构

# 方式1 对应 保存方式1,加载模型
model = torch.load("vgg16_method1.pth",)
print(model)  # 打印出的只是模型的结构,其实它的参数也被保存下来了
notimplementederror: module [vgg16] is missing the required
保存的是网络模型的结构

在print这句打上断点,debug一下,可以看一下模型参数 

方式2:对应保存方式2,打印出的是参数的字典形式

# 方式2 加载模型
model = torch.load("vgg16_method2.pth")
print(model)
notimplementederror: module [vgg16] is missing the required
保存的是参数的字典形式,不再是网络模型

如何恢复网络模型结构?

import torchvision.models

vgg16 = torchvision.models.vgg16(pretrained=False)  # 预训练设置为False
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))  # vgg16通过字典形式,加载状态即参数
print(vgg16)

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

方式1 有陷阱(自己定义网络结构,没有用 vgg16 时)

用方式1保存的话,加载时要让程序能够访问到其定义模型的一种方式 

问题描述 

首先在 model_save.py 中写以下代码:

# 陷阱
from torch import nn

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv = nn.Conv2d(3,64,kernel_size=3)
    def forward(self,x):   # x为输入
        x = self.conv(x)
        return x

tudui = Tudui()  # 有一个卷积层和一些初始化的参数
torch.save(tudui,"tudui_method1.pth")

运行后 src 文件夹底下多出一个文件:

notimplementederror: module [vgg16] is missing the required

再在 model_load.py 中写以下代码:

# 陷阱
import torch

model = torch.load("tudui_method1.pth")
print(model)

运行后发现报错:

notimplementederror: module [vgg16] is missing the required

AttributeError: Can't get attribute 'Tudui' on <module '__main__' from 'C:/Users/11842/Desktop/Learn_torch/src/model_load.py'>

# 不能得到'Tudui'这个属性,因为没有这个类

-------------------------------------------------------------------------------------------------------------------------------- 

解决

还是需要将 model_save.py 中的网络结构复制到 model_load.py 中,即下列代码需要复制到 model_load.py 中(为了确保加载的网络模型是想要的网络模型):

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv = nn.Conv2d(3,64,kernel_size=3)
    def forward(self,x):   # x为输入
        x = self.conv(x)
        return x

但是不需要创建了,即在 model_load.py 中不需要写:

tudui = Tudui()

此时 model_load.py 完整代码为:

# 陷阱
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv = nn.Conv2d(3,64,kernel_size=3)
    def forward(self,x):   # x为输入
        x = self.conv(x)
        return x
    
model = torch.load("tudui_method1.pth")
print(model)

运行结果如下:

notimplementederror: module [vgg16] is missing the required

解决另法:

实际写项目过程中,直接定义在一个单独的文件中(如model_save.py),再在 model_load.py 中:

from model_save import *

23. 完整的模型训练套路

以 CIFAR10 数据集为例,分类问题(10分类)

在语句后面按 Ctrl + d 可以复制这条语句

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

model.py 文件代码

import torch
from torch import nn

# 搭建神经网络(10分类网络)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 把网络放到序列中
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3,out_channels=32,kernel_size=5,stride=1,padding=2), #输入是32x32的,输出还是32x32的(padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=32,kernel_size=5,stride=1,padding=2),  #输入输出都是16x16的(同理padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=64,kernel_size=5,stride=1,padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Flatten(),   # 展平
            nn.Linear(in_features=64*4*4,out_features=64),
            nn.Linear(in_features=64,out_features=10)
        )
    def forward(self,x):
        x = self.model(x)
        return x

if __name__ == '__main__':
    # 测试网络的验证正确性
    tudui = Tudui()
    input = torch.ones((64,3,32,32))  # batch_size=64(代表64张图片),3通道,32x32
    output = tudui(input)
    print(output.shape)

运行结果如下:

notimplementederror: module [vgg16] is missing the required

返回64行数据,每一行数据有10个数据,代表每一张图片在10个类别中的概率

---------------------------------------------------------------------------------------------------------------------------------

train.py 文件代码

(与 model.py 文件必须在同一个文件夹底下)

import torchvision.datasets
from model import *
from torch import nn
from torch.utils.data import DataLoader

# 准备数据集,CIFAR10 数据集是PIL Image,要转换为tensor数据类型
train_data = torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)

# 看一下训练数据集和测试数据集都有多少张(如何获得数据集的长度)
train_data_size = len(train_data)   # length 长度
test_data_size = len(test_data)
# 如果train_data_size=10,那么打印出的字符串为:训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))   # 字符串格式化,把format中的变量替换{}
print("测试数据集的长度为:{}".format(test_data_size))

# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

# 创建网络模型
tudui = Tudui()

# 创建损失函数
loss_fn = nn.CrossEntropyLoss()   # 分类问题可以用交叉熵

# 定义优化器
learning_rate = 0.01   # 另一写法:1e-2,即1x 10^(-2)=0.01
optimizer = torch.optim.SGD(tudui.parameters(),lr=learning_rate)   # SGD 随机梯度下降

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

for i in range(epoch):
    print("----------第{}轮训练开始-----------".format(i+1))  # i从0-9
    # 训练步骤开始
    for data in train_dataloader:   # 从训练的dataloader中取数据
        imgs,targets = data
        outputs = tudui(imgs)
        loss = loss_fn(outputs,targets)

        # 优化器优化模型
        optimizer.zero_grad()    # 首先要梯度清零
        loss.backward()  # 反向传播得到每一个参数节点的梯度
        optimizer.step()   # 对参数进行优化
        total_train_step += 1
        print("训练次数:{},loss:{}".format(total_train_step,loss.item()))

运行结果如下: 

notimplementederror: module [vgg16] is missing the required

print(a) 和 print(a.item()) 的区别

import torch
a = torch.tensor(5)
print(a)
print(a.item())

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

如何知道模型是否训练好,或达到需求?

每次训练完一轮就进行测试,以测试数据集上的损失或正确率来评估模型有没有训练好

测试过程中不需要对模型进行调优,利用现有模型进行测试,所以有以下命令:

with torch.no_grad(): 

在上述 train.py 代码后继续写:

# 测试步骤开始
    total_test_loss = 0
    with torch.no_grad():  # 无梯度,不进行调优
        for data in test_dataloader:
            imgs,targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)  # 该loss为部分数据在网络模型上的损失,为tensor数据类型
            # 求整体测试数据集上的误差或正确率
            total_test_loss = total_test_loss + loss.item()  # loss为tensor数据类型,而total_test_loss为普通数字,所以要.item()一下
    print("整体测试集上的Loss:{}".format(total_test_loss))

结果如下:

notimplementederror: module [vgg16] is missing the required

此处为了使测试的 loss 结果易找,在 train.py 中添加了一句 if 的代码,使train每训练100轮才打印1次:

if total_train_step % 100 ==0:  # 逢百才打印记录
    print("训练次数:{},loss:{}".format(total_train_step,loss.item()))

完整代码

import torchvision.datasets
from model import *
from torch import nn
from torch.utils.data import DataLoader

# 准备数据集,CIFAR10 数据集是PIL Image,要转换为tensor数据类型
train_data = torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)

# 看一下训练数据集和测试数据集都有多少张(如何获得数据集的长度)
train_data_size = len(train_data)   # length 长度
test_data_size = len(test_data)
# 如果train_data_size=10,那么打印出的字符串为:训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))   # 字符串格式化,把format中的变量替换{}
print("测试数据集的长度为:{}".format(test_data_size))

# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

# 创建网络模型
tudui = Tudui()

# 创建损失函数
loss_fn = nn.CrossEntropyLoss()   # 分类问题可以用交叉熵

# 定义优化器
learning_rate = 0.01   # 另一写法:1e-2,即1x 10^(-2)=0.01
optimizer = torch.optim.SGD(tudui.parameters(),lr=learning_rate)   # SGD 随机梯度下降

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


for i in range(epoch):
    print("----------第{}轮训练开始-----------".format(i+1))  # i从0-9
    # 训练步骤开始
    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(total_train_step,loss.item()))

    # 测试步骤开始
    total_test_loss = 0
    with torch.no_grad():  # 无梯度,不进行调优
        for data in test_dataloader:
            imgs,targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)  # 该loss为部分数据在网络模型上的损失,为tensor数据类型
            # 求整体测试数据集上的误差或正确率
            total_test_loss = total_test_loss + loss.item()  # loss为tensor数据类型,而total_test_loss为普通数字
    print("整体测试集上的Loss:{}".format(total_test_loss))

---------------------------------------------------------------------------------------------------------------------------------

与 TensorBoard 结合

import torchvision.datasets
from torch.utils.tensorboard import SummaryWriter

from model import *
from torch import nn
from torch.utils.data import DataLoader

# 准备数据集,CIFAR10 数据集是PIL Image,要转换为tensor数据类型
train_data = torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)

# 看一下训练数据集和测试数据集都有多少张(如何获得数据集的长度)
train_data_size = len(train_data)   # length 长度
test_data_size = len(test_data)
# 如果train_data_size=10,那么打印出的字符串为:训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))   # 字符串格式化,把format中的变量替换{}
print("测试数据集的长度为:{}".format(test_data_size))

# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

# 创建网络模型
tudui = Tudui()

# 创建损失函数
loss_fn = nn.CrossEntropyLoss()   # 分类问题可以用交叉熵

# 定义优化器
learning_rate = 0.01   # 另一写法:1e-2,即1x 10^(-2)=0.01
optimizer = torch.optim.SGD(tudui.parameters(),lr=learning_rate)   # SGD 随机梯度下降

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

# 添加tensorboard
writer = SummaryWriter("../logs_train")

for i in range(epoch):
    print("----------第{}轮训练开始-----------".format(i+1))  # i从0-9
    # 训练步骤开始
    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(total_train_step,loss.item()))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

    # 测试步骤开始
    total_test_loss = 0
    with torch.no_grad():  # 无梯度,不进行调优
        for data in test_dataloader:
            imgs,targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)  # 该loss为部分数据在网络模型上的损失,为tensor数据类型
            # 求整体测试数据集上的误差或正确率
            total_test_loss = total_test_loss + loss.item()  # loss为tensor数据类型,而total_test_loss为普通数字
    print("整体测试集上的Loss:{}".format(total_test_loss))
    writer.add_scalar("test_loss",total_test_loss,total_test_step)
    total_test_step += 1

writer.close()

运行结果:

notimplementederror: module [vgg16] is missing the required

在 Terminal 里输入:

tensorboard --logdir=logs_train

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

保存每一轮训练的模型 

添加两句代码: 

    torch.save(tudui,"tudui_{}.pth".format(i))  # 每一轮保存一个结果
    print("模型已保存")

writer.close()

运行后:

notimplementederror: module [vgg16] is missing the required   

---------------------------------------------------------------------------------------------------------------------------------

正确率的实现(对分类问题) 

即便得到整体测试集上的 loss,也不能很好说明在测试集上的表现效果

  • 分类问题中可以用正确率表示(下述代码改进)
  • 在目标检测/语义分割中,可以把输出放在tensorboard里显示,看测试结果

例子: 

notimplementederror: module [vgg16] is missing the required

第一步:

import torch

outputs = torch.tensor([[0.1,0.2],
                        [0.3,0.4]])
print(outputs.argmax(1))  # 0或1表示方向,1为横向比较大小. 运行结果:tensor([1, 1])

notimplementederror: module [vgg16] is missing the required

第二步:

preds = outputs.argmax(1)
targets = torch.tensor([0,1])
print(preds == targets)  # tensor([False,  True])
print(sum(preds == targets).sum())  # tensor(1),对应位置相等的个数

上例说明了基本用法,现对原问题的代码再进一步优化,计算整体正确率:

    # 测试步骤开始
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():  # 无梯度,不进行调优
        for data in test_dataloader:
            imgs,targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)  # 该loss为部分数据在网络模型上的损失,为tensor数据类型
            # 求整体测试数据集上的误差或正确率
            total_test_loss = total_test_loss + loss.item()  # loss为tensor数据类型,而total_test_loss为普通数字
            # 求整体测试数据集上的误差或正确率
            accuracy = (outputs.argmax(1) == targets).sum()  # 1:横向比较,==:True或False,sum:计算True或False个数
            total_accuracy = total_accuracy + accuracy
    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/imgs.size(0)))
    writer.add_scalar("test_loss",total_test_loss,total_test_step)
    writer.add_scalar("test_accuracy",total_accuracy/imgs.size(0),total_test_step)
    total_test_step += 1

    torch.save(tudui,"tudui_{}.pth".format(i))  # 每一轮保存一个结果
    print("模型已保存")

writer.close()

运行结果:

notimplementederror: module [vgg16] is missing the required

在 Terminal 里输入:

tensorboard --logdir=logs_train

打开网址  http://localhost:6006/ :

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

train.py 完整代码

import torchvision.datasets
from torch.utils.tensorboard import SummaryWriter

from model import *
from torch import nn
from torch.utils.data import DataLoader

# 准备数据集,CIFAR10 数据集是PIL Image,要转换为tensor数据类型
train_data = torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)

# 看一下训练数据集和测试数据集都有多少张(如何获得数据集的长度)
train_data_size = len(train_data)   # length 长度
test_data_size = len(test_data)
# 如果train_data_size=10,那么打印出的字符串为:训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))   # 字符串格式化,把format中的变量替换{}
print("测试数据集的长度为:{}".format(test_data_size))

# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

# 创建网络模型
tudui = Tudui()

# 创建损失函数
loss_fn = nn.CrossEntropyLoss()   # 分类问题可以用交叉熵

# 定义优化器
learning_rate = 0.01   # 另一写法:1e-2,即1x 10^(-2)=0.01
optimizer = torch.optim.SGD(tudui.parameters(),lr=learning_rate)   # SGD 随机梯度下降

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

# 添加tensorboard
writer = SummaryWriter("../logs_train")

for i in range(epoch):
    print("----------第{}轮训练开始-----------".format(i+1))  # i从0-9
    # 训练步骤开始
    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(total_train_step,loss.item()))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

    # 测试步骤开始
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():  # 无梯度,不进行调优
        for data in test_dataloader:
            imgs,targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)  # 该loss为部分数据在网络模型上的损失,为tensor数据类型
            # 求整体测试数据集上的误差或正确率
            total_test_loss = total_test_loss + loss.item()  # loss为tensor数据类型,而total_test_loss为普通数字
            # 求整体测试数据集上的误差或正确率
            accuracy = (outputs.argmax(1) == targets).sum()  # 1:横向比较,==:True或False,sum:计算True或False个数
            total_accuracy = total_accuracy + accuracy
    print("整体测试集上的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 += 1

    torch.save(tudui,"tudui_{}.pth".format(i))  # 每一轮保存一个结果
    print("模型已保存")

writer.close()

---------------------------------------------------------------------------------------------------------------------------------

model.train() 和 model.eval()

notimplementederror: module [vgg16] is missing the required

训练步骤开始之前会把网络模型(我们这里的网络模型叫 tudui)设置为train,并不是说把网络设置为训练模型它才能够开始训练

notimplementederror: module [vgg16] is missing the required

测试网络前写 网络.eval(),并不是说需要这一行才能把网络设置成 eval 状态,才能进行网络测试

-------------------------------------------------------------------------------------------------------------------------------- 

作用 

这两句不写网络依然可以运行,它们的作用是:

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required 本节写的案例没有 Dropout 层或 BatchNorm 层,所以有没有这两行无所谓

如果有这些特殊层,一定要调用

---------------------------------------------------------------------------------------------------------------------------------

回顾案例

首先,要准备数据集,准备对应的 dataloader

import torchvision.datasets
from torch.utils.tensorboard import SummaryWriter

from model import *
from torch import nn
from torch.utils.data import DataLoader

# 准备数据集,CIFAR10 数据集是PIL Image,要转换为tensor数据类型
train_data = torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)

# 看一下训练数据集和测试数据集都有多少张(如何获得数据集的长度)
train_data_size = len(train_data)   # length 长度
test_data_size = len(test_data)
# 如果train_data_size=10,那么打印出的字符串为:训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))   # 字符串格式化,把format中的变量替换{}
print("测试数据集的长度为:{}".format(test_data_size))

# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)

然后,创建网络模型、损失函数、优化器,设置训练中的一些参数、训练轮数 epoch(为了能够进行多次训练)

# 创建网络模型
tudui = Tudui()

# 创建损失函数
loss_fn = nn.CrossEntropyLoss()   # 分类问题可以用交叉熵

# 定义优化器
learning_rate = 0.01   # 另一写法:1e-2,即1x 10^(-2)=0.01
optimizer = torch.optim.SGD(tudui.parameters(),lr=learning_rate)   # SGD 随机梯度下降

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

调用

tudui.train() 

使网络进入训练状态,从训练的 dataloader 中不断取数据,算出误差,放到优化器中进行优化,采用某种特定的方式展示输出,一轮结束后或特定步数后进行测试

    # 训练步骤开始
    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(total_train_step,loss.item()))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

测试过程中可以设置

    tudui.eval() 

要设置

    with torch.no_grad(): 

让网络模型中的参数都没有,因为我们只需要进行测试,不需要对网络模型进行调整,更不需要利用梯度来优化

从测试数据集中取数据,计算误差,构建特殊指标显示出来

        for data in test_dataloader:
            imgs,targets = data
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)  # 该loss为部分数据在网络模型上的损失,为tensor数据类型
            # 求整体测试数据集上的误差或正确率
            total_test_loss = total_test_loss + loss.item()  # loss为tensor数据类型,而total_test_loss为普通数字
            # 求整体测试数据集上的误差或正确率
            accuracy = (outputs.argmax(1) == targets).sum()  # 1:横向比较,==:True或False,sum:计算True或False个数
            total_accuracy = total_accuracy + accuracy

最后可以通过一些方式来展示一下训练的网络在测试集上的效果

    print("整体测试集上的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 += 1

在特定步数或某一轮可以保存模型,保存模型的方式是之前讲的方式1:

    torch.save(tudui,"tudui_{}.pth".format(i))

回忆官方推荐的方式2:

    torch.save(tudui.state_dict,"tudui_{}.pth".format(i))

(将网络模型的状态转化为字典型,展示它的特定保存位置)


24. 利用GPU训练

两种方式实现代码在GPU上训练:

第一种使用GPU训练的方式

notimplementederror: module [vgg16] is missing the required

网络模型: 

notimplementederror: module [vgg16] is missing the required

数据(包括输入、标注):

notimplementederror: module [vgg16] is missing the required
训练过程
notimplementederror: module [vgg16] is missing the required
测试过程

损失函数:

notimplementederror: module [vgg16] is missing the required

更好的写法:

notimplementederror: module [vgg16] is missing the required

其他地方同理加上 

这种写法在CPU和GPU上都可以跑,优先在GPU上跑

---------------------------------------------------------------------------------------------------------------------------------

比较CPU/GPU训练时间 

为了比较时间,引入 time 这个 package

对于CPU

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required  notimplementederror: module [vgg16] is missing the required

运行 train.py,可以看到它运行了4.53s

notimplementederror: module [vgg16] is missing the required

对于GPU

notimplementederror: module [vgg16] is missing the required

时间竟然比CPU长(我不理解orz)

---------------------------------------------------------------------------------------------------------------------------------

查看GPU信息 

在 Terminal 里输入

nvidia-smi

会出现一些GPU的信息

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

Google Colab

Google 为我们提供了一个免费的GPU,默认提供的环境当中就有Pytorch

notimplementederror: module [vgg16] is missing the required

如何使用GPU?

修改 ——> 笔记本设置 ——> 硬件加速器选择GPU(每周免费使用30h)

使用GPU后会重新启动环境

notimplementederror: module [vgg16] is missing the required
前后的序号都没有了,要重新运行
notimplementederror: module [vgg16] is missing the required
重新运行后为True

将 train_gpu_1.py 代码复制进去运行,速度很快,结果如下:

notimplementederror: module [vgg16] is missing the required

查看GPU配置 

在 Google Colab 上运行 terminal 中运行的东西,在语句前加 !(感叹号)

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

第二种使用GPU训练的方式(更常用)

notimplementederror: module [vgg16] is missing the required

以下两种写法对于单显卡来说等价:

device = torch.device("cuda")

device = torch.device("cuda:0")

语法糖(一种语法的简写),程序在 CPU 或 GPU/cuda 环境下都能运行: 

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
notimplementederror: module [vgg16] is missing the required
通过这个变量可以控制是在CPU上运行还是GPU(改成 "cuda" 或 "cuda:0" )上运行
notimplementederror: module [vgg16] is missing the required
这里第二句可以不用再赋值给 tudui,直接 tudui.to(device) 也可以
notimplementederror: module [vgg16] is missing the required
同上
notimplementederror: module [vgg16] is missing the required
必须要赋值
notimplementederror: module [vgg16] is missing the required
必须要赋值

网络模型、损失函数都不需要另外赋值,直接 .to(device) 就可以

但是数据(图片、标注)需要另外转移之后再重新赋值给变量


25. 完整的模型验证(测试、demo)套路

核心:利用已经训练好的模型,给它提供输入进行测试(类似之前案例中测试集的测试部分)

notimplementederror: module [vgg16] is missing the required

pytorch-CycleGAN-and-pix2pix

notimplementederror: module [vgg16] is missing the required

---------------------------------------------------------------------------------------------------------------------------------

示例 

Resize(): 

notimplementederror: module [vgg16] is missing the required

随便在网络上找图片,通过 Resize() 使图片符合模型

# 如何从test.py文件去找到dog文件(相对路径)
import torch
import torchvision.transforms
from PIL import Image
from torch import nn

image_path = "../imgs/dog.png"  # 或右键-> Copy Path-> Absolute Path(绝对路径)
# 读取图片(PIL Image),再用ToTensor进行转换
image = Image.open(image_path)  # 现在的image是PIL类型
print(image)  # <PIL.PngImagePlugin.PngImageFile image mode=RGB size=430x247 at 0x1DF29D33AF0>

# image = image.convert('RGB')
# 因为png格式是四通道,除了RGB三通道外,还有一个透明度通道,所以要调用上述语句保留其颜色通道
# 当然,如果图片本来就是三颜色通道,经过此操作,不变
# 加上这一步后,可以适应 png jpg 各种格式的图片

# 该image大小为430x247,网络模型的输入只能是32x32,进行一个Resize()
# Compose():把transforms几个变换联立在一起
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),  # 32x32大小的PIL Image
                                            torchvision.transforms.ToTensor()])  # 转为Tensor数据类型
image = transform(image)
print(image.shape)  # torch.Size([3, 32, 32])

# 加载网络模型(之前采用的是第一种方式保存,故需要采用第一种方式加载)
# 首先搭建神经网络(10分类网络)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 把网络放到序列中
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3,out_channels=32,kernel_size=5,stride=1,padding=2), #输入是32x32的,输出还是32x32的(padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=32,kernel_size=5,stride=1,padding=2),  #输入输出都是16x16的(同理padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=64,kernel_size=5,stride=1,padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Flatten(),   # 展平
            nn.Linear(in_features=64*4*4,out_features=64),
            nn.Linear(in_features=64,out_features=10)
        )
    def forward(self,x):
        x = self.model(x)
        return x
# 然后加载网络模型
model = torch.load("tudui_0.pth")  # 因为test.py和tudui_0.pth在同一个层级下,所以地址可以直接写
print(model)

output = model(image)
print(output)

运行会报错,报错提示如下:

RuntimeError: Expected 4-dimensional input for 4-dimensional weight [32, 3, 5, 5], but got 3-dimensional input of size [3, 32, 32] instead

notimplementederror: module [vgg16] is missing the required

原因:要求是四维的输入 [batch_size,channel,length,width],但是获得的图片是三维的 —— 图片没有指定 batch_size(网络训练过程中是需要 batch_size 的,而图片输入是三维的,需要reshape() 一下)

解决:torch.reshape() 方法

在上述代码后面加上:

image = torch.reshape(image,(1,3,32,32))
model.eval()  # 模型转化为测试类型
with torch.no_grad():  # 节约内存和性能
    output = model(image)
print(output)

运行结果:notimplementederror: module [vgg16] is missing the required

1.3220 概率最大,预测的是第六类

print(output.argmax(1))

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

notimplementederror: module [vgg16] is missing the required
CIFAR10 对应的真实类别

怎么找到?

notimplementederror: module [vgg16] is missing the required

第六类对应的是 frog(青蛙)

---------------------------------------------------------------------------------------------------------------------------------

预测错误的原因可能是训练次数不够多,在 Google Colab 里,将训练轮数 epoch 改为 30 次,完整代码(train.py)

import torch
import torchvision.datasets
from torch.utils.tensorboard import SummaryWriter

# from model import *
from torch import nn
from torch.utils.data import DataLoader
import time  # time这个package是用来计时的

# 准备数据集,CIFAR10 数据集是PIL Image,要转换为tensor数据类型
device = torch.device("cuda")
print(device)
train_data = torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)

# 看一下训练数据集和测试数据集都有多少张(如何获得数据集的长度)
train_data_size = len(train_data)   # length 长度
test_data_size = len(test_data)
# 如果train_data_size=10,那么打印出的字符串为:训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))   # 字符串格式化,把format中的变量替换{}
print("测试数据集的长度为:{}".format(test_data_size))

# 利用 DataLoader 来加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)


# 搭建神经网络(10分类网络)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 把网络放到序列中
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3,out_channels=32,kernel_size=5,stride=1,padding=2), #输入是32x32的,输出还是32x32的(padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=32,kernel_size=5,stride=1,padding=2),  #输入输出都是16x16的(同理padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=64,kernel_size=5,stride=1,padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Flatten(),   # 展平
            nn.Linear(in_features=64*4*4,out_features=64),
            nn.Linear(in_features=64,out_features=10)
        )
    def forward(self,x):
        x = self.model(x)
        return x

# 创建网络模型
tudui = Tudui()
tudui.to(device)

# 创建损失函数
loss_fn = nn.CrossEntropyLoss()   # 分类问题可以用交叉熵
loss_fn.to(device)

# 定义优化器
learning_rate = 0.01   # 另一写法:1e-2,即1x 10^(-2)=0.01
optimizer = torch.optim.SGD(tudui.parameters(),lr=learning_rate)   # SGD 随机梯度下降

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

# 添加tensorboard
writer = SummaryWriter("../logs_train")
start_time = time.time()  # 记录下此时的时间,赋值给开始时间

for i in range(epoch):
    print("----------第{}轮训练开始-----------".format(i+1))  # i从0-9
    # 训练步骤开始
    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:  # 逢百才打印记录
            end_time = time.time()
            print(end_time - start_time)  # 第一次训练100次所花费的时间
            print("训练次数:{},loss:{}".format(total_train_step,loss.item()))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

    # 测试步骤开始
    tudui.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():  # 无梯度,不进行调优
        for data in test_dataloader:
            imgs,targets = data
            imgs = imgs.to(device)
            targets = targets.to(device)
            outputs = tudui(imgs)
            loss = loss_fn(outputs,targets)  # 该loss为部分数据在网络模型上的损失,为tensor数据类型
            # 求整体测试数据集上的误差或正确率
            total_test_loss = total_test_loss + loss.item()  # loss为tensor数据类型,而total_test_loss为普通数字
            accuracy = (outputs.argmax(1) == targets).sum()  # 1:横向比较,==:True或False,sum:计算True或False个数
            total_accuracy = total_accuracy + accuracy
        print("整体测试集上的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_test_loss,total_test_step,total_test_step)
        total_test_step += 1

        torch.save(tudui,"tudui_{}_gpu.pth".format(i))  # 每一轮保存一个结果
        print("模型已保存")

writer.close()

运行结果:

notimplementederror: module [vgg16] is missing the required

notimplementederror: module [vgg16] is missing the required

下载后复制到 PyCharm 中 Learn_Torch 的 src 文件夹下,然后将之前 test.py 中的路径修改为:

model = torch.load("tudui_29_gpu.pth")

运行后报错,报错提示:

RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor) should be the same or input should be a MKLDNN tensor and weight is a dense tensor

原因:采用GPU训练的模型,在CPU上加载,要从GPU上映射到CPU上(在不同环境中加载已经训练好的模型,需要经过映射)

解决:

model = torch.load("tudui_29_gpu.pth",map_location=torch.device('cpu'))

-------------------------------------------------------------------------------------------------------------------------------- 

test.py(把训练模型运用到实际环境中)完整代码

# 如何从test.py文件去找到dog文件(相对路径)
import torch
import torchvision.transforms
from PIL import Image
from torch import nn

image_path = "../imgs/airplane.png"  # 或右键-> Copy Path-> Absolute Path(绝对路径)
# 读取图片(PIL Image),再用ToTensor进行转换
image = Image.open(image_path)  # 现在的image是PIL类型
print(image)  # <PIL.PngImagePlugin.PngImageFile image mode=RGB size=430x247 at 0x1DF29D33AF0>

# image = image.convert('RGB')
# 因为png格式是四通道,除了RGB三通道外,还有一个透明度通道,所以要调用上述语句保留其颜色通道
# 当然,如果图片本来就是三颜色通道,经过此操作,不变
# 加上这一步后,可以适应 png jpg 各种格式的图片

# 该image大小为430x247,网络模型的输入只能是32x32,进行一个Resize()
# Compose():把transforms几个变换联立在一起
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),  # 32x32大小的PIL Image
                                            torchvision.transforms.ToTensor()])  # 转为Tensor数据类型
image = transform(image)
print(image.shape)  # torch.Size([3, 32, 32])

# 加载网络模型(之前采用的是第一种方式保存,故需要采用第一种方式加载)
# 首先搭建神经网络(10分类网络)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 把网络放到序列中
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3,out_channels=32,kernel_size=5,stride=1,padding=2), #输入是32x32的,输出还是32x32的(padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=32,kernel_size=5,stride=1,padding=2),  #输入输出都是16x16的(同理padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=64,kernel_size=5,stride=1,padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Flatten(),   # 展平
            nn.Linear(in_features=64*4*4,out_features=64),
            nn.Linear(in_features=64,out_features=10)
        )
    def forward(self,x):
        x = self.model(x)
        return x
# 然后加载网络模型
model = torch.load("tudui_29_gpu.pth",map_location=torch.device('cpu'))  # 因为test.py和tudui_0.pth在同一个层级下,所以地址可以直接写
print(model)
image = torch.reshape(image,(1,3,32,32))
model.eval()  # 模型转化为测试类型
with torch.no_grad():
    output = model(image)
print(output)
print(output.argmax(1))

-------------------------------------------------------------------------------------------------------------------------------- 

示例二

再以飞机的图片为例(airplane.png 保存在 imgs 文件夹里)

# 如何从test.py文件去找到dog文件(相对路径)
import torch
import torchvision.transforms
from PIL import Image
from torch import nn

image_path = "../imgs/airplane.png"  # 或右键-> Copy Path-> Absolute Path(绝对路径)
# 读取图片(PIL Image),再用ToTensor进行转换
image = Image.open(image_path)  # 现在的image是PIL类型
print(image)  # <PIL.PngImagePlugin.PngImageFile image mode=RGB size=430x247 at 0x1DF29D33AF0>

# image = image.convert('RGB')
# 因为png格式是四通道,除了RGB三通道外,还有一个透明度通道,所以要调用上述语句保留其颜色通道
# 当然,如果图片本来就是三颜色通道,经过此操作,不变
# 加上这一步后,可以适应 png jpg 各种格式的图片

# 该image大小为430x247,网络模型的输入只能是32x32,进行一个Resize()
# Compose():把transforms几个变换联立在一起
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),  # 32x32大小的PIL Image
                                            torchvision.transforms.ToTensor()])  # 转为Tensor数据类型
image = transform(image)
print(image.shape)  # torch.Size([3, 32, 32])

# 加载网络模型(之前采用的是第一种方式保存,故需要采用第一种方式加载)
# 首先搭建神经网络(10分类网络)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 把网络放到序列中
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3,out_channels=32,kernel_size=5,stride=1,padding=2), #输入是32x32的,输出还是32x32的(padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=32,kernel_size=5,stride=1,padding=2),  #输入输出都是16x16的(同理padding经计算为2)
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32,out_channels=64,kernel_size=5,stride=1,padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Flatten(),   # 展平
            nn.Linear(in_features=64*4*4,out_features=64),
            nn.Linear(in_features=64,out_features=10)
        )
    def forward(self,x):
        x = self.model(x)
        return x
# 然后加载网络模型
model = torch.load("tudui_29_gpu.pth",map_location=torch.device('cpu'))  # 因为test.py和tudui_0.pth在同一个层级下,所以地址可以直接写
print(model)
image = torch.reshape(image,(1,3,32,32))
model.eval()  # 模型转化为测试类型
with torch.no_grad():
    output = model(image)
print(output)
print(output.argmax(1))  # 把输出转换为一种利于解读的方式

运行结果:

notimplementederror: module [vgg16] is missing the required

第 0 类就是 airplane,预测正确 

注意:

model.eval()  # 模型转化为测试类型
with torch.no_grad():

这两行不写也可以,但为了养成良好的代码习惯,最好写上。如果网络模型中正好有 Dropout 或 BatchNorm 时,不写的话预测就会有问题


26. 看看开源项目

notimplementederror: module [vgg16] is missing the required

GitHub - junyanz/pytorch-CycleGAN-and-pix2pix: Image-to-Image Translation in PyTorch

README.md 

先读 README.md(怎么安装、注意事项)

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

train.py

"""General-purpose training script for image-to-image translation.

This script works for various models (with option '--model': e.g., pix2pix, cyclegan, colorization) and
different datasets (with option '--dataset_mode': e.g., aligned, unaligned, single, colorization).
You need to specify the dataset ('--dataroot'), experiment name ('--name'), and model ('--model').

It first creates model, dataset, and visualizer given the option.
It then does standard network training. During the training, it also visualize/save the images, print/save the loss plot, and save models.
The script supports continue/resume training. Use '--continue_train' to resume your previous training.

Example:
    Train a CycleGAN model:
        python train.py --dataroot ./datasets/maps --name maps_cyclegan --model cycle_gan
    Train a pix2pix model:
        python train.py --dataroot ./datasets/facades --name facades_pix2pix --model pix2pix --direction BtoA

See options/base_options.py and options/train_options.py for more training options.
See training and test tips at: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/master/docs/tips.md
See frequently asked questions at: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/master/docs/qa.md
"""
import time
from options.train_options import TrainOptions
from data import create_dataset
from models import create_model
from util.visualizer import Visualizer

if __name__ == '__main__':
    opt = TrainOptions().parse()   # get training options
    dataset = create_dataset(opt)  # create a dataset given opt.dataset_mode and other options
    dataset_size = len(dataset)    # get the number of images in the dataset.
    print('The number of training images = %d' % dataset_size)

    model = create_model(opt)      # create a model given opt.model and other options
    model.setup(opt)               # regular setup: load and print networks; create schedulers
    visualizer = Visualizer(opt)   # create a visualizer that display/save images and plots
    total_iters = 0                # the total number of training iterations

    for epoch in range(opt.epoch_count, opt.n_epochs + opt.n_epochs_decay + 1):    # outer loop for different epochs; we save the model by <epoch_count>, <epoch_count>+<save_latest_freq>
        epoch_start_time = time.time()  # timer for entire epoch
        iter_data_time = time.time()    # timer for data loading per iteration
        epoch_iter = 0                  # the number of training iterations in current epoch, reset to 0 every epoch
        visualizer.reset()              # reset the visualizer: make sure it saves the results to HTML at least once every epoch
        model.update_learning_rate()    # update learning rates in the beginning of every epoch.
        for i, data in enumerate(dataset):  # inner loop within one epoch
            iter_start_time = time.time()  # timer for computation per iteration
            if total_iters % opt.print_freq == 0:
                t_data = iter_start_time - iter_data_time

            total_iters += opt.batch_size
            epoch_iter += opt.batch_size
            model.set_input(data)         # unpack data from dataset and apply preprocessing
            model.optimize_parameters()   # calculate loss functions, get gradients, update network weights

            if total_iters % opt.display_freq == 0:   # display images on visdom and save images to a HTML file
                save_result = total_iters % opt.update_html_freq == 0
                model.compute_visuals()
                visualizer.display_current_results(model.get_current_visuals(), epoch, save_result)

            if total_iters % opt.print_freq == 0:    # print training losses and save logging information to the disk
                losses = model.get_current_losses()
                t_comp = (time.time() - iter_start_time) / opt.batch_size
                visualizer.print_current_losses(epoch, epoch_iter, losses, t_comp, t_data)
                if opt.display_id > 0:
                    visualizer.plot_current_losses(epoch, float(epoch_iter) / dataset_size, losses)

            if total_iters % opt.save_latest_freq == 0:   # cache our latest model every <save_latest_freq> iterations
                print('saving the latest model (epoch %d, total_iters %d)' % (epoch, total_iters))
                save_suffix = 'iter_%d' % total_iters if opt.save_by_iter else 'latest'
                model.save_networks(save_suffix)

            iter_data_time = time.time()
        if epoch % opt.save_epoch_freq == 0:              # cache our model every <save_epoch_freq> epochs
            print('saving the model at the end of epoch %d, iters %d' % (epoch, total_iters))
            model.save_networks('latest')
            model.save_networks(epoch)

        print('End of epoch %d / %d \t Time Taken: %d sec' % (epoch, opt.n_epochs + opt.n_epochs_decay, time.time() - epoch_start_time))

notimplementederror: module [vgg16] is missing the required

-------------------------------------------------------------------------------------------------------------------------------- 

训练参数设置

notimplementederror: module [vgg16] is missing the required

from .base_options import BaseOptions


class TrainOptions(BaseOptions):
    """This class includes training options.

    It also includes shared options defined in BaseOptions.
    """

    def initialize(self, parser):
        parser = BaseOptions.initialize(self, parser)
        # visdom and HTML visualization parameters
        parser.add_argument('--display_freq', type=int, default=400, help='frequency of showing training results on screen')
        parser.add_argument('--display_ncols', type=int, default=4, help='if positive, display all images in a single visdom web panel with certain number of images per row.')
        parser.add_argument('--display_id', type=int, default=1, help='window id of the web display')
        parser.add_argument('--display_server', type=str, default="http://localhost", help='visdom server of the web display')
        parser.add_argument('--display_env', type=str, default='main', help='visdom display environment name (default is "main")')
        parser.add_argument('--display_port', type=int, default=8097, help='visdom port of the web display')
        parser.add_argument('--update_html_freq', type=int, default=1000, help='frequency of saving training results to html')
        parser.add_argument('--print_freq', type=int, default=100, help='frequency of showing training results on console')
        parser.add_argument('--no_html', action='store_true', help='do not save intermediate training results to [opt.checkpoints_dir]/[opt.name]/web/')
        # network saving and loading parameters
        parser.add_argument('--save_latest_freq', type=int, default=5000, help='frequency of saving the latest results')
        parser.add_argument('--save_epoch_freq', type=int, default=5, help='frequency of saving checkpoints at the end of epochs')
        parser.add_argument('--save_by_iter', action='store_true', help='whether saves model by iteration')
        parser.add_argument('--continue_train', action='store_true', help='continue training: load the latest model')
        parser.add_argument('--epoch_count', type=int, default=1, help='the starting epoch count, we save the model by <epoch_count>, <epoch_count>+<save_latest_freq>, ...')
        parser.add_argument('--phase', type=str, default='train', help='train, val, test, etc')
        # training parameters
        parser.add_argument('--n_epochs', type=int, default=100, help='number of epochs with the initial learning rate')
        parser.add_argument('--n_epochs_decay', type=int, default=100, help='number of epochs to linearly decay learning rate to zero')
        parser.add_argument('--beta1', type=float, default=0.5, help='momentum term of adam')
        parser.add_argument('--lr', type=float, default=0.0002, help='initial learning rate for adam')
        parser.add_argument('--gan_mode', type=str, default='lsgan', help='the type of GAN objective. [vanilla| lsgan | wgangp]. vanilla GAN loss is the cross-entropy objective used in the original GAN paper.')
        parser.add_argument('--pool_size', type=int, default=50, help='the size of image buffer that stores previously generated images')
        parser.add_argument('--lr_policy', type=str, default='linear', help='learning rate policy. [linear | step | plateau | cosine]')
        parser.add_argument('--lr_decay_iters', type=int, default=50, help='multiply by a gamma every lr_decay_iters iterations')

        self.isTrain = True
        return parser

notimplementederror: module [vgg16] is missing the required

没有dataroot 

notimplementederror: module [vgg16] is missing the required

点进其继承的父类查看,可以看到有dataroot 

notimplementederror: module [vgg16] is missing the required

下载代码用 PyCharm 打开后,查看代码里有没有 required=True,若有,删掉 required=True ,加一个默认值 default="./dataset/maps" ,就可以在 PyCharm 里右键运行了

即找到所有 required=True 的参数,将它删去并添加上默认值default 文章来源地址https://www.toymoban.com/news/detail-810626.html

到了这里,关于【我是土堆 - PyTorch教程】学习随手记(已更新 | 已完结 | 10w字超详细版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 小土堆pytorch学习笔记001

    目录 1、Pytorch环境的配置与安装。 2、pytorch编辑器的选择 (1)pycharm (下载社区版) (2)jupyter (可以交互) 3、为什么torch.cuda.is_available()返回False 4、python学习中的两大法宝函数 (1)dir() 函数:打开、看见 (2)help()函数:说明书 5、Pycharm 及Jupyter的使用对比: (1)Pych

    2024年01月25日
    浏览(33)
  • 学习pytorch8 土堆说卷积操作

    B站小土堆视频学习笔记 https://pytorch.org/docs/stable/nn.html#convolution-layers 常用torch.nn, nn是对nn.functional的封装,使函数更易用。 卷积核从输入图像左上角,先向右遍历行,stride为1 挪一个格位置,向右遍历完,向下一格,再从左向右遍历。 卷积核和输入图像对应位置相乘后结果想

    2024年02月10日
    浏览(41)
  • 深度学习与计算机视觉教程(8) | 常见深度学习框架介绍(CV通关指南·完结)

    本系列为 斯坦福CS231n 《深度学习与计算机视觉(Deep Learning for Computer Vision)》的全套学习笔记,对应的课程视频可以在 这里 查看。更多资料获取方式见文末。 大家在前序文章中学习了很多关于神经网络的原理知识和实战技巧,在本篇内容中ShowMeAI给大家展开介绍深度学习硬件

    2024年02月19日
    浏览(47)
  • Unity 热更新基础HybridCLR:安装部署(HybridCLR手记二)

    官方地址:  关于HybridCLR (focus-creative-games.github.io) Win 下 打包时遇到 xxxxil2cpplibil2cpputilsIl2CppHashMap.h(71): error C2039: \\\'hash_compare\\\': is not a member of \\\'stdext\\\' 这是.net 7发布后最新版本vs改动打破了一些向后兼容性引起。你可以回退2022的旧版本或者使用2019之类的版本。 所以建议使用

    2024年02月10日
    浏览(40)
  • 深度学习与计算机视觉教程(3) | 损失函数与最优化(CV通关指南·完结)

    在上一篇 深度学习与计算机视觉教程(2) - 图像分类与机器学习基础 内容中,我们对线性分类器做了一些介绍,我们希望线性分类器能够准确地对图像进行分类,要有一套优化其权重参数的方法,这就是本篇ShowMeAI要给大家介绍到的损失函数与最优化相关的知识。 损失函数 数

    2024年02月20日
    浏览(42)
  • Unity 热更新基础HybridCLR:Windows平台使用(HybridCLR手记二)

    【注意:官网教程现已完善,请您访问官网进行学习,此教程现已失效,官网版本已更新至4.0以上,感谢您的观看,官网请访问:快速上手 | HybridCLR (code-philosophy.com)】 项目是根据官网的示例工程进行修改的,版本参数如下: unity:2020.3.30(2023.5.29日更新至wolong最新版,经测试依

    2024年02月01日
    浏览(42)
  • 土堆学习笔记——P28完整的模型训练套路(二)

    怎么知道模型有没有训练好?有没有达到想要的需求? 解决方法:在每轮训练之后加一个测试,在测试数据集上看效果(看损失之类的)。 注意:在测试时候不调优,仅为看效果。 还可以用tensorboard可视化损失 截图最后一行没写完[false, true].sum()=1 这个值/个数 Argmax使用 Ar

    2024年01月17日
    浏览(40)
  • mysql 学习存储过程:一次插入 10W 条记录、卡死了怎么办

    所有的存储过程必须有前缀“proc_”,所有的系统存储过程都有前缀“sp_”。 输入参数以i_开头,输出参数以o_开头。 mysql use test_20230414; mysql CREATE TABLE person ( id int NOT NULL AUTO_INCREMENT, name varchar(15) NOT NULL, PRIMARY KEY ( id ) ) ENGINE=InnoDB AUTO_INCREMENT=10001 ; 使用事务 不使用事务 查询存

    2024年02月01日
    浏览(50)
  • 大数据趣味学习探讨(二):我是怎么坚持学习的

    CSDN话题挑战赛第2期 参赛话题:大数据趣味学习探讨 文章目录 要不要学,为什么要学大数据,最好的机会没有之一 一、根本性的问题 1、打仗最重要的是什么? 2、为什么总是知行不一 二、大数据到底好在哪 1、结论 2、大数据为什么是金矿 三、体系的学习方式 1、打仗最重

    2024年01月16日
    浏览(38)
  • 2022高教社杯全国大学生数学建模竞赛B题解析(更新完结)

    B 题 无人机遂行编队飞行中的纯方位无源定位 无人机集群在遂行编队飞行时,为避免外界干扰,应尽可能保持电磁静默,少向外发射电磁波信号。为保持编队队形,拟采用纯方位无源定位的方法调整无人机的位置,即由编队中某几架无人机发射信号、其余无人机被动接收信号

    2024年02月06日
    浏览(117)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包