前言

B站:pytorch入门

讲的真的基础,入门yyds!!!

0.pytorch安装

前置条件:已安装anaconda

pycharm:ctrl+p查看需要输入的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
// 创建虚拟环境,视频使用python=3.6
conda create -n pytorch python=3.6

# 激活虚拟环境
conda activate pytorch

# 查看虚拟环境列表
conda env list

# 安装cpu版pytorch(没有显卡的忧伤)
conda install pytorch torchvision torchaudio cpuonly -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/win-64/

conda install nb_conda
1
2
3
4
5
# 验证
python # 对应的虚拟环境中

import torch
torch.cuda.is_available() # 返回False,则成功(检查gpu是否可用)
1
2
3
4
5
6
7
# 其他环境的安装

# tensorboard安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorboard

# opencv的安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python==4.5.5.64
  • dir()
  • help()

1.加载数据

  • Dataset
  • DataLoader

1.Dataset类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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.label_dir = label_dir
self.path = os.path.join(root_dir, label_dir)
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)


if __name__ == '__main__':
root_path = './database/hymenoptera_data/train'
ants_lable = 'ants'
bees_lable = 'bees'
ants_database = MyData(root_path, ants_lable)
bees_database = MyData(root_path, bees_lable)

train_database = ants_database + bees_database # 可进行数据集的拼接
print(train_database.__len__())


2.TensorBoard使用

  • TensorBoard的add_scalar使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from torch.utils.tensorboard import SummaryWriter

    if __name__ == '__main__':
    writer = SummaryWriter("logs")

    # writer.add_image()
    for i in range(100):
    writer.add_scalar("y=2x",2*i,i)
    writer.close()
  • 打开logs中的文件(在终端输入)

    1
    2
    3
    4
    5
    # 注意路径的位置
    tensorboard --logdir=".\A01_PytorchLearning\logs"

    # 重新指定端口
    tensorboard --logdir=".\A01_PytorchLearning\logs" -port=6007
  • add_image()的使用,常用来观察训练结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    from torch.utils.tensorboard import SummaryWriter
    import numpy as np
    from PIL import Image


    if __name__ == '__main__':
    writer = SummaryWriter("logs")

    # add_image()的使用,常用来观察训练结果
    image_path = "./database/hymenoptera_data/train/ants/0013035.jpg"
    img_PIL = Image.open(image_path)
    img_array = np.array(img_PIL)
    print(type(img_array))
    print(img_array.shape)
    writer.add_image("test", img_array, 1, dataformats="HWC") # 1:步骤 HWC:高,宽,通道



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

3.transforms使用

  • tensor类型的转换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from torchvision import transforms
    from PIL import Image
    from torch.utils.tensorboard import SummaryWriter

    img_path = './database/hymenoptera_data/train/ants/0013035.jpg'
    img = Image.open(img_path)

    writer = SummaryWriter("logs")

    tersor_trans = transforms.ToTensor()
    tensor_img = tersor_trans(img) # 只传如PIL或者numpy.array


    writer.add_image("Tensor_img",tensor_img)
    writer.close()
  • 常见transforms(关注输入输出的数据类型)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    from torchvision import transforms
    from PIL import Image
    from torch.utils.tensorboard import SummaryWriter

    img_path = './database/hymenoptera_data/train/ants/0013035.jpg'
    img = Image.open(img_path)

    writer = SummaryWriter("logs")

    # ToTensor的使用
    trans_tersor = transforms.ToTensor()
    tensor_img = trans_tersor(img) # 只传如PIL或者numpy.array

    writer.add_image("Tensor_img",tensor_img)

    # normalize的使用:归一化
    trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
    img_norm = trans_norm(tensor_img)
    writer.add_image("Normalize",img_norm)

    # Resize()的使用
    print(img)
    trans_resize = transforms.Resize((512,512))
    img_resize = trans_resize(img)
    img_resize = trans_tersor(img_resize)
    writer.add_image("Resize",img_resize)

    # compose()
    trans_resize_2 = transforms.Resize(512)
    trans_compose = transforms.Compose([trans_resize_2,trans_tersor])
    trans_resize_2 = trans_compose(img)
    writer.add_image("compose",trans_resize_2,1)

    # RandomCrop:随机裁剪
    trans_randomCrop = transforms.RandomCrop((512,768))
    trans_compose_2 = transforms.Compose([trans_randomCrop,trans_tersor])
    for i in range(10):
    img_crop = trans_compose_2(img)
    writer.add_image("RandomCrop",img_crop,i)


    writer.close()

