Pytorch学习笔记

Pytorch学习笔记

基于视频


学习视频

Pytorch下载与安装


  1. 下载与安装
  1. 前置条件

Anaconda下载安装(官网或者清华源)

  1. 安装Pytorch

(42条消息) pytorch快速安装【清华源】ZQ_ZHU的博客-CSDN博客-c pytorch

官网下载地址

注意:下载去掉 -c pytorch!且一定要换源

  1. 输入验证
import torch
torch.cuda.is_availale()

运行成功则安装成功

万能函数


  1. 查看

    dir()

    注意:_ _ xxx _ _为不可修改的变量

  2. 帮助

    help()

Pytorch加载数据机制


  1. Dataset和Dataloader

    • Dataset
      • 提供一种方式去获取数据及其Label
    • Dataloader
      • 为后面的网络提供不同的数据形式
  2. Dataset的使用

    • 基本图像操作
    # python中的 python image library
    from PIL import Image
    
    img_path = "B:\\Desktop\\hymenoptera_data\\train\\ants\\0013035.jpg"
    print(img_path)
    img = image.open(img_path)
    
  • 操作二

    # os.path.join()函数将前后字符串拼接
    self.path = os.path.join(self.root_dir, self.label_dir)
    # 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表
    self.img_path = os.listdir(self.path)
    
    • Dataset文档
    All datasets that represent a map from keys to data samples should subclass
        it. All subclasses should overwrite :meth:`__getitem__`, supporting fetching a
        data sample for a given key. Subclasses could also optionally overwrite
        :meth:`__len__`, which is expected to return the size of the dataset by many
        :class:`~torch.utils.data.Sampler` implementations and the default options
        of :class:`~torch.utils.data.DataLoader`.
    ------------------------------------------------------
    表示从键到数据样本的映射的所有数据集都应子类化,它所有子类都应覆盖:meth:__getitem__函数,支持获取给定密钥的数据样本。子类也可以选择覆盖:meth:__len__函数,它将返回数据集的大小
    
    • 调用
    # 数据集调用MyData方法创建一个对象
    ants_dataset = MyData(root_dir, ants_label_dir)
    bees_dataset = MyData(root_dir, bees_label_dir)
    # 两个数据集的合并
    train_dataset = ants_dataset + bees_dataset
    

