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()
    
  • 运行结果:

  • 使用add_image()方法

  • 根据源码的img_tensor (torch.Tensor, numpy.array, or string/blobname): Image data,传入的图片参数是需要满足以上任一类型的图片。

    从控制台中可以看到:

    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))   # <class 'PIL.JpegImagePlugin.JpegImageFile'>
    
    import numpy as np
    img_array = np.array(img)   
    print(type(img_array))     # <class 'numpy.ndarray'>
    

    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))   # 打印图片类型   <class 'numpy.ndarray'>
    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()
    

    运行结果:

    能够看到tensorboard里面多了一张蚂蚁的图片:

    再对图片和步骤进行更改如下:

    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))   # 打印图片类型   <class 'numpy.ndarray'>
    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()
    

    再次运行结果如下:


    拖动上面的轴线,能够切换图片:

    这是由于添加图片时,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))   # 打印图片类型   <class 'numpy.ndarray'>
    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()
    

    运行效果如下:
    控制台输出
    Tensorboard刷新显示

    八、Transforms的使用

  • 查看图片信息:
  • # 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
    

    补充的图

  • 加载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()
    

    运行结果:

    九、常见的transforms类的使用

    拓展: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)   # <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x249512B1710>
    
    trans_totensor = transforms.ToTensor()   # 创建ToTensor()对象
    img_tensor = trans_totensor(img)   # 传入图片参数,将PIL图片转换成tensor图片
    
    writer.add_image("ToTensor", img_tensor)
    writer.close()
    

    运行结果:

    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)   # <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x249512B1710>
    
    # 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
    


    更改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
    


    更改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
    

    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)   # <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x249512B1710>
    
    # 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)   # <PIL.Image.Image image mode=RGB size=512x512 at 0x1721BCA34A8>
    # 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
    

    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)   # <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x249512B1710>
    
    # 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)   # <PIL.Image.Image image mode=RGB size=512x512 at 0x1721BCA34A8>
    # 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()
    

    运行结果:

    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)   # <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1400x875 at 0x249512B1710>
    
    # 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)   # <PIL.Image.Image image mode=RGB size=512x512 at 0x1721BCA34A8>
    # 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()
    
    

    运行结果:

    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的数据集:

    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])  # (<PIL.Image.Image image mode=RGB size=32x32 at 0x202CE982550>, 3)
    print(test_set.classes)   # 查看所有类别
    # ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
    
    img, target = test_set[0]  # 分别获取图片、所属类别的下标(从0开始)
    print(img)  # <PIL.Image.Image image mode=RGB size=32x32 at 0x202CE982390>
    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中的结果:

    十、DataLoader的使用

    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)
    



    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("运行完毕")
    
    

    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("运行完毕")
    
    

    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("运行完毕")
    
    

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

  • 官方网站位置:https://pytorch.org/docs/stable/nn.html
  • nn即Nerual Network。
  • 1. 骨架/容器(Containers)

  • Module很重要。
  • Module

  • 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)

    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来填充。
  • 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数量,叠加)

  • 选取卷积核包裹范围的乘积和。

    输出通道数(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)
    

    卷积后的图片
    -拓展: VGG16 Modle卷积
    推导公式:

    4. 最大池化操作(MaxPool2d)

  • 选取池中最大值
  • 1. 用二维矩阵展示

    # 最大池化卷积:下采样(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)
    
    

    5. 非线性激活

    1. nn.ReLU

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

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

    # 线性层官方文档: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的简单网络模型


    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()
    

    运行结果:

  • 双击可以展开细节:
  • 8. 损失函数与反向传播

  • Loss Functions(衡量误差)
  • 误差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(交叉熵损失)

  • -0.2+ln(exp(0.1)+exp(0.2)+exp(0.3))
  • # 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)

  • 查看网络模型梯度:

  • 在模型上使用优化器:
  • # 官方文档: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 <module '__main__' from 'C:/Users/lv/Desktop/Pytorch/1. Pytorch的使用(第一次)/src/20.2 网络模型的读取.py'>
    # 解决方法:直接将定义的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. 完整的模型训练套路

    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)
    
    
    

    运行主要结果:

    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
    
    

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

    1. 如何计算正确率:
  • 计算准确率(argmax()方法)
  • 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
  • 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)的方法

    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}
    
    

    运行结果:
    ···python
    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

    ···

    来源:Lvcx

    物联沃分享整理
    物联沃-IOTWORD物联网 » Pytorch的使用

    发表评论