PyTorch clasificador imagen aprendizaje

PyTorch clasificador imagen aprendizaje

Sitio web de aprendizaje

http://pytorch123.com/SecondSection/neural_networks/

Un clasificador imagen Entrenamiento

Por la sección anterior, que ya sabemos cómo definir una red neuronal, así como el cálculo de la pérdida de su función, y el derecho a actualizar los pesos de la red
ahora, vamos a aprender cómo procesar los datos.
En general, cuando se procesa una imagen, texto, vídeo, datos de audio, utilizando el paquete estándar de Python para descargar los datos,
y se convierten en formato de matriz numpy. A continuación, convertirlos en matrices Formato "torch.Tensor"

  • Para la imagen, una almohada, OpenCV paquete
  • Para el audio, puede utilizar, paquete librosa scipy
  • Para el texto, que se puede utilizar Cyphon carga directamente o Python, o el uso de NLTK y SPACY

Para visión, PytorCh crear un paquete de "torchvision", que contiene un número de conjuntos de datos comunes, por ejemplo
IMAGEnet, CIFAR10, MNIST similares, así como algunos módulo de conversión de la imagen: torchvision.datasets, torch.utils.data.DataLoader
siguientes usos CIFAR10 ejemplos del conjunto de datos, la clasificación de imágenes:

CIFAR10: ‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’,‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’.
尺寸:3*32*32

Clasificación de imágenes generalmente se divide en los siguientes cinco pasos

  1. Uso torchvision cargado y normalizados conjuntos de entrenamiento y prueba de datos de CIFAR10
  2. La definición de una red neuronal de convolución
  3. Definir una función de pérdida
  4. entrenamiento de la red en los datos de entrenamiento
  5. Las pruebas en la red de datos muestra de prueba

1. Descargar y normalizados conjunto de datos CIFAR10

import torch
import torchvision
import torchvision.transforms as transforms

########################################################################
# torchvision加载的数据都是PILImage的数据类型,在[0, 1]之间
# 对上述类型的数据集进行归一化为[-1, 1]范围的tensors
# 归一化方法: (X-mean)/std
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) # mean, std
# 检验是否已经存在,若不存在,则下载数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
# 数据加载器,结合了数据集和取样器,并且可以提供多个线程处理数据集。
# 在训练模型时使用到此函数,用来把训练数据分成多个小组,此函数每次抛出一组数据。
# 直至把所有的数据都抛出。就是做一个数据的初始化。
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=0)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=0)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

Algunos de los datos de visualización de imágenes

########################################################################
# 显示数据集中的一些图像

import matplotlib.pyplot as plt
import numpy as np

def imshow(img):
    img = img / 2 + 0.5     # unnormalize, 因为前面是将图像进行了归一化,即 x = (X-0.5)/0.5
    npimg = img.numpy()
    image = np.transpose(npimg, (1, 2, 0))
    plt.imshow(image)    # 1 是和第二个轴交换,2,是和第2个轴交换,0是和第一个轴交换image[Height, Width, Dim]
    plt.show()

# get some random training images
dataiter = iter(trainloader)     # 使得 trainloader 变成迭代器
images, labels = dataiter.next()

# show images
imshow(torchvision.utils.make_grid(images))  # 将若干图像拼成一幅图像
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

2. Definir una red neuronal de convolución

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)   # 输出 6*28*28
        self.pool = nn.MaxPool2d(2, 2)    # 6*14*14
        self.conv2 = nn.Conv2d(6, 16, 5)  # 16*10*10
        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # conv2经过 pooling 后,变成 5*5 map, 所以 16*5*5个全连接神经元
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))   # 卷积 -> Relu -> Pool
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)             # view函数将张量x变形成一维的向量形式,作为全连接的输入
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

net = Net()

3. Definir la función de pérdida y un optimizador

import torch.optim as optim

criterion = nn.CrossEntropyLoss()  # 损失函数
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)  # 优化器 SGD with momentum

4. Red de Formación

for epoch in range(2):  # 训练集训练次数

    running_loss = 0.0
    # enumerate()用于可迭代\可遍历的数据对象组合为一个索引序列,
    # 同时列出数据和数据下标.上面代码的0表示从索引从0开始,
    for i, data in enumerate(trainloader, 0):
        # 获得输入
        inputs, labels = data
        # 初始化参数梯度
        optimizer.zero_grad()
        # 前馈 + 后馈 + 优化
        outputs = net(inputs)
        loss = criterion(outputs, labels)    # labels 会进行二值化,即[1 0 0 0 0 0 0 0 0]
        loss.backward()    # 梯度反向传播
        optimizer.step()   # 更新参数空间

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

