完整实操之:CIFAR10数据集的训练与测试
CIFAR10数据集,有50000张训练图片,有10000张测试图片
下方代码中:
- 训练轮次为
10
轮; batch_size = 64
,50000/64 = 782(向上取整)
,所以训练一轮就等于训练了782
个batch_size
的图片,10
轮就是7820
;- 最终运行结果展示两个部分:
- 画出
782
个batch_size
的10
轮训练损失减小情况,整合成一条曲线,10
轮总共7820
个; - 画出第一个
batch_size
的10
轮训练损失减小情况。
- 画出
- 最终将训练好的模型保存在本地,命名为
CIFAR10_NET_train10
,train10
表示经过了10
轮的训练。
(一)代码一
保存在本地的用于存放神经网络模型的 NN_models.py
文件:
# 此文件用于存放神经网络模型
# 作者:LIANG XIAO
from torch import nn
# CIFAR10的配套网络(加了非线性激活函数)
class CIFAR10_NET(nn.Module):
def __init__(self):
super(CIFAR10_NET, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(3, 32, 5, padding=2), # 输入输出尺寸相同,故根据公式计算出padding的值
nn.MaxPool2d(2, 2),
nn.ReLU(), # 添加ReLU激活函数
nn.Conv2d(32, 32, 5, padding=2),
nn.MaxPool2d(2, 2),
nn.ReLU(), # 添加ReLU激活函数
nn.Conv2d(32, 64, 5, padding=2),
nn.MaxPool2d(2, 2),
nn.ReLU(), # 添加ReLU激活函数
nn.Flatten(),
nn.Linear(1024, 64),
nn.ReLU(), # 添加ReLU激活函数
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
(二)代码二,结合代码一
初步训练代码:
import torch
from torch import nn
import torchvision
from torchvision import transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from NN_models import *
# 检查CUDA是否可用,并设置设备为 GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
dataclass_transform = transforms.Compose([
transforms.ToTensor(),
])
train_dataset = torchvision.datasets.CIFAR10(root='E:\\4_Data_sets\\species recognition', train=True,transform=dataclass_transform, download=True)
test_dataset = torchvision.datasets.CIFAR10(root='E:\\4_Data_sets\\species recognition', train=False,transform=dataclass_transform, download=True)
# 训练和测试数据集的长度
train_data_size = len(train_dataset)
test_size = len(test_dataset)
print(train_data_size,test_size)
train_dataloader = DataLoader(dataset=train_dataset,batch_size=64)
test_dataloader = DataLoader(dataset=test_dataset,batch_size=64)
# 创建网络模型
CIFAR10_NET_Instance = CIFAR10_NET().to(device)
# 定义损失函数
loss = nn.CrossEntropyLoss()
# 定义优化器
learning_rate = 0.01
optimizer = torch.optim.SGD(CIFAR10_NET_Instance.parameters(), lr=learning_rate, momentum=0.9)
# 开始训练
total_train_step = 0
first_train_step = 0
total_test_step = 0
epoch_sum = 10 # 迭代次数
# 添加tensorboard
writer = SummaryWriter('logs')
for i in range(epoch_sum):
print("------------第 {} 轮训练开始了------------:".format(i+1))
# 训练步骤开始
for data in train_dataloader:
imgs, labels = data
imgs, labels = imgs.to(device), labels.to(device) # 将数据和目标移动到GPU
outputs = CIFAR10_NET_Instance(imgs)
loss_real = loss(outputs, labels) # 这里的损失变量 loss_real,千万别和损失函数 loss 相同,否则会报错!
optimizer.zero_grad()
loss_real.backward()
optimizer.step()
total_train_step += 1
# 表示第一轮训练结束,取每一轮的第一个batch_size来看看训练效果,这里的782是通过计算得出来的
if total_train_step % 782 == 0:
first_train_step += 1
print("训练次数为:{}, loss为:{}".format(total_train_step, loss_real)) # 此训练次数非训练轮次,而是训练到第几个batch_size了
writer.add_scalar('first_batch_size', loss_real.item(), first_train_step)
writer.add_scalar('total_batch_size', loss_real.item(), total_train_step)
# 每训练一轮,就使用测试集看看训练效果
total_test_loss = 0
with torch.no_grad():
for data in test_dataloader:
imgs, labels = data
imgs, labels = imgs.to(device), labels.to(device)
outputs = CIFAR10_NET_Instance(imgs)
loss_fake = loss(outputs, labels)
total_test_loss += loss_fake.item()
print("# # 整体测试集上的LOSS为:{}".format(total_test_loss))
writer.close()
torch.save(CIFAR10_NET_Instance,"E:\\5_NN_model\\CIFAR10_NET_train10")
print("模型已保存!!")
运行结果
(三)代码三,结合代码一
☆Tips☆: 训练模型的输出,是一个二维张量,第几行表示第几个 batch_size
样本;列表示每个样本识别成某种类别的概率,CIFAR10
的配套网络模型输出如下:
# batch_size = 64,类别为10,所以行数为64,列数为10。
tensor([[ 0.0377, 0.0153, 0.0289, 0.1006, 0.1039, 0.1300, 0.0667, 0.0739, 0.0362, 0.0660],
[ 0.0406, 0.0162, 0.0250, 0.0995, 0.0990, 0.1308, 0.0637, 0.0725, 0.0351, 0.0714],
[ 0.0341, 0.0162, 0.0297, 0.1037, 0.1007, 0.1342, 0.0674, 0.0733, 0.0366, 0.0693],
[ 0.0367, 0.0144, 0.0289, 0.1066, 0.1045, 0.1290, 0.0714, 0.0734, 0.0344, 0.0662],
...
[ 0.0388, 0.0150, 0.0261, 0.0996, 0.1034, 0.1307, 0.0662, 0.0720, 0.0358, 0.0707]], device='cuda:0', grad_fn=<AddmmBackward0>)
所以,使用 torch.argmax
函数时,通常设置 dim=1
(第二个维度,行)。
完整训练及测试代码
此代码中会加入各种各样的小知识点。
import torch
from torch import nn
import torchvision
from torchvision import transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from NN_models import *
from PIL import Image
import time
# 检查CUDA是否可用,并设置设备为 GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
dataclass_transform = transforms.Compose([
transforms.ToTensor(),
])
train_dataset = torchvision.datasets.CIFAR10(root='E:\\4_Data_sets\\species recognition', train=True,transform=dataclass_transform, download=True)
test_dataset = torchvision.datasets.CIFAR10(root='E:\\4_Data_sets\\species recognition', train=False,transform=dataclass_transform, download=True)
# 训练和测试数据集的长度
train_data_size = len(train_dataset)
test_size = len(test_dataset)
print(train_data_size,test_size)
train_dataloader = DataLoader(dataset=train_dataset,batch_size=64)
test_dataloader = DataLoader(dataset=test_dataset,batch_size=64)
# 创建网络模型
CIFAR10_NET_Instance = CIFAR10_NET().to(device)
# 定义损失函数
loss = nn.CrossEntropyLoss()
# 定义优化器
learning_rate = 0.01
optimizer = torch.optim.SGD(CIFAR10_NET_Instance.parameters(), lr=learning_rate, momentum=0.9)
# 开始训练
total_train_step = 0
first_train_step = 0
total_test_step = 0
epoch_sum = 15 # 迭代次数
# 添加tensorboard
writer = SummaryWriter('logs')
start_time = time.time()
last_epoch_time = time.time() # 记录开始训练的时间
for i in range(epoch_sum):
print("----------------第 {} 轮训练开始了----------------:".format(i+1))
# 训练步骤开始
for data in train_dataloader:
imgs, labels = data
imgs, labels = imgs.to(device), labels.to(device) # 将数据和目标移动到GPU
outputs = CIFAR10_NET_Instance(imgs)
loss_real = loss(outputs, labels) # 这里的损失变量 loss_real,千万别和损失函数 loss 相同,否则会报错!
optimizer.zero_grad()
loss_real.backward()
optimizer.step() # 更新模型参数
total_train_step += 1
# 表示第一轮训练结束,取每一轮的第一个batch_size来看看训练效果
if total_train_step % 782 == 0:
first_train_step += 1
print("训练次数为:{}, loss为:{}".format(total_train_step, loss_real)) # 此训练次数非训练轮次
# 每轮测试结束之后,计算训练的准确率,就拿第一个batch_size来看看准确率
outputs_B = torch.argmax(outputs, dim=1)
outputs_C = (labels == outputs_B).sum() # True默认为1,False默认为0
accuracy = (outputs_C.item() / len(outputs_B)) * 100
accuracy = round(accuracy, 2) # 2表示保留两位小数(四舍五入)
print(f"训练正确率为:{accuracy}%")
writer.add_scalar('first_batch_size', loss_real.item(), first_train_step)
writer.add_scalar('total_batch_size', loss_real.item(), total_train_step)
# 每训练一轮,就使用测试集看看训练效果
total_test_loss = 0
with torch.no_grad():
for data in test_dataloader:
imgs, labels = data
imgs, labels = imgs.to(device), labels.to(device)
outputs = CIFAR10_NET_Instance(imgs)
loss_fake = loss(outputs, labels)
total_test_loss += loss_fake.item()
print("整体测试集上的LOSS为:{}".format(total_test_loss))
one_epoch_time = time.time() # 记录训练一次的时间
one_cost_time = one_epoch_time - last_epoch_time
print(f"训练此轮需要的时间为:{one_cost_time}")
last_epoch_time = one_epoch_time
one_epoch_time = 0
end_time = time.time()
total_time = end_time - start_time
print(f"训练总计需要的时间为:{total_time}")
writer.close()
# 从本地拿出一张图片,看看模型的效果
test_image = Image.open("E:\\4_Data_sets\\others\\horse.jpg")
## 如果这个图片原本是png格式(有四个通道,RGBA,A为透明度),那么使用以下一行代码,只保留其RGB通道
#test_image = test_image.convert('RGB')
test_transforms = transforms.Resize([32,32])
test_image = test_transforms(test_image)
test_image_tensor = dataclass_transform(test_image)
print(test_image_tensor.shape)
test_image_tensor1 = torch.reshape(test_image_tensor, (1,3,32,32)) # 别忘记了!!!!!!!!
test_image_tensor1 = test_image_tensor1.to(device)
test_output = CIFAR10_NET_Instance(test_image_tensor1)
class_image = test_output.argmax(dim=1)
print(f"此图类别为:{class_image.item()}")
torch.save(CIFAR10_NET_Instance,"E:\\5_NN_model\\CIFAR10_NET_train10")
print("模型已保存!!")
运行结果:
Files already downloaded and verified
Files already downloaded and verified
50000 10000
----------------第 1 轮训练开始了----------------:
训练次数为:782, loss为:1.789782166481018
训练正确率为:37.5%
整体测试集上的LOSS为:255.33262872695923
训练此轮需要的时间为:19.126623153686523
----------------第 2 轮训练开始了----------------:
训练次数为:1564, loss为:1.5714988708496094
训练正确率为:43.75%
整体测试集上的LOSS为:198.84848326444626
训练此轮需要的时间为:14.118300914764404
----------------第 3 轮训练开始了----------------:
训练次数为:2346, loss为:1.2563223838806152
训练正确率为:56.25%
整体测试集上的LOSS为:174.16079074144363
训练此轮需要的时间为:14.806405305862427
----------------第 4 轮训练开始了----------------:
训练次数为:3128, loss为:1.1637380123138428
训练正确率为:50.0%
整体测试集上的LOSS为:156.08686345815659
训练此轮需要的时间为:14.412073135375977
----------------第 5 轮训练开始了----------------:
训练次数为:3910, loss为:0.8806682825088501
训练正确率为:62.5%
整体测试集上的LOSS为:155.79341107606888
训练此轮需要的时间为:14.46046495437622
----------------第 6 轮训练开始了----------------:
训练次数为:4692, loss为:0.6021975874900818
训练正确率为:81.25%
整体测试集上的LOSS为:159.8323387503624
训练此轮需要的时间为:14.461666107177734
----------------第 7 轮训练开始了----------------:
训练次数为:5474, loss为:0.6927397847175598
训练正确率为:75.0%
整体测试集上的LOSS为:171.83318477869034
训练此轮需要的时间为:14.535284042358398
----------------第 8 轮训练开始了----------------:
训练次数为:6256, loss为:0.40469425916671753
训练正确率为:87.5%
整体测试集上的LOSS为:178.93722027540207
训练此轮需要的时间为:18.05676531791687
----------------第 9 轮训练开始了----------------:
训练次数为:7038, loss为:0.6831881403923035
训练正确率为:68.75%
整体测试集上的LOSS为:184.60061931610107
训练此轮需要的时间为:15.902337789535522
----------------第 10 轮训练开始了----------------:
训练次数为:7820, loss为:0.2611675262451172
训练正确率为:93.75%
整体测试集上的LOSS为:196.9536812901497
训练此轮需要的时间为:14.7198965549469
----------------第 11 轮训练开始了----------------:
训练次数为:8602, loss为:0.38262906670570374
训练正确率为:81.25%
整体测试集上的LOSS为:185.48081707954407
训练此轮需要的时间为:14.651979684829712
----------------第 12 轮训练开始了----------------:
训练次数为:9384, loss为:0.12091360986232758
训练正确率为:93.75%
整体测试集上的LOSS为:198.3158984184265
训练此轮需要的时间为:14.581665277481079
----------------第 13 轮训练开始了----------------:
训练次数为:10166, loss为:0.2111598700284958
训练正确率为:93.75%
整体测试集上的LOSS为:225.97497355937958
训练此轮需要的时间为:14.554025411605835
----------------第 14 轮训练开始了----------------:
训练次数为:10948, loss为:0.13422876596450806
训练正确率为:100.0%
整体测试集上的LOSS为:221.3252665400505
训练此轮需要的时间为:14.511592149734497
----------------第 15 轮训练开始了----------------:
训练次数为:11730, loss为:0.18214434385299683
训练正确率为:93.75%
整体测试集上的LOSS为:214.04039084911346
训练此轮需要的时间为:14.598362445831299
训练总计需要的时间为:227.4974422454834
torch.Size([3, 32, 32])
此图类别为:7
模型已保存!!
Process finished with exit code 0
类别 7 是马。
上一篇 | 下一篇 |
---|---|
神经网络入门实战(十八) | 待发布 |