pytorch实战

pytorch实战
下载anaconda(较大),或者miniconda(只有conda和python)
anaconda历史版本
miniconda官网

1 pytorch安装

1换源教程

找到C:\Users\用户名下的这个文件
.condarc文件,更换一下内容

ssl_verify: true
show_channel_urls: true

channels:
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/win-64/
  - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/win-64/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/menpo/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/bioconda/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/

运行 conda clean -i 清除索引缓存,保证用的是镜像站提供的索引。
创建虚拟环境
打开开始菜单的Anaconda Prompt
conda create -n pytorch python=3.6

conda init

2激活虚拟环境

conda activate pytorch
进入pytorch官网选择你电脑对应的pytorch版本(cuda是GPU)没有GPU的选择CPU

pytorch实战
回到刚才的
pytorch实战
你有可能会出现进度卡住不动的情况,因为这样还是默认从官方源下载,把官网的命令去掉后面的-c pytorch,比如改成下面这样,
conda install pytorch torchvision torchaudio cudatoolkit=11.3

这样就使用了清华源,安装速度直线提升

检查torch是否按照成功

import torch

torch.cuda.is_available()

3虚拟环境和base的切换

conda info –envs 查看环境目录

pytorch实战

conda activate base 切换到基础环境

pytorch实战

停止环境变量的激活

conda deactivate

pytorch实战

2 torch基础使用

主要以卷积神经网络为例,对卷积神经网络不了解的可以看上一篇文章传送

pytorch可以想象成一个工具箱,

dir()
help()

首先在控制台,

pytorch实战

在python控制台,也是可以多行运行的,按住shift+回车

查看torch中有哪些模块

pytorch实战

可以继续进行查看

dir('Tensor')

pytorch实战

help查看使用方法

help(torch.cuda.is_available)

pytorch实战

2.1 pytorch加载数据

Dataset
DataLoader

Dataset是一个包装类,用来将数据包装为Dataset类,然后传入DataLoader中,我们再使用DataLoader这个类来更加快捷的对数据进行操作(迭代器,方便我们去 多线程地读取数据,并且可以实现 batch以及 shuffle的读取等)。Dataset抽象类,要进行继承后重写

len和getitem这两个函数,前者给出 数据集的大小,后者是用于查找 数据和标签

项目目录结构如下,数据

pytorch实战
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import os
import torchvision

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(root_dir,label_dir)
        self.path_list=os.listdir(self.path)
    def __getitem__(self, item):
        name=self.path_list[item]
        img_name=os.path.join(self.root_dir,self.label_dir,name)
        img=Image.open(img_name)
        label=self.label_dir
        return img,label
    def __len__(self):
        return len(self.path_list)

root_path="../../data/train"
ant_path="ants"
bees_path="bees"
ant_dataset=Mydata(root_path,ant_path)
bees_dataset=Mydata(root_path,bees_path)

train_dataset=ant_dataset+bees_dataset

print(train_dataset[0])
print(train_dataset.__getitem__(0))
print(train_dataset.__len__())
print(train_dataset[167])

"""
(, 'ants')
(, 'ants')
245
(, 'bees')
"""

3 tensorboard

.add_scalar()
.add_image()
from torch.utils.tensorboard import SummaryWriter

writer=SummaryWriter("logs")
for i in range(100):
    writer.add_scalar("y=x",i,i)

writer.close()

pytorch实战

打开

tensorboard --logdir=logs

更改窗口

tensorboard --logdir=logs --port=6007

注意:必须要切换到logs的上一级目录,输入以上指令才能打开

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

writer=SummaryWriter("logs")

img_path="../练手数据集/train/bees_image/16838648_415acd9e3f.jpg"
img_PIL=Image.open(img_path)
img_array=np.array(img_PIL)
print(img_array.shape)
writer.add_image("test",img_array,2,dataformats='HWC')

for i in range(100):
    writer.add_scalar("y=3x",3*i,i)

writer.close()

tensorboard中上一次的数据可能会影响下一次,建议每次运行完毕,删除logs下的文件

pytorch实战
.add_image()

pytorch实战

numpy中的数据格式是(H,W,C)高度宽度和通道,所以要改一下参数设置

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