TensorBoard的使用


  1. 安装

    pip install tensorboard -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    # 调整端口 + 运行
    tensorboard --logdir=你的路径 --port=6007
    
  2. 使用

    from torch.utils.tensorboard import SummaryWriter
    
    # 定义logs文件夹
    writer = SummaryWriter("logs")
    
    
    # y = x
    for i in range(100):
        # 第一个参数:图表的title
        # 第二个参数:X轴
        # 第三个参数:Y轴
        writer.add_scalar("y = 2*x", 3*i, i)
    
    writer.close()
    
  3. Scalar中存在问题

    • 如果将两个函数写到同一个表中,有可能存在自动拟合现象

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OAdVn93x-1668067221437)(https://cdn.jsdelivr.net/gh/cr7tywzrjw/images/img/202210301700452.png)]

  4. 深度

    import numpy as np
    from torch.utils.tensorboard import SummaryWriter
    from PIL import Image
    
    writer = SummaryWriter("logs")
    image_path = "B:\\Desktop\\hymenoptera_data\\train\\ants_image\\0013035.jpg"
    
    img_PIL = Image.open(image_path)
    # 将输入的图片类型由JpegImage转换为Numpy格式
    img_array = np.array(img_PIL)
    # 第一个参数:模块名
    # 第二个参数:图片输入
    # 第三个参数:Step:x
    # 第四个参数:规定数据格式(H 高 W 宽 C 通道)
    writer.add_image("test", img_array, 3, dataformats='HWC')
    

Transform的使用


  1. Transforms的结构和作用

    Pytorch学习笔记_第1张图片

  2. Transforms的实现

    from PIL import Image
    from torchvision import transforms
    
    img_path = "B:\\Desktop\\hymenoptera_data\\train\\ants_image\\0013035.jpg"
    img = Image.open(img_path)
    # 利用Transforms模具去设计一个工具tensor_trans
    tensor_trans = transforms.ToTensor()
    # 同时利用该工具去处理图像得到一个输出
    tensor_img = tensor_trans(img)
    
    print(tensor_img)
    
  3. Tensor数据类型:包装了神经网络所需要的理论基础参数。

  4. Normalize函数

    transform.ToTensor(),
    transform.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))
    
    • ToTensor()能够把灰度范围从0-255变换到0-1之间,而后面的transform.Normalize()则把0-1变换到(-1,1).具体地说,对每个通道而言,Normalize执行以下操作
    image=(image-mean) / std
    
    • 其中mean和std分别通过(0.5,0.5,0.5)和(0.5,0.5,0.5)进行指定。原来的0-1最小值0则变成(0-0.5)/0.5=-1,而最大值1则变成(1-0.5) / 0.5=1

    • 数据标准化—transforms.normalize()详解

      • mean 和 std 要在normalize() 之前自己先算好再传进去的,不然每次normalize() 就得把所有的图片都读取一遍算这两个

      • 应用了torchvision.transforms.ToTensor,其作用是将数据归一化到[0,1](是将数据除以255),transforms.ToTensor() 会把HWC会变成CHW(拓展:格式为(h,w,c),像素顺序为RGB)

      • ToTensor已经[0,1]为什么还要[0.5, 0.5, 0.5]?那么归一化后为什么还要接一个Normalize()呢?Normalize()是对数据按通道进行标准化,即减去均值,再除以方差

      • 解答:数据如果分布在(0,1)之间,可能实际的bias,就是神经网络的输入b会比较大,而模型初始化时b=0的,这样会导致神经网络收敛比较慢,经过Normalize后,可以加快模型的收敛速度。
        因为对RGB图片而言,数据范围是[0-255]的,需要先经过ToTensor除以255归一化到[0,1]之后,再通过Normalize计算过后,将数据归一化到[-1,1]。

  5. Resize函数

    • Resize函数的直接使用

      # 重设大小,输入像素(512, 512)
      trans_resize = transforms.Resize((512, 512))
      img_resize = trans_resize(img)
      # 转为tensor类型
      img_resize_tensor = trans_tensor(img_resize)
      print(img_resize_tensor)
      # 放入tensorboard中
      writer.add_image("Resize", img_resize_tensor, 0)
      
    • compose函数使用

      # 将图片缩放到512,长宽比保持不变 
      trans_resize_2 = transforms.Resize(512)
      # 下列解释:一般用Compose把多个步骤整合到一起
      trans_compose = transforms.Compose([trans_resize_2, trans_tensor])
      img_resize_2 = trans_compose(img)
      writer.add_image("Resize", img_resize_2, 1)
      
      • compose函数中的参数需要是一个列表,在compose中,数据需要的是transforms类型,所以compose函数的意义就是将其中的transforms按照次序依次执行
  6. RandomCrop函数

    • 使用

      # 随机裁剪,输入值为size
      trans_random = transforms.RandomCrop([128, 128])
      trans_compose_2 = transforms.Compose([trans_random, trans_tensor])
      # 裁剪1000张图片
      for i in range(1000):
          img_crop = trans_compose_2(img)
          writer.add_image("RandomCrop", img_crop, i)
      

Torchvision中的数据集使用


  1. 使用

    import torchvision
    # 下载官网数据集
    train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, download=True)
    test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=True)
    # 输出第一个数据集
    print(test_set[0])
    
    img, target = test_set[0]
    print(img)
    print(target)
    print(test_set.classes[target]) 
    img.show()
    
  2. 下载

DataLoader使用


  1. 使用

    import torchvision
    from torch.utils.data import DataLoader
    from torch.utils.tensorboard import SummaryWriter
    
    # 导入数据集
    test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor())
    # num_workers=0 表示只有一个主进程
    # batch_size 表示每次要取64个数据组合
    # drop_last 表示数据不足的时候就舍去
    # shuffle true表示数据随机抓取第二轮
    test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
    
    img, target = test_data[0]
    print(img.shape)
    print(target)
    
    writer = SummaryWriter("dataloader")
    # 循环加载test——loader中的数据
    for epoche in range(2):
        step = 0
        for data in test_loader:
            imgs, targets = data
            # print(imgs.shape)
            # print(targets)
            # 注意为images不是image
            # format()函数的作用是将数据格式化,即epoche为1的时候前面{}中即为1,并存放对应的数据
            writer.add_images("epoche_{}".format(epoche), imgs, step)
            step += 1
    
    writer.close()
    
    • 运行for循环的话就会重新调用test_loader,如果shuffle是True的话,那么bactch_size中的图片每个都不一样

