Quin és el millor framework per programar el Deep Learning? TensorFlow o PyTorch?

english transtation AUTOMATIC ENGLISH TRANSLATION

Traduccion automatica espanolTRADUCCIÓN AUTOMÁTICA AL CASTELLANO

Un dia un alumne em va  preguntar Quin és el millor framework per programar una xarxa neuronal? ¿TensorFlow o PyTorch?. La meva resposta va ser  És igual, no t’hi enmoinis, tu comença amb qualsevol dels dos, no és important quin triïs, l’important es començar, vinga!

Els passos a seguir per programar una xarxa neuronal en ambdós entorns són els habituals en Machine Learning: Import required libraries, Load and Preprocess the Data, Define the Model, Define the Optimizer and the Loss function, Train the Model  i finalment Evaluate the Model.

I aquests passos es poden implementar de manera molt similar en qualsevol dels dos framewors. Anem a seguir-los alhora un per un per construir un model de xarxa neuronal que classifica dígits escrits a ma tant amb l’API de PyTorch com amb l’API Keras de TensorFlow. El codi sencer es pot provar en el GitHub per a que es pugui executar com a notebook en colab de google.

Passos per programar una xarxa neuronal

0. Import required libraries

En ambdós codis hem d’importar primer algunes llibreries de Python i aprofitem per definir els hiperparàmetres que necessitarem per a l’entrenament:

import numpy as np
import matplotlib.pyplot as plt
epochs = 10
batch_size=64

En el cas de TensorFlow cal només aquesta llibreria:

import tensorflow as tf

Mentre que en el cas de PyTorch aquestes dues:

import torch
import torchvision

1.  Load and Preprocessing Data

El carregar i preparar les dades amb TensorFlow es pot fer amb aquestes dues línies de codi:

(x_trainTF_, y_trainTF_), _ = tf.keras.datasets.mnist.load_data()
x_trainTF = x_trainTF_.reshape(60000, 784).astype('float32')/255
y_trainTF = tf.keras.utils.to_categorical(y_trainTF_, num_classes=10)

Mentre que en PyTorch amb aquestes altres dues:

xy_trainPT = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor()]))
xy_trainPT_loader = torch.utils.data.DataLoader(xy_trainPT, batch_size=batch_size)

Podem comprovar que han carregat les mateixes dades amb la llibreria matplotlib.pyplot :

print("TensorFlow:")
fig = plt.figure(figsize=(25, 4))
for idx in np.arange(20):
   ax = fig.add_subplot(2, 20/2, idx+1, xticks=[], yticks=[])
   ax.imshow(x_trainTF_[idx], cmap=plt.cm.binary)
   ax.set_title(str(y_trainTF_[idx]))

print("PyTorch:")
fig = plt.figure(figsize=(25, 4)) 
for idx in np.arange(20):
   ax = fig.add_subplot(2, 20/2, idx+1, xticks=[], yticks=[])
   ax.imshow(torch.squeeze(image, dim = 0).numpy(), cmap=plt.cm.binary)
   image, label = xy_trainPT [idx]
   ax.set_title(str(label))

2. Define Model

Per definir el model en els dos casos es fa amb una sintaxi força semblant. En el cas de TensorFlow amb el següent codi:

modelTF = tf.keras.Sequential([
          tf.keras.layers.Dense(10,activation='sigmoid',input_shape=(784,)),
          tf.keras.layers.Dense(10,activation='softmax')
])

I en PyTorch amb aquest:

modelPT= torch.nn.Sequential(
         torch.nn.Linear(784,10),torch.nn.Sigmoid(),    
         torch.nn.Linear(10,10), torch.nn.LogSoftmax(dim=1)
)

3. Define the Optimizer and the Loss function

Novament la forma d’especificar l’optimitzador i la funció de pèrdua és força equivalent. Amb TensorFlow ho podem fer així:

modelTF.compile(
               loss="categorical_crossentropy",
               optimizer=tf.optimizers.SGD(lr=0.01),
               metrics = ['accuracy']
)

Mentre que amb PyTorch així:

criterion = torch.nn.NLLLoss()
optimizer = torch.optim.SGD(modelPT.parameters(), lr=0.01)

4. Train the model

Pel que fa a l’entrenament es on trobem majors diferències. En el cas de TensorFlow ho farem així:

_ = modelTF.fit(x_trainTF, y_trainTF, epochs=epochs, batch_size=batch_size, verbose = 0)

Mentre que en Pytorch així:

for e in range(epochs):
    for images, labels in xy_trainPT_loader:
        images = images.view(images.shape[0], -1)
        loss = criterion(modelPT(images), labels)
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

En PyTorch no hi ha una funció d’ajust de model a les dades “prefabricada” com fit() en el cas de Keras o Scikit-learn, de manera que el bucle d’entrenament s’ha d’especificar pel programador o programadora. Bé, hi ha un cert compromís aquí, entre simplicitat i practicitat per poder fer coses més a mida.

5. Evaluate the Model

Per avaluar el model ens passa el mateix, mentre que en TensorFlow simplement cal cridar el mètode evaluate() amb les dades de test:

_, (x_testTF, y_testTF)= tf.keras.datasets.mnist.load_data()
x_testTF = x_testTF.reshape(10000, 784).astype('float32')/255
y_testTF = tf.keras.utils.to_categorical(y_testTF, num_classes=10)
_ , test_accTF = modelTF.evaluate(x_testTF, y_testTF)
print('\nAccuracy del model amb TensorFlow =', test_accTF)

En PyTorch queda en mans del programador o programadora especificar el bucle d’avalució:

xy_testPT = torchvision.datasets.MNIST(root='./data', train=False, download=True, 
            transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor()]))
xy_test_loaderPT = torch.utils.data.DataLoader(xy_testPT)
correct_count, all_count = 0, 0
for images,labels in xy_test_loaderPT:
  for i in range(len(labels)):
    img = images[i].view(1, 784)
    logps = modelPT(img)
    ps = torch.exp(logps)
    probab = list(ps.detach().numpy()[0])
    pred_label = probab.index(max(probab))
    true_label = labels.numpy()[i]
    if(true_label == pred_label):
      correct_count += 1
    all_count += 1
print("\nAccuracy del model amb PyTorch =", (correct_count/all_count))

I encara més que convergiran!

Bé, com s’ha demostrat en aquest exemple simple, en realitat no difereix tant la manera de crear una xarxa neuronal en TensorFlow i en PyTorch, a banda d’haver d’implementar el bucle d’entrenament i avaluació, alguns hiperparàmetres com epochs o batch_size s’especifiquen en diferents passos.

En realitat, aquests dos frameworks han estat convergint constantment en aquests darrers dos anys, aprenent un de l’altre i adoptant les seves millors característiques. Per exemple, en la nova versió de TensorFlow 2.2 anunciada fa un parell de setmanes, en l’etapa d’entrenament es pot fer l’equivalent a PyTorch implementant el traint_step() en Keras. Per tant, no us preocupeu de triar el framework “erroni”, ja convergiran! El més important es aprendre els conceptes que hi ha al darrera del Deep Learning, i tot el coneixement que adquireixis en un dels frameworks, et servirà per l’altre.

Producció o recerca?

Ara bé, està clar que es diferent si el que tu vols es posar en producció una solució o fer recerca. En aquest cas la decisió de quin trieu és important.

TensorFlow és una llibreria Python molt potent i madura, amb fortes prestacions de visualització i diverses opcions d’ús per al desenvolupament de models d’alt rendiment. Té opcions de desplegament preparades per a la producció i suport automàtic per a plataformes mòbils i web.

PyTorch, en canvi, és encara un framework jove però amb una comunitat molt activa sobretot en el món de la recerca. El portal The Gradient  mostra en aquesta figura adjunta l’ascens i l’adopció de PyTorch a la comunitat investigadora basat en el nombre de treballs de recerca publicats a les grans conferències del tema (CVPR, ICRL, ICML, NIPS, ACL, ICCV, etc.).