writer=SummaryWriter("logs")

img_path="../../练手数据集/train/bees_image/16838648_415acd9e3f.jpg"
img_PIL=Image.open(img_path)
img_array=np.array(img_PIL)
print(img_array.shape)
"""
(450, 500, 3)     H W C
"""
writer.add_image("test",img_array,2,dataformats='HWC')
writer.close()

pytorch实战

更换路径,加载第二张

img_path="../../练手数据集/train/ants_image/0013035.jpg"
writer.add_image("test",img_array,3,dataformats='HWC')

pytorch实战

如果修改参数tag,那么图片会在另一个区域显示

4 transforms的使用

transforms种有许多好用的工具,进行数据类型转换,改变size等

from torchvision import transforms
from PIL import Image

img_path="../练手数据集/train/ants_image/0013035.jpg"
img=Image.open(img_path)

print(img)
tensor_trans=transforms.ToTensor()
tensor_img=tensor_trans(img)

print(tensor_img)
"""

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],
         ...,
"""

pytorch实战

安装opencv

pip install opencv-python

不同的图片打开方式,对应的存储类型

pytorch实战

代码爆红,alt+回车会显示小灯泡

介绍一些transforms里常见的类Compose(),按住ctrl点击查看源码

pytorch实战

这里有许多属性,简单介绍一下 __call__该方法的功能类似于在类中重载 () 运算符,使得类实例对象可以像调用普通函数那样,以”对象名()”的形式使用。

class Person:
    def __call__(self, name):
        print('__call__'+'hello' ,name)
    def hello(self,name):
        print('hello',name)

person=Person()
person.hello('zhansan')
person('zhansan')
"""
hello zhansan
__call__hello zhansan

"""

def say():
    print("pytorch")

say()
say.__call__()
"""
pytorch
pytorch
"""

Totensor使用,tensorboard输入必须是tensor类型

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

img=Image.open('../练手数据集/train/ants_image/0013035.jpg')
print(img)
writer = SummaryWriter("logs")

转成tensor类型
trans=transforms.ToTensor()
img_tens=trans(img)
writer.add_image("tensor",img_tens)

Normalize归一化

pytorch实战

需要指定均值和标准差

print("img_tensor:",img_tens[1][1][1])
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm=trans_norm(img_tens)
print(img_norm[1][1][1])
writer.add_image("nor_img:",img_norm,3)
writer.close()
"""
img_tensor: tensor(0.5961)
tensor(0.1922)
"""

可以看出,归一化后的变化

pytorch实战

Resize修改尺寸大小,你如果想写代码的时候忽略大小写的匹配(提升代码时不区分大小写),这样你输入torch.r就会提示torch.Resize

pytorch实战
print(img.size)
trans_size=transforms.Resize((300,300))
img_resize=trans_size(img)
print(img_resize)
img_resize=trans(img_resize)
writer.add_image("resize",img_resize,0)
"""
(768, 512)

"""

这样一步步的处理太麻烦了,可以不可直接写在一起呢?答案是可以的,使用Compose


trans_size2=transforms.Resize(512)

trans_compose=transforms.Compose([trans_size2,trans])
img_resize2=trans_compose(img)
writer.add_image("compose",img_resize2,1)

随机裁剪

trans_random=transforms.RandomCrop(100)

trans_compose2=transforms.Compose([trans_random,trans])
for i in range(10):
    img_rand=trans_compose2(img)
    writer.add_image("rand",img_rand,i)

writer.close()

pytorch实战

5 torchvision中的数据集

torchvision软件包由流行的数据集、模型架构和用于计算机视觉的常见图像转换组成

Dataloader

数据加载器。组合数据集和采样器,并提供给定数据集上的迭代。DataLoader 支持具有单进程或多进程加载、自定义加载顺序以及可选的自动批处理

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

data_transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor()])

train_set = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=data_transform,download=True)
"""
root 下载路径,train训练集
"""
test_set = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=data_transform,download=True)
img,label=test_set[0]
print(img)
print(label)
print(test_set.classes)
writer=SummaryWriter("logs")
for i in range(10):
    img,label=train_set[i]
    writer.add_image("test_set",img,i)

