image

Acesse bootcamps ilimitados e +650 cursos

50
%OFF
Article image
Ubiratan Tavares
Ubiratan Tavares20/10/2023 17:32
Compartilhe

Visão Geral de Algumas Bibliotecas de Aprendizagem Profundo

  • #Python
  • #Keras
  • #Tensorflow

1 - INTRODUÇÃO

O aprendizado de máquina é um tópico amplo. O aprendizado profundo, em particular, é uma forma de usar redes neurais para aprendizado de máquina. Uma rede neural é provavelmente um conceito mais antigo que o aprendizado de máquina, que remonta à década de 1950. Não é novidade que muitas bibliotecas foram criadas para isso.

O objetivo a seguir é dar uma visão geral de algumas das famosas bibliotecas para redes neurais e aprendizado profundo.

2 - BIBLIOTECAS C++

O aprendizado profundo ganhou atenção na última década. Antes disso, havia pouca confiança em como treinar uma rede neural com muitas camadas. No entanto, a compreensão de como construir um perceptron multicamadas já existia há muitos anos.

Antes de termos aprendizado profundo, provavelmente a biblioteca de redes neurais mais famosa era a biblioteca libann (consulte [1]). É uma biblioteca para C++ e a funcionalidade é limitada devido à sua idade. Esta biblioteca parou de ser desenvolvida desde 2004.

Uma biblioteca mais recente para C++ é OpenNN (consulte [2]), que permite sintaxe C++ moderna.

Mas isso é tudo para C++. A sintaxe rígida do C++ pode ser o motivo pelo qual não temos muitas bibliotecas para aprendizado profundo. A fase de treinamento de um projeto de aprendizagem profunda é sobre experimentos. Queremos algumas ferramentas que nos permitam iterar mais rapidamente. Portanto, uma linguagem de programação dinâmica poderia ser uma opção melhor. Portanto, você vê o Python entrar em cena.

3 - BIBLIOTECAS PYTHON

Uma das primeiras bibliotecas para aprendizagem profunda é a Caffe (Consulte [3]). Foi desenvolvido na UC Berkeley especificamente para problemas de visão computacional. Embora seja desenvolvido em C++, serve como uma biblioteca com interface Python. Portanto, podemos construir nosso projeto em Python com a rede definida em uma sintaxe semelhante a JSON.

Chainer (Consulte [4]) é outra biblioteca em Python. É influente porque a sintaxe faz muito sentido. Embora seja menos comum hoje em dia, a API em Keras (Consulte [5]) e PyTorch (Consulte [6]) tem uma semelhança com o Chainer.

A outra biblioteca obsoleta é Theano (Consulte [7]). Ele cessou o desenvolvimento, mas já foi uma importante biblioteca para aprendizado profundo. A versão anterior da biblioteca Keras permite escolher entre um back-end Theano ou TensorFlow (consulte [8]). Na verdade, nem Theano nem TensorFlow são exatamente bibliotecas de aprendizado profundo. Em vez disso, são bibliotecas de tensores que tornam as operações de matriz e a diferenciação úteis, sobre as quais as operações de aprendizagem profunda podem ser construídas. Conseqüentemente, esses dois são considerados substitutos um do outro na perspectiva Keras.

CNTK (Consulte [9]) da Microsoft e Apache MXNet (Consulte [10]) são duas outras bibliotecas que valem a pena mencionar. Eles são grandes, com interfaces para vários idiomas. Python, claro, é um deles. CNTK possui interfaces C# e C++, enquanto MXNet fornece interfaces para Java, Scala, R, Julia, C++, Clojure e Perl. Mas recentemente, a Microsoft decidiu parar de desenvolver o CNTK. MXNet tem algum impulso e é provavelmente a biblioteca mais popular depois do TensorFlow e do PyTorch.

4 - BIBLIOTECAS PyTorch E TensorFlow

PyTorch e TensorFlow são as duas principais bibliotecas da atualidade. No passado, quando o TensorFlow estava na versão 1.x, eles eram muito diferentes. Mas como o TensorFlow absorveu Keras como parte de sua biblioteca, essas duas bibliotecas funcionam principalmente de maneira semelhante.

