Pytorch学习笔记

️ Pytorch学习笔记

文章目录

  • :parking: Pytorch学习笔记
      • 1.可视化模块
        • 1.1.Tensorboard
          • 1.1.1.SummaryWriter():用于创建一个Tensorboard项目
          • 1.1.2.writer.add_image():用于写入图片
          • 1.1.3.writer.add_scalar():用于写入标量,即绘图
          • 1.1.4.tensorboard --logdir=logs:运行
          • 1.1.5.示例代码
      • 2.数据转换
        • 2.1.transforms
          • 2.1.1.ToTensor():转化成张量
          • 2.1.2.Normalize():归一化
          • 2.1.3.Resize():尺寸调整
          • 2.1.4.Compose():组合
          • 2.1.5.示例代码
        • 2.2.PIL <-> cv2 <-> tensor
      • 3.数据集处理
        • 3.1.dataset
          • 3.1.1.示例代码
        • 3.2.dataloader
          • 3.2.1.示例代码
      • 4.神经网络搭建
        • 4.1.初始化
        • 4.2.几个常用的部件
          • 4.2.1.nn.Conv2d():二维卷积
          • 4.2.2. nn.BatchNorm2d():批标准化
          • 4.2.3. nn.LeakyReLU():激活函数
          • 4.2.4. nn.Sequential():顺序容器
          • 4.2.5.nn.Linear():实现全连接
        • 4.3 损失计算
        • 4.4.优化器
        • 4.5.保存和加载模型
          • 4.5.1.保存模型
          • 4.5.2.加载模型
        • 4.6.一个完整的网络
          • 4.6.1.CIF_module.py
          • 4.6.2.CIFAR10.py
          • 4.6.3.test.py

1.可视化模块

1.1.Tensorboard

Tensorboard是Pytorch提供的一个可视化包,引入包:

from torch.utils.tensorboard import SummaryWriter
1.1.1.SummaryWriter():用于创建一个Tensorboard项目
  • 参数1:tensorboard文件的存放路径
  • 参数2:表示写入tensorboard文件的时间间隔

使用以下方式调用:

writer = SummaryWriter("logs")
1.1.2.writer.add_image():用于写入图片
  • 参数1:标签
  • 参数2:图片
  • 参数3:第几张
  • dataformats:数据格式转换

使用以下方法调用:

writer.add_image("img",img_cv2,1,dataformats='HWC')
1.1.3.writer.add_scalar():用于写入标量,即绘图
  • 参数1:标签
  • 参数2:纵坐标。即标签的值
  • 参数3:横坐标
writer.add_scalar("scaler",1,1)
1.1.4.tensorboard --logdir=logs:运行

在终端输入tensorboard --logdir=logs即可运行,其中–logdir指定log目录。

1.1.5.示例代码
from torch.utils.tensorboard import SummaryWriter
import cv2
img_path = r"C:\Users\guoyiyu\Desktop\chart_yolo-obj.png"
img_cv2= cv2.imread(img_path)
print(img_cv2.shape)
writer = SummaryWriter("logs")

#显示图片

writer.add_image("img",img_cv2,1,dataformats='HWC')

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

writer.close()

2.数据转换

2.1.transforms

pytorch中的transforms模块中包含了很多种对图像数据进行变换的函数。引入包:

from torchvision import  transforms
2.1.1.ToTensor():转化成张量

使用以下方式调用:

trans_tensor = transforms.ToTensor() #实例化对象
img_tensor = trans_tensor(img_cv2) #因为有__call__函数,所以对象可以像函数一样调用
2.1.2.Normalize():归一化

如果图片有三个通道,则参数为([R1,G1,B1],[R2,G2,B2]),如果图片只有一个通道,则参数为(W1,W2)。计算方法是:
O U T = I N − W 1 W 2 OUT = \frac{IN-W1}{W2} OUT=W2INW1
使用以下方式调用:

trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = trans_norm(img_tensor) #转换后还是张量
2.1.3.Resize():尺寸调整

注意该函数只能裁剪PIL格式的图片