4.torchvision中的数据集使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import torchvision
from torch.utils.tensorboard import SummaryWriter

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

# 下载
# train_set = torchvision.datasets.CIFAR10('./database/CIFAR10', train=True, download=True)
# test_set = torchvision.datasets.CIFAR10('./database/CIFAR10', train=False, download=True)

# 格式转换
train_set = torchvision.datasets.CIFAR10('./database/CIFAR10', transform=dataset_transform, train=True, download=True)
test_set = torchvision.datasets.CIFAR10('./database/CIFAR10', transform=dataset_transform, train=False, download=True)

# 查看数据
print(test_set[0])
print(test_set.classes)
img, target = test_set[0]
print(img)
print(target)

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

writer.close()

5.DataLoader的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

# 准备的测试数据集
test_data = torchvision.datasets.CIFAR10(r'.\database\CIFAR10', train=False, transform=torchvision.transforms.ToTensor())

test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=False)
# shuffle是否打乱顺序图片;num_workers进程数,0是主进程;drop_last是否删除最后的一批数据


# 测试数据集中图片和target
img, target = test_data[0]
# print(img.shape)
# print(target)

writer = SummaryWriter("logs")
for epoch in range(2):
step = 0
for data in test_loader:
imgs, targets = data
# print(imgs.shape)
# print(targets)
writer.add_images(f"epoch:{epoch}", imgs, step)
step += 1

writer.close()

2.神经网络(neural network)

1.基本骨架

nn.MOudle的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import torch
from torch import nn


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

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

module = Module()
x = torch.tensor(1.0)
output = module(x)
print(output)

2.卷积层

  • 卷积操作

    001

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    # nn.functional不常使用

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

    print(input.shape)
    print(kernel.shape)

    output = F.conv2d(input, kernel, stride=1) # stride:移动步数
    print(output)

    output2 = F.conv2d(input, kernel, stride=2)
    print(output2)

    output3 = F.conv2d(input, kernel, stride=1, padding=1) # padding:是否外部填充
    print(output3)
  • 卷积层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    # 常用

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

    dataset = torchvision.datasets.CIFAR10(r'.\database\CIFAR10', train=False, transform=torchvision.transforms.ToTensor(),
    download=True)
    dataloader = DataLoader(dataset, batch_size=64)

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

    moudle = Moudle()

    writer = SummaryWriter("./logs")

    step = 0
    for data in dataloader:
    imgs, targets = data
    output = moudle(imgs)
    print(imgs.shape)
    print(output.shape)
    # torch.Size([64, 3, 32, 32])
    writer.add_images("input", imgs, step)
    # torch.Size([64, 6, 30, 30]) -> [xxx, 3, 30, 30]

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

    step = step + 1


    writer.close()

3.最大池化的使用

保证图像的特征,降低数据

001

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10(r'.\database\CIFAR10', train=False, download=True,
transform=torchvision.transforms.ToTensor())

dataloader = DataLoader(dataset, batch_size=64)

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

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

module = Module()

writer = SummaryWriter("logs")
step = 0

for data in dataloader:
imgs, targets = data
writer.add_images("inputpool", imgs, step)
output = module(imgs)
writer.add_images("outputpool", output, step)
step = step + 1

writer.close()

4.非线性激活

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

input = torch.tensor([[1, -0.5],
[-1, 3]])

input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)

dataset = torchvision.datasets.CIFAR10(r'.\database\CIFAR10', train=False, download=True,
transform=torchvision.transforms.ToTensor())

dataloader = DataLoader(dataset, batch_size=64)

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

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

module = Module()

writer = SummaryWriter("logs")
step = 0
for data in dataloader:
imgs, targets = data
writer.add_images("input", imgs, global_step=step)
output = module(imgs)
writer.add_images("output", output, step)
step += 1

writer.close()

5.线性层及其他层的介绍

001

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10(r'.\database\CIFAR10', train=False, transform=torchvision.transforms.ToTensor(),
download=True)

dataloader = DataLoader(dataset, batch_size=64)

class Module(nn.Module):
def __init__(self):
super(Module, self).__init__()
self.linear1 = Linear(196608, 10)

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

module = Module()

for data in dataloader:
imgs, targets = data
print(imgs.shape)
output = torch.flatten(imgs) # 将图像展平
print(output.shape)
output = module(output)
print(output.shape)

6.案例:CIFAR10模型创建

  • Sequential的使用
  • 神经网络:

001

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


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

module = Module()
print(module)
input = torch.ones((64, 3, 32, 32))
output = module(input)
print(output.shape)

writer = SummaryWriter("logs")
writer.add_graph(module, input)
writer.close()