Com es pot observar en la figura en el 2018 l’ús del framework PyTorch era minoritari, en comparació amb el 2019 que és aclaparador la seva utilització per part dels investigadors i investigadores. Per tant, si voleu crear productes relacionats amb la intel.ligència artificial, TensorFlow és una bona elecció. PyTorch us el recomano si el que voleu fer és recerca.

Davant del dubte, opta per Keras

Si no ho tens clar, comença amb l’API de Keras de TensorFlow. En l’API de PyTorch es té més flexibilitat i control, però està clar que amb l’API Keras de TensorFlow pot resultar més simple començar. I si estàs llegint aquest post puc suposar que t’estàs iniciant en el tema del Deep Learning.  A banda, tens tota una documentació sobre Keras al teu abans en aquesta pàgina web que he preparat durant aquest darrers dos anys.  (Un secret: Tinc previst de cara a l’estiu poder tenir també preparada una documentació equivalent per a PyTorch 😉  ).

A més Keras té previstes diverses novetats per a aquest 2020 que van en la línia de «fer-lo més fàcil”. A continuació us enumero algunes de les noves funcionalitats que han incorporat recentment o han anunciat que s’incorporaran aviat:

Capes i API de preprocessament

Fins ara hem fet el preprocessament amb eines auxiliars escrites en NumPy i PIL (Python Imaging Library). I aquest tipus de preprocessament extern fa que els models siguin menys portables, ja que cada vegada que algú reutilitza un model ja entrenat ha de tornar a reproduir el pipeline de preprocessat. Per tant ara es podrà que el preprocessament formi part del model, mitjançant «capes de preprocessament». Això inclou aspectes com l’estandardització de text, tokenització, vectorització, normalització d’imatges, augment de dades, etc. És a dir, això permetrà als models acceptar el text en brut o les imatges en brut com a entrada. Personalment crec que això resultarà molt interessant.

Keras Tuner

Es tracta d’un framework que permet trobar els millors hiperparamètres d’un model en Keras. A la que porteu un temps treballant en Deep Learning, veureu que això resoldrà un dels problemes costosos en la creació de models, com es el d’afinar els hiperparàmetres de manera que el model doni el millor rendiment. Sempre resulta una tasca molt feixuga.

AutoKeras

Aquest projecte persegueix trobar un bon model ML per unes dades en poques línies de codi, fent una cerca automàtica a l’espai de models possibles, y usant Keras Tuner per als hiperparàmetres. Per a usuaris més avançats, AutoKeras també permet un nivell més elevat de control sobre la configuració de l’espai  i procés de cerca.

Cloud Keras

La visió és facilitar-li al programador o programadora moure un codi (que funcional localment en el nostre portàtil o en el Colab) al Cloud permetent executar aquest codi de manera distribuïda en el Cloud, fent-li transparent la configuració del clúster o els contenidors Docker.

Integració amb TensorFlow

S’està treballant per a una major integració amb TFX (TensorFlow Extended, una plataforma per gestionar aplicacions ML de producció) i un millor suport per exportar models a TF Lite (un motor d’execució de ML per a dispositius mòbils i incrustats). Sens dubte el millorar el suport per a la posta en producció dels models és fonamental per a la fidelització dels programadors i programadores a Keras.

En resum

Comença!, qualsevol dels dos frameworks és igual de bo com a punt de partida. Fent un símil, quin creus que és el millor llenguatge per començar a programar, C++ o Java? Doncs … depèn de per a què el vulguis i depèn sobretot de quines eines tinguis al teu abast per aprendre. Potser no ens posaríem d’acord, ja se que tens una opinió formada al respecte i em seria difícil canviar la teva resposta. Però segurament coincidim en que, malgrat tot, el important és saber programar. I en realitat, tot el què aprenguis de programació en un llenguatge, després et servirà quan facis servir l’altre, oi? Aquí passa el mateix, l’important és saber de Deep Learning, i després ja usaràs aquest coneixement amb el framework què estigui de moda en aquell moment o al que hi tinguis més accés.