PyTorch é apoiado pelo Facebook e sua sintaxe tem se mantido estável ao longo dos anos. Existem também muitos modelos existentes que podemos emprestar. A maneira comum de definir um modelo de aprendizado profundo no PyTorch é criar uma classe:

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

class Model(nn.Module):
def __init__(self):
  super().__init__()
  self.conv1 = nn.Conv2d(1, 6, kernel_size=(5,5), stride=1, padding=2)
  self.pool1 = nn.AvgPool2d(kernel_size=2, stride=2)
  self.conv2 = nn.Conv2d(6, 16, kernel_size=5, stride=1, padding=0)
  self.pool2 = nn.AvgPool2d(kernel_size=2, stride=2)
  self.conv3 = nn.Conv2d(16, 120, kernel_size=5, stride=1, padding=0)
  self.flatten = nn.Flatten()
  self.linear4 = nn.Linear(120, 84)
  self.linear5 = nn.Linear(84, 10)
  self.softmax = nn.LogSoftMax(dim=1)

def forward(self, x):
  x = F.tanh(self.conv1(x))
  x = self.pool1(x)
  x = F.tanh(self.conv2(x))
  x = self.pool2(x)
  x = F.tanh(self.conv3(x))
  x = self.flatten(x)
  x = F.tanh(self.linear4(x))
  x = self.linear5(x)
  return self.softmax(x)

model = Model()

Mas também existe uma sintaxe sequencial para tornar o código mais conciso:

import torch
import torch.nn as nn