神经网络基本骨架Moudle


  1. Containers.moudle

    import torch.nn as nn
    import torch.nn.functional as F
    
    class Model(nn.Module):
        def __init__(self):
    		# 继承父类方法的构造函数
            super().__init__()
            # 卷积
            self.conv1 = nn.Conv2d(1, 20, 5)
            self.conv2 = nn.Conv2d(20, 20, 5)
    	# 前向传播
        def forward(self, x):
            x = F.relu(self.conv1(x))
            return F.relu(self.conv2(x))
    
    • 前向传播

      Input —> forward —> Output

    • 实例应用

      import torch
      from torch import nn
      
      # RJW神经网络
      class RJW(nn.Module):
          # 继承父类
          def __init__(self) -> None:
              super().__init__()
      	# 前向传播,指定一个输入
          def forward(self, input):
              output = input + 1
              return output
      # 新建实例对象
      rjw = RJW()
      # 输入一个tensor类型,torch.Tensor是存储和变换数据的主要工具。
      # Tensor与Numpy的多维数组非常相似。
      x = torch.tensor(1.0)
      output = rjw(x)
      print(output)
      

卷积相关知识的补充


  1. 卷积的组成:输入图像、卷积核

    操作:将每一个位置对应相乘

  2. 当Stride为1时卷积后的输出

  3. 实例使用

    import torch
    import torch.nn.functional as F
    
    # 输入图像
    input = torch.tensor([[1, 2, 0, 3, 1],
                         [0, 1, 2, 3, 1],
                         [1, 2, 1, 0, 0],
                         [5, 2, 3, 1, 1],
                         [2, 1, 0, 1, 1]])
    # 设置卷积和
    kernel = torch.tensor([[1, 2, 1],
                           [0, 1, 0],
                           [2, 1, 0]])
    print(input.shape)
    print(kernel.shape)
    
    # 1个数据 1个通道 高度5 宽度5
    input = torch.reshape(input, (1, 1, 5, 5))
    kernel = torch.reshape(kernel, (1, 1, 3, 3))
    
    print(input.shape)
    print(kernel.shape)
    # stride 步长
    # conv2d 卷积
    output = F.conv2d(input, kernel, stride=1)
    print(output)
    # padding 外边框补齐
    # conv2d 卷积
    output2 = F.conv2d(input, kernel, stride=1, padding=1)
    print(output2)
    

神经网络-卷积层


  1. CONV2D

    # in_channels 输入通道数
    # out_channels 输出通道数等于卷积核数
    # dilation 对应位
    # groups 分组卷积
    # bias 偏置
    # padding_mode 填充模式
    torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)
    
  2. 搭建自己的神经网络

    import torch
    import torchvision.datasets
    from torch import nn
    from torch.utils.data import DataLoader
    from torch.nn import Conv2d
    from torch.utils.tensorboard import SummaryWriter
    # 设置数据集
    dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
    dataloader = DataLoader(dataset, batch_size=64)
    # RJW网络类
    class RJW(nn.Module):
        def __init__(self) -> None:
            super().__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
    
    rjw = RJW()
    # print(rjw)
    writer = SummaryWriter("../data/logs")
    step = 0
    for data in dataloader:
        imgs, targets = data
        output = rjw(imgs)
        # 输出torch.Size([64, 3, 32, 32])
        # 输出torch.Size([64, 6, 30, 30])
        # 64:batch_size 3:out_channels 32:图像大小
        print(imgs.shape)
        print(output.shape)
    
        writer.add_images("input", imgs, step)
    	# -1指的是根据后边的值自动进行计算,其他参数同上
        output = torch.reshape(output, (-1, 3, 30, 30))
        writer.add_images("output", output, step)
        step += 1
    

神经网络-最大池化操作


  1. 最大池化操作

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avRprC6w-1668067221438)(https://cdn.jsdelivr.net/gh/cr7tywzrjw/images/img/202211041103384.png)]

    • 参数详解
      • Ceil_model:决定是不是要忽略边框部分,例如 5 ∗ 5 5*5 55的输入图像中,利用 3 ∗ 3 3*3 33的池化核进行池化,得到的输出有 2 ∗ 2 2*2 22 1 ∗ 1 1*1 11两种差别
      • Kernel_size:池化核的大小
      • dtype:输入图像的数据类型
  2. 池化调用函数

    import torch
    from torch import nn
    from torch.nn import MaxPool2d
    
    input = torch.tensor([[1, 2, 0, 3, 1],
                          [0, 1, 2, 3, 1],
                          [1, 2, 1, 0, 0],
                          [5, 2, 3, 1, 1],
                          [2, 1, 0, 1, 1]], dtype=torch.float32)
    
    input = torch.reshape(input, (-1, 1, 5, 5))
    print(input.shape)
    
    class RJW(nn.Module):
        def __init__(self) -> None:
            super().__init__()
            # 最大池化操作,输入必要参数
            self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)
    
        def forward(self, input):
            output = self.maxpool1(input)
            return output
    
    rjw = RJW()
    output = rjw(input)
    print(output)
    
    
  3. 池化的作用:保留数据特征,减少数据量

  4. Tensorboard中的效果展示

    • 池化展现出的是每个图片的最大特征,同时数据量大小也能降低