使用以下方式调用:

img_resize = Image.fromarray(img_cv2)  #cv2 -> PIL

trans_resize = transforms.Resize((512,512)) 
img_resize = trans_resize(img_resize)  
img_resize = np.array(img_resize)      #PIL -> cv2
2.1.4.Compose():组合

使用以下方式调用:

trans_resize = transforms.Resize((512,512)) 
trans_tensor = transforms.ToTensor()
trans_compose = transforms.Compose([trans_resize, trans_tensor])
img_compose = trans_compose(Image.fromarray(img_cv2)) #PIL -> Resize ->Tensor
2.1.5.示例代码
#transforms学习

from numpy.core.defchararray import array
from torchvision import  transforms
import cv2
import numpy as np
from PIL import Image

img_path = r"C:\Users\guoyiyu\Desktop\123.jpg"
img_cv2= cv2.imread(img_path)
print(type(img_cv2))
print(img_cv2)
cv2.imshow("img_array",img_cv2)
cv2.waitKey(0)

#ToTensor
trans_tensor = transforms.ToTensor()
img_tensor = trans_tensor(img_cv2)
print(type(img_tensor))
print(img_tensor)

#Normalize
trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = trans_norm(img_tensor)
img_array = img_norm.numpy()
print(img_array.shape) #CHW
img_array = np.transpose(img_array,(1,2,0)) #转成成通道HWC才可以用imshow显示
cv2.imshow("img_array",img_array)
cv2.waitKey(0)

#Resize 
trans_resize = transforms.Resize((512,512)) 
img_resize = Image.fromarray(img_cv2)  #cv2 -> PIL
img_resize = trans_resize(img_resize)  
img_resize = np.array(img_resize)      #PIL -> cv2
print(type(img_resize))
cv2.imshow("resize",img_resize)
cv2.waitKey(0)

#Compose
trans_compose = transforms.Compose([trans_resize, trans_tensor])
img_compose = trans_compose(Image.fromarray(img_cv2)) #PIL -> Resize ->Tensor
print(type(img_compose))

2.2.PIL <-> cv2 <-> tensor

Pytorch学习笔记_第1张图片

3.数据集处理

3.1.dataset

pytorch中的dataset模块用于获取并处理数据集,引入包:

import torchvision
  • root:下载的目录位置
  • train:True是训练集,False是测试集
  • download:是否下载
  • transform:数据格式转换

使用以下方式调用

test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=True, transform=torchvision.transforms.ToTensor())
3.1.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, transform=torchvision.transforms.ToTensor())

#test_Set
print(test_set[0]) #打印第一个数据
img, _ = test_set[0]
print(img.shape)

3.2.dataloader

pytorch中的dataloader模块用于批量加载数据集,引入包:

import torch.utils.data as Data
  • dataset:数据集
  • batch_size:每一次批量打包的图片数量
  • shuffle:是否打乱
  • num_workers:是否多线程,0表示只使用主线程。
  • drop_last:最后一轮的图片小于batch_size时是否舍弃

使用以下方式调用:

test_loader = Data.DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
3.2.1.示例代码
import torch.utils.data as Data
from torch.utils.tensorboard import SummaryWriter

test_loader = Data.DataLoader(dataset=test_set, batch_size=64, shuffle=True, num_workers=0, drop_last=False)

#test_loader
writer = SummaryWriter("log")
for epoch in range(2):
    step = 0
    for data in test_loader:
        imgs, _ = data
        writer.add_images("epoch:{}".format(epoch), imgs, step)
        step = step+1
writer.close()

效果如下:

Pytorch学习笔记_第2张图片

4.神经网络搭建

​ Pytorch中的nn模块提供了搭建神经网络所需的包。引入包:

from torch import nn

4.1.初始化

​ 继承nn.Module类,并进行重写。举例如下:

from torch import nn
import torch

class test_nn(nn.Module):
    def __init__(self) -> None:
        super().__init__()
    def forward(self, input):
        output = input + 1
        return output 
test_nn = test_nn()
input = torch.tensor(1.0)
output = test_nn(input)
print(output)

