Pytorch的使用

Pytorch的使用

参考的视频教程:https://www.bilibili.com/video/BV1hE411t7RN?from=search&seid=1911856662818066104&spm_id_from=333.337.0.0

一、环境配置

1. 创建pytorch所需环境

  1. 先创建一个pytorch命名的新的Python环境,Python版本为3.6

conda create -n pytorch python=3.6

  1. 进入pytorch环境

conda activate pytorch

  1. 查看环境中已有的模块

conda list

换回默认安装源:

conda config --remove-key channels

2. 安装pytorch

  1. 先进入pytorch首页:https://www.pytorch.org,选择型号版本,获得下载pytorch的coda命令

  2. 然后访问:https://www.geforce.cn/hardware/technology/cuda/supported-gpus

  3. 可以通过命令:nvidia-sim查看驱动版本

  4. 令行中输入下列命令安装pytorch:

conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch

注意:由于安装不成功,转战清华源:

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes
# reference
# https://mirror.tuna.tsinghua.edu.cn/help/anaconda/

参考文章:https://blog.csdn.net/zzq060143/article/details/88042075

报错:

Solving environment: failed

CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://mirrors.ustc.edu.cn/anaconda/cloud/menpo/win-64/repodata.json>
Elapsed: -

An HTTP error occurred when trying to retrieve this URL.
HTTP errors are often intermittent, and a simple retry will get you on your way.
SSLError(MaxRetryError('HTTPSConnectionPool(host=\'mirrors.bfsu.edu.cn\', port=443): Max retries exceeded with url: /anaconda/cloud/menpo/win-64/repodata.json (Caused by SSLError(SSLError("bad handshake: Error([(\'SSL routines\', \'ssl3_get_server_certificate\', \'certificate verify failed\')])")))'))

参考文章:

(30条消息) 安装scrapy失败CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://conda.anaconda.o_与市场搏斗-CSDN博客

  1. 更新conda:

conda update -n base -c defaults conda

  1. 检查pytorch是否安装成功

输入"python",再输入"import torch"

若没有报错,就说明pytorch安装成功了。

  1. 查看pytorch是否可用显卡:

torch.cuda.is_available()

返回True,说明显卡可用。

另一种方式是先去官网将包下载下来,再利用命令安装

conda install --use-local 完整的包名

二、编辑器的选择

1. Pycharm

  • 创建项目,使用本地的pytorch环境,在Python Console中检查pytorch环境是否成功导入:

2. jupyter notebook

  • 在默认的base环境下用pip list命令查看所有包,能找到ipykernel包,它就是jupyter的包。

使用如下命令安装jupyter:

conda install nb_conda

启动jupyter:

jupyter notebook

创建新的代码。

三、dir()和help()函数的使用方法

1. Python学习当中使用的两大法宝函数

1. dir()

  • 打开,看见
  • 能让我们知道 工具箱 以及 工具箱中的分隔区 有什么东西。

举例:

dir(pytorch)

输出:1、2、3、4

dir(pytorch.3)

输出:a、b、c

2. help()

  • 说明书
  • 能让我们知道每个工具是如何使用的,工具的使用方法。

举例:

help(pytorch.3.a)

输出:将此扳手放在特定地方,然后拧动。

2. 测试

使用:

help(torch.cuda.is_available)

>>>help(torch.cuda.is_available)
Help on function is_available in module torch.cuda:
is_available() -> bool
    Returns a bool indicating if CUDA is currently available.

四、Pytorch中如何加载数据

1. Dataset

  • 提供一种方式去获取数据及其label。
    1. 如何获取每一个数据及其label。
    2. 告诉我们总共有多少的数据。

2. DataLoader

  • 为后面的网络提供不同的数据形式。

六、开始写代码

torch.cuda.is_available()    # 检查torch是否可以使用显卡
Out[4]: True
    
from PIL import Image

img_path = "C:\\Users\\lv\\Desktop\\Pytorch\\1. 第一个Pytorch项目\\dataset\\train\\ants\\6240329_72c01e663e.jpg"    # 找到图片

img = Image.open(img_path)    # 打开图片

img.show()    # 显示图片

dir_path = "dataset/train/ants"   # 添加文件夹路径变量

import os    # 导入os模块,方便操作文件夹及文件
img_path_list = os.listdir(dir_path)   # 将文件夹变量传给列表,列表中包含着每一张图片

img_path_list[0]   # 第一张图片的名称
Out[12]: '0013035.jpg'

root_dir = "dataset/train"

label_dir = "ants"

path = os.path.join(root_dir, label_dir)   # 拼接两个文件名
from torch.utils.data import Dataset
# import cv2    # pip install opencv-python
from PIL import Image
import os


# C:\\Users\\lv\\Desktop\\Pytorch\\1. 第一个Pytorch项目\\dataset\\train\\ants\\6240329_72c01e663e.jpg

class MyData(Dataset):

    def __init__(self, root_dir, label_dir):
        self.root_dir = root_dir
        self.label_dir = label_dir
        self.path = os.path.join(self.root_dir, self.label_dir)   # 拼接目录
        self.img_path = os.listdir(self.path)    # 将目录中的文件映射成列表

    def __getitem__(self, idx):
        img_name = self.img_path[idx]
        img_item_path = os.path.join(self.root_dir, self.label_dir, img_name)   # 合成图片的相对路径
        img = Image.open(img_item_path)
        label = self.label_dir
        return img, label

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


# 构造形成蚂蚁数据集:
root_dir = "dataset/train"
ants_label_dir = "ants"
ants_dataset = MyData(root_dir, ants_label_dir)
img, label = ants_dataset[0]
# img.show()

# 形成蜜蜂数据集:
bees_label_dir = "bees"
bees_dataset = MyData(root_dir, bees_label_dir)
img2, label2 = bees_dataset[0]
# img2.show()

# 整个训练集:
train_dataset = ants_dataset + bees_dataset   # 蚂蚁在前,蜜蜂在后

七、TensorBoard的使用

  • add_scalar()方法中,scalar_value对应的是坐标的y轴,global_step对应的是坐标轴的x轴。

代码

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("logs")

# writer.add_image()
# 函数y = x
for i in range(100):
    writer.add_scalar("y = x", i, i)

writer.close()

报错:

Traceback (most recent call last):
  File "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/3. Tensorboard的使用.py", line 1, in <module>
    from torch.utils.tensorboard import SummaryWriter
  File "D:\Anaconda\envs\pytorch\lib\site-packages\torch\utils\tensorboard\__init__.py", line 1, in <module>
    import tensorboard
ModuleNotFoundError: No module named 'tensorboard'

此报错是需要安装tensorboard.

pip install tensorboard

报错:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/3. Tensorboard的使用.py"
Traceback (most recent call last):
  File "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/3. Tensorboard的使用.py", line 1, in <module>
    from torch.utils.tensorboard import SummaryWriter
  File "D:\Anaconda\envs\pytorch\lib\site-packages\torch\utils\tensorboard\__init__.py", line 4, in <module>
    LooseVersion = distutils.version.LooseVersion
AttributeError: module 'distutils' has no attribute 'version'

此报错需要指定版本:

pip uninstall setuptools

pip install setuptools==59.5.0

运行成功的结果中生成了logs文件夹及相应日志文件。

在终端(Terminal)内运行命令:

tensorboard --logdir=logs

(pytorch) C:\Users\lv\Desktop\Pytorch\1. 第一个Pytorch项目>tensorboard --logdir=logs
TensorFlow installation not found - running with reduced feature set.
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.8.0 at http://localhost:6006/ (Press CTRL+C to quit)

指定端口:

tensorboard --logdir=logs --port=6006

  • 设置成其他端口也可,避免端口冲突。

代码:

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter("logs")

# writer.add_image()
# 函数y = x
for i in range(100):
    writer.add_scalar("y = x", i, i)     # 第一个i是y轴,第二个i是x轴
    writer.add_scalar("y = 2x", 2 * i, i)     # 第一个i是y轴,第二个i是x轴
    writer.add_scalar("y = 3x", 3 * i, i)     # 第一个i是y轴,第二个i是x轴

writer.close()
  • 运行结果:
    在这里插入图片描述
    Pytorch的使用_第1张图片

使用add_image()方法

  • 根据源码的img_tensor (torch.Tensor, numpy.array, or string/blobname): Image data,传入的图片参数是需要满足以上任一类型的图片。
    Pytorch的使用_第2张图片
    从控制台中可以看到:
    Pytorch的使用_第3张图片
    PIL的Image库封装的图片并不满足,所以需要用opencv库来生成numpy类型的图片。
  • 首先需要先安装opencv模块:

pip install opencv-python

安装完成后,用numpy。array()方法对PIL图片进行转换。
转换步骤如下:

image_path = "dataset2/train/ants_image/0013035.jpg"
from PIL import Image
img = Image.open(image_path)
print(type(img))   # 

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

writer.py代码

  • 从PIL到numpy,需要在add_image()中指定shape中的每一个数字/维表示的含义。
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image
# 利用OpenCV中的numpy库可以获得numpy型的图片

writer = SummaryWriter("logs")
img_path = "dataset2/train/ants_image/0013035.jpg"
img_PIL = Image.open(img_path)  # 打开图片
img_array = np.array(img_PIL)    # 图片转换
print(type(img_array))   # 打印图片类型   
print(img_array.shape)   # 打印图片格式  (512, 768, 3) (高、宽、通道数)

writer.add_image("test", img_array, 1, dataformats='HWC')  # 根据img_array.shape来指定,如果不指定dataformats就会报错
# y = 2x
for i in range(100):
    writer.add_scalar("y = 2x", 2*i, i)

writer.close()

运行结果:
Pytorch的使用_第4张图片
能够看到tensorboard里面多了一张蚂蚁的图片:
Pytorch的使用_第5张图片
再对图片和步骤进行更改如下:

from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image
# 利用OpenCV中的numpy库可以获得numpy型的图片

writer = SummaryWriter("logs")
# img_path = "dataset2/train/ants_image/0013035.jpg"
img_path = "dataset2/train/bees_image/16838648_415acd9e3f.jpg"
img_PIL = Image.open(img_path)  # 打开图片
img_array = np.array(img_PIL)    # 图片转换
print(type(img_array))   # 打印图片类型   
print(img_array.shape)   # 打印图片格式  (512, 768, 3) (高、宽、通道数)

# writer.add_image("test", img_array, 1, dataformats='HWC')     # 根据img_array.shape来指定,如果不指定dataformats就会报错
writer.add_image("test", img_array, 2, dataformats='HWC')     # 根据img_array.shape来指定,如果不指定dataformats就会报错
# y = 2x
for i in range(100):
    writer.add_scalar("y = 2x", 2*i, i)

writer.close()

再次运行结果如下:
Pytorch的使用_第6张图片
Pytorch的使用_第7张图片
拖动上面的轴线,能够切换图片:
Pytorch的使用_第8张图片
这是由于添加图片时,title都是test没有变化,所以两张图片在同一个区域上显示。

  • 对title进行修改:
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image
# 利用OpenCV中的numpy库可以获得numpy型的图片

writer = SummaryWriter("logs")
# img_path = "dataset2/train/ants_image/0013035.jpg"
# img_path = "dataset2/train/bees_image/16838648_415acd9e3f.jpg"
img_path = "dataset2/train/ants_image/20935278_9190345f6b.jpg"
img_PIL = Image.open(img_path)  # 打开图片
img_array = np.array(img_PIL)    # 图片转换
print(type(img_array))   # 打印图片类型   
print(img_array.shape)   # 打印图片格式  (512, 768, 3) (高、宽、通道数)

# writer.add_image("test", img_array, 1, dataformats='HWC')     # 根据img_array.shape来指定,如果不指定dataformats就会报错
# writer.add_image("test", img_array, 2, dataformats='HWC')     # 根据img_array.shape来指定,如果不指定dataformats就会报错
writer.add_image("test2", img_array, 1, dataformats='HWC')     # 根据img_array.shape来指定,如果不指定dataformats就会报错
# y = 2x
for i in range(100):
    writer.add_scalar("y = 2x", 2*i, i)

writer.close()

运行效果如下:
Pytorch的使用_第9张图片
Pytorch的使用_第10张图片

八、Transforms的使用

Pytorch的使用_第11张图片

  • 查看图片信息:
# transform表示对图片进行一些变换
# python的用法 -> tensor数据类型
# 通过transform.ToTensor去解决两个问题:
#   transforms该如何使用(Python)?
#   为什么我们需要Tensor的数据类型?
from torchvision import transforms
from PIL import Image

# 绝对路径:C:\Users\lv\Desktop\Pytorch\1. 第一个Pytorch项目\dataset2\train\ants_image\0013035.jpg
# 相对路径:dataset2/train/ants_image/0013035.jpg
img_path = "dataset2/train/ants_image/0013035.jpg"
img = Image.open(img_path)
print(img)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/5. transforms的使用.py"
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=768x512 at 0x1A36EA4DF28>

Process finished with exit code 0
  • 如何使用tensorforms:
# transform表示对图片进行一些变换
# python的用法 -> tensor数据类型
# 通过transform.ToTensor去解决两个问题:
#   transforms该如何使用(Python)?
#   为什么我们需要Tensor的数据类型?
from torchvision import transforms
from PIL import Image

# 绝对路径:C:\Users\lv\Desktop\Pytorch\1. 第一个Pytorch项目\dataset2\train\ants_image\0013035.jpg
# 相对路径:dataset2/train/ants_image/0013035.jpg
img_path = "dataset2/train/ants_image/0013035.jpg"
img = Image.open(img_path)
# print(img)
# transforms该如何使用(Python)
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)

print(tensor_img)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/5. transforms的使用.py"
tensor([[[0.3137, 0.3137, 0.3137,  ..., 0.3176, 0.3098, 0.2980],
         [0.3176, 0.3176, 0.3176,  ..., 0.3176, 0.3098, 0.2980],
         [0.3216, 0.3216, 0.3216,  ..., 0.3137, 0.3098, 0.3020],
         ...,
         [0.3412, 0.3412, 0.3373,  ..., 0.1725, 0.3725, 0.3529],
         [0.3412, 0.3412, 0.3373,  ..., 0.3294, 0.3529, 0.3294],
         [0.3412, 0.3412, 0.3373,  ..., 0.3098, 0.3059, 0.3294]],

        [[0.5922, 0.5922, 0.5922,  ..., 0.5961, 0.5882, 0.5765],
         [0.5961, 0.5961, 0.5961,  ..., 0.5961, 0.5882, 0.5765],
         [0.6000, 0.6000, 0.6000,  ..., 0.5922, 0.5882, 0.5804],
         ...,
         [0.6275, 0.6275, 0.6235,  ..., 0.3608, 0.6196, 0.6157],
         [0.6275, 0.6275, 0.6235,  ..., 0.5765, 0.6275, 0.5961],
         [0.6275, 0.6275, 0.6235,  ..., 0.6275, 0.6235, 0.6314]],

        [[0.9137, 0.9137, 0.9137,  ..., 0.9176, 0.9098, 0.8980],
         [0.9176, 0.9176, 0.9176,  ..., 0.9176, 0.9098, 0.8980],
         [0.9216, 0.9216, 0.9216,  ..., 0.9137, 0.9098, 0.9020],
         ...,
         [0.9294, 0.9294, 0.9255,  ..., 0.5529, 0.9216, 0.8941],
         [0.9294, 0.9294, 0.9255,  ..., 0.8863, 1.0000, 0.9137],
         [0.9294, 0.9294, 0.9255,  ..., 0.9490, 0.9804, 0.9137]]])

