PyTorch深度学习快速入门教程--学习笔记

目录

P4 PyCharm和Jupyter的对比

P5 PyTorch加载数据

P6 Dataset类代码实现

P7 Tensorboard 写日志

读取日志文件

Tensorboard 读图片

P10 Transforms使用

Transforms用途

常见的Transforms工具

P14 torchvision数据集使用

P15 Dataloader使用

 P16   nn.Module模块使用

P17 卷积原理

步幅、填充原理

P18 神经网络——卷积层 

搭建卷积层

​编辑

卷积层处理图片

Tensorboard显示

P19最大池化层

池化层处理数据

池化层处理图片

P20 神经网络——非线性激活

P21 神经网络——线性层及其他层

Linear Layers线性层

线性拉平

P22 搭建小实战和顺序使用

​编辑

搭建神经网络

Sequential神经网络

 Tensorboard显示网络(强推!)

P23 损失函数与逆向传播

损失函数反向传播

 P24 优化器

SGD随机梯度下降

神经网络优化一轮

 神经网络优化多轮

 神经网络学习率优化

P25 网络模型使用及修改

下载网络模型

​编辑

查看函数用法

网络模型添加

网络模型修改

P26 网络模型保存与读取

网络模型保存(方式一)

网络模型导入(方式一)

网络模型保存(方式二)

网络模型导入(方式二)

网络陷阱

P27 完整模型训练套路

CIFAR 10 model 网络模型

 DataLoader加载数据集

测试网络正确

网络训练数据

查看训练损失

保存每一轮后参数

argmax作用

打印正确率(最终版代码)

特殊层作用

P30 利用GPU训练

方式一

方式二

运行Terminal语句

P32 完整模型验证套路

验证狗是否识别

P33 查看开源项目

parser.add_argument


本文基于B站“我是土堆”的课程记录学习笔记,原视频讲解:P4. PyCharm及Jupyter使用及对比_哔哩哔哩_bilibili

P4 PyCharm和Jupyter的对比

测试程序:

#用来测试的错误代码,a是字符型,b是整型,所以加在一起会报错
print("Start")
a = "hello word"
b = 2019
c = a + b
print(c)

#正确的代码,把b也写成字符型
print("Start")
a = "hello word"
b = "2019"
c = a + b
print(c)

python控制台运行代码可读性比较差,可以用来做调试;Jupyter可用于小项目或调试。

P5 PyTorch加载数据

Dataset:提供一种方式去获取数据及其lable。

要实现的功能:

  • 如何获取每一数据及其lable
  • 告诉我们总共有多少个数据(知道训练的时候要迭代多少次)

在Jupyter里查看Dataset的官方文档解释

from torch.utils.data import Dataset
help(Dataset)

#第二种查看方式
Dataset??
  • 函数def __init__(self,xx,xx):

初始化类,创建特例实例时要运行的函数,为整个class提供共一个全局变量,为后面的函数如getitem,length等方法提供它们需要的一些量。这个类中定义的一些self.xx=...能够成为全局变量,方便后续的使用。xx为所需的全局变量

  • 函数def __getitem__(self,idx):

idx一般作为数据的编号,根据图片地址的列表获取每一条数据。

  • 函数def __len__(self):

获取数据集的长度,有多少条数据。

P6 Dataset类代码实现

数据集下载:https://download.pytorch.org/tutorial/hymenoptera_data.zip

from torch.utils.data import Dataset
from PIL import Image
import os

class MyData(Dataset):     
    def __init__(self,root_dir,label_dir):    # 该魔术方法当创建一个事例对象时,会自动调用该函数
        self.root_dir = root_dir # self.root_dir 相当于类中的全局变量
        self.label_dir = label_dir     
        self.path = os.path.join(self.root_dir,self.label_dir) # 字符串拼接,根据是Windows或Lixus系统情况进行拼接               
        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 = "Data/FirstTypeData/train"
