完整实操之:CIFAR10数据集的训练与测试

CIFAR10数据集,有50000张训练图片,有10000张测试图片

下方代码中:

  • 训练轮次为 10 轮;
  • batch_size = 6450000/64 = 782(向上取整) ,所以训练一轮就等于训练了 782batch_size 的图片,10 轮就是 7820
  • 最终运行结果展示两个部分:
    • 画出 782batch_size10 轮训练损失减小情况,整合成一条曲线,10 轮总共 7820 个;
    • 画出第一个 batch_size10 轮训练损失减小情况。
  • 最终将训练好的模型保存在本地,命名为 CIFAR10_NET_train10train10 表示经过了 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 是马。


上一篇 下一篇
神经网络入门实战(十八) 待发布
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