Process finished with exit code 0

Pytorch的使用_第12张图片

  • 加载tensor类型的图片:
# transform表示对图片进行一些变换
# python的用法 -> tensor数据类型
# 通过transform.ToTensor去解决两个问题:
#   transforms该如何使用(Python)?
#   为什么我们需要Tensor的数据类型?
#       因为Tensor包装了反向神经网络所需要的理论基础的一些参数
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from PIL import Image

# 绝对路径:C:\Users\lv\Desktop\Pytorch\1. 第一个Pytorch项目\dataset2\train\ants_image\0013035.jpg
# 相对路径:dataset2/train/ants_image/0013035.jpg
img_path = "dataset2/train/ants_image/0013035.jpg"
img = Image.open(img_path)

writer = SummaryWriter("logs")

# print(img)
# transforms该如何使用(Python)
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)

# print(tensor_img)

writer.add_image("Tensor_img", tensor_img)
writer.close()

运行结果:
Pytorch的使用_第13张图片

九、常见的transforms类的使用

Pytorch的使用_第14张图片

拓展:call()方法的使用

class Person:
    def __call__(self, name):
        print("__call__" + "Hello" + name)

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

# Ctrl + P 查看方法的参数传入方式


person = Person()
person("zhangsan")   # 通过__call__方法可以以此方式来调用
person.hello("lisi")

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/test/CallTest.py"
__call__Hellozhangsan
hellolisi

Process finished with exit code 0

1. ToTensor类

  • 将PIL图片转换成tensor图片。
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter


# Tensor的使用:
writer = SummaryWriter("logs")   # 写入日志
img = Image.open("images/dog.jpg")
print(img)   # 

trans_totensor = transforms.ToTensor()   # 创建ToTensor()对象
img_tensor = trans_totensor(img)   # 传入图片参数,将PIL图片转换成tensor图片

writer.add_image("ToTensor", img_tensor)
writer.close()

运行结果:
Pytorch的使用_第15张图片

2. Normalize类

  • 对tensor类型的图片进行归一化处理。
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter


# Tensor的使用:
writer = SummaryWriter("logs")   # 写入日志
img = Image.open("images/dog.jpg")
print(img)   # 

# ToTensor()的使用
trans_totensor = transforms.ToTensor()   # 创建ToTensor()对象
img_tensor = trans_totensor(img)   # 传入图片参数,将PIL图片转换成tensor图片
writer.add_image("ToTensor", img_tensor)

# Normalize的使用:归一化处理
# 公式:output[channel] = (input[channel] - mean[channel]) / std[channel]
print(img_tensor[0][0][0])   # 归一化处理之前的数据
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])    # 归一化处理之后的结果
writer.add_image("Normalize", img_norm)   # 在tensosrboard中显示

writer.close()

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/6. transforms中常用的方法.py"
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x2766C742DD8>
tensor(0.9255)
tensor(0.8510)

Process finished with exit code 0

Pytorch的使用_第16张图片
更改trans_norm如下:

trans_norm = transforms.Normalize([1, 3, 5], [3, 2, 1])

writer.add_image("Normalize", img_norm, 1)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/6. transforms中常用的方法.py"
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x18CF7692D68>
tensor(0.9255)
tensor(-0.0248)

Process finished with exit code 0

Pytorch的使用_第17张图片
更改trans_norm如下:

trans_norm = transforms.Normalize([6, 3, 2], [9, 3, 5])

writer.add_image("Normalize", img_norm, 2)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/6. transforms中常用的方法.py"
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x18CF7692D68>
tensor(0.9255)
tensor(-0.5638)

Process finished with exit code 0

Pytorch的使用_第18张图片

3. Resize类:

  • 重置图片大小。
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter


writer = SummaryWriter("logs")   # 写入日志
img = Image.open("images/dog.jpg")
print(img)   # 

# ToTensor()的使用:将PIL图片转换成tensor图片
trans_totensor = transforms.ToTensor()   # 创建ToTensor()对象
img_tensor = trans_totensor(img)   # 传入图片参数,将PIL图片转换成tensor图片
writer.add_image("ToTensor", img_tensor)

# Normalize的使用:归一化处理tensor类型的图片
# 公式:output[channel] = (input[channel] - mean[channel]) / std[channel]
print(img_tensor[0][0][0])   # 归一化处理之前的数据
# trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
# trans_norm = transforms.Normalize([1, 3, 5], [3, 2, 1])
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)
# writer.add_image("Normalize", img_norm, 1)
writer.add_image("Normalize", img_norm, 2)

# Resize的使用:重置图片大小
print(img.size)   # (1400, 875)
trans_resize = transforms.Resize((512, 512))
# img PIL -> resize -> img_resize PIL
img_resize = trans_resize(img)
print(img_resize)   # 
# img_resize PIL -> totensor -> img_resize Tensor
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize, 0)
print(img_resize)
writer.close()

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/6. transforms中常用的方法.py"
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x1DBDC3B3E10>
tensor(0.9255)
tensor(-0.5638)
(1400, 875)
<PIL.Image.Image image mode=RGB size=512x512 at 0x1DBD54734E0>
tensor([[[0.9255, 0.9294, 0.9294,  ..., 0.9294, 0.9294, 0.9294],
         [0.9294, 0.9333, 0.9333,  ..., 0.9294, 0.9294, 0.9333],
         [0.9255, 0.9294, 0.9333,  ..., 0.9294, 0.9294, 0.9294],
         ...,
         [0.8745, 0.8706, 0.8667,  ..., 0.8588, 0.8549, 0.8588],
         [0.8706, 0.8706, 0.8667,  ..., 0.8549, 0.8549, 0.8588],
         [0.8706, 0.8667, 0.8667,  ..., 0.8549, 0.8549, 0.8588]],

        [[0.9255, 0.9294, 0.9294,  ..., 0.9294, 0.9294, 0.9294],
         [0.9294, 0.9333, 0.9333,  ..., 0.9294, 0.9294, 0.9333],
         [0.9255, 0.9294, 0.9333,  ..., 0.9294, 0.9294, 0.9294],
         ...,
         [0.8824, 0.8784, 0.8745,  ..., 0.8627, 0.8627, 0.8667],
         [0.8784, 0.8784, 0.8745,  ..., 0.8549, 0.8588, 0.8667],
         [0.8784, 0.8745, 0.8745,  ..., 0.8549, 0.8627, 0.8667]],

        [[0.9255, 0.9294, 0.9294,  ..., 0.9294, 0.9294, 0.9294],
         [0.9294, 0.9333, 0.9333,  ..., 0.9294, 0.9294, 0.9333],
         [0.9255, 0.9294, 0.9333,  ..., 0.9294, 0.9294, 0.9294],
         ...,
         [0.8745, 0.8745, 0.8706,  ..., 0.8549, 0.8510, 0.8549],
         [0.8745, 0.8745, 0.8706,  ..., 0.8471, 0.8510, 0.8549],
         [0.8745, 0.8706, 0.8667,  ..., 0.8431, 0.8471, 0.8549]]])

Process finished with exit code 0

Pytorch的使用_第19张图片

4. Compose的使用

  • 等比例缩放。
  • Compose的使用:整体缩放,不改变高宽比例
  • Compose()中的参数需要的是一个列表,列表中的数据需要的是transforms类型。
  • 即 Compose([transforms参数1, transforms参数2, …])
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter


writer = SummaryWriter("logs")   # 写入日志
img = Image.open("images/dog.jpg")
print(img)   # 

# ToTensor()的使用:将PIL图片转换成tensor图片
trans_totensor = transforms.ToTensor()   # 创建ToTensor()对象
img_tensor = trans_totensor(img)   # 传入图片参数,将PIL图片转换成tensor图片
writer.add_image("ToTensor", img_tensor)

# Normalize的使用:归一化处理tensor类型的图片
# 公式:output[channel] = (input[channel] - mean[channel]) / std[channel]
print(img_tensor[0][0][0])   # 归一化处理之前的数据
# trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
# trans_norm = transforms.Normalize([1, 3, 5], [3, 2, 1])
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)
# writer.add_image("Normalize", img_norm, 1)
writer.add_image("Normalize", img_norm, 2)

# Resize的使用:重置图片大小
print(img.size)   # (1400, 875)
trans_resize = transforms.Resize((512, 512))
# img PIL -> resize -> img_resize PIL
img_resize = trans_resize(img)
print(img_resize)   # 
# img_resize PIL -> totensor -> img_resize Tensor
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize, 0)
# print(img_resize)

# Compose的使用:整体缩放,不改变高宽比例
# Compose()中的参数需要的是一个列表,列表中的数据需要的是transforms类型。
# 即 Compose([transforms参数1, transforms参数2, ...])
trans_resize_2 = transforms.Resize(512)
# PIL -> PIL -> tensor
trans_compose = transforms.Compose([trans_resize_2, trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2, 1)

writer.close()

运行结果:
Pytorch的使用_第20张图片

5. RandomCrop类的使用

  • 随机裁剪。
from PIL import Image
from torchvision import transforms
from torch.utils.tensorboard import SummaryWriter


writer = SummaryWriter("logs")   # 写入日志
img = Image.open("images/dog.jpg")
print(img)   # 

# ToTensor()的使用:将PIL图片转换成tensor图片
trans_totensor = transforms.ToTensor()   # 创建ToTensor()对象
img_tensor = trans_totensor(img)   # 传入图片参数,将PIL图片转换成tensor图片
writer.add_image("ToTensor", img_tensor)

# Normalize的使用:归一化处理tensor类型的图片
# 公式:output[channel] = (input[channel] - mean[channel]) / std[channel]
print(img_tensor[0][0][0])   # 归一化处理之前的数据
# trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
# trans_norm = transforms.Normalize([1, 3, 5], [3, 2, 1])
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)
# writer.add_image("Normalize", img_norm, 1)
writer.add_image("Normalize", img_norm, 2)

# Resize的使用:重置图片大小
print(img.size)   # (1400, 875)
trans_resize = transforms.Resize((512, 512))
# img PIL -> resize -> img_resize PIL
img_resize = trans_resize(img)
print(img_resize)   # 
# img_resize PIL -> totensor -> img_resize Tensor
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize, 0)
# print(img_resize)

# Compose的使用:整体缩放,不改变高宽比例
# Compose()中的参数需要的是一个列表,列表中的数据需要的是transforms类型。
trans_resize_2 = transforms.Resize(512)
# PIL -> PIL -> tensor
trans_compose = transforms.Compose([trans_resize_2, trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2, 1)


# RendomCrop类的使用:随机裁剪
# trans_random = transforms.RandomCrop(512)
trans_random = transforms.RandomCrop(1000, 500)
trans_compose_2 = transforms.Compose([trans_random, trans_totensor])
for i in range(10):
    img_crop = trans_compose_2(img)
    # writer.add_image("RancomCrop", img_crop, i)
    writer.add_image("RancomCropHW", img_crop, i)


writer.close()

运行结果:
Pytorch的使用_第21张图片

6. 使用方法总结

  • 关注方法的输入输出的类型。
    • 若不确定方法的返回值时,可以直接用print()方法打印结果来进行查看。(print)
    • 还可以在print()方法哪里打断点。(Debug)
  • 多看官方文档,比一般别人的回答要准确。
  • 关注方法需要什么参数。

十、torchvision中的数据集使用

数据集地址:https://pytorch.org/vision/stable/index.html

  • CIFAR-10(用于物体识别):https://www.cs.toronto.edu/~kriz/cifar.html

1. 通过torchivision代码下载数据集

# CIFAR-10官方文档:https://pytorch.org/vision/stable/generated/torchvision.datasets.CIFAR10.html#torchvision.datasets.CIFAR10
import torchvision

train_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=True, download=True)   # 创建训练集
test_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=False, download=True)   # 创建测试集

运行上面的代码即可下载CIFAR10的数据集:
Pytorch的使用_第22张图片

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. 第一个Pytorch项目/7. dataset和transform的联合使用.py"
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./7. dataset\cifar-10-python.tar.gz
100.0%
Extracting ./7. dataset\cifar-10-python.tar.gz to ./7. dataset
Files already downloaded and verified

Process finished with exit code 0

2. 查看torchvision下载下来的数据集

import torchvision

train_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=True, download=True)   # 创建训练集
test_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=False, download=True)   # 创建测试集

print(test_set[0])  # (, 3)
print(test_set.classes)   # 查看所有类别
# ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

img, target = test_set[0]  # 分别获取图片、所属类别的下标(从0开始)
print(img)  # 
print(target)    # 3
print(test_set.classes[target])   # cat
img.show()

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/7. dataset和transform的联合使用.py"
Files already downloaded and verified
Files already downloaded and verified
(<PIL.Image.Image image mode=RGB size=32x32 at 0x210ECE83550>, 3)
['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
<PIL.Image.Image image mode=RGB size=32x32 at 0x210ECE83390>
3
cat

Process finished with exit code 0

3. 将torchvision和transform结合起来使用

1. 将PIL类型的图片转换成Tensor数据类型的图片

import torchvision

# 使用transform:   // 将PIL图片转换为Totensor图片
dataset_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])

train_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=True, transform=dataset_transform, download=True)   # 创建训练集
test_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=False, transform=dataset_transform, download=True)   # 创建测试集

print(test_set[0])

运行结果如下:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/7. dataset和transform的联合使用.py"
Files already downloaded and verified
Files already downloaded and verified
(tensor([[[0.6196, 0.6235, 0.6471,  ..., 0.5373, 0.4941, 0.4549],
         [0.5961, 0.5922, 0.6235,  ..., 0.5333, 0.4902, 0.4667],
         [0.5922, 0.5922, 0.6196,  ..., 0.5451, 0.5098, 0.4706],
         ...,
         [0.2667, 0.1647, 0.1216,  ..., 0.1490, 0.0510, 0.1569],
         [0.2392, 0.1922, 0.1373,  ..., 0.1020, 0.1137, 0.0784],
         [0.2118, 0.2196, 0.1765,  ..., 0.0941, 0.1333, 0.0824]],

        [[0.4392, 0.4353, 0.4549,  ..., 0.3725, 0.3569, 0.3333],
         [0.4392, 0.4314, 0.4471,  ..., 0.3725, 0.3569, 0.3451],
         [0.4314, 0.4275, 0.4353,  ..., 0.3843, 0.3725, 0.3490],
         ...,
         [0.4863, 0.3922, 0.3451,  ..., 0.3804, 0.2510, 0.3333],
         [0.4549, 0.4000, 0.3333,  ..., 0.3216, 0.3216, 0.2510],
         [0.4196, 0.4118, 0.3490,  ..., 0.3020, 0.3294, 0.2627]],

        [[0.1922, 0.1843, 0.2000,  ..., 0.1412, 0.1412, 0.1294],
         [0.2000, 0.1569, 0.1765,  ..., 0.1216, 0.1255, 0.1333],
         [0.1843, 0.1294, 0.1412,  ..., 0.1333, 0.1333, 0.1294],
         ...,
         [0.6941, 0.5804, 0.5373,  ..., 0.5725, 0.4235, 0.4980],
         [0.6588, 0.5804, 0.5176,  ..., 0.5098, 0.4941, 0.4196],
         [0.6275, 0.5843, 0.5176,  ..., 0.4863, 0.5059, 0.4314]]]), 3)