4.2.几个常用的部件

4.2.1.nn.Conv2d():二维卷积

格式:nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)

例子:self.conv1 = nn.Conv2d(inplanes, planes[0], kernel_size=1,stride=1, padding=0, bias=False)

  • in_channels:是输入的四维张量[N, C, H, W](其中N表示输入样本的数量; H表示特征图的高;W表示特征图的宽; C表示特征图的通道数。)中的C了,即输入张量的通道数。这个形参是确定权重等可学习参数所必需的。
  • out_channels:期望的四维输出张量的channels数
  • kernel_size:卷积核的大小,一般我们会使用3x3这种长宽两个数相同的卷积核,因此这种情况只需要写kernel_size = 3这样的就行了。如果长宽两个数不同,比如3x5的卷积核,那么写作kernel_size = (3, 5),注意需要写一个元组。
  • stride:卷积核在图像窗口上每次平移的间隔,即所谓的步长
  • padding :图像填充,后面常数代表填充的多少(行数、列数),默认为0。需要注意的是这里的填充包括图像的上下左右,以padding = 1为例,若原始图像大小为32x32,那么padding后的图像大小就变成了34x34,而不是33x33
  • bias:是否要添加偏置参数作为可学习参数的一个,默认为True。
4.2.2. nn.BatchNorm2d():批标准化
4.2.3. nn.LeakyReLU():激活函数
4.2.4. nn.Sequential():顺序容器

一个有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行,同时以神经网络模块为元素的有序字典也可以作为传入参数。

4.2.5.nn.Linear():实现全连接

示例代码如下:

import torch
from torch import nn
import torch.utils.data as Data
import torchvision

test_dataset = torchvision.datasets.CIFAR10(root="\data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
test_dataloader = Data.DataLoader(dataset=test_dataset, batch_size=64, shuffle=True, num_workers=0, drop_last=True)

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

test_nn = test_nn()

for data in test_dataloader:
    img, _ = data 
    print(img.shape)
    img_fatten = torch.flatten(img) #展平
    print(img_fatten.shape)
    img_linear = test_nn(img_fatten)
    print(img_linear.shape)

4.3 损失计算

示例代码如下:

import torch
import torch.nn as nn

#L1loss
input = torch.tensor([1, 2, 3], dtype=torch.float32)
target =  torch.tensor([1, 2, 5], dtype=torch.float32)
input = torch.reshape(input, (1,1,1,-1))
target = torch.reshape(target,(1,1,1,-1))
loss_L1los = nn.L1Loss(reduction="sum")
result_L1loss = loss_L1los(input, target)
print(result_L1loss)

#CrossEntropyLoss
input = torch.tensor([0.1, 0.8, 0.1])
target =  torch.tensor([1])
input = torch.reshape(input, (1,-1)) #-1表示自适应
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(input, target)
print(result_cross)

4.4.优化器

​ 在计算出损失梯度后,需要优化器进行损失更新。通过以下方式引入:

optim = torch.optim.SGD(test_nn.parameters(), lr=0.01)
  • 在计算梯度损失之前,需要先初始化优化器
optim.zero_grad()
  • 在计算梯度损失之后,启动优化器
optim.step()

4.5.保存和加载模型

4.5.1.保存模型

​ 在整个训练流程结束后,需要保存模型,pytroch提供以下两种保存模型的方式。

import torch

#方式1, 保存模型结构和参数
torch.save(net,"XXX.pth")

#方式2,保存模型参数,用字典的方式保存
torch.save(net.state.dict(), "xxx.pth")
4.5.2.加载模型

​ 加载模型也有两种方式,与保存对应

import torch

#方式1
model = torch.load("xxx.pth")

#方式2
model = net()
model.load_state(torch.load("xxx.pth"))

4.6.一个完整的网络

目录结构如下:
CIFAR10
|
|---CIF_module.py
|
|---CIFAR10.py
|
|---test.py
4.6.1.CIF_module.py

该文件实现了模型类,给另外两个文件调用,代码如下:

import torch.nn as nn
import torch
class net(nn.Module):
    def __init__(self) -> None:
        super().__init__()
        self.model = 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, input):
        input = self.model(input)
        return input

