Pytorch Primeros pasos Notas 04

entrenar un clasificador

Aquí has ​​visto cómo definir una red neuronal, calcular la pérdida y actualizar los pesos de la red. ahora podrías estar pensando

¿Qué son los datos?

En general, cuando se trata de datos de imagen, texto, audio o video, puede usar paquetes estándar de Python para cargar los datos en matrices numpy. Luego puede convertir esta matriz en antorcha. * Tensor.

  • Para imágenes, puede usar Pillow, OpenCV
  • Para audio, puedes usar scipy y librosa
  • Para el texto, use Python o Cython sin formato o NLTK y SpaCy

Especialmente para la visión, creamos un paquete llamado torchvision, que tiene cargadores de datos para conjuntos de datos públicos, como ImageNet, CIRFAR10, MNIST, etc. Imagen a datos. torchvision.datasets y torch.utils.data.DataLoader.

Esto proporciona una gran comodidad y evita escribir código repetitivo.

Para este tutorial, usamos el conjunto de datos CIFAR10. Tiene categorías: 'avión', 'automóvil', 'pájaro', 'gato', 'venado', 'perro', 'rana', 'caballo', 'barco', 'camión'. La imagen de CIFAR10 es 3 * 32 * 32

Por favor agregue una descripción de la imagen

entrenar un clasificador de imágenes

Realizaremos los siguientes pasos:

  1. Cargue y normalice los conjuntos de datos de prueba y entrenamiento de CIFAR10 con torchvision
  2. Definir una red neuronal convolucional
  3. definir una función de pérdida
  4. Entrenar la red en el conjunto de entrenamiento
  5. Probar la red en el equipo de prueba

Cargar y normalizar CIFAR10

Usando torchvision, cargar CIFAR10 es muy simple

import torch
import torchvision
import torchvision.transforms as transforms

El conjunto de datos de salida de torchvision es un PILImage en el rango [0,1]. Los convertimos al rango estándar [-1,1] para tensores.

**Nota:** Si hay un BrokenPipeError en la plataforma de Windows, establezca num_worker en torch.utils.data.DataLoader() en 0

import matplotlib.pyplot as plt
import numpy as np

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]
)

batch_size = 4
trainset = torchvision.datasets.CIFAR10(root='./cifar10',
                                        train=True,
                                        download=True,
                                        transform=transform)
trainloader = Data.DataLoader(trainset,
                              batch_size=batch_size,
                              shuffle=True,
                              num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./cifar10', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,
                                         shuffle=False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

afuera:

Descargando https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz a ./cifar10\cifar-10-python.tar.gz
170500096it [02:27, 1156941.89it/s]

Muestra algunas imágenes del entrenamiento.

Por favor agregue una descripción de la imagen

afuera:

Archivos ya descargados y verificados
perro barco avión barco

Definir una red neuronal convolucional

Copie la red neuronal del capítulo de redes neuronales y modifíquela para obtener una imagen de 3 canales.

import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 单通道图像输入, 输出6通道, 5x5 卷积核
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2,2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # 一个仿射变换操作(Affine) : y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120) # 5*5 来自图像的维度
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
    def forward(self, x):
        # Max池化,窗口为(2,2)
        x = self.pool(F.relu(self.conv1(x)))
        # 如果尺寸是正方形, 你可以用一个数字来指定
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x, 1) # 批处理除外,所有数据降维展平,意思就是二维图像转成一行数组。
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    net = Net()

Definir la función de pérdida y el optimizador

Usamos error de entropía cruzada y SGD con impulso

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

red de formación

Aquí es donde se pone interesante, recorremos el iterador de datos, alimentamos los datos a la red y optimizamos.

for epoch in range(2):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # 获取输入;数据是一个list类型的[inputs, labels]
        inputs, labels = data

        # 梯度参数设为0
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # 打印统计数据
        running_loss += loss.item()
        if i % 2000 == 1999:
            print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
print('Finished Training')

afuera:

[1, 2000] pérdida: 2,211
[1, 4000] pérdida: 1,825
[1, 6000] pérdida: 1,648
[1, 8000] pérdida: 1,562
[1, 10000] pérdida: 1,504
[1, 12000] pérdida: 1,448
[2 , 2000] pérdida: 1,397
[2, 4000] pérdida: 1,353
[2, 6000] pérdida: 1,341
[2, 8000] pérdida: 1,313
[2, 10000] pérdida: 1,270
[2, 12000] pérdida: 1,280
Entrenamiento terminado