Process finished with exit code 0

2. 将dataset中的图片显示在tensorboard上

# CIFAR-10官方文档:https://pytorch.org/vision/stable/generated/torchvision.datasets.CIFAR10.html#torchvision.datasets.CIFAR10
import torchvision
from torch.utils.tensorboard import SummaryWriter

# 使用transform:   // 将PIL图片转换为Totensor图片
dataset_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])

train_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=True, transform=dataset_transform, download=True)   # 创建训练集
test_set = torchvision.datasets.CIFAR10(root="./7. dataset", train=False, transform=dataset_transform, download=True)   # 创建测试集

writer = SummaryWriter("7. logs")    # 通过在终端用命令:tensorboard --logdir="7. logs"   打开tensorboard面板入口
for i in range(10):
    img, target = test_set[i]
    writer.add_image("test_set", img, i)    # Ctrl + P 弹出方法的提示

writer.close()

# 视频地址:https://www.bilibili.com/video/BV1hE411t7RN?p=14&spm_id_from=pageDriver

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/7. dataset和transform的联合使用.py"
Files already downloaded and verified
Files already downloaded and verified

Process finished with exit code 0

终端:

(pytorch) C:\Users\lv\Desktop\Pytorch\1. Pytorch的
使用(第一次)>tensorboard --logdir="7. logs"
TensorFlow installation not found - running with reduced feature set.
Serving TensorBoard on localhost; to expose to the network, use a proxy
 or pass --bind_all
TensorBoard 2.8.0 at http://localhost:6006/ (Press CTRL+C to quit)

TensorBoard中的结果:
Pytorch的使用_第23张图片
Pytorch的使用_第24张图片

Pytorch的使用_第25张图片

十、DataLoader的使用

Pytorch的使用_第26张图片

1. 查看测试数据集中的第一张图片及其target下标

# 官方参考文档:https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader
import torchvision

# 准备的测试数据集:
from torch.utils.data import DataLoader

test_data = torchvision.datasets.CIFAR10("./7. dataset", train=False, transform=torchvision.transforms.ToTensor())

# 导入测试集
test_loader = DataLoader(dataset=test_data, batch_size=4, shuffle=True, num_workers=0, drop_last=False)
# batch_size表示一次性从数据集中抽取多少个,shuffle表示是否打乱顺序

# 测试数据集中的第一张图片及其target下标
img, target = test_data[0]
print(img.shape)   # torch.Size([3, 32, 32])
print(target)   # 3
print(test_data.classes)   # ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/8. dataloader的使用.py"
torch.Size([3, 32, 32])
3
['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

Process finished with exit code 0

2. 查看用DateLoader封装后的数据

# 官方参考文档:https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader
import torchvision

# 准备的测试数据集:
from torch.utils.data import DataLoader

test_data = torchvision.datasets.CIFAR10("./7. dataset", train=False, transform=torchvision.transforms.ToTensor())

# 导入测试集
test_loader = DataLoader(dataset=test_data, batch_size=4, shuffle=True, num_workers=0, drop_last=False)
# batch_size表示一次性从数据集中抽取多少个,shuffle表示是否打乱顺序

# 查看用DateLoader封装后的数据样式:
for data in test_loader:
    imgs, targets = data
    print(imgs.shape)
    print(targets)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/8. dataloader的使用.py"
torch.Size([4, 3, 32, 32])
tensor([0, 1, 3, 4])
torch.Size([4, 3, 32, 32])
tensor([5, 9, 7, 4])
torch.Size([4, 3, 32, 32])
tensor([9, 0, 4, 7])
torch.Size([4, 3, 32, 32])
tensor([4, 6, 1, 1])
torch.Size([4, 3, 32, 32])
tensor([0, 8, 8, 9])
.......

3. 将图片加载到Tensorboard中查看

1. drop_last=False(不舍去不足64张的图片)

# 官方参考文档:https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader
import torchvision

# 准备的测试数据集:
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10("./7. 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表示一次性从数据集中抽取多少个,shuffle表示是否打乱顺序

# 测试数据集中的第一张图片及其target下标
# img, target = test_data[0]
# print(img.shape)   # torch.Size([3, 32, 32])
# print(target)   # 3
# print(test_data.classes)
# ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

# 用Tensorboard查看:
writer = SummaryWriter("./8. dataloader_logs")
step = 0
# 查看用DateLoader封装后的数据样式:
for data in test_loader:
    imgs, targets = data
    # print(imgs.shape)
    # print(targets)
    writer.add_images("test_data", imgs, step)
    step += 1
writer.close()
print("运行完毕")

运行结果:

(pytorch) C:\Users\lv\Desktop\Pytorch\1. Pytorch的使用(第一次)>tensorboard --logdi
r="8. dataloader_logs"
TensorFlow installation not found - running with reduced feature set.
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_a
ll
TensorBoard 2.8.0 at http://localhost:6006/ (Press CTRL+C to quit)

Pytorch的使用_第27张图片
Pytorch的使用_第28张图片
Pytorch的使用_第29张图片

2. drop_last=True(舍去不足64张的图片)

# 官方参考文档:https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader
import torchvision

# 准备的测试数据集:
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10("./7. dataset", train=False, transform=torchvision.transforms.ToTensor())

# 导入测试集
# test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)   # 剩余图片数不足的舍去
# batch_size表示一次性从数据集中抽取多少个,shuffle表示是否打乱顺序

# 测试数据集中的第一张图片及其target下标
# img, target = test_data[0]
# print(img.shape)   # torch.Size([3, 32, 32])
# print(target)   # 3
# print(test_data.classes)
# ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

# 用Tensorboard查看:
writer = SummaryWriter("./8. dataloader_logs")
step = 0
# 查看用DateLoader封装后的数据样式:
for data in test_loader:
    imgs, targets = data
    # print(imgs.shape)
    # print(targets)
    # writer.add_images("test_data", imgs, step)
    writer.add_images("test_data_drop_last", imgs, step)
    step += 1
writer.close()
print("运行完毕")

Pytorch的使用_第30张图片

4. 抽取的两轮是一模一样的(shuffle=False)

# 官方参考文档:https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader
import torchvision

# 准备的测试数据集:
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10("./7. dataset", train=False, transform=torchvision.transforms.ToTensor())

# 导入测试集
# test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=False, num_workers=0, drop_last=True)   # 剩余图片数不足的舍去
# batch_size表示一次性从数据集中抽取多少个,shuffle表示是否打乱顺序

# 测试数据集中的第一张图片及其target下标
# img, target = test_data[0]
# print(img.shape)   # torch.Size([3, 32, 32])
# print(target)   # 3
# print(test_data.classes)
# ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

# 用Tensorboard查看:
writer = SummaryWriter("./8. dataloader_logs")
step = 0
# 查看用DateLoader封装后的数据样式:
for epoch in range(2):
    for data in test_loader:
        imgs, targets = data
        # print(imgs.shape)
        # print(targets)
        # writer.add_images("test_data", imgs, step)
        # writer.add_images("test_data_drop_last", imgs, step)
        writer.add_images("Epoch: {}".format(epoch), imgs, step)
        step += 1
writer.close()
print("运行完毕")

Pytorch的使用_第31张图片

4. 抽取的两轮是是不一样的(shuffle=True)

# 官方参考文档:https://pytorch.org/docs/stable/data.html?highlight=dataloader#torch.utils.data.DataLoader
import torchvision

# 准备的测试数据集:
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10("./7. dataset", train=False, transform=torchvision.transforms.ToTensor())

# 导入测试集
# test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
# test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=False, num_workers=0, drop_last=True) # 剩余图片数不足的舍去
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)   # 剩余图片数不足的舍去
# batch_size表示一次性从数据集中抽取多少个,shuffle表示是否打乱顺序

# 测试数据集中的第一张图片及其target下标
# img, target = test_data[0]
# print(img.shape)   # torch.Size([3, 32, 32])
# print(target)   # 3
# print(test_data.classes)
# ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

# 用Tensorboard查看:
writer = SummaryWriter("./8. dataloader_logs")
# 查看用DateLoader封装后的数据样式:
for epoch in range(2):
	step = 0
    for data in test_loader:
        imgs, targets = data
        # print(imgs.shape)
        # print(targets)
        # writer.add_images("test_data", imgs, step)   # 不去掉最后不足64张图片的一次 drop_last=False
        # writer.add_images("test_data_drop_last", imgs, step)  # 去掉最后不足64张图片的一次 drop_last=True
        # writer.add_images("Epoch: {}".format(epoch), imgs, step)   # 两轮的抽取是一样的
        writer.add_images("Epoch2: {}".format(epoch), imgs, step)   # 两轮的抽取是不一样的
        step += 1
writer.close()
print("运行完毕")

Pytorch的使用_第32张图片

十一、神经网络(torch.nn)

  • 官方网站位置:https://pytorch.org/docs/stable/nn.html
  • nn即Nerual Network。

1. 骨架/容器(Containers)

  • Module很重要。
  • Module
    Pytorch的使用_第33张图片
    Pytorch的使用_第34张图片

2. 基本骨架——nn.Mobule的使用(创建简单的神经网络)

import torch
from torch import nn


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

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


nn_modle = NN_Module()    # 实例化一个神经网络
x = torch.tensor(1.0)   # 输入的内容
output = nn_modle(x)    # 输出结果
print(output)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:\Users\lv\Desktop\Pytorch\1. Pytorch的使用(第一次)\9. nn_module的简单使用.py"
tensor(2.)

Process finished with exit code 0

3. 卷积操作(Convolution Layers)

1. 二维卷积(Conv2d)

  • conv2代表二维卷积。
  • 选取卷积核包裹范围的乘积和。
  • https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d
1. 卷积操作代码一(步长stride分别为1和2)

Pytorch的使用_第35张图片

import torch
import torch.nn.functional as F
# 执行卷积操作


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

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

# 查看尺寸
print("变换之前的尺寸:")
print(input.shape)   # torch.Size([5, 5])
print(kernel.shape)   # torch.Size([3, 3])

# 进行尺寸变换:
input = torch.reshape(input, (1, 1, 5, 5))
kernel = torch.reshape(kernel, (1, 1, 3, 3))

# 查看尺寸
print("变换之后的尺寸:")
print(input.shape)   # torch.Size([1, 1, 5, 5])
print(kernel.shape)   # torch.Size([1, 1, 3, 3])

# 进行卷积,移动步长为1(左移和下移都为1,默认是先左移后下移)
output = F.conv2d(input, kernel, stride=1)
print(output)

# 进行卷积,移动步长为2(左移和下移都为2,默认是先左移后下移)
output = F.conv2d(input, kernel, stride=2)
print(output)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/10. nn_conv(卷积操作).py"
变换之前的尺寸:
torch.Size([5, 5])
torch.Size([3, 3])
变换之后的尺寸:
torch.Size([1, 1, 5, 5])
torch.Size([1, 1, 3, 3])
tensor([[[[10, 12, 12],
          [18, 16, 16],
          [13,  9,  3]]]])
tensor([[[[10, 12],
          [13,  3]]]])

Process finished with exit code 0

2. 卷积操作代码二(设置padding)
  • padding中的数据默认是用0来填充。
    Pytorch的使用_第36张图片
import torch
import torch.nn.functional as F
# 执行卷积操作


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

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

# 查看尺寸
print("变换之前的尺寸:")
print(input.shape)   # torch.Size([5, 5])
print(kernel.shape)   # torch.Size([3, 3])

# 进行尺寸变换:
input = torch.reshape(input, (1, 1, 5, 5))
kernel = torch.reshape(kernel, (1, 1, 3, 3))

# 查看尺寸
print("变换之后的尺寸:")
print(input.shape)   # torch.Size([1, 1, 5, 5])
print(kernel.shape)   # torch.Size([1, 1, 3, 3])

# 进行卷积,移动步长为1(左移和下移都为1,默认是先左移后下移)
output1 = F.conv2d(input, kernel, stride=1)
print(output1)

# 进行卷积,移动步长为2(左移和下移都为2,默认是先左移后下移)
output2 = F.conv2d(input, kernel, stride=2)
print(output2)

# 进行卷积,移动步长为1,设置内边距(padding)为1(会空出一个像素,用0填充)
output3 = F.conv2d(input, kernel, stride=1, padding=1)
print(output3)

# https://www.bilibili.com/video/BV1hE411t7RN?p=17&spm_id_from=pageDriver

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/10. nn_conv(卷积操作).py"
变换之前的尺寸:
torch.Size([5, 5])
torch.Size([3, 3])
变换之后的尺寸:
torch.Size([1, 1, 5, 5])
torch.Size([1, 1, 3, 3])
tensor([[[[10, 12, 12],
          [18, 16, 16],
          [13,  9,  3]]]])
tensor([[[[10, 12],
          [13,  3]]]])
tensor([[[[ 1,  3,  4, 10,  8],
          [ 5, 10, 12, 12,  6],
          [ 7, 18, 16, 16,  8],
          [11, 13,  9,  3,  4],
          [14, 13,  9,  7,  4]]]])

Process finished with exit code 0

2. 卷积层(Conv2d)(设置out_channel数量,叠加)

  • 选取卷积核包裹范围的乘积和。
    Pytorch的使用_第37张图片
    输出通道数(output_channel)
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10("../7. dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)  # 创建数据集(测试集)

dataloader = DataLoader(dataset, batch_size=64)


# 搭建神经网络:
class NN_Conv2d_Model(nn.Module):
    def __init__(self):
        super(NN_Conv2d_Model, self).__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

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


nn_Conv2d_model = NN_Conv2d_Model()
# print(nn_Conv2d_model)  # NN_Conv2d_Model((conv1): Conv2d(3, 6, kernel_size=(3, 3), stride=(1, 1)))

writer = SummaryWriter("../11. logs")
step = 0
for data in dataloader:
    imgs, targets = data
    output = nn_Conv2d_model(imgs)
    # torch.Size([64, 3, 32, 32])
    writer.add_images("Conv2d-input:", imgs, step)
    # torch.Size([64, 6, 30, 30])  --转换--->  [XXX, 3, 30, 30]
    output_re = torch.reshape(output, (-1, 3, 30, 30))
    writer.add_images("Conv2d-output:", output_re, step)
    print(imgs.shape)   # torch.Size([64, 3, 32, 32])
    print(output.shape)   # torch.Size([64, 6, 30, 30])  # 卷积操作后的结果
    step += 1
  
# https://www.bilibili.com/video/BV1hE411t7RN?p=18&spm_id_from=pageDriver

运行结果

(pytorch) C:\Users\lv\Desktop\Pytorch\1. Pytorch的使用
(第一次)>tensorboard --logdir="11. logs"
TensorFlow installation not found - running with reduced f
eature set.
Serving TensorBoard on localhost; to expose to the network
, use a proxy or pass --bind_all
TensorBoard 2.8.0 at http://localhost:6006/ (Press CTRL+C
to quit)

Pytorch的使用_第38张图片
-拓展: VGG16 Modle卷积
推导公式:
Pytorch的使用_第39张图片

4. 最大池化操作(MaxPool2d)

  • 选取池中最大值

1. 用二维矩阵展示

Pytorch的使用_第40张图片

# 最大池化卷积:下采样(MaxPool2d)
# https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html#torch.nn.MaxPool2d
import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
# 最大池化的目的:保留数据特征,同时能把数据量减少

list1 = [[1, 2, 0, 3, 1],
         [0, 1, 2, 3, 1],
         [1, 2, 1, 0, 0],
         [5, 2, 3, 1, 1],
         [2, 1, 0, 1, 1]]
input = torch.tensor(list1, dtype=torch.float32)   # 报错:RuntimeError: "max_pool2d" not implemented for 'Long',需要加上类型设置
input = torch.reshape(input, [-1, 1, 5, 5])  # 第一个-1表示自动识别大小,第2个1表示一个通道
print(input.shape)


class NN_MaxPool_Model(nn.Module):
    def __init__(self):
        super(NN_MaxPool_Model, self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)   # ceil_mode=True表示超出边界后的部分也会求得最大池化值,如果为False,超出边界的范围的池就不会计算

    def forward(self, input):
        output = self.maxpool1(input)
        return output


maxpool_test = NN_MaxPool_Model()
output = maxpool_test(input)
print(output)


# 视频:https://www.bilibili.com/video/BV1hE411t7RN?p=19&spm_id_from=pageDriver

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/12. nn_ConvPool(池化卷积).py"
torch.Size([1, 1, 5, 5])
tensor([[[[2., 3.],
          [5., 1.]]]])

Process finished with exit code 0

2. 利用数据集的图片展示(显示在TensorBoard上)

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


class NN_MaxPool_Modle(nn.Module):
    def __init__(self):
        super(NN_MaxPool_Modle, self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)

    def forward(self, input):
        output = self.maxpool1(input)
        return output


maxpool_test = NN_MaxPool_Modle()


writer = SummaryWriter("../12.1 logs_maxpool")    # tensorboard --logdir="12.1 logs_maxpool"
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input", imgs, step)
    output = maxpool_test(imgs)
    writer.add_images("output", output, step)
    step += 1

writer.close()
print("运行完毕")

运行结果:

(pytorch) C:\Users\lv\Desktop\Pytorch\1. Pytorch的使用(第一次)>tensorboard --logdi
r="12.1 logs_maxpool"
TensorFlow installation not found - running with reduced feature set.
Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_a
ll
TensorBoard 2.8.0 at http://localhost:6006/ (Press CTRL+C to quit)

Pytorch的使用_第41张图片

5. 非线性激活

1. nn.ReLU

Pytorch的使用_第42张图片

# nn.Relu
import torch
from torch import nn
from torch.nn import ReLU
# 非线性激活的作用:给神经网络引入一些非线性特质
# 官方文档:https://pytorch.org/docs/stable/generated/torch.nn.ReLU.html#torch.nn.ReLU


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

# print(input.shape)
input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)


