Neste artigo, vouche dicir como configurar un ambiente de aprendizaxe automática en 30 minutos, crear unha rede neuronal para o recoñecemento de imaxes e, a continuación, executar a mesma rede nun procesador gráfico (GPU).
En primeiro lugar, imos definir o que é unha rede neuronal.
No noso caso, este é un modelo matemático, así como a súa incorporación de software ou hardware, construído sobre o principio de organización e funcionamento das redes neuronais biolóxicas: redes de células nerviosas dun organismo vivo. Este concepto xurdiu mentres se estudaban os procesos que ocorren no cerebro e se trataba de modelar estes procesos.
As redes neuronais non están programadas no sentido habitual da palabra, están adestradas. A capacidade de aprender é unha das principais vantaxes das redes neuronais fronte aos algoritmos tradicionais. Tecnicamente, a aprendizaxe consiste en atopar os coeficientes de conexións entre neuronas. Durante o proceso de adestramento, a rede neuronal é capaz de identificar dependencias complexas entre os datos de entrada e os datos de saída, así como realizar a xeneralización.
Desde o punto de vista da aprendizaxe automática, unha rede neuronal é un caso especial de métodos de recoñecemento de patróns, análise discriminante, métodos de agrupación e outros métodos.
Оборудование
En primeiro lugar, vexamos o equipamento. Necesitamos un servidor co sistema operativo Linux instalado. O equipo necesario para operar sistemas de aprendizaxe automática é bastante potente e, como resultado, caro. Para aqueles que non teñan unha boa máquina á man, recoméndolles prestar atención ás ofertas dos provedores na nube. Podes alugar o servidor necesario rapidamente e pagar só polo tempo de uso.
En proxectos nos que é necesario crear redes neuronais, uso os servidores dun dos provedores de nube rusos. A compañía ofrece servidores na nube para alugar especificamente para a aprendizaxe automática con potentes procesadores gráficos (GPU) Tesla V100 de NVIDIA. En resumo: usar un servidor cunha GPU pode ser decenas de veces máis eficiente (rápido) en comparación cun servidor de custo similar que utiliza unha CPU (a coñecida unidade central de procesamento) para os cálculos. Isto conséguese debido ás características da arquitectura GPU, que afronta os cálculos máis rápido.
Para implementar os exemplos descritos a continuación, compramos o seguinte servidor durante varios días:
- Disco SSD de 150 GB
- RAM 32 GB
- Procesador Tesla V100 de 16 Gb con 4 núcleos
Instalamos Ubuntu 18.04 na nosa máquina.
Configurando o medio ambiente
Agora imos instalar todo o necesario para traballar no servidor. Dado que o noso artigo é principalmente para principiantes, falarei sobre algúns puntos que lles serán útiles.
Gran parte do traballo ao configurar un ambiente realízase a través da liña de comandos. A maioría dos usuarios usan Windows como o seu sistema operativo. A consola estándar deste sistema operativo deixa moito que desexar. Polo tanto, utilizaremos unha ferramenta conveniente
ssh root@server-ip-or-hostname
En lugar de server-ip-or-hostname, especifique o enderezo IP ou o nome DNS do seu servidor. A continuación, introduza o contrasinal e se a conexión se realiza correctamente, deberíamos recibir unha mensaxe semellante a esta.
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-74-generic x86_64)
A linguaxe principal para desenvolver modelos de ML é Python. E a plataforma máis popular para o seu uso en Linux é
Instalámolo no noso servidor.
Comezamos actualizando o xestor de paquetes local:
sudo apt-get update
Instalar curl (utilidade de liña de comandos):
sudo apt-get install curl
Descarga a última versión de Anaconda Distribution:
cd /tmp
curl –O https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh
Imos comezar a instalación:
bash Anaconda3-2019.10-Linux-x86_64.sh
Durante o proceso de instalación, pediráselle que confirme o acordo de licenza. Tras a instalación exitosa, deberías ver isto:
Thank you for installing Anaconda3!
Agora creáronse moitos frameworks para o desenvolvemento de modelos de ML; traballamos cos máis populares:
Usar o marco permítelle aumentar a velocidade de desenvolvemento e utilizar ferramentas preparadas para tarefas estándar.
Neste exemplo traballaremos con PyTorch. Instalémolo:
conda install pytorch torchvision cudatoolkit=10.1 -c pytorch
Agora necesitamos lanzar Jupyter Notebook, unha ferramenta de desenvolvemento popular para especialistas en ML. Permítelle escribir código e ver inmediatamente os resultados da súa execución. Jupyter Notebook está incluído con Anaconda e xa está instalado no noso servidor. Debes conectarte a el desde o noso sistema de escritorio.
Para iso, primeiro lanzaremos Jupyter no servidor especificando o porto 8080:
jupyter notebook --no-browser --port=8080 --allow-root
A continuación, abrindo outra pestana na nosa consola Cmder (menú superior - Cadro de diálogo Nova consola) conectarémonos a través do porto 8080 ao servidor mediante SSH:
ssh -L 8080:localhost:8080 root@server-ip-or-hostname
Cando introduzamos o primeiro comando, ofrecerémonos ligazóns para abrir Jupyter no noso navegador:
To access the notebook, open this file in a browser:
file:///root/.local/share/jupyter/runtime/nbserver-18788-open.html
Or copy and paste one of these URLs:
http://localhost:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
or http://127.0.0.1:8080/?token=cca0bd0b30857821194b9018a5394a4ed2322236f116d311
Usemos a ligazón para localhost:8080. Copia o camiño completo e pégao na barra de enderezos do navegador local do teu PC. Abrirase o Jupyter Notebook.
Imos crear un novo caderno: Novo - Caderno - Python 3.
Comprobamos o correcto funcionamento de todos os compoñentes que instalamos. Introduzamos o código PyTorch de exemplo en Jupyter e executemos a execución (botón Executar):
from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)
O resultado debería ser algo así:
Se tes un resultado semellante, configuramos todo correctamente e podemos comezar a desenvolver unha rede neuronal.
Creación dunha rede neuronal
Crearemos unha rede neuronal para o recoñecemento de imaxes. Tomemos isto como base
Usaremos o conxunto de datos CIFAR10 dispoñible para o público para adestrar a rede. Ten clases: “avión”, “coche”, “paxaro”, “gato”, “cervo”, “can”, “ra”, “cabalo”, “barco”, “camión”. As imaxes en CIFAR10 son 3x32x32, é dicir, imaxes en cor de 3 canles de 32x32 píxeles.
Para traballar, usaremos o paquete creado por PyTorch para traballar con imaxes - torchvision.
Faremos os seguintes pasos en orde:
- Carga e normalización de conxuntos de datos de adestramento e proba
- Definición da rede neuronal
- Formación en rede sobre datos de formación
- Probas de rede sobre datos de proba
- Repetimos o adestramento e as probas usando GPU
Imos executar todo o código a continuación en Jupyter Notebook.
Cargando e normalizando CIFAR10
Copia e executa o seguinte código en Jupyter:
import torch
import torchvision
import torchvision.transforms as transforms
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
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=2)
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=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
A resposta debe ser:
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
Extracting ./data/cifar-10-python.tar.gz to ./data
Files already downloaded and verified
Imos amosar varias imaxes de adestramento para probar:
import matplotlib.pyplot as plt
import numpy as np
# functions to show an image
def imshow(img):
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
# get some random training images
dataiter = iter(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)))
Definición da rede neuronal
Consideremos primeiro como funciona unha rede neuronal para o recoñecemento de imaxes. Esta é unha rede simple punto a punto. Toma datos de entrada, pásaos por varias capas unha por unha e, finalmente, produce datos de saída.
Imos crear unha rede similar no noso entorno:
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)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
Tamén definimos unha función de perda e un optimizador
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
Formación en rede sobre datos de formación
Comecemos a adestrar a nosa rede neuronal. Ten en conta que despois de executar este código, terás que esperar un tempo ata que remate o traballo. Levoume 5 minutos. Leva tempo adestrar a rede.
for epoch in range(2): # loop over the dataset multiple times
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
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')
Obtemos o seguinte resultado:
Gardamos o noso modelo adestrado:
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)
Probas de rede sobre datos de proba
Adestramos a rede utilizando un conxunto de datos de adestramento. Pero temos que comprobar se a rede aprendeu algo.
Probaremos isto predicindo a etiqueta de clase que saca a rede neuronal e probándoa para ver se é verdade. Se a predición é correcta, engadimos a mostra á lista de predicións correctas.
Imos mostrar unha imaxe do conxunto de probas:
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)))
Agora imos pedirlle á rede neuronal que nos diga o que hai nestas imaxes:
net = Net()
net.load_state_dict(torch.load(PATH))
outputs = net(images)
_, predicted = torch.max(outputs, 1)
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
for j in range(4)))
Os resultados parecen bastante bos: a rede identificou correctamente tres de cada catro imaxes.
Vexamos como funciona a rede en todo o conxunto 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))
Parece que a rede sabe algo e está funcionando. Se determinase as clases ao chou, a precisión sería do 10%.
Agora vexamos que clases identifica mellor a rede:
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()
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]))
Parece que a rede é a mellor para identificar coches e barcos: 71% de precisión.
Así que a rede está funcionando. Agora imos tentar transferir o seu traballo ao procesador gráfico (GPU) e ver que cambia.
Adestramento dunha rede neuronal en GPU
En primeiro lugar, explicarei brevemente o que é CUDA. CUDA (Compute Unified Device Architecture) é unha plataforma de computación paralela desenvolvida por NVIDIA para a computación xeral en unidades de procesamento de gráficos (GPU). Con CUDA, os desenvolvedores poden acelerar drasticamente as aplicacións informáticas aproveitando o poder das GPU. Esta plataforma xa está instalada no noso servidor que compramos.
Imos primeiro definir a nosa GPU como o primeiro dispositivo cuda visible.
device = torch . device ( "cuda:0" if torch . cuda . is_available () else "cpu" )
# Assuming that we are on a CUDA machine, this should print a CUDA device:
print ( device )
Envío da rede á GPU:
net.to(device)
Tamén teremos que enviar entradas e obxectivos en cada paso á GPU:
inputs, labels = data[0].to(device), data[1].to(device)
Volvemos adestrar a rede na GPU:
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(2): # loop over the dataset multiple times
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data[0].to(device), data[1].to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs)
loss = criterion(outputs, labels)
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')
Esta vez, o adestramento en rede durou uns 3 minutos. Lembremos que a mesma etapa nun procesador convencional duraba 5 minutos. A diferenza non é significativa, isto ocorre porque a nosa rede non é tan grande. Cando se usan grandes matrices para adestrar, a diferenza entre a velocidade da GPU e un procesador tradicional aumentará.
Iso parece ser todo. O que conseguimos facer:
- Observamos o que é unha GPU e seleccionamos o servidor no que está instalada;
- Configuramos un entorno de software para crear unha rede neuronal;
- Creamos unha rede neuronal para o recoñecemento de imaxes e adestramos;
- Repetimos o adestramento da rede usando a GPU e recibimos un aumento de velocidade.
Estarei encantado de responder ás preguntas nos comentarios.
Fonte: www.habr.com