Guardemos rápidamente nuestro modelo entrenado

PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

Probar la red en el equipo de prueba

Entrenamos la red 2 veces en el conjunto de datos de entrenamiento. Pero tenemos que comprobar que la red ha aprendido todo. Verificaremos esto prediciendo las etiquetas de clase generadas por la red neuronal y validándolas contra la verdad básica. Si la predicción es correcta, agregamos esa muestra a la lista de predicciones correctas.

El primer paso es mostrar una imagen del conjunto de prueba

dataiter = iter(testloader)
images, labels = dataiter.next()

# print images
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

Por favor agregue una descripción de la imagen

afuera:

GroundTruth: gato barco barco avión

A continuación, cargamos el modelo previamente guardado (nota: no es necesario guardar y volver a cargar el modelo aquí, lo hacemos solo para ilustrar cómo hacerlo)

net = Net()
net.load_state_dict(torch.load(PATH))

Ahora veamos cómo ve la red neuronal los ejemplos anteriores:

outputs = net(images)

La salida es la energía de 10 clases. Cuanto mayor sea la energía de una clase, más pensará la red que la imagen pertenece a esta clase. Entonces, obtengamos el índice de mayor energía:

_, predicted = torch.max(outputs, 1)
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))

afuera:

Predicted:   frog  ship  ship  ship

Vea cómo funciona la red en todo el conjunto de datos

correct = 0
total = 0
# 由于我们没有训练,我们不需要为我们的输出计算梯度
with torch.no_grad():
    for data in testloader:
        images, labels = data        
        # 图像通过网络计算输出        
        outputs = net(images)        
        # 我们选择能量最高的类型作为预测        _, 
        _, predicted = torch.max(outputs.data, 1)        
        total += labels.size(0)        
        correct += (predicted == labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

afuera:

Precisión de la red en las 10000 imágenes de prueba: 54 %

Esto se ve mucho mejor que probabilístico (10% de precisión) (elegir al azar un tipo de 10). Parece que la red ha aprendido algo.

Hmmm, qué tipos funcionan bien y qué tipos no.

# 对每个类型准备计数
correct_pred = {
    
    classname: 0 for classname in classes}
total_pred = {
    
    classname: 0 for classname in classes}
# 不需要梯度
with torch.no_grad():
    for data in testloader:        
    images, labels = data        
    outputs = net(images)        
    _, predictions = torch.max(outputs, 1)       
    # 对每一个类型预测正确解收集        
    for label, prediction in zip(labels, predictions):            
    	if label == prediction:                
    	correct_pred[classes[label]] += 1            
    	total_pred[classes[label]] += 1
# 打印每个类型的准确率
for classname, correct_count in correct_pred.items():
    accuracy = 100 * float(correct_count) / total_pred[classname]    
    print("Accuracy for class {:5s} is: {:.1f} %".format(classname,                                                   accuracy))

afuera:

La precisión para la clase avión es: 60,1 %
La precisión para la clase coche es: 69,8 %
La precisión para la clase pájaro es: 45,2 %
La precisión para la clase gato es: 26,4 % La
precisión para la clase ciervo es: 30,5 % La
precisión para la clase perro es: 60,4 % La
precisión para la clase rana es: 70,7 %
La precisión para la clase caballo es: 69,5 %
La precisión para la clase barco es: 53,3 %
La precisión para la clase camión es: 61,0 %

entrenar en GPU

Al igual que coloca tensores en la GPU, coloque la red neuronal en la GPU.

Primero defina nuestro dispositivo como cuda primero visible, si cuda está disponible:

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")# 假设我们在CUDA机器,这里应该打印CUDA设备print(device)

afuera:

cuda:0

Estos métodos luego pasarán recursivamente por todos los módulos y convertirán sus argumentos y búferes en tensores CUDA:

net.to(device)

Recuerde que también envía la entrada y el destino a la GPU en cada paso

inputs, labels = data[0].to(device), data[1].to(device)

¿Por qué no hay énfasis en la aceleración de MASSIVE en comparación con la CPU? Porque su red es demasiado pequeña.

Supongo que te gusta

Origin blog.csdn.net/qq_36571422/article/details/120752795
Recomendado
Clasificación