# 搭建神经网络:
class NN_ReLu_Model(nn.Module):
    def __init__(self):
        super(NN_ReLu_Model, self).__init__()
        self.relu1 = ReLU()   # 里面的参数中默认inplace=False

    def forward(self, input):
        output = self.relu1(input)
        return output


nn_relu_model1 = NN_ReLu_Model()
output = nn_relu_model1.forward(input)
print(output)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/13. nn_Relu(神经网络--非线性激活).py"
torch.Size([1, 1, 2, 2])
tensor([[[[1., 0.],
          [0., 3.]]]])

Process finished with exit code 0

2. nn.Sigmoid

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

dataloader = DataLoader(dataset, batch_size=64)


# 创建神经网络
class NN_Sigmoid_Model(nn.Module):
    def __init__(self):
        super(NN_Sigmoid_Model, self).__init__()
        self.sigmoid1 = Sigmoid()

    def forward(self, input):
        output = self.sigmoid1(input)
        return output


nn_sigmoid_model = NN_Sigmoid_Model()

writer = SummaryWriter("../14. logs_sigmoid")   # Terminal中输入:tensorboard --logdir="14. logs_sigmoid"
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input", imgs, global_step=step)
    output = nn_sigmoid_model(imgs)
    writer.add_images("output", output, global_step=step)
    step += 1

writer.close()

运行结果:

(pytorch) C:\Users\lv\Desktop\Pytorch\1. Pytorch的使
用(第一次)>tensorboard --logdir="14. logs_sigmoid"
TensorFlow installation not found - running with reduced
 feature set.
Serving TensorBoard on localhost; to expose to the netwo
rk, use a proxy or pass --bind_all
TensorBoard 2.8.0 at http://localhost:6006/ (Press CTRL+
C to quit)

Pytorch的使用_第43张图片

6. 线性层(nn.linear)——线性操作

Pytorch的使用_第44张图片

# 线性层官方文档:https://pytorch.org/docs/stable/generated/torch.nn.Linear.html#torch.nn.Linear
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

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

dataloader = DataLoader(dataset, batch_size=64, drop_last=True)

# 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])


class NN_Linear_Model(nn.Module):
    def __init__(self):
        super(NN_Linear_Model, self).__init__()
        self.linear1 = Linear(196608, 10)
        # self.linear1 = Linear(49152, 10)

    def forward(self, input):
        output = self.linear1(input)
        return output


nn_linear_model1 = NN_Linear_Model()

for data in dataloader:
    imgs, targets = data
    print("原始:", imgs.shape)   # torch.Size([64, 3, 32, 32])
    # output = torch.reshape(imgs, (1, 1, 1, -1))   # 重置:可改变通道数
    output = torch.flatten(imgs)        # 摊平:将多维数据变成一维的数据
    print("重置后:", output.shape)
    output = nn_linear_model1(output)
    print("线性变换后:", output.shape)

# 由于最后一张合成图中只有16张图片,不足64张,所以最后一次会报错: 解决办法:在DataLoader中设置drop_last=True

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/15. nn_linear(线性层及其他层的介绍).py"
Files already downloaded and verified
原始: torch.Size([64, 3, 32, 32])
重置后: torch.Size([196608])
线性变换后: torch.Size([10])
原始: torch.Size([64, 3, 32, 32])
重置后: torch.Size([196608])
线性变换后: torch.Size([10])
......

7. 搭建CIFAR10的简单网络模型以及Sequential的使用

1. 搭建CIFAR10的简单网络模型

Pytorch的使用_第45张图片
在这里插入图片描述

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


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = Conv2d(3, 32, 5, padding=2)   # 第一次卷积操作
        self.maxpool1 = MaxPool2d(2)   # 第一次池化操作
        self.conv2 = Conv2d(32, 32, 5, padding=2)   # 第二次卷积操作
        self.maxpool2 = MaxPool2d(2)   # 第二次池化操作
        self.conv3 = Conv2d(32, 64, 5, padding=2)   # 第三次卷积操作
        self.maxpool3 = MaxPool2d(2)   # 第三次池化操作
        # 利用Flatten展平数据:
        self.flatten = Flatten()
        # 第一次线性操作:
        self.linear1 = Linear(1024, 64)
        # 第二次线性操作:
        self.linear2 = Linear(64, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)
        x = self.conv3(x)
        x = self.maxpool3(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.linear2(x)    # 每一次都将前面的x覆盖掉
        return x


model1 = Model()

print(model1)

# 检查网络的正确性:
input = torch.ones((64, 3, 32, 32))
output = model1(input)
print(output.shape)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/16. 搭建网络和Sequential的使用.py"
Model(
  (conv1): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
  (maxpool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (conv2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
  (maxpool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (conv3): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
  (maxpool3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear1): Linear(in_features=1024, out_features=64, bias=True)
  (linear2): Linear(in_features=64, out_features=10, bias=True)
)
torch.Size([64, 10])

Process finished with exit code 0

2. 利用Sequential搭建CIFAR10的简单网络模型(代码更加简洁)

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


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        # self.conv1 = Conv2d(3, 32, 5, padding=2)   # 第一次卷积操作
        # self.maxpool1 = MaxPool2d(2)   # 第一次池化操作
        # self.conv2 = Conv2d(32, 32, 5, padding=2)   # 第二次卷积操作
        # self.maxpool2 = MaxPool2d(2)   # 第二次池化操作
        # self.conv3 = Conv2d(32, 64, 5, padding=2)   # 第三次卷积操作
        # self.maxpool3 = MaxPool2d(2)   # 第三次池化操作
        # # 利用Flatten展平数据:
        # self.flatten = Flatten()
        # # 第一次线性操作:
        # self.linear1 = Linear(1024, 64)
        # # 第二次线性操作:
        # self.linear2 = Linear(64, 10)

        # 使用Sequential:
        self.sequential1 = Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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


model1 = Model()

print(model1)

# 检查网络的正确性:
input = torch.ones((64, 3, 32, 32))
output = model1(input)
print(output.shape)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/16. 搭建网络和Sequential的使用.py"
Model(
  (sequential1): Sequential(
    (0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (6): Flatten(start_dim=1, end_dim=-1)
    (7): Linear(in_features=1024, out_features=64, bias=True)
    (8): Linear(in_features=64, out_features=10, bias=True)
  )
)
torch.Size([64, 10])

Process finished with exit code 0

3. 利用Tensorboard展示网络模型

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


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


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

writer = SummaryWriter("../16.3 logs_seq_model")   # Terminal中输入:tensorboard --logdir="16.3 logs_seq_model"
writer.add_graph(model1, input)
writer.close()

运行结果:
Pytorch的使用_第46张图片

  • 双击可以展开细节:
    Pytorch的使用_第47张图片

8. 损失函数与反向传播

  • Loss Functions(衡量误差)
    Pytorch的使用_第48张图片
  • 误差Loss越小越好。
  • LossFunction用于分析实际输出与目标之间的差距。
    在这里插入图片描述
    在这里插入图片描述

1. L1Loss

# 官方文档地址:https://pytorch.org/docs/stable/nn.html#loss-functions
# Loss Function:(L1Loss)https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html#torch.nn.L1Loss
import torch
from torch.nn import L1Loss

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

inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))

loss = L1Loss()
result = loss(inputs, targets)
print(result)   # tensor(0.6667)

# 视频地址:https://www.bilibili.com/video/BV1hE411t7RN?p=23&spm_id_from=pageDriver

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/17. nn_Loss(损失函数与反向传播).py"
tensor(0.6667)

Process finished with exit code 0

2. MSELoss

# 官方文档地址:https://pytorch.org/docs/stable/nn.html#loss-functions
# Loss Function:(L1Loss)https://pytorch.org/docs/stable/generated/torch.nn.L1Loss.html#torch.nn.L1Loss
import torch
from torch.nn import L1Loss, MSELoss

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

inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))

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

print(result_mse)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/17. nn_MSELoss平方差(损失函数与反向传播).py"
tensor(1.3333)

Process finished with exit code 0

3. CrossEntropyLoss(交叉熵损失)

Pytorch的使用_第49张图片

  • -0.2+ln(exp(0.1)+exp(0.2)+exp(0.3))
    Pytorch的使用_第50张图片
# Loss Function:(CrossEntropyLoss)https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss
import torch
from torch import nn


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)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/17.3 nn_CrossEntropyLoss交叉熵(损失函数与反向传播).py"
tensor(1.1019)

Process finished with exit code 0

4. 交叉熵运用在神经网络模型上

import torch
from torch import nn
import torchvision

# 准备数据集:
from torch.utils.data import DataLoader

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


