In [ ]:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Differenziazione automatica e gradient tape

Note: La nostra comunità di Tensorflow ha tradotto questi documenti. Poichè questa traduzioni della comunità sono best-effort, non c'è garanzia che questa sia un riflesso preciso e aggiornato della documentazione ufficiale in inglese. Se avete suggerimenti per migliorare questa traduzione, mandate per favore una pull request al repository Github tensorflow/docs. Per proporsi come volontari alla scrittura o alla review delle traduzioni della comunità contattate la mailing list docs@tensorflow.org.

Nel tutorial precedente abbiamo introdotto i Tensori e le loro operazioni. In questo tutorial copriremo la differenziazione automatica, una tecnica importante per ottimizare i modelli di machine learning.

Setup


In [ ]:
import tensorflow as tf

Gradient tapes

TensorFlow fornisce l'API tf.GradientTape per la differenziazione automatica che calcola il gradiente di una computazione rispetto alle sue variabili in input. Tensorflow "registra" tutte le operazioni eseguite dentro il contesto di un tf.GradientTape su un "tape". Tensorflow quindi usa quel "tape" e i gradienti associati con ogni operazione registrata per calcolare il gradiente di una computazione "registrata" utilizzando l'accumulazione inversa.

Per esempio:


In [ ]:
x = tf.ones((2, 2))

with tf.GradientTape() as t:
  t.watch(x)
  y = tf.reduce_sum(x)
  z = tf.multiply(y, y)

# Derivative of z with respect to the original input tensor x
dz_dx = t.gradient(z, x)
for i in [0, 1]:
  for j in [0, 1]:
    assert dz_dx[i][j].numpy() == 8.0

Puoi anche richiedere i gradienti dell'output rispetto ai valori intermedi calcolati in un contesto "registrato" di tf.GradientTape.


In [ ]:
x = tf.ones((2, 2))

with tf.GradientTape() as t:
  t.watch(x)
  y = tf.reduce_sum(x)
  z = tf.multiply(y, y)

# Use the tape to compute the derivative of z with respect to the
# intermediate value y.
dz_dy = t.gradient(z, y)
assert dz_dy.numpy() == 8.0

Di default, le risorse tenute da un GradientTape sono rilasciate non appena il metodo GradientTape.gradient() è chiamato. Per calcolare multipli gradienti sullo stesso calcolo, crea un persistent gradient tape. Questo da la possibilità di fare chiamate multiple del metodo gradient() non appena le risorse sono rilasciate quando l'oggetto tape è liberato dal garbage collector. Per esempio:


In [ ]:
x = tf.constant(3.0)
with tf.GradientTape(persistent=True) as t:
  t.watch(x)
  y = x * x
  z = y * y
dz_dx = t.gradient(z, x)  # 108.0 (4*x^3 at x = 3)
dy_dx = t.gradient(y, x)  # 6.0
del t  # Drop the reference to the tape

Flusso di controllo della registrazione

Poichè i "tape" registrano operazione nel momento in cui le eseugono, il flusso di controllo Python (usando if e while per esempio) è gestito naturalmente:


In [ ]:
def f(x, y):
  output = 1.0
  for i in range(y):
    if i > 1 and i < 5:
      output = tf.multiply(output, x)
  return output

def grad(x, y):
  with tf.GradientTape() as t:
    t.watch(x)
    out = f(x, y)
  return t.gradient(out, x)

x = tf.convert_to_tensor(2.0)

assert grad(x, 6).numpy() == 12.0
assert grad(x, 5).numpy() == 12.0
assert grad(x, 4).numpy() == 4.0

Gradienti di ordine superiore

Le operazioni dentro il gestore di contesto di GradientTape sono registrati per la differenziazione automatica. Se i gradienti sono calcolati nello stesso contesto, allora anche il calcolo del gradiente è registrato. Come risultato, la stessa API funziona per gradienti di ordine superiore. Per esempio:


In [ ]:
x = tf.Variable(1.0)  # Create a Tensorflow variable initialized to 1.0

with tf.GradientTape() as t:
  with tf.GradientTape() as t2:
    y = x * x * x
  # Compute the gradient inside the 't' context manager
  # which means the gradient computation is differentiable as well.
  dy_dx = t2.gradient(y, x)
d2y_dx2 = t.gradient(dy_dx, x)

assert dy_dx.numpy() == 3.0
assert d2y_dx2.numpy() == 6.0

Passi successivi

In questo tutorial abbiamo coperto il calcolo di gradienti in TensorFlow. Con questo abbiamo abbastanza primitive richieste per costruire e addestrare reti neurali.