étapes complètes
Préparer l'ensemble de données
DataLoader charger l'ensemble de données
Créer un modèle de réseau Créer
une instance de modèle de réseau
Définir la fonction de perte
Définir l'optimiseur Définir
les paramètres de formation du réseau
Démarrer la formation
Vérifier le modèle
Enregistrer le modèle
Visualiser les résultats de la formation (réalisés à l'aide du tensorboard)
Introduction à l'ensemble de données
CIFAR10 est un ensemble de données de vision par ordinateur collectées par les étudiants de Hinton Alex Krizhevsky et Ilya Sutskever pour la reconnaissance universelle d'objets. Il contient 60 000 images couleur 32 X 32 RVB, un total de 10 catégories. Parmi elles, 50 000 images sont utilisées pour l’ensemble de formation et 10 000 images sont utilisées pour l’ensemble de test.
Structure du modèle CIFAR
code complet
Structure du modèle de réseau CIFAR10 :
# model.py文件
# 搭建CIFAR10神经网络
import torch
from torch import nn
class Tudui(nn.Module):
def __init__(self):
super(Tudui, 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(1024, 64), # 1024=64*4*4
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
# 验证搭建的网络是否正确
if __name__ == '__main__':
tudui = Tudui()
input = torch.ones((64, 3, 32, 32))
output = tudui(input)
print(output.shape)
Code de formation de la version du processeur
# train.py文件
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from model import *
# 准备数据集
# 训练数据集
train_data = torchvision.datasets.CIFAR10(root="./dataset", train=True, download=False,
transform=torchvision.transforms.ToTensor())
# 测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=False,
transform=torchvision.transforms.ToTensor())
# 观察训练数据集、测试数据集中的图像有多少张
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size)) # 训练数据集的长度为:50000
print("测试数据集的长度为:{}".format(test_data_size)) # 测试数据集的长度为:10000
# 使用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64) # 训练数据集加载
test_dataloader = DataLoader(test_data, batch_size=64) # 测试数据集加载
# 创建网络模型
tudui = Tudui()
# 创建损失函数
# 分类问题采用交叉熵损失函数
loss_fn = nn.CrossEntropyLoss()
# 设定优化器
learning_rate = 0.01 # 0.01=1e-2
# learning_rate = 1e-2
optimizer = torch.optim.SGD(params=tudui.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter("./CIFAR10_train")
for i in range(epoch):
print("———————第{}轮训练开始——————".format(i+1))
# 训练步骤开始
for data in train_dataloader:
imgs, targets = data
outputs = tudui(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)
# 测试步骤
total_test_loss = 0
total_accuracy_num = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
outputs = tudui(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy_num = total_accuracy_num + accuracy
print("整体测试集上的Loss:{}".format(total_test_loss))
print("整体测试集上的正确率:{}".format(total_accuracy_num/test_data_size))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
writer.add_scalar(("test_accuracy", (total_accuracy_num/test_data_size), total_test_step))
total_test_step = total_test_step + 1
# 保存每轮运行的模型
torch.save(tudui, "tudui_{}.pth".format(i))
print("模型已保存!")
writer.close()
Version GPU_1
Cette méthode consiste à importer cuda dans le modèle de réseau, les données et la fonction de perte dans la version CPU.
Par exemple :
Pour le modèle réseau : dans la version CPU, il suffit de tudui = Tudui() lors de l'instanciation du réseau ; dans la version GPU_1, nous devons réécrire tudui = Tudui() en tudui = Tudui lors de l'instanciation du réseau. cuda().
Pour les données : dans la version CPU, les données que nous utilisons lors de la formation et des tests n'ont besoin que de
pour les données dans train_dataloader : # 训练 imgs, cibles = sorties de données = tudui(imgs)
pour les données dans test_dataloader : # 测试 imgs, cibles = sorties de données = tudui(imgs)
Ça y est ; alors que dans la version GPU_1, c'est :
pour les données dans train_dataloader : # 训练 imgs, cibles = data # 使用GPU imgs = imgs.cuda() cibles = cibles.cuda() sorties = tudui(imgs)
pour les données dans test_dataloader : # 测试 imgs, cibles = data # 使用GPU imgs = imgs.cuda() cibles = cibles.cuda() sorties = tudui(imgs)
Pour la fonction de perte : Dans la version CPU, la fonction de perte que nous utilisons n'a besoin que de
#Créer une fonction de perte # Le problème de classification utilise la fonction de perte d'entropie croisée loss_fn = nn.CrossEntropyLoss()
Ça y est ; et dans la version GPU_1, il y a :
#Créer une fonction de perte #Le problème de classification utilise la fonction de perte d'entropie croisée loss_fn = nn.CrossEntropyLoss() loss_fn = loss_fn.cuda() #Utiliser le GPU
Code de formation de la version GPU_1
# train_GPU_1.py文件
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
# 准备数据集
# 训练数据集
train_data = torchvision.datasets.CIFAR10(root="./dataset", train=True, download=False,
transform=torchvision.transforms.ToTensor())
# 测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=False,
transform=torchvision.transforms.ToTensor())
# 观察训练数据集、测试数据集中的图像有多少张
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size)) # 训练数据集的长度为:50000
print("测试数据集的长度为:{}".format(test_data_size)) # 测试数据集的长度为:10000
# 使用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64) # 训练数据集加载
test_dataloader = DataLoader(test_data, batch_size=64) # 测试数据集加载
# 创建网络模型
# 搭建CIFAR10神经网络
import torch
from torch import nn
class Tudui(nn.Module):
def __init__(self):
super(Tudui, 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(1024, 64), # 1024=64*4*4
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
tudui = Tudui()
tudui = tudui.cuda() # 使用GPU
# 创建损失函数
# 分类问题采用交叉熵损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.cuda() # 使用GPU
# 设定优化器
learning_rate = 0.01 # 0.01=1e-2
# learning_rate = 1e-2
optimizer = torch.optim.SGD(params=tudui.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter("./CIFAR10_train")
for i in range(epoch):
print("———————第{}轮训练开始——————".format(i+1))
# 训练步骤开始
for data in train_dataloader:
imgs, targets = data
# 使用GPU
imgs = imgs.cuda()
targets = targets.cuda()
outputs = tudui(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)
# 测试步骤
total_test_loss = 0
total_accuracy_num = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
# 使用GPU
imgs = imgs.cuda()
targets = targets.cuda()
outputs = tudui(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy_num = total_accuracy_num + accuracy
print("整体测试集上的Loss:{}".format(total_test_loss))
test_accuracy = total_accuracy_num/test_data_size # 测试准确率
print("整体测试集上的正确率:{}".format(test_accuracy))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
writer.add_scalar("test_accuracy", test_accuracy, total_test_step)
total_test_step = total_test_step + 1
# 保存每轮运行的模型
torch.save(tudui, "tudui_{}.pth".format(i))
print("模型已保存!")
writer.close()
Version GPU_2
Cette méthode consiste à utiliser la méthode to.(device) pour le modèle de réseau, les données et la fonction de perte dans la version CPU.
Par exemple :
nous devons d’abord définir le périphérique, c’est-à-dire device = torch.device("cpu") (version cpu) ou device = torch.device("cuda") (version GPU).
Pour le modèle réseau : dans la version CPU, il suffit d'instancier le réseau avec tudui = Tudui(); tandis que dans la version GPU_2, nous devons réécrire tudui = Tudui() lors de l'instanciation du réseau comme
tudui = Tudui() tudui.to(appareil)# utiliser le GPU
Pour les données : dans la version CPU, les données que nous utilisons lors de la formation et des tests n'ont besoin que de
pour les données dans train_dataloader : # 训练 imgs, cibles = sorties de données = tudui(imgs)
pour les données dans test_dataloader : # 测试 imgs, cibles = sorties de données = tudui(imgs)
et dans la version GPU_2, c'est :
pour les données dans train_dataloader : # fichiers imgs, cibles = données # processeur GPU imgs = imgs.to(device) cibles = cibles.to(device) sorties = tudui(imgs)
pour les données dans test_dataloader : # 测试 imgs, cibles = données # 使用GPU imgs = imgs.to(device) cibles = cibles.to(device) sorties = tudui(imgs)
Pour la fonction de perte : Dans la version CPU, la fonction de perte que nous utilisons n'a besoin que de
#Créer une fonction de perte # Le problème de classification utilise la fonction de perte d'entropie croisée loss_fn = nn.CrossEntropyLoss()
Ça y est ; et dans la version GPU_2, il y a :
# Créer une fonction de perte # Le problème de classification utilise la fonction de perte d'entropie croisée loss_fn = nn.CrossEntropyLoss() loss_fn.to(device) # Utiliser le GPU
Code de formation de la version GPU_2
# train_GPU_2.py文件
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
device = torch.device("cuda") # 定义训练设备
# 准备数据集
# 训练数据集
train_data = torchvision.datasets.CIFAR10(root="./dataset", train=True, download=False,
transform=torchvision.transforms.ToTensor())
# 测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset", train=False, download=False,
transform=torchvision.transforms.ToTensor())
# 观察训练数据集、测试数据集中的图像有多少张
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size)) # 训练数据集的长度为:50000
print("测试数据集的长度为:{}".format(test_data_size)) # 测试数据集的长度为:10000
# 使用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64) # 训练数据集加载
test_dataloader = DataLoader(test_data, batch_size=64) # 测试数据集加载
# 创建网络模型
# 搭建CIFAR10神经网络
import torch
from torch import nn
class Tudui(nn.Module):
def __init__(self):
super(Tudui, 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(1024, 64), # 1024=64*4*4
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
tudui = Tudui()
tudui.to(device)# 使用GPU
# 创建损失函数
# 分类问题采用交叉熵损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn.to(device) # 使用GPU
# 设定优化器
learning_rate = 0.01 # 0.01=1e-2
# learning_rate = 1e-2
optimizer = torch.optim.SGD(params=tudui.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter("./CIFAR10_train")
for i in range(epoch):
print("———————第{}轮训练开始——————".format(i+1))
# 训练步骤开始
for data in train_dataloader:
imgs, targets = data
# 使用GPU
imgs = imgs.to(device)
targets = targets.to(device)
outputs = tudui(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)
# 测试步骤
total_test_loss = 0
total_accuracy_num = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
# 使用GPU
imgs = imgs.to(device)
targets = targets.to(device)
outputs = tudui(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy_num = total_accuracy_num + accuracy
print("整体测试集上的Loss:{}".format(total_test_loss))
test_accuracy = total_accuracy_num/test_data_size # 测试准确率
print("整体测试集上的正确率:{}".format(test_accuracy))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
writer.add_scalar("test_accuracy", test_accuracy, total_test_step)
total_test_step = total_test_step + 1
# 保存每轮运行的模型
torch.save(tudui, "tudui_{}.pth".format(i))
print("模型已保存!")
writer.close()
Visualisation des résultats basée sur le tensorboard
Nous utilisons le code de la version GPU (les modes 1 et 2 sont tous deux disponibles) pour compléter le processus de formation à la visualisation Tensorboard et les résultats des tests.
Exécutez le code, vous obtiendrez un dossier CIFAR10_train dans le dossier du projet.
Merci à ce code ! ! écrivain = RésuméWriter("./CIFAR10_train")
Exécutez la commande dans Terminal : tensorboard --logdir=CIFAR10_train, obtenez l'URL suivante : http://localhost:6006/, ouvrez l'URL.
Obtenez le résultat de la visualisation, comme indiqué dans la figure ci-dessous.
Obtenez la perte de formation du modèle de réseau
Les résultats ci-dessus sont les résultats de 10 cycles de formation sur modèle !
Prédire le combat réel
Testons le modèle entraîné sur des images aléatoires pour voir comment il fonctionne.
Nous avons formé le réseau sur l'ensemble de données d'entraînement pendant 30 tours et avons constaté que le modèle formé au 30ème tour était meilleur et que le taux correct du modèle sur l'ensemble de test atteignait 64,56 %, nous avons donc utilisé le modèle au 30ème tour. pour vérifier des images aléatoires.
Nous sélectionnons au hasard une photo d'un chien, une photo d'un avion et une photo d'un chat sur Internet, comme le montre la figure ci-dessous.
Enregistrez ces trois images dans le dossier images du dossier du projet, comme indiqué dans l'image ci-dessous.
Montrez ces trois images dans pycharm.
Dix étiquettes de vérité terrain de catégorie.
Vérifier le code du chien
import torch
import torchvision.transforms
from PIL import Image
from torch import nn
img_path = "./images/dog.png" # .表示当前目录
image = Image.open(img_path)
# print(image) # <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=405x303 at 0x2834CC62F48>
image = image.convert("RGB") # 该代码的作用:
# 因为png格式的图片是四个通道,除了RGB三通道外,还有一个透明度通道。
# 所以我们调用image = image.convert("RGB"),保留其颜色通道。
# print(image) # <PIL.Image.Image image mode=RGB size=405x303 at 0x2834CD7AB88>
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
torchvision.transforms.ToTensor()])
image = transform(image)
# print(image.size)
# CIFAR10网络模型结构
class Tudui(nn.Module):
def __init__(self):
super(Tudui, 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(1024, 64), # 1024=64*4*4
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
# 加载网络模型参数
model = torch.load("tudui_29.pth", map_location=torch.device("cpu"))
# map_location=torch.device("cpu") 将GPU版本的模型对应到CPU上
# print(model)
image = torch.reshape(image, (1, 3, 32, 32))
model.eval()
with torch.no_grad():
output = model(image)
print(output) # tensor([[ -3.3239, -5.6744, 5.5848, 3.1388, 4.8541, 13.1417, -3.0066, 4.5897, -14.3501, -7.2900]])
print(output.argmax(1)) # tensor([5]) 标签5对应的是狗
Vérification réussie !
Vérifier le code de l'avion
import torch
import torchvision.transforms
from PIL import Image
from torch import nn
img_path = "./images/plane.png" # .表示当前目录
image = Image.open(img_path)
# print(image) # <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=405x303 at 0x2834CC62F48>
image = image.convert("RGB") # 该代码的作用:
# 因为png格式的图片是四个通道,除了RGB三通道外,还有一个透明度通道。
# 所以我们调用image = image.convert("RGB"),保留其颜色通道。
# print(image) # <PIL.Image.Image image mode=RGB size=405x303 at 0x2834CD7AB88>
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
torchvision.transforms.ToTensor()])
image = transform(image)
# print(image.size)
# CIFAR10网络模型结构
class Tudui(nn.Module):
def __init__(self):
super(Tudui, 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(1024, 64), # 1024=64*4*4
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
# 加载网络模型参数
model = torch.load("tudui_29.pth", map_location=torch.device("cpu"))
# map_location=torch.device("cpu") 将GPU版本的模型对应到CPU上
# print(model)
image = torch.reshape(image, (1, 3, 32, 32))
model.eval()
with torch.no_grad():
output = model(image)
print(output) # tensor([[10.6781, -2.0109, 4.5609, 1.3858, -1.3748, -1.3599, 3.4883, -7.2311, -3.5088, -3.3030]])
print(output.argmax(1)) # tensor([0]) 标签0对应的是飞机
Vérification réussie !
Vérifier le code du chat
import torch
import torchvision.transforms
from PIL import Image
from torch import nn
img_path = "./images/cat.png" # .表示当前目录
image = Image.open(img_path)
# print(image) # <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=405x303 at 0x2834CC62F48>
image = image.convert("RGB") # 该代码的作用:
# 因为png格式的图片是四个通道,除了RGB三通道外,还有一个透明度通道。
# 所以我们调用image = image.convert("RGB"),保留其颜色通道。
# print(image) # <PIL.Image.Image image mode=RGB size=405x303 at 0x2834CD7AB88>
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
torchvision.transforms.ToTensor()])
image = transform(image)
# print(image.size)
# CIFAR10网络模型结构
class Tudui(nn.Module):
def __init__(self):
super(Tudui, 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(1024, 64), # 1024=64*4*4
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
# 加载网络模型参数
model = torch.load("tudui_29.pth", map_location=torch.device("cpu"))
# map_location=torch.device("cpu") 将GPU版本的模型对应到CPU上
# print(model)
image = torch.reshape(image, (1, 3, 32, 32))
model.eval()
with torch.no_grad():
output = model(image)
print(output) # tensor([[-1.4196, -5.0211, 1.2063, 4.8532, -2.0156, 2.7169, 0.4598, 0.5168, -0.3567, -0.8418]])
print(output.argmax(1)) # tensor([3]) 标签3对应的是猫
Vérification réussie !
Bien que le taux correct du modèle entraîné pendant 30 tours sur l'ensemble de test ne soit que de 64,56 %, nous pouvons voir grâce à une vérification aléatoire que l'effet du modèle est toujours très bon. Nous n'avons vérifié que trois photos, bien sûr, nous pouvons également vérifier plus de photos.