# 搭建圣经网络:
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(
            nn.Conv2d(3, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(1024, 64),
            nn.Linear(64, 10)
        )

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


if __name__ == "__main__":
    loss = nn.CrossEntropyLoss()
    model_1 = Model()
    for data in dataloader:
        imgs, targets = data
        outputs = model_1(imgs)
        result_loss = loss(outputs, targets)
        print(result_loss)   # 计算神经网络输出与实际的误差
        result_loss.backward()   # 能够生成梯度
        print("ok")

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/17.4 nn_loss_function(在神经网络中运用LossFunction).py"
Files already downloaded and verified
tensor(2.2806, grad_fn=<NllLossBackward0>)
ok
tensor(2.2392, grad_fn=<NllLossBackward0>)
ok
tensor(2.2373, grad_fn=<NllLossBackward0>)
ok
tensor(2.2459, grad_fn=<NllLossBackward0>)
ok
tensor(2.2912, grad_fn=<NllLossBackward0>)
......

9. 优化器(torch.optim)

  • 查看网络模型梯度:
    Pytorch的使用_第51张图片
    Pytorch的使用_第52张图片
  • 在模型上使用优化器:
# 官方文档:https://pytorch.org/docs/stable/optim.html
# lr(learning rate):学习速率
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader


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

dataloader = DataLoader(dataset, batch_size=1, drop_last=True)


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(
            nn.Conv2d(3, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, padding=2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(1024, 64),
            nn.Linear(64, 10)
        )

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


loss = nn.CrossEntropyLoss()
model_1 = Model()

# 1. 设置优化器:(设置随机梯度下降优化器)
optim = torch.optim.SGD(model_1.parameters(), lr=0.01)  # lr不能设置得太大或太小,太大模型会不稳定,太小模型训练会很慢(推荐开始选择较大的lr,后面选择较小的lr)

for epcoh in range(5):   # 循环几次就是尽行几轮学习
    running_loss = 0.0   # 保存整体误差总和
    for data in dataloader:  # 仅进行了一轮的学习
        imgs, targets = data
        outputs = model_1(imgs)
        result_loss = loss(outputs, targets)
        optim.zero_grad()  # 2. 调用优化器,让网络中的每一个参数的梯度置零
        result_loss.backward()  # 反向传播,求出每一个节点的梯度
        optim.step()  # 3. 调用优化器,对每一个参数进行调优
        # print(result_loss)
        running_loss += result_loss   # 整体误差总和
    print(running_loss)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/18. nn_optim(优化器).py"
Files already downloaded and verified
tensor(18683.0371, grad_fn=<AddBackward0>)
tensor(16126.9668, grad_fn=<AddBackward0>)
tensor(15419.0205, grad_fn=<AddBackward0>)
tensor(15867.6797, grad_fn=<AddBackward0>)
tensor(17589.4316, grad_fn=<AddBackward0>)

Process finished with exit code -1

10. 现有网络模型的使用

1. 加载VGG模型

1. pretrained=False
# 文档:https://arxiv.org/abs/1409.1556
# 官方地址:https://pytorch.org/vision/stable/models.html#classification
# 常用 VGG16 或 VGG19
# 需要安装scipy模块:pip install scipy
import torchvision.datasets

# train_data = torchvision.datasets.ImageNet("../19. dataset_image_net", split="train", download=True,
#                                            transform=torchvision.transforms.ToTensor())
# 由于ImageNet的训练数据集不被公开访问了,所以不能这样下载了(该数据集有140多G,太大了)

vgg16_false = torchvision.models.vgg16(pretrained=False)   # 加载网络模型,不会下载(等同于前面我们写的Model()网络架构) 参数是默认的参数
# vgg16_true = torchvision.models.vgg16(pretrained=True)   # 会从网上下载网络模型,参数是已经被训练好的参数
print(vgg16_false)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/19. VGG模型_pretrained(现有网络模型的使用).py"
VGG(
  (features): Sequential(
    (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)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

Process finished with exit code 0

2. pretrained=True
# 文档:https://arxiv.org/abs/1409.1556
# 官方地址:https://pytorch.org/vision/stable/models.html#classification
# 常用 VGG16 或 VGG19
# 需要安装scipy模块:pip install scipy
import torchvision.datasets

# train_data = torchvision.datasets.ImageNet("../19. dataset", split="train", download=True,
#                                            transform=torchvision.transforms.ToTensor())
# 由于ImageNet的训练数据集不被公开访问了,所以不能这样下载了(该数据集有140多G,太大了)

# vgg16_false = torchvision.models.vgg16(pretrained=False)   # 加载网络模型,不会下载(等同于前面我们写的Model()网络架构) 参数是默认的参数
vgg16_true = torchvision.models.vgg16(pretrained=True)   # 会从网上下载网络模型,参数是已经被训练好的参数
# Downloading: "https://download.pytorch.org/models/vgg16-397923af.pth" to C:\Users\lv/.cache\torch\hub\checkpoints\vgg16-397923af.pth

# print(vgg16_false)
print(vgg16_true)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/19. VGG模型_pretrained(现有网络模型的使用).py"
Downloading: "https://download.pytorch.org/models/vgg16-397923af.pth" to C:\Users\lv/.cache\torch\hub\checkpoints\vgg16-397923af.pth
100.0%
VGG(
  (features): Sequential(
    (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)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

Process finished with exit code 0

2. 修改VGG网络模型

# 文档:https://arxiv.org/abs/1409.1556
# 官方地址:https://pytorch.org/vision/stable/models.html#classification
# 常用 VGG16 或 VGG19
# 需要安装scipy模块:pip install scipy
import torchvision.datasets
from torch import nn

# train_data = torchvision.datasets.ImageNet("../19. dataset", split="train", download=True,
#                                            transform=torchvision.transforms.ToTensor())
# 由于ImageNet的训练数据集不被公开访问了,所以不能这样下载了(该数据集有140多G,太大了)

vgg16_false = torchvision.models.vgg16(pretrained=False)   # 加载网络模型,不会下载(等同于前面我们写的Model()网络架构) 参数是默认的参数
vgg16_true = torchvision.models.vgg16(pretrained=True)   # 会从网上下载网络模型,参数是已经被训练好的参数
# Downloading: "https://download.pytorch.org/models/vgg16-397923af.pth" to C:\Users\lv/.cache\torch\hub\checkpoints\vgg16-397923af.pth

# print(vgg16_false)
# print(vgg16_true)

train_data = torchvision.datasets.CIFAR10("../19. dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True)
# 添加操作:
vgg16_true.add_module('add_linear1', nn.Linear(1000, 10))   # 添加一个线性层(添加在最后面)
# print(vgg16_true)
vgg16_true.classifier.add_module("add_linear2", nn.Linear(1000, 10))  # 添加到classifier里面
print(vgg16_true)

print(vgg16_false)
# 修改操作:
vgg16_false.classifier[6] = nn.Linear(in_features=4096, out_features=10)
print(vgg16_false)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/19. VGG模型_pretrained(现有网络模型的使用).py"
Files already downloaded and verified
VGG(
  (features): Sequential(
    (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)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
    (add_linear2): Linear(in_features=1000, out_features=10, bias=True)
  )
  (add_linear1): Linear(in_features=1000, out_features=10, bias=True)
)
VGG(
  (features): Sequential(
    (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)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)
VGG(
  (features): Sequential(
    (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)
    (6): Linear(in_features=4096, out_features=10, bias=True)
  )
)

Process finished with exit code 0

11. 网络模型的保存和加载/读取

1. 网络模型的保存

import torch
import torchvision
from torch import nn

vgg16 = torchvision.models.vgg16(pretrained=False)   # 使用未经过训练的VGG16网络模型(预训练设置为False)

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

# 保存方式2:模型参数(官方推荐)(不保存模型结构,不保存网络模型的结构)
# state_dict()是保存成字典的形式
torch.save(vgg16.state_dict(), "vgg16_method2.pth")    # 该种方式保存的文件会比方式1小一些,可在终端中用"dir"命令查看文件大小(需要用"cd src"命令切换到src目录下)


# 方式1的陷阱:
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

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


model_text = Model()
torch.save(model_text, "my_model_method1.pth")

运行结果:
在这里插入图片描述

2. 网络模型的加载/读取

import torch


# 读取网络模型:对应 保存方式1
# 保存方式1的读取:
# model1 = torch.load("vgg16_method1.pth")
# print(model1)


# 保存方式2的读取:加载模型
import torchvision

model2 = torch.load("vgg16_method2.pth")
# print(model2)
# 方式2如果要恢复成网络模型,需要新建一个网络结构:
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(model2)
# print(vgg16)


from torch import nn
# 方式1的陷阱:(用自己的网络模型时会出现的问题)
class Model(nn.Module):   # 此类就是需要加过来的部分
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

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


model3 = torch.load("my_model_method1.pth")
print(model3)
# 会报错:AttributeError: Can't get attribute
# 'Model' on 
# 解决方法:直接将定义的class模型类放过来即可。

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/20.2 网络模型的读取.py"
Model(
  (conv1): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1))
)

Process finished with exit code 0

12. 完整的模型训练套路

Pytorch的使用_第53张图片

1. 优化前

import torchvision
from torch.utils.data import DataLoader
# 5. 引入我们自己写的模型
from model_21 import *


# 1. 准备数据集
# 1.1 准备训练数据集:
train_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)  # 此处transform参数用于将数据集中原本的PIL图片转换为Tensor类型的图片。
# 1.2 准备测试数据集:
test_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=False,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=True)
# 查看数据集的大小(有多少张照片)
train_data_size = len(train_data)  # 50000
test_data_size = len(test_data)  # 10000
print("训练数据集的长度为:", train_data_size)
print("测试数据集的长度为:", test_data_size)

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

# 6. 创建网络模型:
model1 = Model()

# 7. 创建损失函数(LossFunction)
loss_fn = nn.CrossEntropyLoss()   # 交叉熵

# 8. 定义优化器
# learning_rate = 0.01   # 学习速率
learning_rate = 1e-2  # 科学计数法表示 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(model1.parameters(), lr=learning_rate)   # 随机梯度下降

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


for i in range(epoch):
    print("-----------第 {} 轮训练开始-----------".format(i + 1))
    # 10. 训练步骤开始:
    for data in train_dataloader:
        # 10.1 拿到数据:
        imgs, targets = data
        # 10.2 将数据放进网络模型中:
        outputs = model1(imgs)     # 将数据放到网络当中
        # 10.3 获得损失值:(损失值越小越好,越少说明输出结果和实际结果更接近)
        loss = loss_fn(outputs, targets)    # 查看损失值(输出值,真实值)

        # 10.4 优化器优化模型:
        optimizer.zero_grad()     # 利用优化器将梯度清零
        loss.backward()    # 损失值反向传播,得到每一个参数的梯度
        optimizer.step()   # 对得到的参数进行优化

        total_train_step += 1
        # print("训练次数:{},Loss:{}".format(total_train_step, loss))
        print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))   # item()方法用于将tensor数据类型转换为真实的数字

    # 11. 测试步骤开始:
    # 为了确定模型是否训练好,即是否达到自己的需求,可以利用如下方式:
    # 在每一轮训练完成之后,在测试集上进行一下测试,通过查看在测试数据集上的损失和正确率来评估判断模型训练是否达标
    total_test_loss = 0
    with torch.no_grad():  # 此时在测试集上就不需要调优了,所以就不设置梯度
        for data in test_dataloader:
            imgs, targets = data
            outputs = model1(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
        print("整体测试集上的Loss:{}".format(total_test_loss))
# 3. 搭建神经网络:
import torch
from torch import nn


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(  # 将网络放进序列中,避免了forward()方法的代码冗余
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),   # 展平:64*4*4
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )

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


# 4. 测试网络的正确性:
if __name__ == '__main__':
    model = Model()
    # 测试方法:给定一个输入的尺寸,查看输出尺寸是否是自己想要的
    input = torch.ones(64, 3, 32, 32)
    output = model(input)
    print(output.shape)


运行主要结果:
Pytorch的使用_第54张图片

2. 优化后

import torchvision
from torch.utils.data import DataLoader
# 5. 引入我们自己写的模型
from torch.utils.tensorboard import SummaryWriter

from model_21 import *


# 1. 准备数据集
# 1.1 准备训练数据集:
train_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)  # 此处transform参数用于将数据集中原本的PIL图片转换为Tensor类型的图片。
# 1.2 准备测试数据集:
test_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=False,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=True)
# 查看数据集的大小(有多少张照片)
train_data_size = len(train_data)  # 50000
test_data_size = len(test_data)  # 10000
print("训练数据集的长度为:", train_data_size)
print("测试数据集的长度为:", test_data_size)

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

# 6. 创建网络模型:
model1 = Model()

# 7. 创建损失函数(LossFunction)
loss_fn = nn.CrossEntropyLoss()   # 交叉熵

# 8. 定义优化器
# learning_rate = 0.01   # 学习速率
learning_rate = 1e-2  # 科学计数法表示 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(model1.parameters(), lr=learning_rate)   # 随机梯度下降

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

# 12. 添加tensorboard:
# 12.1 定义日志目录:
writer = SummaryWriter("../21. logs_train")

for i in range(epoch):
    print("-----------第 {} 轮训练开始-----------".format(i + 1))
    # 10. 训练步骤开始:
    for data in train_dataloader:
        # 10.1 拿到数据:
        imgs, targets = data
        # 10.2 将数据放进网络模型中:
        outputs = model1(imgs)     # 将数据放到网络当中
        # 10.3 获得损失值:(损失值越小越好,越少说明输出结果和实际结果更接近)
        loss = loss_fn(outputs, targets)    # 查看损失值(输出值,真实值)

        # 10.4 优化器优化模型:
        optimizer.zero_grad()     # 利用优化器将梯度清零
        loss.backward()    # 损失值反向传播,得到每一个参数的梯度
        optimizer.step()   # 对得到的参数进行优化

        total_train_step += 1
        # print("训练次数:{},Loss:{}".format(total_train_step, loss))
        if total_train_step % 100 == 0:   # 每逢100次打印一下记录
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))   # item()方法用于将tensor数据类型转换为真实的数字
            # 12.2 将训练集的损失值添加到tensorboard中:
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # 11. 测试步骤开始:
    # 为了确定模型是否训练好,即是否达到自己的需求,可以利用如下方式:
    # 在每一轮训练完成之后,在测试集上进行一下测试,通过查看在测试数据集上的损失和正确率来评估判断模型训练是否达标
    total_test_loss = 0
    with torch.no_grad():  # 此时在测试集上就不需要调优了,所以就不设置梯度
        for data in test_dataloader:
            imgs, targets = data
            outputs = model1(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
    print("整体测试集上的Loss:{}".format(total_test_loss))
    # 12.3 将测试集的损失值添加到tensorboard中:
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    total_test_step += 1
    # 13. 保存每一轮训练的模型(一般会保存每一轮训练的结果)
    torch.save(model1, "model21_{}.pth".format(i))
    print("模型已保存")

writer.close()
# 3. 搭建神经网络:
import torch
from torch import nn


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(  # 将网络放进序列中,避免了forward()方法的代码冗余
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),   # 展平:64*4*4
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )

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


# 4. 测试网络的正确性:
if __name__ == '__main__':
    model = Model()
    # 测试方法:给定一个输入的尺寸,查看输出尺寸是否是自己想要的
    input = torch.ones(64, 3, 32, 32)
    output = model(input)
    print(output.shape)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/21. 完整的模型训练套路(以CIFAR10数据集为例).py"
Files already downloaded and verified
Files already downloaded and verified
训练数据集的长度为: 50000
测试数据集的长度为: 10000
-----------1 轮训练开始-----------
训练次数:100,Loss:2.2925751209259033
训练次数:200,Loss:2.284406900405884
训练次数:300,Loss:2.271050453186035
训练次数:400,Loss:2.207911729812622
训练次数:500,Loss:2.080270290374756
训练次数:600,Loss:2.0761666297912598
训练次数:700,Loss:1.9891338348388672
整体测试集上的Loss:307.4119518995285
模型已保存
-----------2 轮训练开始-----------
训练次数:800,Loss:1.9731290340423584
训练次数:900,Loss:2.0486114025115967
训练次数:1000,Loss:1.9224594831466675
训练次数:1100,Loss:1.658496618270874
训练次数:1200,Loss:1.7208967208862305
训练次数:1300,Loss:1.6665420532226562
训练次数:1400,Loss:1.7540117502212524
训练次数:1500,Loss:1.6843773126602173
整体测试集上的Loss:267.65855038166046
模型已保存
-----------3 轮训练开始-----------
训练次数:1600,Loss:1.5847516059875488
训练次数:1700,Loss:1.7675801515579224
训练次数:1800,Loss:1.7038624286651611
训练次数:1900,Loss:1.524741291999817
训练次数:2000,Loss:1.8022964000701904
训练次数:2100,Loss:1.6436841487884521
训练次数:2200,Loss:1.6749669313430786
训练次数:2300,Loss:1.7578243017196655
整体测试集上的Loss:245.9545168876648
模型已保存
-----------4 轮训练开始-----------
训练次数:2400,Loss:1.658545732498169
训练次数:2500,Loss:1.5426204204559326
训练次数:2600,Loss:1.524390697479248
训练次数:2700,Loss:1.544264554977417
训练次数:2800,Loss:1.6165740489959717
训练次数:2900,Loss:1.683912992477417
训练次数:3000,Loss:1.6036295890808105
训练次数:3100,Loss:1.5629819631576538
整体测试集上的Loss:232.34321570396423
模型已保存
-----------5 轮训练开始-----------
训练次数:3200,Loss:1.5927608013153076
训练次数:3300,Loss:1.5902777910232544
训练次数:3400,Loss:1.3824384212493896
训练次数:3500,Loss:1.3588529825210571
训练次数:3600,Loss:1.644023060798645
训练次数:3700,Loss:1.3318898677825928
训练次数:3800,Loss:1.6108362674713135
训练次数:3900,Loss:1.245458722114563
整体测试集上的Loss:221.39628267288208
模型已保存
-----------6 轮训练开始-----------
训练次数:4000,Loss:1.3756872415542603
训练次数:4100,Loss:1.4219857454299927
训练次数:4200,Loss:1.315463662147522
训练次数:4300,Loss:1.4958460330963135
训练次数:4400,Loss:1.4487323760986328
训练次数:4500,Loss:1.4050123691558838
训练次数:4600,Loss:1.4384880065917969
整体测试集上的Loss:211.88410007953644
模型已保存
-----------7 轮训练开始-----------
训练次数:4700,Loss:1.510286569595337
训练次数:4800,Loss:1.1430772542953491
训练次数:4900,Loss:1.3690186738967896
训练次数:5000,Loss:1.3852487802505493
训练次数:5100,Loss:1.2908730506896973
训练次数:5200,Loss:1.4217464923858643
训练次数:5300,Loss:1.1573139429092407
训练次数:5400,Loss:1.321250081062317
整体测试集上的Loss:203.59074747562408
模型已保存
-----------8 轮训练开始-----------
训练次数:5500,Loss:1.2158926725387573
训练次数:5600,Loss:1.4616506099700928
训练次数:5700,Loss:1.3022576570510864
训练次数:5800,Loss:1.299230694770813
训练次数:5900,Loss:1.3799153566360474
训练次数:6000,Loss:1.126561164855957
训练次数:6100,Loss:1.3739831447601318
训练次数:6200,Loss:1.136829137802124
整体测试集上的Loss:195.9818039536476
模型已保存
-----------9 轮训练开始-----------
训练次数:6300,Loss:1.2773315906524658
训练次数:6400,Loss:1.2952018976211548
训练次数:6500,Loss:1.2996463775634766
训练次数:6600,Loss:1.3380697965621948
训练次数:6700,Loss:0.9762742519378662
训练次数:6800,Loss:1.4590245485305786
训练次数:6900,Loss:1.235298991203308
训练次数:7000,Loss:1.1624468564987183
整体测试集上的Loss:188.6087030172348
模型已保存
-----------10 轮训练开始-----------
训练次数:7100,Loss:1.3110350370407104
训练次数:7200,Loss:1.337066411972046
训练次数:7300,Loss:1.2135053873062134
训练次数:7400,Loss:0.7884792685508728
训练次数:7500,Loss:1.1569792032241821
训练次数:7600,Loss:1.014362096786499
训练次数:7700,Loss:1.1731568574905396
训练次数:7800,Loss:1.202620029449463
整体测试集上的Loss:182.26045763492584
模型已保存