7.损失函数与反向传播

1.损失函数

001

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import torch
from torch.nn import L1Loss
from torch import nn

inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)

inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))

loss = L1Loss(reduction='sum')
result = loss(inputs, targets)

loss_mse = nn.MSELoss()
result_mse = loss_mse(inputs, targets)

print(result)
print(result_mse)


x = torch.tensor([0.1, 0.2, 0.3])
y = torch.tensor([1])
x = torch.reshape(x, (1, 3))
loss_cross = nn.CrossEntropyLoss()
result_cross = loss_cross(x, y)
print(result_cross)

2.反向传播

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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(r'.\database\CIFAR10', train=False, transform=torchvision.transforms.ToTensor(),
download=True)

dataloader = DataLoader(dataset, batch_size=1)

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


loss = nn.CrossEntropyLoss()
module = Module()
for data in dataloader:
imgs, targets = data
outputs = module(imgs)
result_loss = loss(outputs, targets)
result_loss.backward()
print(result_loss)

8.优化器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.optim.lr_scheduler import StepLR
from torch.utils.data import DataLoader

dataset = torchvision.datasets.CIFAR10(r'.\database\CIFAR10', train=False, transform=torchvision.transforms.ToTensor(),
download=True)

dataloader = DataLoader(dataset, batch_size=1)

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


loss = nn.CrossEntropyLoss()
module = Module()
optim = torch.optim.SGD(module.parameters(), lr=0.01)
# scheduler = StepLR(optim, step_size=5, gamma=0.1)
for epoch in range(20):
running_loss = 0.0
for data in dataloader:
imgs, targets = data
outputs = module(imgs)
result_loss = loss(outputs, targets)
optim.zero_grad()
result_loss.backward()
# scheduler.step()
optim.step()
running_loss = running_loss + result_loss
print(running_loss)

9.现有网络模型的使用和修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import torchvision

# train_data = torchvision.datasets.ImageNet("../data_image_net", split='train', download=True,
# transform=torchvision.transforms.ToTensor())
from torch import nn

vgg16_false = torchvision.models.vgg16(pretrained=False)
# vgg16_true = torchvision.models.vgg16(pretrained=True)

# print(vgg16_true)
#
# train_data = torchvision.datasets.CIFAR10(r'.\database\CIFAR10', train=True, transform=torchvision.transforms.ToTensor(),
# download=True)

# vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
# print(vgg16_true)

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

10.网络模型的保存与读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import torch
import torchvision
from torch import nn

vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1,模型结构+模型参数
torch.save(vgg16, "./A01_PytorchLearning/tmp/vgg16_method1.pth")

# 方式一陷阱
class Module(nn.Module):
def __init__(self):
super(Module, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

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

module = Module()
torch.save(module, "./A01_PytorchLearning/tmp/method1.pth")

# 保存方式2,模型参数(官方推荐)
torch.save(vgg16.state_dict(), "./A01_PytorchLearning/tmp/vgg16_method2.pth")


# ============================模型的加载============================

# 方式1,加载模型
model = torch.load("./A01_PytorchLearning/tmp/vgg16_method1.pth")
# print(model)

# 方式2,加载模型
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("./A01_PytorchLearning/tmp/vgg16_method2.pth"))
# model = torch.load("./A01_PytorchLearning/tmp/vgg16_method2.pth")
# print(vgg16)

# 陷阱1:方式1的加载
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

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

model = torch.load('./A01_PytorchLearning/tmp/method1.pth')
print(model)

3.完整模型训练套路

1.模型搭建

在model.py中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import torch
from torch import nn

# 搭建神经网络
class Module(nn.Module):
def __init__(self):
super(Module, self).__init__()
self.model = nn.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.model(x)
return x


if __name__ == '__main__':
module = Module()
input = torch.ones((64, 3, 32, 32))
output = module(input)
print(output.shape)

2.模型训练

在train.py中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import torchvision
from torch.utils.tensorboard import SummaryWriter
from model import *
from torch import nn
from torch.utils.data import DataLoader

# 准备数据集
train_data = torchvision.datasets.CIFAR10(
root="./A01_PytorchLearning/database/CIFAR10",
train=True,
transform=torchvision.transforms.ToTensor(),
download=True,
)
test_data = torchvision.datasets.CIFAR10(
root="./A01_PytorchLearning/database/CIFAR10",
train=False,
transform=torchvision.transforms.ToTensor(),
download=True,
)

# 查看数据量
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))


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

# 创建网络模型
module = Module()

# 损失函数
loss_fn = nn.CrossEntropyLoss()

