Get started quickly with pytorch

This article is written based on the small mound tutorial (this up is super good, and the kindergarten graduate said it sounds stress-free, I recommend those who just started to take a look).

Ant and bee/practice data set: Link: https://pan.baidu.com/s/1jZoTmoFzaTLWh4lKBHVbEA Password: 5suq

Official documentation: torch.nn — PyTorch 1.10.0 documentation

This blog will illustrate with examples based on my own understanding. There are detailed annotations in the examples. I suggest you try it yourself.

Table of contents

0. Environmental description

1. Load data

2. tensorboard visualization tool

3. Transform operates on images

4. DataSet loads the dataset

5. dataloader loads data

6. Convolution operation

7. Convolution layer

8. Pooling layer

9. Nonlinear activation layer

10. Linear layer (fully connected layer)

11. Simple neural network

12. Loss function

13. Backpropagation

14. Optimizer

15. Import existing network

16. Model storage

17. Model reading

18. Label selection

19. Classic examples (see here for basic recommendations)

20. Utilize GPUs

21. Test

22. numpy and tensor


0. Environmental description

torch1.1+torchvision0.11.1+cudatoolkit10.0.130, download whatever is missing from other prompts

1. Load data

    The first is to load the data, here is a class Dataset (data set), there will be some discrepancies with the following code in use, it depends on the situation.

    For example, for the data set read by the following code, its class name is directly used as the name of the folder, and then inside the folder is a series of pictures, so root_dir points to the data set, label_dir indicates the category, and the root_dir+label_dir link address can find this A picture of the class, which is what the MyData class does.

     Note: output the complete tensor:

torch.set_printoptions(profile="full")

    What the main function does is to read the two class pictures separately and then merge them to get the total data set.

#加载数据#
import torch
from torch.utils.data import Dataset
from PIL import Image
import os

class MyData(Dataset):
    #初始化#
    def __init__(self,root_dir,label_dir):
        #加self表示类变量#
        self.root_dir=root_dir#基础路径(根目录)#
        self.label_dir=label_dir#指向基础路径下的目标文件地址#label_dir是图片文件夹名称即图片标签
        self.path=os.path.join(root_dir,label_dir)#将两个文件路径进行连接#
        self.img_path=os.listdir(self.path)#读取path指向的文件目录下每一个图片名称#

    #返回第idx张图片及其标签#
    def __getitem__(self, idx):
        img_name=self.img_path[idx]#获得第idx张图片名称#
        img_item_path=os.path.join(self.path,img_name)#此路径指向该图片#
        img=Image.open(img_item_path)#加载图片#
        #↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓使用时注意该句子↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓#
        #label_dir是图片文件夹名称即图片标签
        label=self.label_dir
        return label,img#label是img的类别#

    #返回图片列表长度即训练集/测试集大小#
    def __len__(self):
        return len(self.img_path)#图片数量#
'''
#单张图片的读取
img_path = "pct/2959730355_416a18c63c.jpg"  # 图片路径并非图片文件夹“#
img = Image.open(img_path)
img.show()#显示图片#

'''

#利用Dataset读取
root_dir=""#基础路径(根目录)#
ants_dir="ant"
ants_dataset=MyData(root_dir,ants_dir)
label_0,img_0=ants_dataset[0]#第0号图片及其标签
#img_0.show()
print(label_0)
bees_dir="bee"
bees_dataset=MyData(root_dir,bees_dir)
label_0,img_0=bees_dataset[0]#第0号图片及其标签
#img_0.show()
print(label_0)
#将两个数据集进行合并#
all_dataset=ants_dataset+bees_dataset
print(len(all_dataset))

2. tensorboard visualization tool

    Tensorboard is a visual tool. The key is to understand how to write and read. These are all written in the following code. When using it, remember to execute close at the end.

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

writer=SummaryWriter("logs")#把数据写入logs文件夹内