神经网络-最大非线性激活操作


  1. ReLU函数作用:激活函数是加入非线性因素,线性不能非常好的拟合现实的情况,加入非线性因素可以增强拟合的能力,否则模型泛化能力变差

  2. ReLU函数的使用

  3. 相似的-Sigmoid函数的使用

神经网络-线性层及其他


  1. Linear函数-线性层

        # 先利用output.reshape(1, 1, 1, -1)
        # 得到输出196608,有多少列
        # 再使用Linear函数
        def __init__(self) -> None:
            super().__init__()
            # 10:每一个输出图像的大小
            self.linear1 = Linear(196608, 10)
    
  2. torch.flatten函数

    • 替代torch.reshape函数

      output = torch.flatten(imgs)
      

神经网络实战


  1. 神经网络实现实战

  2. 根据公式计算神经网络参数

  3. 代码实现

    • 未加入Sequential

    • 加入Sequential

       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)
              )
      
    • 整体实现

      import torch
      from torch import nn
      from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
      from torch.utils.tensorboard import SummaryWriter
      
      
      class RJW(nn.Module):
          def __init__(self) -> None:
              super().__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
      
      
      rjw = RJW()
      print(rjw)
      print("----------------------------")
      input = torch.ones((64, 3, 32, 32))
      output = rjw(input)
      print(output.shape)
      
      writer = SummaryWriter("logs_nn_network")
      writer.add_graph(rjw, input)
      writer.close()
      
    • 引入实际的数据集进行实现

      import torchvision
      from torch import nn
      from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
      from torch.utils.data import DataLoader
      
      dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(),
                                             download=True)
      dataloader = DataLoader(dataset, batch_size=1)
      
      class RJW(nn.Module):
          def __init__(self) -> None:
              super().__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
          
      rjw = RJW()
      for data in dataloader:
          imgs, targets = data
          outputs = rjw(imgs)
          print(outputs)
          # print(imgs)
          print(targets)
          print("---------------")
      
      • 在实际的数据集中输出结果如下所示

        tensor([[-0.0630, 0.0902, 0.0604, 0.0883, -0.0663, 0.0701, -0.0184, -0.0324,
        -0.0339, -0.1069]], grad_fn=)

        tensor([1])

        其中,-0.0630、0.0902等等数据,为通过卷积、池化等一系列操作由网络计算出的数据,tensor([1])的具体含义为第1类的图片同目标图片最为匹配即,0.0902在同一组数据中最大。

损失函数


  1. Loss的作用

    • 计算实际输出和目标之间的差距
    • 为我们更新输出提供一定的依据,即反向传播
  2. L1Loss函数与MSELoss函数应用举例

    import torch
    from torch.nn import L1Loss, MSELoss
    
    inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
    targets = torch.tensor([1, 2, 5])
    
    inputs = torch.reshape(inputs, (1, 1, 1, 3))
    targets = torch.reshape(targets, (1, 1, 1, 3))
    # 将相差的加起来取平均
    # loss = L1Loss()
    # 将相差的值加起来
    loss = L1Loss(reduction='sum')
    # 每个取平方再加起来取平均
    loss_mse = MSELoss()
    result = loss(inputs, targets)
    result_mse = loss_mse(inputs, targets)
    print(result)
    print(result_mse)
    
  3. CrossEntropyLoss函数的使用

    • CrossEntropyLoss函数详解
    • 只有当命中的时候,即对应的x[class]的值取到比较大的时候,Loss函数才比较小。

    • output输出相当于对Person和dog和cat的值的预测,如果输出结果相差不大,那么意味着分类器性能较低。

    • Target的值就是class的值,其为实际过程中给出的,1则为针对dog的预测结果

    • 实例使用

      x = torch.tensor([.1, .2, .3])
      y = torch.tensor([1])
      x = torch.reshape(x, [1, 3])
      loss_cross = nn.CrossEntropyLoss()
      result_cross = loss_cross(x, y)
      print(result_cross)
      
  4. 神经网络实战和Loss函数结合

    # 引入loss函数,看每一次的loss具体有多少
    loss = nn.CrossEntropyLoss()
    
    for data in dataloader:
        imgs, targets = data
        outputs = rjw(imgs)
        # 输入outputs即输出的结果
        # 输入target目标结果进行匹配
        # 观察最后的输出结果有多少偏差
        result = loss(outputs, targets)
        print(result)
    # 输出:
    # tensor(2.2747, grad_fn=)
    # 相差2.2747,这个值越小越好
    
  5. 梯度Grad的概念

    • 梯度的示意图:图中所示的Gradient为梯度,点Weight的位置每次都可以根据该梯度Gradient来进行一个自动的调整。