writer.close()

data中取数据dataloader

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

test_data=torchvision.datasets.CIFAR10(root='./dataset',
                                 train=False,transform=torchvision.transforms.ToTensor())
test_loader=DataLoader(dataset=test_data,batch_size=100,shuffle=True,num_workers=0)

img,label=test_data[0]
print(img.shape)
print(label)
writer=SummaryWriter("dataloader")

for each in range(2):
    step = 0
    for data in test_loader:
        imgs,labels=data
        print(imgs.shape)
        print(labels)
        writer.add_images("each{}".format(each),imgs,step)
        step+=1

writer.close()

6 深度学习框架

import torch
import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model,self).__init__()

    def forward(self, input):
        output=input+1
        return output

test = Model()
x=torch.tensor(1.0)
out_put=test(x)
print(out_put)

7 卷积层

在Pytorch中,张量默认采用[N, C, H, W]的顺序

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]])
input_=torch.reshape(input_,(1,1,5,5))
kernel=torch.reshape(kernel,(1, 1,3,3))

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

stride=1

pytorch实战

接着向右移动

pytorch实战

最后

pytorch实战

padding=1

pytorch实战

使用tensorboard查看

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

dataset=torchvision.datasets.CIFAR10(root='./dataset',train=False,download=True,
                                     transform=torchvision.transforms.ToTensor())

dataloader=DataLoader(dataset,batch_size=64)

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.cov1=Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)

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

net=Network()
print(net)
writer=SummaryWriter("logs")
step=0
for data in dataloader:
    imgs,labels=data
    output=net(imgs)
    print(imgs.shape)

    print(output.shape)
    writer.add_images("input",imgs,step)

    output=torch.reshape(output,(-1,3,30,30))
    writer.add_images("output",output,step)
    step+=1

8 池化层

最大池化

pytorch实战

默认的stride=kernel_size(3)

最大池化:保留主要的特征,减少数据量,加快训练速度

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import MaxPool2d
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

data=torchvision.datasets.CIFAR10(root='./dataset',train=False,download=True,
                                  transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(data,batch_size=64)

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=True)

    def forward(self,x):
        return self.maxpool1(x)

kk=Network()

writer=SummaryWriter('./logs')
step=0
for data in dataloader:
    imgs,labels=data
    writer.add_images("input",imgs,step)
    output=kk(imgs)
    writer.add_images("pool",output,step)
    step+=1
writer.close()

9 非线性激活


import torch
import torch.nn as nn
import torchvision
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader

from torch.utils.tensorboard import SummaryWriter

data=torchvision.datasets.CIFAR10(root='./dataset',train=False,download=True,
                                  transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(data,batch_size=64)

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.ReLu1=ReLU()
        self.sigmoid=Sigmoid()

    def forward(self,x):
        output_=self.sigmoid(x)
        return output_

kk=Network()

writer=SummaryWriter('./logs')
step=0
for data in dataloader:
    imgs,labels=data
    writer.add_images("input",imgs,global_step=step)
    out=kk(imgs)
    writer.add_images("out",out,step)
    step+=1
writer.close()

10 实战

例子CIFAR-10

pytorch实战

import torch
import torch.nn as nn
from torch.nn import Conv2d, Flatten, Linear
from torch.nn import MaxPool2d

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.conv1=Conv2d(3,32,5,padding=2)
        self.maxpool1=MaxPool2d(kernel_size=2)
        self.conv2=Conv2d(32,32,5,padding=2)
        self.maxpool2=MaxPool2d(kernel_size=2)
        self.conv3=Conv2d(32,64,5,padding=2)
        self.maxpool3=MaxPool2d(kernel_size=2)
        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)
        return x

nn = Network()
print(nn)
input_=torch.ones((64,3,32,32))
out=nn(input_)
print(out.shape)

也可以直接用Sequential来简化代码


import torch
import torch.nn as nn
from torch.nn import Conv2d, Flatten, Linear, Sequential
from torch.nn import MaxPool2d

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.model1=Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

nn = Network()
print(nn)
input_=torch.ones((64,3,32,32))
out=nn(input_)
print(out.shape)

也可以用tensorboard展示