Process finished with exit code 0

Pytorch的使用_第55张图片

3. 二次优化(补充正确率的计算)

1. 如何计算正确率:
  • 计算准确率(argmax()方法)
  • Pytorch的使用_第56张图片
import torch


outputs = torch.tensor([[0.1, 0.2],
                       [0.05, 0.4]])

# argmax()里面的参数是0时,纵向看;argmax()里面的参数是1时,横向看。(标号从0开始)
print(outputs.argmax(1))   # 横向看,取最大值的标号。tensor([1, 1])
print(outputs.argmax(0))   # 纵向看,取最大值的标号。tensor([0, 1])

preds = outputs.argmax(1)
targets = torch.tensor([0, 1])
print(preds == targets)   # tensor([False,  True])
print((preds == targets).sum())   # 计算正确的个数   # tensor(1)

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/test/准确率的计算.py"
tensor([1, 1])
tensor([0, 1])
tensor([False,  True])
tensor(1)

Process finished with exit code 0
2. 将正确率的计算应用在模型上
import torchvision
from torch.utils.data import DataLoader
# 5. 引入我们自己写的模型
from torch.utils.tensorboard import SummaryWriter

from model_21 import *


# 1. 准备数据集
# 1.1 准备训练数据集:
train_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)  # 此处transform参数用于将数据集中原本的PIL图片转换为Tensor类型的图片。
# 1.2 准备测试数据集:
test_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=False,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=True)
# 查看数据集的大小(有多少张照片)
train_data_size = len(train_data)  # 50000
test_data_size = len(test_data)  # 10000
print("训练数据集的长度为:", train_data_size)
print("测试数据集的长度为:", test_data_size)

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

# 6. 创建网络模型:
model1 = Model()

# 7. 创建损失函数(LossFunction)
loss_fn = nn.CrossEntropyLoss()   # 交叉熵

# 8. 定义优化器
# learning_rate = 0.01   # 学习速率
learning_rate = 1e-2  # 科学计数法表示 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(model1.parameters(), lr=learning_rate)   # 随机梯度下降

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

# 12. 添加tensorboard:
# 12.1 定义日志目录:
writer = SummaryWriter("../21. logs_train")

for i in range(epoch):
    print("-----------第 {} 轮训练开始-----------".format(i + 1))
    # 10. 训练步骤开始:
    for data in train_dataloader:
        # 10.1 拿到数据:
        imgs, targets = data
        # 10.2 将数据放进网络模型中:
        outputs = model1(imgs)     # 将数据放到网络当中
        # 10.3 获得损失值:(损失值越小越好,越少说明输出结果和实际结果更接近)
        loss = loss_fn(outputs, targets)    # 查看损失值(输出值,真实值)

        # 10.4 优化器优化模型:
        optimizer.zero_grad()     # 利用优化器将梯度清零
        loss.backward()    # 损失值反向传播,得到每一个参数的梯度
        optimizer.step()   # 对得到的参数进行优化

        total_train_step += 1
        # print("训练次数:{},Loss:{}".format(total_train_step, loss))
        if total_train_step % 100 == 0:   # 每逢100次打印一下记录
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))   # item()方法用于将tensor数据类型转换为真实的数字
            # 12.2 将训练集的损失值添加到tensorboard中:
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # 11. 测试步骤开始:
    # 为了确定模型是否训练好,即是否达到自己的需求,可以利用如下方式:
    # 在每一轮训练完成之后,在测试集上进行一下测试,通过查看在测试数据集上的损失和正确率来评估判断模型训练是否达标
    total_test_loss = 0
    # 14. 添加测试正确率:
    # 14.1 定义保存总体正确个数的变量:
    total_accuracy = 0    # 计算整体正确的个数

    with torch.no_grad():  # 此时在测试集上就不需要调优了,所以就不设置梯度
        for data in test_dataloader:
            imgs, targets = data
            outputs = model1(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
            # 14.2 确定本次正确的个数:
            accuracy = (outputs.argmax(1) == targets).sum()
            # 14.3 累加在总的正确个数上:
            total_accuracy += accuracy

    print("整体测试集上的Loss:{}".format(total_test_loss))
    # 14.4 打印正确率:
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))    # 测试正确率 = 正确总个数 / 测试总个数
    # 12.3 将测试集的损失值添加到tensorboard中:
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    # 14.5 将正确率添加到tensorboard上:
    writer.add_scalar("test_accuracy_rate", total_accuracy/test_data_size, total_test_step)
    total_test_step += 1
    # 13. 保存每一轮训练的模型(一般会保存每一轮训练的结果)
    torch.save(model1, "model21_{}.pth".format(i))
    print("模型已保存")

writer.close()

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/21. 完整的模型训练套路(以CIFAR10数据集为例).py"
Files already downloaded and verified
Files already downloaded and verified
训练数据集的长度为: 50000
测试数据集的长度为: 10000
-----------1 轮训练开始-----------
训练次数:100,Loss:2.2897186279296875
训练次数:200,Loss:2.286137342453003
训练次数:300,Loss:2.280489921569824
训练次数:400,Loss:2.2376134395599365
训练次数:500,Loss:2.184150457382202
训练次数:600,Loss:2.1074447631835938
训练次数:700,Loss:2.0025322437286377
整体测试集上的Loss:315.00807452201843
整体测试集上的正确率:0.267300009727478
模型已保存
-----------2 轮训练开始-----------
训练次数:800,Loss:1.9873543977737427
训练次数:900,Loss:2.0799002647399902
训练次数:1000,Loss:1.9843636751174927
训练次数:1100,Loss:1.6882442235946655
训练次数:1200,Loss:1.7451348304748535
训练次数:1300,Loss:1.6969656944274902
训练次数:1400,Loss:1.757988691329956
训练次数:1500,Loss:1.7167037725448608
整体测试集上的Loss:274.21765780448914
整体测试集上的正确率:0.37630000710487366
模型已保存
-----------3 轮训练开始-----------
训练次数:1600,Loss:1.5984545946121216
训练次数:1700,Loss:1.8257877826690674
训练次数:1800,Loss:1.7015177011489868
训练次数:1900,Loss:1.5435922145843506
训练次数:2000,Loss:1.8306862115859985
训练次数:2100,Loss:1.620747447013855
训练次数:2200,Loss:1.6893324851989746
训练次数:2300,Loss:1.7770516872406006
整体测试集上的Loss:249.13458859920502
整体测试集上的正确率:0.4275999963283539
模型已保存
-----------4 轮训练开始-----------
训练次数:2400,Loss:1.643716812133789
训练次数:2500,Loss:1.608774185180664
训练次数:2600,Loss:1.5446621179580688
训练次数:2700,Loss:1.5399816036224365
训练次数:2800,Loss:1.6210824251174927
训练次数:2900,Loss:1.6688711643218994
训练次数:3000,Loss:1.6144829988479614
训练次数:3100,Loss:1.6151965856552124
整体测试集上的Loss:233.4448812007904
整体测试集上的正确率:0.4636000096797943
模型已保存
-----------5 轮训练开始-----------
训练次数:3200,Loss:1.536098837852478
训练次数:3300,Loss:1.5872925519943237
训练次数:3400,Loss:1.4043664932250977
训练次数:3500,Loss:1.3682256937026978
训练次数:3600,Loss:1.6117099523544312
训练次数:3700,Loss:1.420597791671753
训练次数:3800,Loss:1.6109082698822021
训练次数:3900,Loss:1.2196366786956787
整体测试集上的Loss:221.355699300766
整体测试集上的正确率:0.49149999022483826
模型已保存
-----------6 轮训练开始-----------
训练次数:4000,Loss:1.3846321105957031
训练次数:4100,Loss:1.3860175609588623
训练次数:4200,Loss:1.3283567428588867
训练次数:4300,Loss:1.4771405458450317
训练次数:4400,Loss:1.4300284385681152
训练次数:4500,Loss:1.4045897722244263
训练次数:4600,Loss:1.4277993440628052
整体测试集上的Loss:211.07184171676636
整体测试集上的正确率:0.5195000171661377
模型已保存
-----------7 轮训练开始-----------
训练次数:4700,Loss:1.5646435022354126
训练次数:4800,Loss:1.1132608652114868
训练次数:4900,Loss:1.4092223644256592
训练次数:5000,Loss:1.3427751064300537
训练次数:5100,Loss:1.3039690256118774
训练次数:5200,Loss:1.4188222885131836
训练次数:5300,Loss:1.116021990776062
训练次数:5400,Loss:1.2808016538619995
整体测试集上的Loss:202.14063453674316
整体测试集上的正确率:0.5393999814987183
模型已保存
-----------8 轮训练开始-----------
训练次数:5500,Loss:1.2065008878707886
训练次数:5600,Loss:1.4955896139144897
训练次数:5700,Loss:1.314663290977478
训练次数:5800,Loss:1.2717032432556152
训练次数:5900,Loss:1.318851113319397
训练次数:6000,Loss:1.1185832023620605
训练次数:6100,Loss:1.3185045719146729
训练次数:6200,Loss:1.2105915546417236
整体测试集上的Loss:194.26216197013855
整体测试集上的正确率:0.5595999956130981
模型已保存
-----------9 轮训练开始-----------
训练次数:6300,Loss:1.3029778003692627
训练次数:6400,Loss:1.218829870223999
训练次数:6500,Loss:1.2660713195800781
训练次数:6600,Loss:1.413455605506897
训练次数:6700,Loss:0.9697590470314026
训练次数:6800,Loss:1.4254883527755737
训练次数:6900,Loss:1.2643316984176636
训练次数:7000,Loss:1.1839011907577515
整体测试集上的Loss:187.40601152181625
整体测试集上的正确率:0.5745000243186951
模型已保存
-----------10 轮训练开始-----------
训练次数:7100,Loss:1.3359482288360596
训练次数:7200,Loss:1.3060959577560425
训练次数:7300,Loss:1.155340552330017
训练次数:7400,Loss:0.8022401928901672
训练次数:7500,Loss:1.1651530265808105
训练次数:7600,Loss:0.9878881573677063
训练次数:7700,Loss:1.256567358970642
训练次数:7800,Loss:1.1833606958389282
整体测试集上的Loss:181.56459486484528
整体测试集上的正确率:0.5896999835968018
模型已保存

Process finished with exit code 0

4. 最终完整的网络模型

import torchvision
from torch.utils.data import DataLoader
# 5. 引入我们自己写的模型
from torch.utils.tensorboard import SummaryWriter

from model_21 import *


# 1. 准备数据集
# 1.1 准备训练数据集:
train_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)  # 此处transform参数用于将数据集中原本的PIL图片转换为Tensor类型的图片。
# 1.2 准备测试数据集:
test_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=False,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=True)
# 查看数据集的大小(有多少张照片)
train_data_size = len(train_data)  # 50000
test_data_size = len(test_data)  # 10000
print("训练数据集的长度为:", train_data_size)
print("测试数据集的长度为:", test_data_size)

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

# 6. 创建网络模型:
model1 = Model()

# 7. 创建损失函数(LossFunction)
loss_fn = nn.CrossEntropyLoss()   # 交叉熵

# 8. 定义优化器
# learning_rate = 0.01   # 学习速率
learning_rate = 1e-2  # 科学计数法表示 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(model1.parameters(), lr=learning_rate)   # 随机梯度下降

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

# 12. 添加tensorboard:
# 12.1 定义日志目录:
writer = SummaryWriter("../21. logs_train")

for i in range(epoch):
    print("-----------第 {} 轮训练开始-----------".format(i + 1))
    # 10. 训练步骤开始:
    # model1.train()    # 让网络进入训练状态,参考官方文档Module板块(只有使用了特定层才有作用,一般可不使用)
    for data in train_dataloader:
        # 10.1 拿到数据:
        imgs, targets = data
        # 10.2 将数据放进网络模型中:
        outputs = model1(imgs)     # 将数据放到网络当中
        # 10.3 获得损失值:(损失值越小越好,越少说明输出结果和实际结果更接近)
        loss = loss_fn(outputs, targets)    # 查看损失值(输出值,真实值)

        # 10.4 优化器优化模型:
        optimizer.zero_grad()     # 利用优化器将梯度清零
        loss.backward()    # 损失值反向传播,得到每一个参数的梯度
        optimizer.step()   # 对得到的参数进行优化

        total_train_step += 1
        # print("训练次数:{},Loss:{}".format(total_train_step, loss))
        if total_train_step % 100 == 0:   # 每逢100次打印一下记录
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))   # item()方法用于将tensor数据类型转换为真实的数字
            # 12.2 将训练集的损失值添加到tensorboard中:
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # 11. 测试步骤开始:
    model1.eval()  # 让网络进入评估模式,参考官方文档Module板块(只有使用了特定层(`Dropout`,`BatchNorm`)才有作用,一般可不使用)
    # 为了确定模型是否训练好,即是否达到自己的需求,可以利用如下方式:
    # 在每一轮训练完成之后,在测试集上进行一下测试,通过查看在测试数据集上的损失和正确率来评估判断模型训练是否达标
    total_test_loss = 0
    # 14. 添加测试正确率:
    # 14.1 定义保存总体正确个数的变量:
    total_accuracy = 0    # 计算整体正确的个数
    with torch.no_grad():  # 此时在测试集上就不需要调优了,所以就不设置梯度
        for data in test_dataloader:
            imgs, targets = data
            outputs = model1(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
            # 14.2 确定本次正确的个数:
            accuracy = (outputs.argmax(1) == targets).sum()
            # 14.3 累加在总的正确个数上:
            total_accuracy += accuracy

    print("整体测试集上的Loss:{}".format(total_test_loss))
    # 14.4 打印正确率:
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))    # 测试正确率 = 正确总个数 / 测试总个数
    # 12.3 将测试集的损失值添加到tensorboard中:
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    # 14.5 将正确率添加到tensorboard上:
    writer.add_scalar("test_accuracy_rate", total_accuracy/test_data_size, total_test_step)
    total_test_step += 1
    # 13. 保存每一轮训练的模型(一般会保存每一轮训练的结果)
    torch.save(model1, "model21_{}.pth".format(i))
    # torch.save(model1.state_dict(), "model21_{}.pth".format(i))   # 官方推荐的保存方式(只保存数据,不保存结构)
    print("模型已保存")

writer.close()
  • model_21.py:
# 3. 搭建神经网络:
import torch
from torch import nn


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(  # 将网络放进序列中,避免了forward()方法的代码冗余
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),   # 展平:64*4*4
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )

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


# 4. 测试网络的正确性:
if __name__ == '__main__':
    model = Model()
    # 测试方法:给定一个输入的尺寸,查看输出尺寸是否是自己想要的
    input = torch.ones(64, 3, 32, 32)
    output = model(input)
    print(output.shape)