优化器


  1. 优化器的必要步骤

    for input, target in dataset:
        # 必须清零,防止上一步参数对本步产生的影像
        optimizer.zero_grad()
        output = model(input)
        loss = loss_fn(output, target)
        loss.backward()
        optimizer.step()
    
  2. 优化器的使用

    rjw = RJW()
    # lr:学习的速率
    # parmeters:神经网络基本参数
    optim = torch.optim.SGD(rjw.parameters(), lr=0.01)
    
    loss = nn.CrossEntropyLoss()
    for epoche in range(1, 10):
        # 做一个结果展示
        running_loss = 0.0
        for data in dataloader:
            imgs, targets = data
            outputs = rjw(imgs)
            result = loss(outputs, targets)
            # 清零
            optim.zero_grad()
            # 得到了每一个参数对应梯度
            result.backward()
            # 调用优化器的step()函数计算
            optim.step()
            running_loss += result
        print(running_loss)
    

VGG16网络模型的修改与添加


  1. 参数pretrained 为false和true时的区别

    vgg16_false = torchvision.models.vgg16(pretrained = False)
    #False,下载的是网络模型,默认参数

    vgg16_true = torchvision.models.vgg16(pretrained = True)
    #True,下载的是网络模型,并且在数据集上面训练好的参数。

  2. 网络模型的修改

    • VGG16网络模型

      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_linear): Linear(in_features=1000, out_features=10, bias=True)
        )
          # 整体添加
          (add_linear): Linear(in_features=1000, out_features=10, bias=True)
      )
      
    • 针对整体添加一个线性层

      vgg16_true.add_module("add_linear", nn.Linear(1000, 10))
      # (add_linear): Linear(in_features=1000, out_features=10, bias=True)
      
    • 针对classifier添加一个线性层

      vgg16_true.classifier.add_module("add_linear", nn.Linear(1000, 10))
      # (add_linear): Linear(in_features=1000, out_features=10, bias=True)
      
    • 局部修改

      vgg16_false.classifier[6] = nn.Linear(4096, 10)
      # (6): Linear(in_features=4096, out_features=10, bias=True)
      

网络模型的保存与训练


  1. 模型保存与加载方式合集

    • 保存方式1与对应的加载方式

      # 保存的是模型的结构和模型的参数
      torch.save(vgg16, "vgg16_method1.pth")
      model = torch.load("vgg16_method1.pth")
      print(model)
      
    • 保存方式2

      # 只保存模型参数
      torch.save(vgg16.state_dict(), "vgg16_method2.pth")
      # 加载
      vgg16 = torchvision.vgg16(pretrained=False)
      vgg16.load_state_dict(torch.load("vgg16_method2.pth"))
      print(vgg16)
      
  2. 网络训练状态和测试状态开始

    # 训练
    rjw.train()
    # 测试
    rjw.eval()
    

利用GPU进行训练


  1. 需要对原有代码进行改进

    GPU可以进行加速的环节:

       	1. 网络模型本身
       	2. 数据本身(包括输入以及标注)
       	3. 损失函数
    
  2. 使用方法:

    • 方法1

      if torch.cuda.is_avaiable():
          imgs = imgs.cuda()
      
    • 方法2

      device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
      imgs = imgs.to(device)
      
  3. 免费开源的训练平台:Google Colab

  4. With关键字

    With的出现可以自动的处理对文件的关闭操作,更加节约性能

  5. 跑模型需要注意的点(删除Required=True,意思就是不需要手动输入参数“–dataroot /…/…”)

你可能感兴趣的:(笔记,pytorch,学习,深度学习)