ants_label_dir = "ants"
bees_label_dir = "bees"
ants_dataset = MyData(root_dir, ants_label_dir)
bees_dataset = MyData(root_dir, bees_label_dir)
print(len(ants_dataset))
print(len(bees_dataset))
train_dataset = ants_dataset + bees_dataset # train_dataset 就是两个数据集的集合了     
print(len(train_dataset))

img,label = train_dataset[200]
print("label:",label)
img.show()

Datalodader:为后面的网络提供不同的数据形式。将数据打包

P7 Tensorboard 写日志

from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("logs") # 创建一个logs文件夹,writer写的文件都在该文件夹下
#writer.add_image()
for i in range(100):
    writer.add_scalar("y=2x",2*i,i)
writer.close()

运行之后会产生一个log目录和一个日志文件

读取日志文件

 在 Anaconda 终端里面,激活py3.6.3环境,再输入

 tensorboard --logdir=logs #你自己的logs路径

命将网址赋值浏览器的网址栏,回车,即可查看tensorboard显示日志情况。

② 为避免多人使用端口导致冲突,也可以在后面加上后缀,使得端口独立

tensorboard --logdir=C:\Users\wangy\Desktop\03CV\logs --port=6007

③ 输入网址可得Tensorboard界面。

Tensorboard 读图片

from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np

img_path1 = "Data/FirstTypeData/train/ants/0013035.jpg" 
img_PIL1 = Image.open(img_path1)
img_array1 = np.array(img_PIL1)

img_path2 = "Data/SecondTypeData/train/bees_image/17209602_fe5a5a746f.jpg" 
img_PIL2 = Image.open(img_path2)
img_array2 = np.array(img_PIL2)

writer = SummaryWriter("logs") 
writer.add_image("test",img_array1,1,dataformats="HWC") # 1 表示该图片在第1步
writer.add_image("test",img_array2,2,dataformats="HWC") # 2 表示该图片在第2步                   
writer.close()

通过这种方式可以很直观的观察训练过程中给model提供了哪些数据,或者说想对model测试的时候可以看到它每阶段的输出结果,或者可以看到每个阶段的一些不同的显示。

P10 Transforms使用

Transforms用途

① Transforms当成工具箱的话,里面的class就是不同的工具。例如像totensor、resize这些工具。

② Transforms拿一些特定格式的图片,经过Transforms里面的工具,获得我们想要的结果。

transforms.Totensor使用

from torchvision import transforms
from PIL import Image

img_path = "Data/FirstTypeData/val/bees/10870992_eebeeb3a12.jpg"
img = Image.open(img_path)  

tensor_trans = transforms.ToTensor()  # 创建 transforms.ToTensor类 的实例化对象
tensor_img = tensor_trans(img)  # 调用 transforms.ToTensor类 的__call__的魔术方法   
print(tensor_img)

需要Tensor数据类型原因

Tensor有一些属性,比如反向传播、梯度等属性,它包装了神经网络需要的一些属性。

常见的Transforms工具

Transforms的工具主要关注他的输入、输出、作用。

Compose()用法
Compose()中的参数需要是一个列表,Python中,列表的表示形式为[数据1,数据2,….]
在Compose中,数据需要是 transforms类型,所以得到,Compose([transforms参数1,transforms参数2....]

Compose类就是把不同的transform结合在一起。

transforms.Compose([
    transforms.Centercrop(10),
    transforms.ToTensor(),
])

P14 torchvision数据集使用

pytorch提供的数据集API:torchvision — Torchvision master documentation

 torchvision数据集介绍

① torchvision中有很多数据集,当我们写代码时指定相应的数据集指定一些参数,它就可以自行下载。

② CIFAR-10数据集包含60000张32×32的彩色图片,一共10个类别,其中50000张训练图片,10000张测试图片。

运行代码下载数据集:

import torchvision
train_set = torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True) # root为存放数据集的相对路线
test_set = torchvision.datasets.CIFAR10(root="./dataset",train=False,download=True) # train=True是训练集,train=False是测试集  