model = nn.Sequential(
# assume input 1x28x28
nn.Conv2d(1, 6, kernel_size=(5,5), stride=1, padding=2),
nn.Tanh(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(6, 16, kernel_size=5, stride=1, padding=0),
nn.Tanh(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(16, 120, kernel_size=5, stride=1, padding=0),
nn.Tanh(),
nn.Flatten(),
nn.Linear(120, 84),
nn.Tanh(),
nn.Linear(84, 10),
nn.LogSoftmax(dim=1)
)

O TensorFlow na versão 2.x adotou Keras como parte de suas bibliotecas. No passado, esses dois eram projetos separados. No TensorFlow 1.x, precisamos construir um gráfico de computação, configurar uma sessão e derivar gradientes de uma sessão para o modelo de aprendizado profundo. Portanto, é um pouco detalhado. Keras foi projetado como uma biblioteca para ocultar todos esses detalhes de baixo nível.

A mesma rede acima pode ser produzida pela sintaxe Keras do TensorFlow da seguinte forma:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Dense, AveragePooling2D, Flatten

model = Sequential([
Conv2D(6, (5,5), input_shape=(28,28,1), padding="same", activation="tanh"),
AveragePooling2D((2,2), strides=2),
Conv2D(16, (5,5), activation="tanh"),
AveragePooling2D((2,2), strides=2),
Conv2D(120, (5,5), activation="tanh"),
Flatten(),
Dense(84, activation="tanh"),
Dense(10, activation="softmax")
])

Uma grande diferença entre a sintaxe PyTorch e Keras está no loop de treinamento. No Keras, precisamos apenas atribuir a função de perda, o algoritmo de otimização, o conjunto de dados e alguns outros parâmetros ao modelo. Então temos uma função fit() para fazer todo o trabalho de treinamento, como segue:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Dense, AveragePooling2D, Flatten
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical

(X_train, y_train), (X_test, y_test) = mnist.load_data()
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

model = Sequential([
Conv2D(6, (5,5), input_shape=(28,28,1), padding="same", activation="tanh"),
AveragePooling2D((2,2), strides=2),
Conv2D(16, (5,5), activation="tanh"),
AveragePooling2D((2,2), strides=2),
Conv2D(120, (5,5), activation="tanh"),
Flatten(),
Dense(84, activation="tanh"),
Dense(10, activation="softmax")
])

model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=100, batch_size=32)

Mas no PyTorch, precisamos escrever nosso próprio código de loop de treinamento, como segue:

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision

# Load MNIST data
transform = torchvision.transforms.Compose([
torchvision.transforms.ToTensor(), # required, otherwise MNIST are in PIL format
#torchvision.transforms.Normalize((0.5,), (0.5,)),
])
train = torchvision.datasets.MNIST('./datafiles/', train=True, download=True, transform=transform)
test = torchvision.datasets.MNIST('./datafiles/', train=True, download=True, transform=transform)

# For manual feed into the model
X_train = train.data.reshape(-1,1,28,28)
y_train = train.targets
X_test = test.data.reshape(-1,1,28,28)
y_test = test.targets

# As iterator for data and target
train_loader = torch.utils.data.DataLoader(train, batch_size=32, shuffle=True)
test_loader = torch.utils.data.DataLoader(test, batch_size=32, shuffle=True)

# Neural network model
model = nn.Sequential(
# assume input 1x28x28
nn.Conv2d(1, 6, kernel_size=(5,5), stride=1, padding=2),
nn.Tanh(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(6, 16, kernel_size=5, stride=1, padding=0),
nn.Tanh(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(16, 120, kernel_size=5, stride=1, padding=0),
nn.Tanh(),
nn.Flatten(),
nn.Linear(120, 84),
nn.Tanh(),
nn.Linear(84, 10),
nn.LogSoftmax(dim=1)
)

# self-defined training loop function
def training_loop(model, optimizer, loss_fn, train_loader, val_loader=None, n_epochs=100):
best_loss, best_epoch = np.inf, -1
best_state = model.state_dict()

for epoch in range(n_epochs):
  # Training
  model.train()
  train_loss = 0
  for data, target in train_loader:
    output = model(data)
    loss = loss_fn(output, target)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    train_loss += loss.item()
  # Validation
  model.eval()
  status = (f"{str(datetime.datetime.now())} End of epoch {epoch}, "
       f"training loss={train_loss/len(train_loader)}")
  if val_loader:
    val_loss = 0
    for data, target in val_loader:
      output = model(data)
      loss = loss_fn(output, target)
      val_loss += loss.item()
    status += f", validation loss={val_loss/len(val_loader)}"
  print(status)

optimizer = optim.Adam(model.parameters())
criterion = nn.NLLLoss()
training_loop(model, optimizer, criterion, train_loader, test_loader, n_epochs=100)

Isso pode não ser um problema se você estiver experimentando um novo design de rede no qual deseja ter mais controle sobre como a perda é calculada e como o otimizador atualiza os pesos do modelo. Caso contrário, você apreciará a sintaxe mais simples do Keras.

Observe que PyTorch e TensorFlow são bibliotecas com interface Python. Portanto, é possível ter interface para outras linguagens também. Por exemplo, existem Torch for R (Consulte [11]) e TensorFlow for R (Consulte [12]).

Além disso, observe que as bibliotecas mencionadas acima são bibliotecas completas que incluem treinamento e previsão. Se você considerar um ambiente de produção onde você faz uso de um modelo treinado, poderá haver uma escolha mais ampla. O TensorFlow possui uma contraparte denominada “TensorFlow Lite” que permite que um modelo treinado seja executado em um dispositivo móvel ou na web.

5 - REFERÊNCIAS

  1. libann
  2. OpenNN
  3. Caffe
  4. Chainer
  5. Keras
  6. PyTorch
  7. Theano
  8. TensorFlow
  9. CNTK
  10. MXNet
  11. Torch for R
  12. TensorFlow for R
Compartilhe
Recomendados para você
Suzano - Python Developer
BairesDev - Machine Learning Practitioner
Santander - Cibersegurança #2
Comentários (1)
Carlos Lima
Carlos Lima - 07/04/2024 01:25

Ubiratan Tavares, ótimo post! Gosto da forma como teve a preocupação de mostrar a implementação do PyTorch, por exemplo. Inclusive, uma ferramenta que considero indispensável nos dias de hoje é o fast.ai, especialmente porque foi desenvolvida no topo do PyTorch, tornando a implementação e o uso de redes neurais muito mais simples do que começar do zero (para algumas situações, não tem jeito haha).