image_path="./ant/308196310_1db5ffa01b.jpg"
img=Image.open(image_path)#此时img类型为JpegImageFile
img_array=np.array(img)#将img转化为numpy型
writer.add_image("test",img_array,1,dataformats="HWC")

'''
add_image(self, tag, img_tensor, global_step=None, walltime=None, dataformats='CHW'):
tag:标题
img_tensor:图像(类型:torch.Tensor, numpy.array, or string/blobname)
global_step:步数
dataformats:图像类型HWC表示高度、宽度、通道(可以利用img_array.shape进行查看)
生成文件后放在前面在类中定义的logs文件夹中

阅读生成的文件:
控制台输入
tensorboard --logdir="logs" --port=6007
#logdir指定目录
#port指定接入端口
#点击TensorBoard 2.4.0 at http://localhost:6006/ (Press CTRL+C to quit)中的“http://localhost:6006/”

如果是在服务器下Tensorboard然后在本地查看:
可见https://zhuanlan.zhihu.com/p/231790992亲测有用
'''

for i in range(100):
    writer.add_scalar("y=x",i,i)
''' 
add_scalar(self, tag, scalar_value, global_step=None, walltime=None):
tag:图表标题
scalar_value:数值,与global_step对应,y轴
global_step:步数,训练多少步时对应数值是多少,x轴
生成文件后放在前面在类中定义的logs文件夹中

阅读生成的文件:
终端输入
tensorboard --logdir="logs" --port=6006
#logdir指定目录
#port指定接入端口
#点击TensorBoard 2.4.0 at http://localhost:6006/ (Press CTRL+C to quit)中的“http://localhost:6006/”
'''
writer.close()

3. Transform operates on images

    transform has a series of operations on images, such as type conversion, size change, cropping, etc.

#transform对图像进行操作

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

#↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓使用时注意该句子↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓#
img_path="pct/2959730355_416a18c63c.jpg"
img=Image.open(img_path)#打开图片为PIL数据类型
print(img)

"""
利用transform.ToTensor将PIL或numpy数据类型的img转化为Tensor数据类型的图片
tensor:包装了神经网络所需要的参数如梯度、反向传播等
"""
tensor_trans=transforms.ToTensor()
tensor_img=tensor_trans(img)#执行__call__将img转化为tensor类型
print(tensor_img)

#"""test2中所用到的SummaryWriter类"""
#writer=SummaryWriter("log")
#writer.add_image("Tensor_img",tensor_img)
#writer.close()

"""
Totensor的使用
Normalize归一化
resize调整大小
RandomCrop随机裁剪
"""

"""
Normalize(均值,方差)
output[channel] = (input[channel] - mean[channel]) / std[channel]
"""
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])#(output-0.5)/0.5
img_norm=trans_norm(tensor_img)

"""
resize调整大小
参数为大小(序列或整数):所需的输出大小。
如果大小是这样的序列(h,w),输出大小将与此匹配。如果大小是整数,图像的较小边缘将与此数字匹配。
"""
trans_resize=transforms.Resize((512,512))#调整到512X512的PIL类型img
img_resize=trans_resize(img)#这里输入为PIL,输出为PIL
print(img_resize)

trans_resize_2=transforms.Resize(1000)
#串联两个操作即先执行trans_resize_2再执行tensor_trans
trans_compose=transforms.Compose([trans_resize_2,tensor_trans])
img_resize_2=trans_compose(img)

"""
RandomCrop输入一个PIL类型的img
"""
trans_random=transforms.RandomCrop(20)#裁剪为512X512的,若指定(n,m)则裁剪大小为nXm
trans_compose_2=transforms.Compose([trans_random,tensor_trans])
for i in range(10):
    img_crop=trans_compose_2(img)


4. DataSet loads the dataset

    Note that this section is different from the first section. It contains some commonly used datasets such as MNIST, FakeData, COCO, LSUN, ImageFolder, DatasetFolder, ImageNet, and CIFAR, which can be downloaded and used directly.

