Google I/O è un involucro! Recupera le sessioni di TensorFlow Visualizza le sessioni

Nozioni di base su TensorFlow

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza l'origine su GitHub Scarica quaderno

Questa guida fornisce una rapida panoramica delle basi di TensorFlow . Ogni sezione di questo documento è una panoramica di un argomento più ampio: puoi trovare collegamenti a guide complete alla fine di ogni sezione.

TensorFlow è una piattaforma end-to-end per l'apprendimento automatico. Supporta quanto segue:

  • Calcolo numerico basato su array multidimensionali (simile a NumPy .)
  • GPU ed elaborazione distribuita
  • Differenziazione automatica
  • Costruzione, formazione ed esportazione di modelli
  • E altro ancora

Tensori

TensorFlow opera su array multidimensionali o tensori rappresentati come oggetti tf.Tensor . Ecco un tensore bidimensionale:

import tensorflow as tf

x = tf.constant([[1., 2., 3.],
                 [4., 5., 6.]])

print(x)
print(x.shape)
print(x.dtype)
tf.Tensor(
[[1. 2. 3.]
 [4. 5. 6.]], shape=(2, 3), dtype=float32)
(2, 3)
<dtype: 'float32'>

Gli attributi più importanti di un tf.Tensor sono la sua shape e dtype :

  • Tensor.shape : indica la dimensione del tensore lungo ciascuno dei suoi assi.
  • Tensor.dtype : ti dice il tipo di tutti gli elementi nel tensore.

TensorFlow implementa operazioni matematiche standard sui tensori, oltre a molte operazioni specializzate per l'apprendimento automatico.

Per esempio:

x + x
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[ 2.,  4.,  6.],
       [ 8., 10., 12.]], dtype=float32)>
5 * x
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[ 5., 10., 15.],
       [20., 25., 30.]], dtype=float32)>
x @ tf.transpose(x)
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[14., 32.],
       [32., 77.]], dtype=float32)>
tf.concat([x, x, x], axis=0)
<tf.Tensor: shape=(6, 3), dtype=float32, numpy=
array([[1., 2., 3.],
       [4., 5., 6.],
       [1., 2., 3.],
       [4., 5., 6.],
       [1., 2., 3.],
       [4., 5., 6.]], dtype=float32)>
tf.nn.softmax(x, axis=-1)
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[0.09003057, 0.24472848, 0.6652409 ],
       [0.09003057, 0.24472848, 0.6652409 ]], dtype=float32)>
tf.reduce_sum(x)
<tf.Tensor: shape=(), dtype=float32, numpy=21.0>

L'esecuzione di calcoli di grandi dimensioni sulla CPU può essere lenta. Se configurato correttamente, TensorFlow può utilizzare l'hardware dell'acceleratore come le GPU per eseguire operazioni molto rapidamente.

if tf.config.list_physical_devices('GPU'):
  print("TensorFlow **IS** using the GPU")
else:
  print("TensorFlow **IS NOT** using the GPU")
TensorFlow **IS** using the GPU

Fare riferimento alla guida Tensor per i dettagli.

Variabili

Gli oggetti normali tf.Tensor sono immutabili. Per memorizzare i pesi del modello (o altro stato mutabile) in TensorFlow, utilizzare un tf.Variable .

var = tf.Variable([0.0, 0.0, 0.0])
var.assign([1, 2, 3])
<tf.Variable 'UnreadVariable' shape=(3,) dtype=float32, numpy=array([1., 2., 3.], dtype=float32)>
var.assign_add([1, 1, 1])
<tf.Variable 'UnreadVariable' shape=(3,) dtype=float32, numpy=array([2., 3., 4.], dtype=float32)>

Fare riferimento alla guida alle variabili per i dettagli.

Differenziazione automatica

La discesa del gradiente e i relativi algoritmi sono una pietra miliare del moderno machine learning.

Per consentire ciò, TensorFlow implementa la differenziazione automatica (autodiff), che utilizza il calcolo per calcolare i gradienti. In genere lo utilizzerai per calcolare il gradiente dell'errore o della perdita di un modello rispetto ai suoi pesi.

x = tf.Variable(1.0)

def f(x):
  y = x**2 + 2*x - 5
  return y