查看CIFAR10数据集内容

import torchvision
train_set = torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True) # root为存放数据集的相对路线
test_set = torchvision.datasets.CIFAR10(root="./dataset",train=False,download=True) # train=True是训练集,train=False是测试集  

print(test_set[0])       # 输出的3是target 
print(test_set.classes)  # 测试数据集中有多少种

img, target = test_set[0] # 分别获得图片、target
print(img)
print(target)

print(test_set.classes[target]) # 3号target对应的种类
img.show()

与Transform结合

定义Transform的图像变换,下载数据时加入transform

dataset_transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])     
train_set = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=dataset_transform,download=True) # 将ToTensor应用到数据集中的每一张图片,每一张图片转为Tensor数据类型     
test_set = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=dataset_transform,download=True)   

P15 Dataloader使用

① Dataset只是去告诉我们程序,我们的数据集在什么位置,数据集第一个数据给它一个索引0,它对应的是哪一个数据。

② Dataloader就是把数据加载到神经网络当中,Dataloader所做的事就是每次从Dataset中取数据,至于怎么取,是由Dataloader中的参数决定的。

加载数据的参数中:dataset数据位置,batch_size每次加载的数据量,shuffle是否要打乱数据,num_works设置多进程,默认0只设置主进程,dorp_last选数据如果有不足batch_size个剩余数的话要不要丢弃,True丢弃。

import torchvision
from torch.utils.data import DataLoader

# 准备的测试数据集
test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor())               
img, target = test_data[0]
print(img.shape)
print(img)

# batch_size=4 使得 img0, target0 = dataset[0]、img1, target1 = dataset[1]、img2, target2 = dataset[2]、img3, target3 = dataset[3],然后这四个数据作为Dataloader的一个返回      
test_loader = DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)      
# 用for循环取出DataLoader打包好的四个数据
for data in test_loader:
    imgs, targets = data # 每个data都是由4张图片组成,imgs.size 为 [4,3,32,32],四张32×32图片三通道,targets由四个标签组成             
    print(imgs.shape)
    print(targets)

dataloder返回的是图片和标签的打包形式,比如batch_size=4,返回的是4个img叠起来的imgs和4个target叠起来的targets。下面可以看到 imgs的形状是4个(3,32,32)形状的图片,而targets包含了4个标签分别是2,3,6,8对应四张图片。

Tensorboard展示+Dataloader多轮次

shuffle如果设置为False则第一个epoch和第二个epoch的图片顺序都一样,设置为True则每次取的图片顺序都不一样。

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())               
# batch_size=4 使得 img0, target0 = dataset[0]、img1, target1 = dataset[1]、img2, target2 = dataset[2]、img3, target3 = dataset[3],然后这四个数据作为Dataloader的一个返回      
test_loader = DataLoader(dataset=test_data,batch_size=64,shuffle=True,num_workers=0,drop_last=True)      
# 用for循环取出DataLoader打包好的四个数据
writer = SummaryWriter("logs")
for epoch in range(2):
    step = 0
    for data in test_loader:
        imgs, targets = data # 每个data都是由4张图片组成,imgs.size 为 [4,3,32,32],四张32×32图片三通道,targets由四个标签组成             
        writer.add_images("Epoch:{}".format(epoch),imgs,step)
        step = step + 1
    
writer.close()

 P16   nn.Module模块使用

torch.nn — PyTorch 2.4 documentation

关于神经网络的使用在torch.nn里边,其中nn是Neural network的缩写

nn.Module模块使用

① nn.Module是对所有神经网络提供一个基本的类。init初始化函数,forward前向传播函数接受输入,处理后输出。x指输入

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

② 我们的神经网络是继承nn.Module这个类,即nn.Module为父类,nn.Module为所有神经网络提供一个模板,对其中一些我们不满意的部分进行修改。

import torch
from torch import nn

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()  # 继承父类的初始化
        
    def forward(self, input):          # 将forward函数进行重写
        output = input + 1
        return output
    
