Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

MengFanjun的博客

原视频链接:Pytorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】

土堆老师的Github地址

之前学的也不少了,现在要去训练一个完整的神经网络,利用Pytorch和CIFAR10数据集

准备数据集

1
2
3
4
5
6
import torchvision#导入torchvision
##准备数据集
train_data=torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),
download=True)##数据集的目录,是否训练,将PIL型变为Tensor型,需要下载
test_data=torchvision.datasets.CIFAR10(root="../data",train=False,transform=torchvision.transforms.ToTensor(),
download=True)

### 测试数据集长度

1
2
3
4
5
6
#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))#{},会被替换为后面的值,把他变成字符串了

输出结果

1
2
3
4
Files already downloaded and verified
Files already downloaded and verified
训练数据集长度为:50000
测试数据集长度为:10000

### 用DataLoader加载数据

1
2
3
#利用dataloader来加载数据集
train_dataloader=DataLoader(train_data,batch_size=64)#一次训练所抓取的数据样本数量为64
test_dataloader=DataLoader(test_data,batch_size=64)

搭建神经网络

在这里插入图片描述 这是CIFAR10 model的结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class NetWork(nn.Module):
def __init__(self):
super(NetWork, 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

将此程序放入另一个新创建的python文件中,注意在同一个文件夹下

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
from torch import nn
import torch
class NetWork(nn.Module):
def __init__(self):
super(NetWork, 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__':
network=NetWork()
input=torch.ones((64,3,32,32))
output=network(input)
print(output.shape)

输出结果:

1
torch.Size([64, 10])

输出了64行,每一行上有10个数据,10代表了我们每一张图片在我们十个类别中的概率

### 创建损失函数

1
loss_fn=nn.CrossEntropyLoss()#交叉熵

创建优化器

1
2
learning_rate=0.01#学习速率
optimizer=torch.optim.SGD(network.parameters(),lr=learning_rate)#随机梯度下降,先填网络模型,然后是学习速率

开始训练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#设置训练网络的一些参数
total_train_step=0#记录训练次数
#记录测试的次数
total_test_step=0
#训练的轮数
epoch=10

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

#训练步骤开始
for data in train_dataloader:
imgs,targets=data
outputs=network(imgs)
loss=loss_fn(outputs,targets)
#优化器优化模型
optimizer.zero_grad()#优化器梯度清零
loss.backward()#反向传播
optimizer.step()#优化器进行优化

total_train_step=total_train_step+1 #记录训练次数
print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Files already downloaded and verified
Files already downloaded and verified
训练数据集长度为:50000
测试数据集长度为:10000
----------------第1轮训练开始-------------
训练次数:1,Loss:2.31258487701416
训练次数:2,Loss:2.312842607498169
训练次数:3,Loss:2.302748918533325
训练次数:4,Loss:2.3247387409210205
训练次数:5,Loss:2.307778835296631
训练次数:6,Loss:2.311138868331909
训练次数:7,Loss:2.290013551712036
训练次数:8,Loss:2.302402973175049
训练次数:9,Loss:2.293430805206299
训练次数:10,Loss:2.2981677055358887

这里如果不停止会一直输出,所以,我们要把训练过程改善一下

1
2
3
4
5
6
7
8
9
10
11
12
for data in train_dataloader:
imgs,targets=data
outputs=network(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:#每100次才打印
print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))

每100次才打印数据 ### 开始测试步骤 训练完毕之后,我们接下来采用测试数据进行测试

1
2
3
4
5
6
7
8
total_test_loss=0
with torch.no_grad():
for data in test_dataloader:
imgs,targets =data
outputs =network(imgs)#输入放到网络当中我们可以得到对应输出
loss =loss_fn(outputs,targets)#计算误差
total_test_loss=total_test_loss+loss.item()
print("整体测试集上的Loss:{}".format(total_test_loss))

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Files already downloaded and verified
Files already downloaded and verified
训练数据集长度为:50000
测试数据集长度为:10000
----------------第1轮训练开始-------------
训练次数:100,Loss:2.2861547470092773
训练次数:200,Loss:2.273378372192383
训练次数:300,Loss:2.238002300262451
训练次数:400,Loss:2.1429920196533203
训练次数:500,Loss:2.050020694732666
训练次数:600,Loss:2.005511522293091
训练次数:700,Loss:2.015151262283325
整体测试集上的Loss:314.1541121006012
----------------第2轮训练开始-------------
训练次数:800,Loss:1.8569183349609375

训练结果可视化

为了使得我们可以清晰地看到训练结果,我们用Tensorboard把他画出来

需要在训练步骤和测试步骤里面加上一句代码

开头启用Tensorboard

1
writer=SummaryWriter("logs_train")

训练步骤下

1
2
3
4
if total_train_step %100==0:#每100次才打印
print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
writer.add_scalar("train_loss",loss.item(),total_train_step)##标题,loss值,训练次数
writer.add_scalar("train_loss",loss.item(),total_train_step)##标题,loss值,训练次数

测试步骤下

1
2
writer.add_scalar("test_loss",total_test_loss,total_test_step)##标题,测试误差值,测试次数
total_test_step=total_test_step+1

最后加上

1
writer.close()
在Terminal中加上启动tensorboard的代码,要在pytorch的环境下

1
tensorboard --logdir=logs_train

打开连接后,画出的图像如下

输出结果

train_loss 在这里插入图片描述 test_loss 在这里插入图片描述 loss一直在下降,证明训练有一定效果

拓展

二分类问题求准确率

先来了解一个函数叫做Argmax()

1
2
3
4
import torch
outputs=torch.Tensor([[0.1,0.2],
[0.3,0.4]])
print(outputs.argmax(1))#1表示横向,0表示纵向比较

输出结果

1
tensor([1, 1])

表示在横向上,0.2比0.1大,为1,0.4比0.3大,也为1,如果将argmax换成0

1
2
3
4
import torch
outputs=torch.Tensor([[0.1,0.2],
[0.05,0.4]])
print(outputs.argmax(0))#1表示横向,0表示纵向比较

输出结果

1
tensor([0, 1])

在纵向上,0.05比0.1小,所以是0,另一纵向同理

再将其与真实结果比较,计算其总和

1
2
3
4
5
6
7
8
import torch
outputs=torch.Tensor([[0.1,0.2],
[0.05,0.4]])
print(outputs.argmax(0))#1表示横向,0表示纵向比较

preds=outputs.argmax(1)
targets =torch.Tensor([0,1])
print((preds==targets).sum())

输出结果

1
2
tensor([1, 1])
tensor(1)

测试模型的准确率

通过以上的内容,我们可以优化我们的模型,计算其准确率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
total_test_loss=0
total_accuracy=0#整体正确率
with torch.no_grad():
for data in test_dataloader:
imgs,targets =data
outputs =network(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

输出结果

1
2
3
4
5
6
7
8
9
10
----------------第1轮训练开始-------------
训练次数:100,Loss:2.2833285331726074
训练次数:200,Loss:2.2706451416015625
训练次数:300,Loss:2.203575849533081
训练次数:400,Loss:2.102896213531494
训练次数:500,Loss:2.012601852416992
训练次数:600,Loss:2.006645441055298
训练次数:700,Loss:1.9837690591812134
整体测试集上的Loss:309.36241841316223
整体测试集上的正确率:0.2946999967098236

在Tensorboard中显示 在这里插入图片描述 准确率是在上升的

以上就是训练一个完整的模型的步骤了

完整代码

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
#######################一个完整的神经网络 准备数据,加载数据,准备模型,设置损失函数,设置优化器,开始训练,最后验证,结果聚合展示

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

from model import *#引入model中的所有import
##准备数据集
train_data=torchvision.datasets.CIFAR10(root="../data",train=True,transform=torchvision.transforms.ToTensor(),
download=True)##数据集的目录,是否训练,将PIL型变为Tensor型,需要下载

test_data=torchvision.datasets.CIFAR10(root="../data",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)#一次训练所抓取的数据样本数量为64
test_dataloader=DataLoader(test_data,batch_size=64)

#创建网络模型
network=NetWork()

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

#优化器
learning_rate=0.01#学习速率
optimizer=torch.optim.SGD(network.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))

#训练步骤开始
network.train()
for data in train_dataloader:
imgs,targets=data
outputs=network(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:#每100次才打印
print("训练次数:{},Loss:{}".format(total_train_step,loss.item()))
writer.add_scalar("train_loss",loss.item(),total_train_step)##标题,loss值,训练次数
#测试步骤开始
network.eval()
total_test_loss=0
total_accuracy=0#整体正确率
with torch.no_grad():#网络模型没有梯度,不需要梯度优化
for data in test_dataloader:
imgs,targets =data
outputs =network(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(network,"network_{}.pth".format(i))#保存每一轮的训练结果
print("模型已保存")

writer.close()

利用GPU去训练神经网络

只需要稍作改动

1
2
3
4
#创建网络模型
network=NetWork()
if torch.cuda.is_available():
network=network.cuda()#利用gpu进行训练

损失函数改成cuda

1
2
3
#损失函数
loss_fn=nn.CrossEntropyLoss()#交叉熵
loss_fn=loss_fn.cuda()#利用gpu训练

在训练和测试那里,吧imgs和targets改成cuda就OK了

1
2
imgs=imgs.cuda()
targets=targets.cuda()

跟CPU跑的比较了下,CPU跑100轮用了4.9s,GPU用了3.2s,确实会快

验证网络模型

万事俱备只欠东风,现在我们可以去拿训练好的网络去预测一只狗狗了,

首先从网上找一个狗狗的照片,这里就不展示了

将狗狗的照片放入你的Pytorch文件夹下,然后就可以编写代码了

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
import torch
import torchvision.transforms
from PIL import Image
from torch import nn

image_path="你的狗狗照片的绝对路径"
image=Image.open(image_path)

image=image.convert('RGB')#保持其颜色通道
transform=torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
torchvision.transforms.ToTensor()])## 将输入图片resize成统一尺寸,# 将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间

image=transform(image)

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


model=torch.load("network_gpu_9.pth",map_location=torch.device('cpu'))#保存模型,从gpu映射到cpu上,读取之前训练好的模型,我用的是训练10轮的
image=torch.reshape(image,(1,3,32,32))#batch_size,3个颜色通道 32*32
model.eval()
with torch.no_grad():
output=model(image)
print(output)
print(output.argmax(1))

输出结果

1
2
3
tensor([[-0.5509, -0.1295,  1.7645,  3.3668, -3.0762,  4.5566,  3.2504,  0.9605,
-6.5720, -1.3539]])
tensor([5])

在这里插入图片描述 对照表格,我们可以发现,经过训练,电脑大概知道了狗狗的样子

评论