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