writer=SummaryWriter("./logs_seq")
writer.add_graph(nn,input_)
writer.close()

在Terminal输入

tensorboard –logdir=logs_seq

pytorch实战

双击Nework可以查看详细内容

pytorch实战

11 损失函数和反向传播

比如nn.L1Loss(相当于机器学习里的MAE)

pytorch实战

import torch
from torch.nn import L1Loss

y=torch.tensor([1.0,2.0,3.0])
y_=torch.tensor([1.1,2.1,3.9])

y=torch.reshape(y,(1,1,1,3))
y_=torch.reshape(y_,(1,1,1,3))

loss=L1Loss()
res=loss(y,y_)
print(res)
"""
tensor(0.3667)
"""

MSE

pytorch实战
loss1=nn.MSELoss()
res=loss1(y,y_)
print(res)
"""
tensor(0.2767)
"""

前面的评估指标都是针对回归问题,下面看一个分类问题

pytorch实战
x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x = torch.reshape(x,(1,3))
loss_class=nn.CrossEntropyLoss()
res_class=loss_class(x,y)
print(res_class)
"""
tensor(1.1019)
"""

pytorch实战

计算网络中的loss


import torch
import torch.nn as nn
from torch import nn
from torch.nn import Conv2d, Flatten, Linear, Sequential
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
import torchvision

dataset=torchvision.datasets.CIFAR10(root='./dataset',train=False,transform=torchvision.transforms.ToTensor(),
                                     download=True)
dataloader=DataLoader(dataset,batch_size=1)

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.model1=Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

nn_w = Network()
loss_class=nn.CrossEntropyLoss()
for data in dataloader:
    imgs,labels=data
    out=nn_w(imgs)

    res=loss_class(out,labels)
    print(res)

有了lossfation接下来就要反向传播了


import torch
import torch.nn as nn
from torch import nn
from torch.nn import Conv2d, Flatten, Linear, Sequential
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
import torchvision

dataset=torchvision.datasets.CIFAR10(root='./dataset',train=False,transform=torchvision.transforms.ToTensor(),
                                     download=True)
dataloader=DataLoader(dataset,batch_size=1)

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.model1=Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

nn_w = Network()
loss_class=nn.CrossEntropyLoss()
for data in dataloader:
    imgs,labels=data
    out=nn_w(imgs)

    res=loss_class(out,labels)
    res.backward()
    print("ok")

有了各个节点的梯度,接下来选择合适的优化器,使loss降低

pytorch实战

可以看到grad目前是None

12 优化器

基础使用,在torch.optim下

for input, target in dataset:
    optimizer.zero_grad()
    output = model(input)
    loss = loss_fn(output, target)
    loss.backward()
    optimizer.step()

要使用torch,必须构造一个优化器对象,该对象将保持当前状态,并根据计算的梯度更新参数


import torch
import torch.nn as nn
from torch import nn
from torch.nn import Conv2d, Flatten, Linear, Sequential
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
import torchvision

dataset=torchvision.datasets.CIFAR10(root='./dataset',train=False,transform=torchvision.transforms.ToTensor(),
                                     download=True)