"""
使用官方提供的数据集
CIFAR10:6万32X32的图片,5万训练,1万测试
"""
import torchvision
from torch.utils.tensorboard import SummaryWriter

dataset_transform=torchvision.transformsz.Compose([
    torchvision.transforms.ToTensor()
])

#下载CIFAR10到root路径下,train=True表示下载的是训练集,False表示下载的是测试集,download表示要下载
#transform=dataset_transform转化成Tensor数据类型
#↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓使用时注意修改该句子↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓#
train_set=torchvision.datasets.CIFAR10(root="./DataSet",train=True,transform=dataset_transform,download=True)
test_set=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)

# print(test_set.classes)
#
# print(test_set[0])#输出图片+标签信息
# img,target=test_set[0]#img存放图片信息,target存放标签信息
# print(img)
# print(target)
# print(test_set.classes[target])#输出标签类别
# img.show()#显示图片

writer=SummaryWriter("logs")
for i in range(10):
    img,target=test_set[i]
    writer.add_image("test_set",img,i)

writer.close()

5. dataloader loads data

    Here is to read the data downloaded in the fourth step. The dataloader is essentially an iterable object. It encapsulates the custom Dataset into a Batch Size Tensor according to the batch size and whether it is shuffle, which is used for subsequent training.

#DataLoader加载数据

import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
test_data=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)

"""
dataset:数据集
batch_size:一次取多少数据
shuffle:是否按顺序读取,默认为false
num_workers:多进程,默认为0,用主进程加载,>0时windows下可能出错
drop_last:对余数的处理(除不尽)
"""
test_loader=DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)

writer=SummaryWriter("dataloader")
for epoch in range(2):
    step=0
    for data in test_loader:
        img,targets=data
        writer.add_images("epoch_{}".format(epoch),img,step)
        step=step+1

writer.close()

6. Convolution operation

    Here is the convolution using the function.

#conv2d卷积操作
import torch
from torch import nn
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]])
input=torch.reshape(input,(1,1,5,5))#尺寸变化,Conv2d有要求
kernel=torch.reshape(kernel,(1,1,3,3))
"""
二维卷积
conv2d(input,weight,bias=None,stride=1,padding=0,dilation=1,groups=1):
input:输入要求是(batch,通道,高,宽)
weight:权重(卷积核),输入要求是(输出通道,输入通道,高,宽)
bias:偏置
stride:步长,单个数(横纵皆是),俩数(横步长,纵步长)
padding:填充边框,单个数四周按此值填充,元组(横填充,纵填充)
"""
output=F.conv2d(input,kernel,stride=1)
print(output)
output2=F.conv2d(input,kernel,stride=2)
print(output2)
output3=F.conv2d(input,kernel,stride=1,padding=1)
print(output3)

7. Convolution layer

    Different from Section 6, the concept of model is introduced here, and the size and step size of the convolution kernel are defined by themselves to obtain the results through forward propagation. The convolutional layer is also a layer commonly used in the future

#nn.Conv2d卷积层
import torch
import torchvision
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch import nn
from torch.utils.tensorboard import SummaryWriter

#加载数据集
dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
dataset=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)
dataloader=DataLoader(dataset,batch_size=64)

"""
nn.Conv2d(in_channels,out_channels,kernel_size,stride=1,
        padding=0,dilation=1,groups=1,bias=True,padding_mode='zeros'):
in_channels:输入通道数,RGB图像一般为3通道
out_channels:输出通道数,通道数1->2,两个卷积核
kernel_size:卷积核大小,数或者元组(行,列),卷积核中参数训练得到
stride:步长,单个数(横纵皆是),俩数(横步长,纵步长)
padding:填充边框,单个数四周按此值填充,元组(横填充,纵填充)
下面的不太常用一般设为默认值
dilation:卷积核对应位的距离
groups:分组卷积
bias:结果是否加减一个常数
padding_mode:按怎样模式填充
"""

class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, 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

myModule=MyModule()
writer=SummaryWriter("nn.conv")
step=0