tudui = Tudui()
x = torch.tensor(1.0)  # 创建一个值为 1.0 的tensor
output = tudui(x)
print(output)

super(Myclass, self).__init__()

① 简单理解就是子类把父类的__init__()放到自己的__init__()当中,这样子类就有了父类的__init__()的那些东西。

② Myclass类继承nn.Module,super(Myclass, self).__init__()就是对继承自父类nn.Module的属性进行初始化。而且是用nn.Module的初始化方法来初始化继承的属性。

③ super().__init()__()来通过初始化父类属性以初始化自身继承了父类的那部分属性;这样一来,作为nn.Module的子类就无需再初始化那一部分属性了,只需初始化新加的元素。

③ 子类继承了父类的所有属性和方法,父类属性自然会用父类方法来进行初始化。

forward函数

① 使用pytorch的时候,不需要手动调用forward函数,只要在实例化一个对象中传入对应的参数就可以自动调用 forward 函数。

② 因为 PyTorch 中的大部分方法都继承自 torch.nn.Module,而 torch.nn.Module 的__call__(self)函数中会返回 forward()函数 的结果,因此PyTroch中的 forward()函数等于是被嵌套在了__call__(self)函数中;因此forward()函数可以直接通过类名被调用,而不用实例化对象。

P17 卷积原理

torch.nn.functional.conv2d — PyTorch 2.4 documentation

① 卷积核不停的在原图上进行滑动,对应元素相乘再相加。

② 下图为每次滑动移动1格,然后再利用原图与卷积核上的数值进行计算得到缩略图矩阵的数据,如下图右所示。

stride=1时默认横向、纵向的步幅都为1。stride=2时,表示横向和纵向步幅都为2,即计算完第一个之后,卷积核移两步。先横向走再纵向走

代码实现:

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)
input = torch.reshape(input, (1,1,5,5))
kernel = torch.reshape(kernel, (1,1,3,3))
print(input.shape)
print(kernel.shape)

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

代码中原始input的形状为torch.Size([5, 5]),但是从官方文档里可以看到还要有batch批次、channel通道的维度,所以还要把input的形状改一下,用到了reshape。F是卷积函数。

padding表示填充 ,默认为0即不填充,padding=1时,表示在输入图像周围添加一圈,默认值都为0,再根据步幅去做计算。

代码实现:

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)
input = torch.reshape(input, (1,1,5,5))
kernel = torch.reshape(kernel, (1,1,3,3))
print(input.shape)
print(kernel.shape)

output3 = F.conv2d(input, kernel, stride=1, padding=1)  # 周围只填充一层
print(output3)

步幅、填充原理

① 步幅:卷积核经过输入特征图的采样间隔。设置步幅的目的:希望减小输入参数的数目,减少计算量。

② 填充:在输入特征图的每一边添加一定数目的行列。设置填充的目的:希望每个输入方块都能作为卷积窗口的中心,或使得输出的特征图的长、宽 = 输入的特征图的长、宽。

③ 一个尺寸 a * a 的特征图,经过 b * b 的卷积层,步幅(stride)= c,填充(padding)= d,若d等于0,也就是不填充,输出的特征图的尺寸 =(a-b)/ c+1;若d不等于0,也就是填充,输出的特征图的尺寸 =(a+2d-b)/ c+1。

例子1:一个特征图尺寸为4 * 4的输入,使用3 * 3的卷积核,步幅=1,填充=0,输出的尺寸=(4 - 3)/1 + 1 = 2。

例子2: 一个特征图尺寸为5 * 5的输入,使用3 * 3的卷积核,步幅=1,填充=1,输出的尺寸=(5 + 2 * 1 - 3)/1 + 1 = 5。

例子3:一个特征图尺寸为5 * 5的输入, 使用3 * 3的卷积核,步幅=2,填充=0,输出的尺寸=(5-3)/2 + 1 = 2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值