dataloader=DataLoader(dataset,batch_size=1)

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.model1=Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(kernel_size=2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

nn_w = Network()
loss_class=nn.CrossEntropyLoss()
optim=torch.optim.SGD(nn_w.parameters(),lr=0.01)
for echo in range(20):
    running_loss=0.0
    for data in dataloader:
        imgs,labels=data
        out=nn_w(imgs)

        res=loss_class(out,labels)
        optim.zero_grad()
        res.backward()
        optim.step()
        running_loss += res
    print(running_loss)

"""
tensor(18693.3516, grad_fn=)
tensor(16138.8145, grad_fn=)
tensor(15454.3359, grad_fn=)
"""

13 现有网络模型的使用

pytorch为我们提供了一些现有的模型

pytorch实战

我们这里使用torchvison里的模型

pytorch实战

import torch
import torch.nn as nn
import torchvision

vgg16_false=torchvision.models.vgg16(pretrained=False)
vgg16_ture=torchvision.models.vgg16(pretrained=True)

print(vgg16_ture)

"""
修改网络模型
"""
vgg16_ture.add_module('add_linear',nn.Linear(1000,10))

添加到classifier

vgg16_ture.classifier.add_module('linear')

修改某一层

vgg16_ture.classifier[6]=nn.Linear(4096,10)

14 网络模型的读取与保存

import torch
import torchvision
import torch.nn as nn

vgg16=torchvision.models.vgg16(pretrained=False)

torch.save(vgg16,"./vgg16_model1.pth")

model=torch.load("vgg16_model1.pth")
print(model)

第二种方式

torch.save(vgg16.state_dict(),"vgg16_model2.pth")

vgg16=torchvision.models.vgg16(pretrained=False)
dict_=torch.load("vgg16_model2.pth")
vgg16.load_state_dict(dict_)
print(vgg16)

注意保存自己的模型时,如果使用torch.save(),加载模型的时候要导入你之前模型的类,

比如模型写在save_model文件中,加载模型的文件叫read_model,那么要在read_model开头加上

from save_model import *

不然会报错

AttributeError: Can’t get attribute ‘NetWork’ on

15 完整的模型训练流程

以CIFAR10数据集为例,首先准备数据


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

train_data=torchvision.datasets.CIFAR10('./dataset',train=True,download=True,
                                        transform=torchvision.transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10('./dataset',train=False,download=True,
                                       transform=torchvision.transforms.ToTensor())

train_data_len=len(train_data)
test_data_len=len(test_data)
print('训练集的数据量:{}'.format(train_data_len))
print("测试集的数据量:{}".format(test_data_len))
"""
训练集的数据量:50000
测试集的数据量:10000
"""

加载数据集


train_data_loader=DataLoader(train_data,batch_size=64)
test_data_loader=DataLoader(test_data,batch_size=64)

搭建神经网络

pytorch实战

新建一个model.py文件


import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential

class NetWork(nn.Module):
    def __init__(self):
        super(NetWork, self).__init__()
        self.model=Sequential(
            Conv2d(3,32,kernel_size=5,padding=2),
            MaxPool2d(2),
            Conv2d(32,32,kernel_size=5,padding=2),
            MaxPool2d(2),
            Conv2d(32,64,kernel_size=5,padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(64*4*4,64),
            Linear(64,10)
        )

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

if __name__ =='__main__':
    nn_=NetWork()
    x=torch.ones((64,3,32,32))
    out=nn_(x)
    print(out.shape)

在原来的文件开头加上下面这段话,导入model下的NetWork

from model import *

设置优化器


learn_rate=0.01
optimzier=torch.optim.SGD(wan.parameters(),lr=learn_rate)

搭建训练流程


total_train_step=0
total_test_step=0
epoch=10

for i in range(epoch):
    print("------------第{}轮训练开始-------------".format(i+1))

    for data in train_data_loader:
        imgs,labels=data
        out=wan(imgs)
        loss=loss_function(out,labels)

        optimzier.zero_grad()
        loss.backward()
        optimzier.step()

        total_train_step+=1
        print("训练次数{},loss={}".format(total_train_step,loss.item()))

item的作用

a=torch.tensor(5)
print(type(a))
print(type(a.item()))

在测试集上验证

for i in range(epoch):
    print("------------第{}轮训练开始-------------".format(i+1))

    for data in train_data_loader:
        imgs,labels=data
        out=wan(imgs)
        loss=loss_function(out,labels)

        optimzier.zero_grad()
        loss.backward()
        optimzier.step()

        total_train_step+=1
        if total_train_step % 100==0:
            print("训练次数{},loss={}".format(total_train_step,loss.item()))

    test_total_loss=0
    with torch.no_grad():
        for data in test_data_loader:
            imgs,labels=data
            out=wan(imgs)
            loss=loss_function(out,labels)
            test_total_loss+=loss
    print("整体测试集上的loss={}".format(test_total_loss))

至此模型的训练就基本完成了,下面添加tensorboard观察训练的情况


import torch
import torchvision
import torch.nn as nn
from torch.utils.tensorboard import SummaryWriter

from model import *

from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

train_data=torchvision.datasets.CIFAR10('./dataset',train=True,download=True,
                                        transform=torchvision.transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10('./dataset',train=False,download=True,
                                       transform=torchvision.transforms.ToTensor())

train_data_len=len(train_data)
test_data_len=len(test_data)
print('训练集的数据量:{}'.format(train_data_len))
print("测试集的数据量:{}".format(test_data_len))

train_data_loader=DataLoader(train_data,batch_size=64)
test_data_loader=DataLoader(test_data,batch_size=64)

wan=NetWork()

loss_function=nn.CrossEntropyLoss()

learn_rate=0.01
optimzier=torch.optim.SGD(wan.parameters(),lr=learn_rate)

total_train_step=0
total_test_step=0
epoch=10

writer=SummaryWriter("./log_model")

for i in range(epoch):
    print("------------第{}轮训练开始-------------".format(i+1))

    for data in train_data_loader:
        imgs,labels=data
        out=wan(imgs)
        loss=loss_function(out,labels)

        optimzier.zero_grad()
        loss.backward()
        optimzier.step()

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

    test_total_loss=0
    with torch.no_grad():
        for data in test_data_loader:
            imgs,labels=data
            out=wan(imgs)
            loss=loss_function(out,labels)
            test_total_loss+=loss
    print("整体测试集上的loss={}".format(test_total_loss))
    writer.add_scalar("test_loss",test_total_loss,total_test_step)
    total_test_step+=1

    torch.save(wan,"model_{}.pth".format(i+1))
    print("模型{}已保存".format(i+1))

writer.close()

可以看出loss一直在减小

pytorch实战

需要注意的一点是pytorch的output是

假设是二分类问题,2 个input
[0.1,0.2]   # 第一个样本属于1类和2类的概率分别是多少

[0.3,0.1]

如果你想要计算准确率,可以通过以下方式

out=torch.tensor([[0.5,0.1],
                  [0.3,0.2]])

print(out.argmax(0))

print(out.argmax(1))

pred=out.argmax(1)
label=torch.tensor([0,1])

print((pred==label).sum()/len(label))

完整的代码就是


import torch
import torchvision
import torch.nn as nn
from torch.utils.tensorboard import SummaryWriter

from model import *

from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

train_data=torchvision.datasets.CIFAR10('./dataset',train=True,download=True,
                                        transform=torchvision.transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10('./dataset',train=False,download=True,
                                       transform=torchvision.transforms.ToTensor())

train_data_len=len(train_data)
test_data_len=len(test_data)
print('训练集的数据量:{}'.format(train_data_len))
print("测试集的数据量:{}".format(test_data_len))

train_data_loader=DataLoader(train_data,batch_size=64)
test_data_loader=DataLoader(test_data,batch_size=64)

wan=NetWork()

loss_function=nn.CrossEntropyLoss()

learn_rate=0.01
optimzier=torch.optim.SGD(wan.parameters(),lr=learn_rate)

total_train_step=0
total_test_step=0
epoch=10

writer=SummaryWriter("./log_model")

for i in range(epoch):
    print("------------第{}轮训练开始-------------".format(i+1))

    for data in train_data_loader:
        imgs,labels=data
        out=wan(imgs)
        loss=loss_function(out,labels)

        optimzier.zero_grad()
        loss.backward()
        optimzier.step()

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

    test_total_loss=0
    total_acc=0
    with torch.no_grad():
        for data in test_data_loader:
            imgs,labels=data
            out=wan(imgs)
            loss=loss_function(out,labels)
            test_total_loss+=loss
            acc=(out.argmax(1)==labels).sum()
            total_acc+=acc
    print("整体测试集上的loss={}".format(test_total_loss))
    print("整体测试集上的acc={}".format(total_acc/test_data_len))
    writer.add_scalar("test_loss",test_total_loss,total_test_step)
    total_test_step+=1

    torch.save(wan,"model_{}.pth".format(i+1))
    print("模型{}已保存".format(i+1))

writer.close()

我们发现有些人在训练模型前喜欢加上

wan.train()  # 将模块设置为训练模式。

测试模型前加上

wan.eval()  #

pytorch实战

其实只对一些特定的层有作用,当你的代码里出现这些层时,调用这句

16 利用GPU加速训练

网络模型

数据(输入,标注)

损失函数

.cuda() 再返回即可

比如模型就是 wan=wan.cuda()

使用GPU加速的代码


import torch
import torchvision
import torch.nn as nn
from torch.utils.tensorboard import SummaryWriter

from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

train_data=torchvision.datasets.CIFAR10('./dataset',train=True,download=True,
                                        transform=torchvision.transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10('./dataset',train=False,download=True,
                                       transform=torchvision.transforms.ToTensor())

train_data_len=len(train_data)
test_data_len=len(test_data)
print('训练集的数据量:{}'.format(train_data_len))
print("测试集的数据量:{}".format(test_data_len))

train_data_loader=DataLoader(train_data,batch_size=64)
test_data_loader=DataLoader(test_data,batch_size=64)

class NetWork(nn.Module):
    def __init__(self):
        super(NetWork, self).__init__()
        self.model=Sequential(
            Conv2d(3,32,kernel_size=5,padding=2),
            MaxPool2d(2),
            Conv2d(32,32,kernel_size=5,padding=2),
            MaxPool2d(2),
            Conv2d(32,64,kernel_size=5,padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(64*4*4,64),
            Linear(64,10)
        )

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

wan=NetWork()
if torch.cuda.is_available():
    wan=wan.cuda()

loss_function=nn.CrossEntropyLoss()
if torch.cuda.is_available():
    loss_function=loss_function.cuda()

learn_rate=0.01
optimzier=torch.optim.SGD(wan.parameters(),lr=learn_rate)

total_train_step=0
total_test_step=0
epoch=10

writer=SummaryWriter("./log_model")

for i in range(epoch):
    print("------------第{}轮训练开始-------------".format(i+1))

    wan.train()
    for data in train_data_loader:
        imgs,labels=data
        if torch.cuda.is_available():
            imgs=imgs.cuda()
            labels=labels.cuda()
        out=wan(imgs)
        loss=loss_function(out,labels)

        optimzier.zero_grad()
        loss.backward()
        optimzier.step()

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

    wan.eval()
    test_total_loss=0
    total_acc=0
    with torch.no_grad():
        for data in test_data_loader:
            imgs,labels=data
            if torch.cuda.is_available():
                imgs=imgs.cuda()
                labels=labels.cuda()
            out=wan(imgs)
            loss=loss_function(out,labels)
            test_total_loss+=loss
            acc=(out.argmax(1)==labels).sum()
            total_acc+=acc
    print("整体测试集上的loss={}".format(test_total_loss))
    print("整体测试集上的acc={}".format(total_acc/test_data_len))
    writer.add_scalar("test_loss",test_total_loss,total_test_step)
    total_test_step+=1

    torch.save(wan,"model_{}.pth".format(i+1))
    print("模型{}已保存".format(i+1))

writer.close()

没有GPU的可以使用google Colab ,具体怎么打开这个网站,需要某种方法

使用CPU

训练次数100,loss=2.2980024814605713
训练时间8.45753264427185

使用GPU加速

训练次数100,loss=2.294966459274292
训练时间4.0068957805633545

!nvidia-smi 查看显卡的情况

pytorch实战

第二种使用使用GPU的方式

.to(device)

device=torch.device(“cuda”)

device=torch.device(“cuda:0”) 指定第一块显卡

device=torch.device(“cuda:1”) 指定第二块显卡


import torch
import torchvision
import torch.nn as nn
from torch.utils.tensorboard import SummaryWriter
import time

from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

device=torch.device("cuda:0")
print(device)
train_data=torchvision.datasets.CIFAR10('./dataset',train=True,download=True,
                                        transform=torchvision.transforms.ToTensor())
test_data=torchvision.datasets.CIFAR10('./dataset',train=False,download=True,
                                       transform=torchvision.transforms.ToTensor())

train_data_len=len(train_data)
test_data_len=len(test_data)
print('训练集的数据量:{}'.format(train_data_len))
print("测试集的数据量:{}".format(test_data_len))

train_data_loader=DataLoader(train_data,batch_size=64)
test_data_loader=DataLoader(test_data,batch_size=64)

class NetWork(nn.Module):
    def __init__(self):
        super(NetWork, self).__init__()
        self.model=Sequential(
            Conv2d(3,32,kernel_size=5,padding=2),
            MaxPool2d(2),
            Conv2d(32,32,kernel_size=5,padding=2),
            MaxPool2d(2),
            Conv2d(32,64,kernel_size=5,padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(64*4*4,64),
            Linear(64,10)
        )

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

wan=NetWork()
wan=wan.to(device)

loss_function=nn.CrossEntropyLoss()
loss_function=loss_function.to(device)

learn_rate=0.01
optimzier=torch.optim.SGD(wan.parameters(),lr=learn_rate)

total_train_step=0
total_test_step=0
epoch=10

writer=SummaryWriter("./log_model")
start_time=time.time()

for i in range(epoch):
    print("------------第{}轮训练开始-------------".format(i+1))

    wan.train()
    for data in train_data_loader:
        imgs,labels=data
        imgs=imgs.to(device)
        labels=labels.to(device)
        out=wan(imgs)
        loss=loss_function(out,labels)

        optimzier.zero_grad()
        loss.backward()
        optimzier.step()

        total_train_step+=1
        if total_train_step % 100==0:
            end_time=time.time()
            print("训练次数{},loss={}".format(total_train_step,loss.item()))
            print("训练时间{}".format(end_time-start_time))
            writer.add_scalar("train_loss",loss.item(),total_train_step)

    wan.eval()
    test_total_loss=0
    total_acc=0
    with torch.no_grad():
        for data in test_data_loader:
            imgs,labels=data
            out=wan(imgs)
            loss=loss_function(out,labels)
            test_total_loss+=loss
            acc=(out.argmax(1)==labels).sum()
            total_acc+=acc
    print("整体测试集上的loss={}".format(test_total_loss))
    print("整体测试集上的acc={}".format(total_acc/test_data_len))
    writer.add_scalar("test_loss",test_total_loss,total_test_step)
    total_test_step+=1

    torch.save(wan,"model_{}.pth".format(i+1))
    print("模型{}已保存".format(i+1))

writer.close()

只有一块显卡的情况下,下面这两条语句相同

device=torch.device("cuda")
device=torch.device("cuda:0")

你可能会见到这种写法

device=torch.device("cuda" if torch.cuda.is_available() else "cpu")

这是为了保证代码可以在各类设备上运行

17 进行测试


import torch
from PIL import Image
import torchvision
from model import *
path='../imgs/dog.png'
image=Image.open(path)
print(image)
image=image.convert('RGB')

transform=torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                          torchvision.transforms.ToTensor()])

img=transform(image)
print(img.shape)
img=torch.reshape(img,(1,3,32,32))

model=torch.load("model_1.pth")
model.eval()
with torch.no_grad():
    out=model(img)
print(out)
print(out.argmax(1))
"""
tensor([6])
"""

查看标签对应的类别

pytorch实战

发现预测的并不准确,这是因为模型训练次数太少了,我们换一个训练30次的模型试试,在Google colab上使用GPU训练30次,并把模型下载到本地

pytorch实战

import torch
from PIL import Image
import torchvision
from model import *
path='../imgs/dog.png'
image=Image.open(path)
print(image)
image=image.convert('RGB')

transform=torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                          torchvision.transforms.ToTensor()])

img=transform(image)
print(img.shape)
img=torch.reshape(img,(1,3,32,32))

model=torch.load("model_GPU30.pth",map_location=torch.device('cpu'))
model.eval()
with torch.no_grad():
    out=model(img)
print(out)
print(out.argmax(1))
"""
tensor([5])
"""

就比较准确了,使用的图片链接

18 查看开源代码

登录github

pytorch实战

比如看一下 junyanz / pytorch-CycleGAN-and-pix2pix

点击train文件,找到下面这句

pytorch实战

点一下 TrainOptions

pytorch实战

可以看到里面有很多的参数,比如lr学习速率等

pytorch实战

pytorch实战

可以直接把required删掉,加上default=’./datasets/maps’ 这样就可以在pycharm中右键运行

Original: https://blog.csdn.net/m0_52118763/article/details/123732779
Author: 开始King
Title: pytorch实战

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/710129/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球