for data in dataloader:
    imgs,targets=data
    output=myModule(imgs)
    writer.add_images("input",imgs,step)
    #变化成六通道后不能显示(报错),需要reshape转化为三通道
    output=torch.reshape(output,(-1,3,30,30))#设-1会自动计算结果
    writer.add_images("output",output,step)
    step=step+1

writer.close()

8. Pooling layer

    The pooling operation, same as 7, is also a level in the module.

#pooling池化层
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))#尺寸变化,MaxPool2d有要求


"""
nn.MaxPool2d(kernel_size, stride,padding, dilation, ceil_mode,return_indices)
kernel_size:窗口大小,数字或元组
stride:横向或纵向路径大小,默认值是窗口大小
padding:填充边框,单个数四周按此值填充,元组(横填充,纵填充)
dilation:窗口对应位的距离
ceil_mode:True则ceil模式(向下取整),False则floor模式(向上取整),设计到对边缘数的处理同理,默认为False
"""
class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=True)

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

MyModule=MyModule()
output=MyModule(input)
print(output)



9. Nonlinear activation layer

#非线性激活层
import torch
from torch import nn
from torch.nn import ReLU

input=torch.tensor([[1,-0.5],
                    [-1,3]])
output=torch.reshape(input,(-1,1,2,2))
"""
ReLU(inplace)
负数归0
inplace:是否覆盖input,true覆盖,False不覆盖,默认为False

Sigmoid()
归一化归至(-1,1)
"""

class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.relu1=ReLU()

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

MyModule=MyModule()
output=MyModule(input)
print(output)

10. Linear layer (fully connected layer)

#线性层
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

#加载数据集
dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
dataset=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)
dataloader=DataLoader(dataset,batch_size=64,drop_last=True)

"""
torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None):
in_features:输入大小
out_features:输出大小
bias:True则设偏置学习,False不设
"""
class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.linear1=Linear(196608,10)

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

MyModule=MyModule()
for data in dataloader:
    imgs,targets=data
    print(imgs.shape)
    """
    flatten将输入展成一行
    [[1,2],[3,4]]->[1,2,3,4]
    """
    input=torch.flatten(imgs)
    print(input.shape)
    output=MyModule(input)

11. Simple neural network

    This section combines 7~10 sections to form a simple neural network. Of course, there is only forward propagation. There is a tensorboard black technology at the end of this code, remember to try it.

#构建一个简单的神经网络
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, 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)
        self.flatten=Flatten()
        self.linear1=Linear(1024,64)
        self.linear2=Linear(64,10)


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

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

MyModule=MyModule()
input=torch.ones((64,3,32,32))#定义大小,其中元素全部复制为1
output=MyModule(input)

writer=SummaryWriter("../compute")
writer.add_graph(MyModule,input)#生成计算图,很神奇,记得点几下
writer.close()

12. Loss function

For training, the loss function is essential. Here are several common loss functions such as MSELoss and CrossEntropyLoss.

#loss实际与预测值的损失,用于更新(反向传播)  注意输入输出
import torch
from torch.nn import L1Loss
from torch import nn

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,3))
target=torch.reshape(target,(1,1,1,3))

"""
torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean'):
reduction:mean:求均值;sum:求和
"""
loss=L1Loss()
result=loss(input,target)
print(result)

"""
nn.MSELoss()
先求平方差,再求均值
"""
loss_mse=nn.MSELoss()
result_mse=loss_mse(input,target)
print(result_mse)

"""
nn.CrossEntropyLoss():
交叉熵损失,常用于分类问题
input:(N,C)  N batch size,C类
output:实际标签
"""
x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x=torch.reshape(x,(1,3))
loss_CE=nn.CrossEntropyLoss()
print(loss_CE(x,y))

13. Backpropagation

    Coupled with backpropagation, you can use the debugging function of pycharm to see the changes in the gradient.

#Back propagation反向传播,在test14网络的基础上进行
import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
test_data=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)
dataloader=DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)