# 优化器
# learning_rate = 0.01
# 1e-2=1 x (10)^(-2) = 1 /100 = 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(module.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("A01_PytorchLearning/B03_Complete_Module/logs_train")

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

# 训练步骤开始
module.train()
for data in train_dataloader:
imgs, targets = data
outputs = module(imgs)
loss = loss_fn(outputs, targets)

# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()

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

# 测试步骤开始
module.eval()
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
outputs = module(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss.item()
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy = total_accuracy + accuracy

print("整体测试集上的Loss: {}".format(total_test_loss))
print("整体测试集上的正确率: {}".format(total_accuracy / test_data_size))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step)
total_test_step = total_test_step + 1

torch.save(module, "A01_PytorchLearning/B03_Complete_Module/module/module_{}.pth".format(i))
print("模型已保存")

writer.close()

3.GPU的使用

使用的场景:

  • 网络模型
  • 数据(输入,标注)
  • 损失函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter

# from model import *
# 准备数据集
from torch import nn
from torch.utils.data import DataLoader

# 定义训练的设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

train_data = torchvision.datasets.CIFAR10(
root="./A01_PytorchLearning/database/CIFAR10",
train=True,
transform=torchvision.transforms.ToTensor(),
download=True,
)
test_data = torchvision.datasets.CIFAR10(
root="./A01_PytorchLearning/database/CIFAR10",
train=False,
transform=torchvision.transforms.ToTensor(),
download=True,
)

# length 长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 训练数据集的长度为:10
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))


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

# 创建网络模型
class Module(nn.Module):
def __init__(self):
super(Module, self).__init__()
self.model = nn.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.model(x)
return x


module = Module()
module = module.to(device)

# 损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)
# 优化器
# learning_rate = 0.01
# 1e-2=1 x (10)^(-2) = 1 /100 = 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(module.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10

# 添加tensorboard
writer = SummaryWriter("../logs_train")

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

# 训练步骤开始
module.train()
for data in train_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
outputs = module(imgs)
loss = loss_fn(outputs, targets)

# 优化器优化模型
optimizer.zero_grad()
loss.backward()
optimizer.step()

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

# 测试步骤开始
module.eval() # eval() 不会计算梯度
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
outputs = module(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss.item()
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy = total_accuracy + accuracy

print("整体测试集上的Loss: {}".format(total_test_loss))
print("整体测试集上的正确率: {}".format(total_accuracy / test_data_size))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step)
total_test_step = total_test_step + 1

torch.save(
module, "A01_PytorchLearning/B03_Complete_Module/module/module{}.pth".format(i)
)
print("模型已保存")

writer.close()

4.模型验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import torch
import torchvision
from PIL import Image
from torch import nn

image_path = "A01_PytorchLearning/database/airplane.png"
image = Image.open(image_path)
print(image)
image = image.convert('RGB')
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
torchvision.transforms.ToTensor()])

image = transform(image)
print(image.shape)

class Tudui(nn.Module):
# 定义一个继承自nn.Module的类TudModuleui
# 定义一个继承自nn.Module的类
def __init__(self):
# 初始化函数
# 调用父类的初始化函数
super(Tudui, self).__init__()
# 定义一个Sequential容器,用于存储网络层
self.model = nn.Sequential(
# 定义一个二维卷积层,输入通道数为3,输出通道数为32,卷积核大小为5,步长为1,填充为2
nn.Conv2d(3, 32, 5, 1, 2),
# 定义一个最大池化层,池化核大小为2
nn.MaxPool2d(2),
# 定义一个二维卷积层,输入通道数为32,输出通道数为32,卷积核大小为5,步长为1,填充为2
nn.Conv2d(32, 32, 5, 1, 2),
# 定义一个最大池化层,池化核大小为2
nn.MaxPool2d(2),
# 定义一个二维卷积层,输入通道数为32,输出通道数为64,卷积核大小为5,步长为1,填充为2
nn.Conv2d(32, 64, 5, 1, 2),
# 定义一个最大池化层,池化核大小为2
nn.MaxPool2d(2),
# 定义一个展平层,将多维数据展平为一维数据
nn.Flatten(),
# 定义一个全连接层,输入特征数为64*4*4,输出特征数为64
nn.Linear(64*4*4, 64),
nn.Linear(64, 10)
)

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

model = torch.load("A01_PytorchLearning/B03_Complete_Module/tudui_29_gpu.pth", map_location=torch.device('cpu'))
print(model)
image = torch.reshape(image, (1, 3, 32, 32))
model.eval()
with torch.no_grad():
output = model(image)
print(output)


print(output.argmax(1))