if __name__ == '__main__':

    #验证下模型输入张量和输出张量是否正常
    net = net()
    input = torch.ones((64,3,32,32))
    print(input.shape)
    output = net(input)
    print(output.shape)
  • if __name__ == '__main__':定义该语句后,可以通过python CIF_module.py的方式调用,测试模型的输入输出的张量是否正常
4.6.2.CIFAR10.py

该文件实现了具体的网络加载训练。具体实现如下:

import torchvision
import torch
import torch.utils.data as Data
from CIF_module import *
from torch.utils.tensorboard import SummaryWriter
#可视化
writer = SummaryWriter("./log")

#加载数据集
train_set = torchvision.datasets.CIFAR10(root="./train_set", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_set = torchvision.datasets.CIFAR10(root="./test_set", train=False, transform=torchvision.transforms.ToTensor(), download=True)
test_data_size = len(test_set) 


#加载测试集
train_loader = Data.DataLoader(train_set, batch_size=64)
test_loader = Data.DataLoader(test_set, batch_size=64)

#初始化网络
net = net()
if torch.cuda.is_available():
    net = net.cuda()

#初始化优化器
lr = 0.003
optim = torch.optim.SGD(net.parameters(), lr)

#初始化损失函数
cross_loss = nn.CrossEntropyLoss()
if torch.cuda.is_available():
    cross_loss = cross_loss.cuda()

#指定训练代数
total_epoch = 100 
total_train_step = 0
total_test_step = 0
#开始迭代

print("---------开始训练----------")
for epoch in range(total_epoch):
    #进入训练模式
    net.train()
    for data in train_loader:
        img, target = data
        if torch.cuda.is_available():
            img = img.cuda()
            target = target.cuda()
        output = net(img)

        #计算损失
        loss = cross_loss(output, target)
        #total_train_loss = total_train_loss + loss

        #优化器梯度清0
        optim.zero_grad()

        #计算损失梯度
        loss.backward()

        #梯度下降
        optim.step()

        total_train_step=total_train_step+1
        if total_train_step % 200 == 0:
            print("训练次数:{},损失:{}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss", loss, total_train_step)

    #进入测试模式
    net.eval()
    total_test_loss = 0
    total_test_accuracy = 0
    with torch.no_grad():
        for data in test_loader:
            img,target = data
            if torch.cuda.is_available():
                img = img.cuda()
                target = target.cuda()
            output = net(img)
            #计算损失
            loss = cross_loss(output, target)
            total_test_loss = total_test_loss + loss

            #计算正确率
            accuracy = (output.argmax(1) == target).sum()
            total_test_accuracy = accuracy.item() + total_test_accuracy
    print("第{}次测试的总损失:{}".format(epoch+1, total_test_loss))
    print("准确率:{}".format(total_test_accuracy/test_data_size))
    writer.add_scalar("test_loss", loss, total_test_step)
    writer.add_scalar("accuracy", total_test_accuracy/test_data_size, total_test_step)
    total_test_step = total_test_step + 1
    #保存模型
    torch.save(net,"./weights/CIFAR_epoch{}.pth".format(epoch))
writer.close()
4.6.3.test.py

该文件实现了如何测试自己的图片。

from PIL import Image
import torch
import torchvision
from CIF_module import *

classes = ["airplane","automobile","bird","cat","deer","dog","frog","horse","ship","truck"]

img_path = "./imgs/dog.png"
img_PIL = Image.open(img_path)
img_PIL = img_PIL.convert('RGB')
trans = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)), torchvision.transforms.ToTensor()])
img = trans(img_PIL)
img = torch.reshape(img,(1,3,32,32))
img = img.cuda()
print(img.shape)
net = torch.load("./weights/CIFAR_epoch99.pth")
print(net)
#进入测试模式
net.eval()
with torch.no_grad():
    result = net(img)
print("结果是:{}".format(classes[result.argmax(1).item()]))

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