13. 使用GPU进行训练

1. 第一种调用GPU(显卡)的方式:

  • 使用GPU训练,程序运行的速度会快很多。
  • 终端内输入“nvidia-smi”命令可以查看GPU的信息。
  • 如果电脑上有GPU,可以使用电脑上的GPU。如果没有,可以使用google colab上的免费GPU,前提是能进入google,还需要登录google账号。
  • 可以参考的网址:
    • https://cloud.tencent.com/developer/article/1101164?from=article.detail.1518627
    • https://www.jianshu.com/p/564b3fb5e190
  • 本节视频链接:https://www.bilibili.com/video/BV1hE411t7RN?p=30&spm_id_from=pageDriver
    Pytorch的使用_第57张图片
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
# 5. 引入我们自己写的模型
from torch.utils.tensorboard import SummaryWriter
import time

# from model_21 import *


# 1. 准备数据集
# 1.1 准备训练数据集:
train_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)  # 此处transform参数用于将数据集中原本的PIL图片转换为Tensor类型的图片。
# 1.2 准备测试数据集:
test_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=False,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=True)
# 查看数据集的大小(有多少张照片)
train_data_size = len(train_data)  # 50000
test_data_size = len(test_data)  # 10000
print("训练数据集的长度为:", train_data_size)
print("测试数据集的长度为:", test_data_size)

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


# 6. 创建网络模型:
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(  # 将网络放进序列中,避免了forward()方法的代码冗余
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),  # 展平:64*4*4
            nn.Linear(64 * 4 * 4, 64),
            nn.Linear(64, 10)
        )

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


model1 = Model()
# 调用GPU:
# (1)将网络模型转移到cuda上
if torch.cuda.is_available():
    model1 = model1.cuda()


# 7. 创建损失函数(LossFunction)
loss_fn = nn.CrossEntropyLoss()  # 交叉熵
# (2)将损失函数页转移到cuda上
if torch.cuda.is_available():
    loss_fn = loss_fn.cuda()

# 8. 定义优化器
# learning_rate = 0.01   # 学习速率
learning_rate = 1e-2  # 科学计数法表示 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(model1.parameters(), lr=learning_rate)  # 随机梯度下降

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

# 12. 添加tensorboard:
# 12.1 定义日志目录:
writer = SummaryWriter("../21. logs_train")

start_time = time.time()
for i in range(epoch):
    print("-----------第 {} 轮训练开始-----------".format(i + 1))
    # 10. 训练步骤开始:
    # model1.train()    # 让网络进入训练状态,参考官方文档Module板块(只有使用了特定层才有作用,一般可不使用)
    for data in train_dataloader:
        # 10.1 拿到数据:
        imgs, targets = data

        # (3)将训练的数据转移到cuda上
        if torch.cuda.is_available():
            imgs = imgs.cuda()
            targets = targets.cuda()

        # 10.2 将数据放进网络模型中:
        outputs = model1(imgs)  # 将数据放到网络当中
        # 10.3 获得损失值:(损失值越小越好,越少说明输出结果和实际结果更接近)
        loss = loss_fn(outputs, targets)  # 查看损失值(输出值,真实值)

        # 10.4 优化器优化模型:
        optimizer.zero_grad()  # 利用优化器将梯度清零
        loss.backward()  # 损失值反向传播,得到每一个参数的梯度
        optimizer.step()  # 对得到的参数进行优化

        total_train_step += 1
        # print("训练次数:{},Loss:{}".format(total_train_step, loss))
        if total_train_step % 100 == 0:  # 每逢100次打印一下记录
            end_time = time.time()
            print("耗时:", end_time - start_time)
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))  # item()方法用于将tensor数据类型转换为真实的数字
            # 12.2 将训练集的损失值添加到tensorboard中:
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # 11. 测试步骤开始:
    model1.eval()  # 让网络进入评估模式,参考官方文档Module板块(只有使用了特定层(`Dropout`,`BatchNorm`)才有作用,一般可不使用)
    # 为了确定模型是否训练好,即是否达到自己的需求,可以利用如下方式:
    # 在每一轮训练完成之后,在测试集上进行一下测试,通过查看在测试数据集上的损失和正确率来评估判断模型训练是否达标
    total_test_loss = 0
    # 14. 添加测试正确率:
    # 14.1 定义保存总体正确个数的变量:
    total_accuracy = 0  # 计算整体正确的个数
    with torch.no_grad():  # 此时在测试集上就不需要调优了,所以就不设置梯度
        for data in test_dataloader:
            imgs, targets = data
            # (4)将测试的数据转移到cuda上
            if torch.cuda.is_available():
                imgs = imgs.cuda()
                targets = targets.cuda()

            outputs = model1(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
            # 14.2 确定本次正确的个数:
            accuracy = (outputs.argmax(1) == targets).sum()
            # 14.3 累加在总的正确个数上:
            total_accuracy += accuracy

    print("整体测试集上的Loss:{}".format(total_test_loss))
    # 14.4 打印正确率:
    print("整体测试集上的正确率:{}".format(total_accuracy / test_data_size))  # 测试正确率 = 正确总个数 / 测试总个数
    # 12.3 将测试集的损失值添加到tensorboard中:
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    # 14.5 将正确率添加到tensorboard上:
    writer.add_scalar("test_accuracy_rate", total_accuracy / test_data_size, total_test_step)
    total_test_step += 1
    # 13. 保存每一轮训练的模型(一般会保存每一轮训练的结果)
    torch.save(model1, "model21_{}.pth".format(i))
    # torch.save(model1.state_dict(), "model21_{}.pth".format(i))   # 官方推荐的保存方式(只保存数据,不保存结构)
    print("模型已保存")

writer.close()

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/22. 使用GPU进行训练_方式一.py"
Files already downloaded and verified
Files already downloaded and verified
训练数据集的长度为: 50000
测试数据集的长度为: 10000
-----------1 轮训练开始-----------
耗时: 4.923176050186157
训练次数:100,Loss:2.297931432723999
耗时: 5.921273231506348
训练次数:200,Loss:2.2846615314483643
耗时: 6.901058197021484
训练次数:300,Loss:2.264888286590576
耗时: 7.874129772186279
训练次数:400,Loss:2.204425811767578
耗时: 8.85122275352478
训练次数:500,Loss:2.1267499923706055
耗时: 9.831907272338867
训练次数:600,Loss:2.084637403488159
耗时: 10.819923400878906
训练次数:700,Loss:1.9675300121307373
整体测试集上的Loss:302.99005687236786
整体测试集上的正确率:0.3066999912261963
模型已保存
-----------2 轮训练开始-----------
耗时: 13.392845869064331
训练次数:800,Loss:1.9570894241333008
耗时: 14.376711368560791
训练次数:900,Loss:2.008781909942627
耗时: 15.364539384841919
训练次数:1000,Loss:1.8806016445159912
耗时: 16.352423191070557
训练次数:1100,Loss:1.618012547492981
耗时: 17.331926584243774
训练次数:1200,Loss:1.6897209882736206
耗时: 18.31286597251892
训练次数:1300,Loss:1.6832395792007446
耗时: 19.297619104385376
训练次数:1400,Loss:1.7501848936080933
耗时: 20.280442476272583
训练次数:1500,Loss:1.681038737297058
整体测试集上的Loss:264.8065128326416
整体测试集上的正确率:0.39249998331069946
模型已保存
-----------3 轮训练开始-----------
耗时: 22.837970733642578
训练次数:1600,Loss:1.5688610076904297
耗时: 23.84554934501648
训练次数:1700,Loss:1.7839593887329102
耗时: 24.82080316543579
训练次数:1800,Loss:1.6723309755325317
耗时: 25.81070041656494
训练次数:1900,Loss:1.4974217414855957
耗时: 26.790045738220215
训练次数:2000,Loss:1.7786809206008911
耗时: 27.77305579185486
训练次数:2100,Loss:1.6359188556671143
耗时: 28.76244068145752
训练次数:2200,Loss:1.6583070755004883
耗时: 29.751869201660156
训练次数:2300,Loss:1.7329357862472534
整体测试集上的Loss:244.6054891347885
整体测试集上的正确率:0.44039997458457947
模型已保存
-----------4 轮训练开始-----------
耗时: 32.31385374069214
训练次数:2400,Loss:1.6423664093017578
耗时: 33.30508637428284
训练次数:2500,Loss:1.540467619895935
耗时: 34.2907235622406
训练次数:2600,Loss:1.5103951692581177
耗时: 35.28338408470154
训练次数:2700,Loss:1.514695405960083
耗时: 36.27612328529358
训练次数:2800,Loss:1.6078778505325317
耗时: 37.27000141143799
训练次数:2900,Loss:1.6505825519561768
耗时: 38.26200485229492
训练次数:3000,Loss:1.575993299484253
耗时: 39.255757331848145
训练次数:3100,Loss:1.6188088655471802
整体测试集上的Loss:231.28115379810333
整体测试集上的正确率:0.4684999883174896
模型已保存
-----------5 轮训练开始-----------
耗时: 41.84382390975952
训练次数:3200,Loss:1.5270856618881226
耗时: 42.84325194358826
训练次数:3300,Loss:1.5576322078704834
耗时: 43.852818727493286
训练次数:3400,Loss:1.3824635744094849
耗时: 44.83521318435669
训练次数:3500,Loss:1.3660717010498047
耗时: 45.82822060585022
训练次数:3600,Loss:1.5993531942367554
耗时: 46.815056562423706
训练次数:3700,Loss:1.377953052520752
耗时: 47.80471348762512
训练次数:3800,Loss:1.6025937795639038
耗时: 48.79122495651245
训练次数:3900,Loss:1.2406208515167236
整体测试集上的Loss:220.70796501636505
整体测试集上的正确率:0.49459999799728394
模型已保存
-----------6 轮训练开始-----------
耗时: 51.34356737136841
训练次数:4000,Loss:1.3762238025665283
耗时: 52.336166858673096
训练次数:4100,Loss:1.3632949590682983
耗时: 53.32389283180237
训练次数:4200,Loss:1.277361512184143
耗时: 54.31937336921692
训练次数:4300,Loss:1.4505447149276733
耗时: 55.31698179244995
训练次数:4400,Loss:1.430572509765625
耗时: 56.31524467468262
训练次数:4500,Loss:1.415419578552246
耗时: 57.300695180892944
训练次数:4600,Loss:1.431068778038025
整体测试集上的Loss:210.44779920578003
整体测试集上的正确率:0.5246999859809875
模型已保存
-----------7 轮训练开始-----------
耗时: 59.85842204093933
训练次数:4700,Loss:1.5017774105072021
耗时: 60.868016481399536
训练次数:4800,Loss:1.0926897525787354
耗时: 61.85830354690552
训练次数:4900,Loss:1.3860713243484497
耗时: 62.8494348526001
训练次数:5000,Loss:1.356190800666809
耗时: 63.85549855232239
训练次数:5100,Loss:1.344128131866455
耗时: 64.8457260131836
训练次数:5200,Loss:1.428498387336731
耗时: 65.8467800617218
训练次数:5300,Loss:1.0951019525527954
耗时: 66.83253264427185
训练次数:5400,Loss:1.355404019355774
整体测试集上的Loss:201.57076859474182
整体测试集上的正确率:0.5480999946594238
模型已保存
-----------8 轮训练开始-----------
耗时: 69.3960452079773
训练次数:5500,Loss:1.17838454246521
耗时: 70.38440227508545
训练次数:5600,Loss:1.4806355237960815
耗时: 71.3741147518158
训练次数:5700,Loss:1.2703773975372314
耗时: 72.36600637435913
训练次数:5800,Loss:1.261744499206543
耗时: 73.36564373970032
训练次数:5900,Loss:1.2737648487091064
耗时: 74.36718106269836
训练次数:6000,Loss:1.1499111652374268
耗时: 75.3628396987915
训练次数:6100,Loss:1.3139559030532837
耗时: 76.36102104187012
训练次数:6200,Loss:1.1623998880386353
整体测试集上的Loss:193.50051295757294
整体测试集上的正确率:0.5633000135421753
模型已保存
-----------9 轮训练开始-----------
耗时: 78.93300032615662
训练次数:6300,Loss:1.3307939767837524
耗时: 79.92539381980896
训练次数:6400,Loss:1.1864173412322998
耗时: 80.91911673545837
训练次数:6500,Loss:1.2865761518478394
耗时: 81.91094326972961
训练次数:6600,Loss:1.4354530572891235
耗时: 82.90335583686829
训练次数:6700,Loss:0.9533255696296692
耗时: 83.90857601165771
训练次数:6800,Loss:1.3769410848617554
耗时: 84.89318084716797
训练次数:6900,Loss:1.2743254899978638
耗时: 85.8838415145874
训练次数:7000,Loss:1.228893756866455
整体测试集上的Loss:186.09802329540253
整体测试集上的正确率:0.5812000036239624
模型已保存
-----------10 轮训练开始-----------
耗时: 88.44364309310913
训练次数:7100,Loss:1.3039929866790771
耗时: 89.43258237838745
训练次数:7200,Loss:1.3306399583816528
耗时: 90.42528629302979
训练次数:7300,Loss:1.1453813314437866
耗时: 91.41645860671997
训练次数:7400,Loss:0.8025000095367432
耗时: 92.39818215370178
训练次数:7500,Loss:1.1619906425476074
耗时: 93.385244846344
训练次数:7600,Loss:1.0510789155960083
耗时: 94.37789249420166
训练次数:7700,Loss:1.165479302406311
耗时: 95.36655116081238
训练次数:7800,Loss:1.1886197328567505
整体测试集上的Loss:179.50672507286072
整体测试集上的正确率:0.5967999696731567
模型已保存

Process finished with exit code 0

2. 第二种调用显卡(GPU)的方法

Pytorch的使用_第58张图片

import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
# 5. 引入我们自己写的模型
from torch.utils.tensorboard import SummaryWriter
import time

# from model_21 import *


# 1. 准备数据集
# 1.1 准备训练数据集:
train_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=True,
                                          transform=torchvision.transforms.ToTensor(),
                                          download=True)  # 此处transform参数用于将数据集中原本的PIL图片转换为Tensor类型的图片。
# 1.2 准备测试数据集:
test_data = torchvision.datasets.CIFAR10(root="../19. dataset", train=False,
                                         transform=torchvision.transforms.ToTensor(),
                                         download=True)

# (1)定义训练的设备:
# device = torch.device("cpu")    # 使用cpu
# device = torch.device("cuda:0")   # 使用GPU
# device = torch.device("cuda")   # 等同于上一句,使用GPU
# device = torch.device("cuda:1")    # 当电脑撒谎那个有多个GPU时,可以通过这种方式,使用另一个GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")    # 语法简写:如果有GPU可以用就用GPU,没有则用CPU


# 查看数据集的大小(有多少张照片)
train_data_size = len(train_data)  # 50000
test_data_size = len(test_data)  # 10000
print("训练数据集的长度为:", train_data_size)
print("测试数据集的长度为:", test_data_size)

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


# 6. 创建网络模型:
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(  # 将网络放进序列中,避免了forward()方法的代码冗余
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),  # 展平:64*4*4
            nn.Linear(64 * 4 * 4, 64),
            nn.Linear(64, 10)
        )

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


model1 = Model()
# (2)将模型传给定义的设备:
model1 = model1.to(device)