f(x)
<tf.Tensor: shape=(), dtype=float32, numpy=-2.0>

A x = 1.0 , y = f(x) = (1**2 + 2*1 - 5) = -2 .

La derivata di y è y' = f'(x) = (2*x + 2) = 4 . TensorFlow può calcolarlo automaticamente:

with tf.GradientTape() as tape:
  y = f(x)

g_x = tape.gradient(y, x)  # g(x) = dy/dx

g_x
<tf.Tensor: shape=(), dtype=float32, numpy=4.0>

Questo esempio semplificato prende solo la derivata rispetto a un singolo scalare ( x ), ma TensorFlow può calcolare il gradiente rispetto a qualsiasi numero di tensori non scalari contemporaneamente.

Fare riferimento alla guida della differenza automatica per i dettagli.

Grafici e funzione tf

Sebbene tu possa utilizzare TensorFlow in modo interattivo come qualsiasi libreria Python, TensorFlow fornisce anche strumenti per:

  • Ottimizzazione delle prestazioni : per velocizzare l'allenamento e l'inferenza.
  • Esporta : così puoi salvare il tuo modello quando ha terminato l'allenamento.

Questi richiedono l'uso di tf.function per separare il codice TensorFlow puro da Python.

@tf.function
def my_func(x):
  print('Tracing.\n')
  return tf.reduce_sum(x)

La prima volta che esegui tf.function , sebbene venga eseguito in Python, acquisisce un grafico completo e ottimizzato che rappresenta i calcoli TensorFlow eseguiti all'interno della funzione.

x = tf.constant([1, 2, 3])
my_func(x)
Tracing.
<tf.Tensor: shape=(), dtype=int32, numpy=6>

Nelle chiamate successive TensorFlow esegue solo il grafico ottimizzato, saltando tutti i passaggi non TensorFlow. Di seguito, nota che my_func non stampa la traccia poiché print è una funzione Python, non una funzione TensorFlow.

x = tf.constant([10, 9, 8])
my_func(x)
<tf.Tensor: shape=(), dtype=int32, numpy=27>

Un grafico potrebbe non essere riutilizzabile per input con una firma diversa ( shape e dtype ), quindi viene invece generato un nuovo grafico:

x = tf.constant([10.0, 9.1, 8.2], dtype=tf.float32)
my_func(x)
Tracing.
<tf.Tensor: shape=(), dtype=float32, numpy=27.3>

Questi grafici acquisiti offrono due vantaggi:

  • In molti casi forniscono una notevole velocità di esecuzione (sebbene non questo banale esempio).
  • Puoi esportare questi grafici, utilizzando tf.saved_model , per eseguirli su altri sistemi come un server o un dispositivo mobile , senza che sia richiesta l'installazione di Python.

Fare riferimento a Introduzione ai grafici per maggiori dettagli.

Moduli, livelli e modelli

tf.Module è una classe per la gestione degli oggetti tf.Variable e degli oggetti tf.function che operano su di essi. La classe tf.Module è necessaria per supportare due caratteristiche significative:

  1. Puoi salvare e ripristinare i valori delle tue variabili usando tf.train.Checkpoint . Ciò è utile durante l'addestramento poiché consente di salvare e ripristinare rapidamente lo stato di un modello.
  2. È possibile importare ed esportare i valori tf.Variable e i grafici tf.function utilizzando tf.saved_model . Ciò ti consente di eseguire il tuo modello indipendentemente dal programma Python che lo ha creato.

Ecco un esempio completo di esportazione di un semplice oggetto tf.Module :

class MyModule(tf.Module):
  def __init__(self, value):
    self.weight = tf.Variable(value)

  @tf.function
  def multiply(self, x):
    return x * self.weight
mod = MyModule(3)
mod.multiply(tf.constant([1, 2, 3]))
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([3, 6, 9], dtype=int32)>

Salva il Module :

save_path = './saved'
tf.saved_model.save(mod, save_path)
INFO:tensorflow:Assets written to: ./saved/assets
2022-01-19 02:29:48.135588: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.