class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, 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)
        self.flatten=Flatten()
        self.linear1=Linear(1024,64)
        self.linear2=Linear(64,10)


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

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

MyModule=MyModule()
loss=nn.CrossEntropyLoss()
for data in dataloader:
    imgs,targets=data
    # 向前传播  该网络输出为一个10维向量,每一维表示是此类的概率
    outputs=MyModule(imgs)
    #利用交叉熵计算损失
    result_loss=loss(outputs,targets)
    #反向传播,计算梯度
    result_loss.backward()

14. Optimizer

    The optimizer will modify the model weights according to the gradient generated in Section 13 in order to reduce the loss. There are many optimizers, and you can choose the appropriate optimizer according to your needs.

#根据梯度选择合适的优化器进行调参
"""
torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0):
params:要调节的模型参数
lr:学习速率
"""

#Back propagation反向传播,在test14网络的基础上进行
import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset_transform=torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
test_data=torchvision.datasets.CIFAR10(root="./DataSet",train=False,transform=dataset_transform,download=True)
dataloader=DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)


class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, 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)
        self.flatten=Flatten()
        self.linear1=Linear(1024,64)
        self.linear2=Linear(64,10)


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

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

MyModule=MyModule()
loss=nn.CrossEntropyLoss()
#定义优化器
optim=torch.optim.SGD(MyModule.parameters(),lr=0.01)
for epoch in range(20):#进行20次迭代调参
    running_loss=0.0#测试每一次迭代所有的误差,对比可以发现逐渐减小
    for data in dataloader:#对所有数据
        imgs,targets=data
        outputs=MyModule(imgs)
        result_loss=loss(outputs,targets)
        # 将上一步的梯度置零
        optim.zero_grad()
        result_loss.backward()
        # 优化器调整weight
        optim.step()
        running_loss=running_loss+result_loss
    print(running_loss)

15. Import existing network

    The official defines a series of excellent network structures for direct use, including pre-trained weights. The following is an example of VGG16:

#VGG网络
import torchvision
from torch import nn

"""
直接将VGG16的网络结构拿过来使用
"""
vgg16_F=torchvision.models.vgg16(pretrained=False)#不要预训练的权重
vgg16_T=torchvision.models.vgg16(pretrained=True)#需要预训练的权重

print(vgg16_T)#查看网络结构
"""
可以发现vgg16是对1000个类别进行识别,而CIFAR10仅有10个标签,如何利用vgg16在CIFAR10上进行使用呢
"""
train_data=torchvision.datasets.CIFAR10(root="./DataSet",train=True,
                                       transform=torchvision.transforms.ToTensor(),
                                       download=True)


#1、在vgg16的最后增加一个线性层输入为1000维输出为10维
vgg16_T.add_module('add_linear',nn.Linear(1000,10))
print(vgg16_T)#查看网络结构
"""
修改网络结构的方式:
1、在某类中加:
vgg16_T.classifier.add_module('add_linear',nn.Linear(1000,10))
2、在网络的最后加:
vgg16_T.add_module('add_linear',nn.Linear(1000,10))
3、对某一层进行修改:
找到那一层直接赋值:
vgg16_T.classifier[6]=nn.Linear(1000,10)
"""

16. Model storage

    There are two ways to store the trained model for next use:

#模型的存放与读取
import torchvision
import torch

vgg16=torchvision.models.vgg16(pretrained=False)#需要预训练的权重
"""
保存方式1:torch.save(vgg16,"vgg16_method1.pth")
保存了网络模型结构+参数

注意:对于自己定义的模型,在读取是需要将那个模型类重新定义一下,但无需创建对象,class需要定义,
    mymodule=MyModule()不用
"""
torch.save(vgg16,"vgg16_method1.pth")


"""
保存方式2:
将参数保存为字典的形式,仅保存参数(官方推荐),占有空间小
"""
torch.save(vgg16.state_dict(),"vgg16_merhod2.pth")

17. Model reading

    Combined with 16, different storage methods correspond to different reading methods:

#模型的存放与读取
import torchvision
import torch

"""
读取方式1:对应保存方式1
"""
model=torch.load("vgg16_method1.pth")
print(model)

"""
读取方式2:对应保存方式2
需要定义模型,然后将参数加载到模型中
"""
vgg16=torchvision.models.vgg16(pretrained=False)
model=torch.load("vgg16_method2.pth")
vgg16.load_state_dict(model)
print(model)

18. Label selection

    For classification tasks, the network will score the corresponding images and labels, we need to choose the one with the highest score, here is an example to illustrate

#选择分数最大的一项作为此图的类别
import torch

#模拟得分,共0,1两个类别,一个[]表示一张图片的得分
input=torch.tensor([[0.1,0.2],
                   [0.3,0.4]])
preds=input.argmax(1)#横向进行选择,0的时候为纵向
print(preds)

19. Classic examples (see here for basic recommendations)

    This example is very classic. It uses all the content mentioned above. It is a classification task performed on the CIFAR10 data set. There are mainly these steps: prepare data, load data, prepare model, set loss function, set optimizer, start training, finally verify, and aggregate and display the results.

#样例 准备数据,加载数据,准备模型,设置损失函数,设置优化器,开始训练,最后验证,结果聚合展示

import torch
import torchvision
from torch.nn import Sequential
from torch.utils.data import DataLoader
from torch import nn
from torch.utils.tensorboard import SummaryWriter

"""准备数据集"""
#训练
train_data=torchvision.datasets.CIFAR10(root="./DataSet",train=True,
                                       transform=torchvision.transforms.ToTensor(),
                                       download=True)
#测试
test_data=torchvision.datasets.CIFAR10(root="./DataSet",train=False,
                                      transform=torchvision.transforms.ToTensor(),
                                      download=True)

train_data_size=len(train_data)
test_data_size=len(test_data)
print("训练数据集的长度为{}".format(train_data_size))#50000
print("测试数据集的长度为{}".format(test_data_size))#10000

#利用DataLoader加载数据集
train_dataloader=DataLoader(train_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)

#搭建神经网络
class MyModule(nn.Module):
    def __init__(self):#注意是init!!!
        super(MyModule, self).__init__()
        self.model1=Sequential(
            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(),
            nn.Linear(64*4*4,64),
            nn.Linear(64,10)
        )


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

#初始化
#创建模型
myModule=MyModule()
#损失函数
loss_fn=nn.CrossEntropyLoss()
#定义优化器
learning_rate=0.01
optimize=torch.optim.SGD(myModule.parameters() ,lr=learning_rate )

#负责记录
#tensorboard
writer=SummaryWriter("logs")
#训练次数
train_step=0
#测试次数
test_step=0
#训练轮数
epoch=10

#开始训练
#训练迭代几次
for i in range(epoch):
    print("------第 {} 轮训练开始------".format(i+1))
    #每一次的训练
    myModule.train()
    for data in train_dataloader:
        imgs,targets=data
        outputs=myModule(imgs)
        #计算损失
        loss=loss_fn(outputs,targets)
        # 利用优化器对参数优化,调优
        optimize.zero_grad()
        loss.backward()
        optimize.step()

        train_step=train_step+1#一张图片加一次
        # y轴:loss,x轴:训练次数
        writer.add_scalar("train_loss", loss.item(), train_step)
        if train_step%100==0:
            print("训练次数:{},Loss:{}".format(train_step,loss.item()))#加item将tensor转化为数字

    #对每一次训练进行测试
    myModule.eval()
    total_test_loss=0#损失
    total_accuracy=0#正确率
    test_step=test_step+1
    with torch.no_grad():#不要梯度,不训练
        for data in test_dataloader:
            imgs,targets=data
            output=myModule(imgs)
            loss=loss_fn(output,targets)
            total_test_loss=total_test_loss+loss.item()
            #测试值与真实值相同的个数表示准确率
            total_accuracy=total_accuracy+(output.argmax(1)==targets).sum()
    print("第{}次测试误差为{}".format(test_step,total_test_loss))
    print("测试数据集上的准确率{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss",total_test_loss,test_step)
    writer.add_scalar("test_accutacy",total_accuracy/test_data_size,test_step)

    #保存每一轮训练后的模型
    torch.save(myModule.state_dict(),"myModule_{}.pth".format(i))
    print("模型已保存")