# 7. 创建损失函数(LossFunction)
loss_fn = nn.CrossEntropyLoss()  # 交叉熵
# (3)将损失函数页传到定义的设备上:
loss_fn = loss_fn.to(device)

# 8. 定义优化器
# learning_rate = 0.01   # 学习速率
learning_rate = 1e-2  # 科学计数法表示 1e-2 = 1 * 10^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(model1.parameters(), lr=learning_rate)  # 随机梯度下降

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

# 12. 添加tensorboard:
# 12.1 定义日志目录:
writer = SummaryWriter("../21. logs_train")

start_time = time.time()
for i in range(epoch):
    print("-----------第 {} 轮训练开始-----------".format(i + 1))
    # 10. 训练步骤开始:
    # model1.train()    # 让网络进入训练状态,参考官方文档Module板块(只有使用了特定层才有作用,一般可不使用)
    for data in train_dataloader:
        # 10.1 拿到数据:
        imgs, targets = data

        # (4)将训练的数据传到定义的设备上
        imgs = imgs.to(device)
        targets = targets.to(device)

        # 10.2 将数据放进网络模型中:
        outputs = model1(imgs)  # 将数据放到网络当中
        # 10.3 获得损失值:(损失值越小越好,越少说明输出结果和实际结果更接近)
        loss = loss_fn(outputs, targets)  # 查看损失值(输出值,真实值)

        # 10.4 优化器优化模型:
        optimizer.zero_grad()  # 利用优化器将梯度清零
        loss.backward()  # 损失值反向传播,得到每一个参数的梯度
        optimizer.step()  # 对得到的参数进行优化

        total_train_step += 1
        # print("训练次数:{},Loss:{}".format(total_train_step, loss))
        if total_train_step % 100 == 0:  # 每逢100次打印一下记录
            end_time = time.time()
            print("耗时:", end_time - start_time)
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))  # item()方法用于将tensor数据类型转换为真实的数字
            # 12.2 将训练集的损失值添加到tensorboard中:
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # 11. 测试步骤开始:
    model1.eval()  # 让网络进入评估模式,参考官方文档Module板块(只有使用了特定层(`Dropout`,`BatchNorm`)才有作用,一般可不使用)
    # 为了确定模型是否训练好,即是否达到自己的需求,可以利用如下方式:
    # 在每一轮训练完成之后,在测试集上进行一下测试,通过查看在测试数据集上的损失和正确率来评估判断模型训练是否达标
    total_test_loss = 0
    # 14. 添加测试正确率:
    # 14.1 定义保存总体正确个数的变量:
    total_accuracy = 0  # 计算整体正确的个数
    with torch.no_grad():  # 此时在测试集上就不需要调优了,所以就不设置梯度
        for data in test_dataloader:
            imgs, targets = data
            # (5)将测试的数据传到定义的设备上
            imgs = imgs.to(device)
            targets = targets.to(device)

            outputs = model1(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()
            # 14.2 确定本次正确的个数:
            accuracy = (outputs.argmax(1) == targets).sum()
            # 14.3 累加在总的正确个数上:
            total_accuracy += accuracy

    print("整体测试集上的Loss:{}".format(total_test_loss))
    # 14.4 打印正确率:
    print("整体测试集上的正确率:{}".format(total_accuracy / test_data_size))  # 测试正确率 = 正确总个数 / 测试总个数
    # 12.3 将测试集的损失值添加到tensorboard中:
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    # 14.5 将正确率添加到tensorboard上:
    writer.add_scalar("test_accuracy_rate", total_accuracy / test_data_size, total_test_step)
    total_test_step += 1
    # 13. 保存每一轮训练的模型(一般会保存每一轮训练的结果)
    torch.save(model1, "model21_{}.pth".format(i))
    # torch.save(model1.state_dict(), "model21_{}.pth".format(i))   # 官方推荐的保存方式(只保存数据,不保存结构)
    print("模型已保存")

writer.close()

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/22.2 使用GPU进行训练_方式二.py"
Files already downloaded and verified
Files already downloaded and verified
训练数据集的长度为: 50000
测试数据集的长度为: 10000
-----------1 轮训练开始-----------
耗时: 6.666868448257446
训练次数:100,Loss:2.2842886447906494
耗时: 7.694902181625366
训练次数:200,Loss:2.270528554916382
耗时: 8.712234497070312
训练次数:300,Loss:2.2226648330688477
耗时: 9.76292872428894
训练次数:400,Loss:2.123183250427246
耗时: 10.756134033203125
训练次数:500,Loss:2.0269904136657715
耗时: 11.802060842514038
训练次数:600,Loss:1.9955990314483643
耗时: 12.870223999023438
训练次数:700,Loss:1.9691498279571533
整体测试集上的Loss:305.35107231140137
整体测试集上的正确率:0.29649999737739563
模型已保存
-----------2 轮训练开始-----------
耗时: 15.539869546890259
训练次数:800,Loss:1.9788057804107666
耗时: 16.499584913253784
训练次数:900,Loss:2.051286458969116
耗时: 17.499370574951172
训练次数:1000,Loss:1.9378248453140259
耗时: 18.514090299606323
训练次数:1100,Loss:1.6403523683547974
耗时: 19.504164457321167
训练次数:1200,Loss:1.7256402969360352
耗时: 20.51738476753235
训练次数:1300,Loss:1.6718839406967163
耗时: 21.506285429000854
训练次数:1400,Loss:1.7534723281860352
耗时: 22.483935594558716
训练次数:1500,Loss:1.6704151630401611
整体测试集上的Loss:270.2608778476715
整体测试集上的正确率:0.3781999945640564
模型已保存
-----------3 轮训练开始-----------
耗时: 25.030548095703125
训练次数:1600,Loss:1.5608513355255127
耗时: 26.059017181396484
训练次数:1700,Loss:1.7768158912658691
耗时: 27.00142478942871
训练次数:1800,Loss:1.6967567205429077
耗时: 27.969423055648804
训练次数:1900,Loss:1.5231211185455322
耗时: 28.903074979782104
训练次数:2000,Loss:1.801447868347168
耗时: 29.851893663406372
训练次数:2100,Loss:1.61238431930542
耗时: 30.795844078063965
训练次数:2200,Loss:1.6808489561080933
耗时: 31.73485231399536
训练次数:2300,Loss:1.7388417720794678
整体测试集上的Loss:245.6873083114624
整体测试集上的正确率:0.4377000033855438
模型已保存
-----------4 轮训练开始-----------
耗时: 34.170658349990845
训练次数:2400,Loss:1.6736152172088623
耗时: 35.113181829452515
训练次数:2500,Loss:1.5710351467132568
耗时: 36.04949378967285
训练次数:2600,Loss:1.5084037780761719
耗时: 37.012978076934814
训练次数:2700,Loss:1.4902925491333008
耗时: 37.956440925598145
训练次数:2800,Loss:1.5907717943191528
耗时: 38.913291931152344
训练次数:2900,Loss:1.6659212112426758
耗时: 39.84586763381958
训练次数:3000,Loss:1.575939655303955
耗时: 40.78300476074219
训练次数:3100,Loss:1.645302414894104
整体测试集上的Loss:233.53828501701355
整体测试集上的正确率:0.4624999761581421
模型已保存
-----------5 轮训练开始-----------
耗时: 43.223291635513306
训练次数:3200,Loss:1.5247035026550293
耗时: 44.159050703048706
训练次数:3300,Loss:1.5351026058197021
耗时: 45.12818431854248
训练次数:3400,Loss:1.3810744285583496
耗时: 46.05564069747925
训练次数:3500,Loss:1.3292346000671387
耗时: 46.98894143104553
训练次数:3600,Loss:1.620406150817871
耗时: 47.918192863464355
训练次数:3700,Loss:1.3757078647613525
耗时: 48.84572768211365
训练次数:3800,Loss:1.6293727159500122
耗时: 49.782917499542236
训练次数:3900,Loss:1.2306959629058838
整体测试集上的Loss:223.1653529405594
整体测试集上的正确率:0.4903999865055084
模型已保存
-----------6 轮训练开始-----------
耗时: 52.19120669364929
训练次数:4000,Loss:1.411436676979065
耗时: 53.126442670822144
训练次数:4100,Loss:1.420030951499939
耗时: 54.055376291275024
训练次数:4200,Loss:1.3187339305877686
耗时: 54.98124861717224
训练次数:4300,Loss:1.505440354347229
耗时: 55.91581392288208
训练次数:4400,Loss:1.4029964208602905
耗时: 56.8693208694458
训练次数:4500,Loss:1.3967833518981934
耗时: 57.80340766906738
训练次数:4600,Loss:1.4301002025604248
整体测试集上的Loss:212.42449724674225
整体测试集上的正确率:0.5153999924659729
模型已保存
-----------7 轮训练开始-----------
耗时: 60.24119257926941
训练次数:4700,Loss:1.6077704429626465
耗时: 61.176737785339355
训练次数:4800,Loss:1.1246665716171265
耗时: 62.1333441734314
训练次数:4900,Loss:1.382673978805542
耗时: 63.072837114334106
训练次数:5000,Loss:1.377209186553955
耗时: 64.02987599372864
训练次数:5100,Loss:1.308245301246643
耗时: 64.95243811607361
训练次数:5200,Loss:1.418842077255249
耗时: 65.87331318855286
训练次数:5300,Loss:1.124040961265564
耗时: 66.81282830238342
训练次数:5400,Loss:1.3288600444793701
整体测试集上的Loss:203.40331053733826
整体测试集上的正确率:0.5343999862670898
模型已保存
-----------8 轮训练开始-----------
耗时: 69.21697998046875
训练次数:5500,Loss:1.148829698562622
耗时: 70.15680384635925
训练次数:5600,Loss:1.4901899099349976
耗时: 71.09262871742249
训练次数:5700,Loss:1.322636365890503
耗时: 72.02316379547119
训练次数:5800,Loss:1.234808087348938
耗时: 72.955894947052
训练次数:5900,Loss:1.3367561101913452
耗时: 73.91346406936646
训练次数:6000,Loss:1.134941816329956
耗时: 74.84356713294983
训练次数:6100,Loss:1.3465211391448975
耗时: 75.77949786186218
训练次数:6200,Loss:1.1853519678115845
整体测试集上的Loss:195.3301376104355
整体测试集上的正确率:0.554099977016449
模型已保存
-----------9 轮训练开始-----------
耗时: 78.21278715133667
训练次数:6300,Loss:1.3467941284179688
耗时: 79.14480066299438
训练次数:6400,Loss:1.212073802947998
耗时: 80.09001588821411
训练次数:6500,Loss:1.2584960460662842
耗时: 81.02557277679443
训练次数:6600,Loss:1.3527040481567383
耗时: 81.95775604248047
训练次数:6700,Loss:1.0061984062194824
耗时: 82.90536141395569
训练次数:6800,Loss:1.4239755868911743
耗时: 83.82980823516846
训练次数:6900,Loss:1.237653136253357
耗时: 84.75678586959839
训练次数:7000,Loss:1.195392370223999
整体测试集上的Loss:187.98144674301147
整体测试集上的正确率:0.5715999603271484
模型已保存
-----------10 轮训练开始-----------
耗时: 87.18333864212036
训练次数:7100,Loss:1.3618402481079102
耗时: 88.13255095481873
训练次数:7200,Loss:1.3309695720672607
耗时: 89.05999493598938
训练次数:7300,Loss:1.2348980903625488
耗时: 89.99397468566895
训练次数:7400,Loss:0.8044885396957397
耗时: 90.9220724105835
训练次数:7500,Loss:1.1153995990753174
耗时: 91.84887933731079
训练次数:7600,Loss:1.030860424041748
耗时: 92.788503408432
训练次数:7700,Loss:1.2277518510818481
耗时: 93.72009301185608
训练次数:7800,Loss:1.2313294410705566
整体测试集上的Loss:181.6148488521576
整体测试集上的正确率:0.5870999693870544
模型已保存

Process finished with exit code 0

14. 完整的模型验证套路

  • (测试、demo)
  • 利用已经训练好的模型,然后给它提供输入。

1. 验证未经过训练的模型

  • 能看到基本上都不准确。
import torch
import torchvision
from PIL import Image
from torch import nn

image_path = "../images/dog2.png"
image = Image.open(image_path)   # 读取图片
image = image.convert("RGB")   # 仅保留RGB颜色通道
# print(image)

transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
                                           torchvision.transforms.ToTensor()])     # 将PIL图片转换为tensor图片

image = transform(image)
print(image.shape)   # torch.Size([3, 32, 32])


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(  # 将网络放进序列中,避免了forward()方法的代码冗余
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),   # 展平:64*4*4
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )

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


# 保存模型:
model_text = Model()   # 需要加上这一句
torch.save(model_text, "model_23.pth")

# 加载网络模型:
model = torch.load("model_23.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))  # tensor([9])  # 类别选择不正确(由于该模型未经过训练)


# {'airplane':0, 'automobile': 1, 'bird:2, 'cat': 3, 'deer':4, 'dog': 5, 'frog': 6, 'horse':7, 'ship': 8, 'truck':9}

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/23. test.py"
torch.Size([3, 32, 32])
tensor([[ 0.0590,  0.0321, -0.0449, -0.0546, -0.0143,  0.1509,  0.0214, -0.0299,
         -0.0170,  0.1550]])
tensor([9])

Process finished with exit code 0

2. 验证原来经过10次训练的模型

-可以发现有的准确,有的不准确。

import torch
import torchvision
from PIL import Image
from torch import nn

# image_path = "../images/dog2.png"
image_path = "../images/bird2.png"
image = Image.open(image_path)   # 读取图片
image = image.convert("RGB")   # 仅保留RGB颜色通道
# print(image)

# 数据集(为了获取识别出来的类别)
test_data = torchvision.datasets.CIFAR10("../7. dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
classes_list = test_data.classes

transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
                                           torchvision.transforms.ToTensor()])     # 将PIL图片转换为tensor图片

image = transform(image)
print(image.shape)   # torch.Size([3, 32, 32])


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.model1 = nn.Sequential(  # 将网络放进序列中,避免了forward()方法的代码冗余
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),   # 展平:64*4*4
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )

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


# 保存模型:
# model_text = Model()   # 需要加上这一句
# torch.save(model_text, "model_23.pth")

# 加载网络模型:
# model = torch.load("model21_9.pth", map_location=torch.device('cpu'))   # 只有cpu的情况下使用gpu训练过的模型应该这样写(将GPU上的模型映射到cpu上)
model = torch.load("model21_9.pth", map_location='cpu')      # 等同上一句
# 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))  # tensor([9])  # 类别选择不正确(由于该模型未经过训练)
classes_index = output.argmax(1).item()    # 获取到该tensor数据类型值的数值
print("识别的结果是:", classes_list[classes_index])


# {'airplane':0, 'automobile': 1, 'bird:2, 'cat': 3, 'deer':4, 'dog': 5, 'frog': 6, 'horse':7, 'ship': 8, 'truck':9}

运行结果:

D:\Anaconda\envs\pytorch\python.exe "C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/23. 完整的模型的验证_2(验证训练后的模型).py"
Files already downloaded and verified
torch.Size([3, 32, 32])
tensor([[-0.1059, -1.9070,  3.5285,  0.8725,  1.4967,  0.5833,  0.8507, -0.6100,
         -2.4425, -2.7577]])
tensor([2])
识别的结果是: bird

Process finished with exit code 0

你可能感兴趣的:(Python,学习,python,pytorch)