Il SavedModel risultante è indipendente dal codice che lo ha creato. Puoi caricare un SavedModel da Python, altre associazioni di lingua o TensorFlow Serving . Puoi anche convertirlo per funzionare con TensorFlow Lite o TensorFlow JS .

reloaded = tf.saved_model.load(save_path)
reloaded.multiply(tf.constant([1, 2, 3]))
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([3, 6, 9], dtype=int32)>

Le classi tf.keras.layers.Layer e tf.keras.Model si basano su tf.Module fornendo funzionalità aggiuntive e metodi pratici per la creazione, l'addestramento e il salvataggio di modelli. Alcuni di questi sono illustrati nella sezione successiva.

Fare riferimento a Introduzione ai moduli per i dettagli.

Cicli di formazione

Ora metti tutto insieme per costruire un modello di base e addestrarlo da zero.

Innanzitutto, crea alcuni dati di esempio. Questo genera una nuvola di punti che segue vagamente una curva quadratica:

import matplotlib
from matplotlib import pyplot as plt

matplotlib.rcParams['figure.figsize'] = [9, 6]
x = tf.linspace(-2, 2, 201)
x = tf.cast(x, tf.float32)

def f(x):
  y = x**2 + 2*x - 5
  return y

y = f(x) + tf.random.normal(shape=[201])

plt.plot(x.numpy(), y.numpy(), '.', label='Data')
plt.plot(x, f(x),  label='Ground truth')
plt.legend();

png

Crea un modello:

class Model(tf.keras.Model):
  def __init__(self, units):
    super().__init__()
    self.dense1 = tf.keras.layers.Dense(units=units,
                                        activation=tf.nn.relu,
                                        kernel_initializer=tf.random.normal,
                                        bias_initializer=tf.random.normal)
    self.dense2 = tf.keras.layers.Dense(1)

  def call(self, x, training=True):
    # For Keras layers/models, implement `call` instead of `__call__`.
    x = x[:, tf.newaxis]
    x = self.dense1(x)
    x = self.dense2(x)
    return tf.squeeze(x, axis=1)
model = Model(64)
plt.plot(x.numpy(), y.numpy(), '.', label='data')
plt.plot(x, f(x),  label='Ground truth')
plt.plot(x, model(x), label='Untrained predictions')
plt.title('Before training')
plt.legend();

png

Scrivi un ciclo di formazione di base:

variables = model.variables

optimizer = tf.optimizers.SGD(learning_rate=0.01)

for step in range(1000):
  with tf.GradientTape() as tape:
    prediction = model(x)
    error = (y-prediction)**2
    mean_error = tf.reduce_mean(error)
  gradient = tape.gradient(mean_error, variables)
  optimizer.apply_gradients(zip(gradient, variables))

  if step % 100 == 0:
    print(f'Mean squared error: {mean_error.numpy():0.3f}')
Mean squared error: 16.123
Mean squared error: 0.997
Mean squared error: 0.964
Mean squared error: 0.946
Mean squared error: 0.932
Mean squared error: 0.921
Mean squared error: 0.913
Mean squared error: 0.907
Mean squared error: 0.901
Mean squared error: 0.897
plt.plot(x.numpy(),y.numpy(), '.', label="data")
plt.plot(x, f(x),  label='Ground truth')
plt.plot(x, model(x), label='Trained predictions')
plt.title('After training')
plt.legend();

png

Funziona, ma ricorda che le implementazioni delle utilità di formazione comuni sono disponibili nel modulo tf.keras . Quindi considera di usarli prima di scriverne uno tuo. Per cominciare, i metodi Model.compile e Model.fit implementano un ciclo di formazione per te:

new_model = Model(64)
new_model.compile(
    loss=tf.keras.losses.MSE,
    optimizer=tf.optimizers.SGD(learning_rate=0.01))

history = new_model.fit(x, y,
                        epochs=100,
                        batch_size=32,
                        verbose=0)

model.save('./my_model')
INFO:tensorflow:Assets written to: ./my_model/assets
plt.plot(history.history['loss'])
plt.xlabel('Epoch')
plt.ylim([0, max(plt.ylim())])
plt.ylabel('Loss [Mean Squared Error]')
plt.title('Keras training progress');

png

Fare riferimento a cicli di formazione di base e alla guida Keras per maggiori dettagli.