writer.close()

"""
注:
训练时有些代码利用myModule.train():只对Dropout、BatchNorm有作用
测试时有些代码利用myModule.eval():只对Dropout、BatchNorm有作用
"""

20. Utilize GPUs

Method 1: Use .cuda()

    In this way, the model, data, and loss function can be accelerated

#在19的基础上


#初始化
#创建模型
myModule=MyModule()
"""模型GPU加速"""
if torch.cuda.is_available():
    myModule=myModule.cuda()

loss_fn=nn.CrossEntropyLoss()
"""损失函数GPU加速"""
if torch.cuda.is_available():
    loss_fn=loss_fn.cuda()

imgs,targets=data
    """数据GPU加速"""
    if torch.cuda.is_available():
       imgs=imgs.cuda()
       targets=targets.cuda()

Method 2: Use .to(device)

First define the device, and then transplant the relevant parts in the code.

#在19的基础上


"""
torch.device()里面可以写cpu/cuda/cuda:0
"""
#定义设备
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
#GPU可用的情况下用cuda,否则cpu

#初始化
#创建模型
myModule=MyModule()
"""模型GPU加速"""
myModule=myModule.to(device)
#注意模型和损失函数其实不用写=,可以直接写myModule.to(device),但数据必须得写,
#为了方便记忆所以这里直接都写=了

loss_fn=nn.CrossEntropyLoss()
"""损失函数GPU加速"""
loss_fn=loss_fn.to(device)

imgs,targets=data
"""数据GPU加速"""
imgs=imgs.to(device)
targets=targets.to(device)

21. Test

    Read the picture and apply the trained model for testing.

#读取现有的模型myModule_0.pth进行测试
import torch
import torchvision
from PIL import Image
from torch import nn
from torch.nn import Sequential

image_path="imgs/8d6ffeef9c4ccd32304fd2df50d40d47.jpeg"
image=Image.open(image_path)
image=image.convert('RGB')#改变通道使其为RGB,此步是为了适应png、jpg等图片类型的图片

#将图片大小变为32*32,再变成tensor类型,此步是预处理为了对应于网络的输入
transform=torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                          torchvision.transforms.ToTensor()])
image=transform(image)
image=torch.reshape(image,(1,3,32,32))
print(image.shape)#[1,3,32,32]

#搭建神经网络
class MyModule(nn.Module):
    def __init__(self):#注意是init!!!
        super(MyModule, self).__init__()
        self.model1=Sequential(
            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(),
            nn.Linear(64*4*4,64),
            nn.Linear(64,10)
        )


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

#加载保存的模型,注意与保存方式对应
myModule = MyModule()
#如果是在GPU生成模型加载到cpu运行需要进行指明
#model=torch.load("myModule_0.pth",map_location=torch.device('cpu'))
model=torch.load("myModule_0.pth")
myModule.load_state_dict(model)
#不要忘记写,不训练了
myModule.eval()
with torch.no_grad():
    output=myModule(image)
    print(output)
    print(output.argmax(1))#概率最大的类别标签

22. numpy and tensor

import torch
import numpy as np

#初始化
Ta=torch.rand((3,4))
Na=np.array([[1,2,3],[4,5,6],[7,8,9]])

print(Ta)
print(Na)

#相互转换
Tb=torch.from_numpy(Na)
Nb=Ta.numpy()

print(Tb)
print(Nb)

#维度转化
Ta=Ta.view(2,-1)
Na=Na.reshape(9,-1)

print(Ta)
print(Na)

Guess you like

Origin blog.csdn.net/hihui1231/article/details/121030699