Los datos de prueba establecidos en la estructura de red

Como ya se ha llevado a cabo dos ciclos de formación completa en el conjunto de entrenamiento, pero necesitamos comprobar si la red realmente aprendió algunas de las cosas. El método de prueba es el resultado del conjunto de datos de salida de red conectada a tierra verdad comparar.

  1. En primer lugar, muestran algunas imágenes
dataiter = iter(testloader)
images, labels = dataiter.next()
# 输出图像
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
print : 
GroundTruth:    cat  ship  ship plane
  1. Ver la salida de la red
outputs = net(images)
outputs
tensor([[-1.3145, -2.4341, -0.7362,  6.8300,  0.5993,  2.2841, -0.9894, -0.9424,
          1.3211, -3.0649],
        [ 4.2055,  8.5567, -2.8397, -2.3198, -3.1733, -4.6069, -8.4125, -2.9534,
         10.5395,  5.7375],
        [ 1.3612,  1.1350,  0.3872, -0.3729, -0.1908, -1.1665, -3.7862, -0.3712,
          3.3340, -0.1305],

salidas de cada categoría se predice valor energético de 10 tipos, es decir, cuanto mayor sea el valor de un cierto tipo de energía, que se considera que es el más grande es la probabilidad de la categoría. Por lo tanto, necesitamos el tipo de salidas correspondientes a la clase es la máxima energía.

_, predicted = torch.max(outputs, 1)   # predicted 对应的种类
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
                              for j in range(4)))
Predicted:    cat  ship  ship  ship
tensor([3, 8, 8, 8])

Desde la salida anterior para ver los resultados de las pruebas parecen buenas.
A continuación, nos fijamos en la formación de rendimiento de la red a través de 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))

Accuracy of the network on the 10000 test images: 55 %

Debido a que la probabilidad predicha de 10% (10 predicción de la clase de una clase), por lo que el 55% se ve mucho mejor que la predicción aleatoria, parece haber aprendido algunas cosas.
Ahora, vamos a echar un vistazo más de cerca, para predecir qué tipo de un poco mejor, que no es un buen rendimiento.

class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()   # 将shape中为1的维度去掉
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()   # 正确预测累计
            class_total[label] += 1               # 每一类的总数

for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))   # 每一类的准确率
Accuracy of plane : 52 %
Accuracy of   car : 70 %
Accuracy of  bird : 44 %
Accuracy of   cat : 28 %
Accuracy of  deer : 54 %
Accuracy of   dog : 41 %
Accuracy of  frog : 66 %
Accuracy of horse : 60 %
Accuracy of  ship : 65 %
Accuracy of truck : 68 %

6. Los datos de entrenamiento en la GPU

El entrenamiento de la red neuronal en la GPU, como la transferencia de un tensor como la GPU.
En primer lugar, vamos a definir nuestro dispositivo como el primer dispositivo CUDA visible.

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 如果程序运行在CUDA机器上,下面会输出一个device的id
print(device)
cuda:0

Después de que el conjunto, estos métodos de forma recursiva a través de todos los módulos y sus parámetros y tampones convierten tensores cuda de
las siguientes afirmaciones es esencial:

net.to(device)

Al mismo tiempo, cada paso debe ser enviada a las entradas y objetivos de una GPU.

 inputs, labels = inputs.to(device), labels.to(device)

Cuando la red es muy pequeña, sin sentir la tasa de cambio, se puede cambiar a una salida de la convolucional 128, 128 a la entrada de una convolución 2, el efecto observado. Más tarde cambió a 128, después de la tasa de formación de precisión de 2 veces

Accuracy of the network on the 10000 test images: 60 %

Los resultados parecen más características que la Fig. 6, en donde la figura mejor, la siguiente es la salida de cada clase

Accuracy of plane : 73 %
Accuracy of   car : 82 %
Accuracy of  bird : 27 %
Accuracy of   cat : 32 %
Accuracy of  deer : 53 %
Accuracy of   dog : 55 %
Accuracy of  frog : 75 %
Accuracy of horse : 76 %
Accuracy of  ship : 70 %
Accuracy of truck : 54 %

Nota:
habrá un cambio después de haber recibido la carrera GPU de la siguiente manera:

TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.

solución:

将 npimg = img.numpy() 改为
npimg = img.cpu().numpy()
Publicado 38 artículos originales · ganado elogios 29 · Vistas a 50000 +

Supongo que te gusta

Origin blog.csdn.net/ruotianxia/article/details/103547947
Recomendado
Clasificación