Introducción a las nuevas funciones de Tensorflow 2.0, la versión más detallada

TensorFlow 2 efectivo

Se han realizado varios cambios en TensorFlow 2.0 para que los usuarios de TensorFlow sean más eficientes. TensorFlow 2.0 elimina la API redundante , hace que la API sea más consistente ( RNN unificado , optimizador unificado ) y se integra mejor con el tiempo de ejecución de Python a través de la ejecución Eager .

Muchas RFC explican los cambios en TensorFlow 2.0. Esta guía presenta la apariencia del desarrollo de TensorFlow 2.0. Suponga que tiene algún conocimiento de TensorFlow 1.x.

Breve resumen de cambios importantes

Limpieza de API

En TF 2.0, muchas API han desaparecido o se han movido . Algunos de los cambios principales incluyen la eliminación y tf.app, para admitir el absl-py , ahora de código abierto , la reubicación reside en el proyecto y mueve las funciones menos utilizadas a los subpaquetes limpiando el espacio de nombres principal . Ciertos APIs han sido reemplazados por sus equivalentes 2.0 , y . La forma más sencilla de aplicar automáticamente estos cambios de nombre es utilizar el script de actualización v2 .tf.flagstf.loggingtf.contribtf.*tf.mathtf.summarytf.keras.metricstf.keras.optimizers

Ansioso por ejecutar

TensorFlow 1.X requiere que los usuarios unan tf.*manualmente árboles de sintaxis abstracta (gráficos) llamando a la API . Luego, le pide al usuario session.run()que compile manualmente el árbol de sintaxis abstracta pasando un conjunto de tensores de salida y tensores de entrada a la llamada. TensorFlow 2.0 se ejecuta con entusiasmo (como suele hacer Python), y en 2.0, los gráficos y las sesiones deben sentirse como detalles de implementación.

Un subproducto importante de la ejecución ávida es que ya no es necesario tf.control_dependencies(), porque todas las líneas de código tf.functionse ejecutan secuencialmente (en tf.function, el código con efectos secundarios se ejecuta en el orden en que se escribió).

No más variables globales

TensorFlow 1.X se basa en gran medida en el espacio de nombres global implícito. Cuando lo llame tf.Variable(), se colocará en el gráfico predeterminado, incluso si pierde la variable de Python que lo señala, permanecerá en el gráfico predeterminado. Luego, puede restaurarlo tf.Variable, pero tf.Variableconoce el nombre del archivo que desea crear. Si no puede controlar la creación de variables, es difícil hacerlo. Como resultado, varios mecanismos surgieron nuevamente para ayudar a los usuarios a encontrar su variable y marco para encontrar variables creadas por el usuario: alcance variable, colección global, como tf.get_global_step(), tf.global_variables_initializer()método de clase auxiliar para optimizar el programa de gradiente, calcular implícitamente todas las variables de entrenamiento. , Y así sucesivamente. TensorFlow 2.0 elimina todos estos mecanismos ( Variables 2.0 RFC ) y usa el mecanismo predeterminado: ¡seguimiento de variables! Si se olvida tf.Variable, se recogerá la basura.

El requisito de realizar un seguimiento de las variables genera un trabajo adicional para el usuario, pero para los objetos Keras (ver más abajo), la carga se minimiza.

Función en lugar de sesión

session.run()Una llamada es casi como una llamada a una función: especifique la entrada y la función a llamar, y luego obtenga un conjunto de salidas. En TensorFlow 2.0, puede tf.function()decorar una función de Python para marcarla como compilada JIT para que TensorFlow pueda ejecutarla como un solo gráfico ( Función 2.0 RFC ). Este mecanismo permite a TensorFlow 2.0 obtener todas las ventajas del modo gráfico:

  • Rendimiento: las funciones se pueden optimizar (poda de nodos, fusión de kernel, etc.)
  • Portabilidad: esta función se puede exportar / volver a importar ( SavedModel 2.0 RFC ), lo que permite a los usuarios reutilizar y compartir funciones modulares de TensorFlow.
# TensorFlow 1.X
outputs = session.run(f(placeholder), feed_dict={
    
    placeholder: input})
# TensorFlow 2.0
outputs = f(input)

Con la distribución gratuita de código Python y TensorFlow, los usuarios pueden aprovechar el poder expresivo de Python. Pero TensorFlow portátil se ejecuta en un contexto sin un intérprete de Python, como dispositivos móviles, C ++ y JavaScript. Para ayudar a los usuarios a evitar @tf.functiontener que reescribir el código al agregar , AutoGraph convierte un subconjunto de construcciones de Python en sus equivalentes de TensorFlow:

  • for/ while-> tf.while_loop( breakY continuesoporte)
  • if -> tf.cond
  • for _ in dataset dataset.reduce > dataset.reduce

AutoGraph admite el anidamiento arbitrario del flujo de control, lo que hace posible implementar de manera eficiente y concisa muchos programas de ML complejos, como modelos de secuencia, aprendizaje por refuerzo, ciclos de entrenamiento personalizados, etc.

Recomendaciones idiomáticas de TensorFlow 2.0

Refactorice el código en funciones más pequeñas

Un patrón de uso común en TensorFlow 1.X es la estrategia del "fregadero de la cocina", que primero da cuenta de la unión de todos los cálculos posibles y luego session.run()evalúa el tensor seleccionado. En TensorFlow 2.0, los usuarios deben refactorizar su código en funciones más pequeñas y llamar a estas funciones según sea necesario. Generalmente, no es necesario tf.functiondecorar todas las funciones más pequeñas; solo tf.functiondecorar cálculos avanzados, por ejemplo, un paso de entrenamiento o el pase de avance del modelo.

Use capas y modelos de Keras para administrar variables

Los modelos y capas de Keras proporcionan conveniencia variablesy trainable_variablesatributos, que recopilan todas las variables dependientes de manera recursiva. Esto facilita la gestión de variables localmente donde se utilizan.

Comparado:

def dense(x, W, b):
  return tf.nn.sigmoid(tf.matmul(x, W) + b)

@tf.function
def multilayer_perceptron(x, w0, b0, w1, b1, w2, b2 ...):
  x = dense(x, w0, b0)
  x = dense(x, w1, b1)
  x = dense(x, w2, b2)
  ...

# You still have to manage w_i and b_i, and their shapes are defined far away from the code.

Utilice la versión de Keras:

# Each layer can be called, with a signature equivalent to linear(x)
layers = [tf.keras.layers.Dense(hidden_size, activation=tf.nn.sigmoid) for _ in range(n)]
perceptron = tf.keras.Sequential(layers)

# layers[3].trainable_variables => returns [w3, b3]
# perceptron.trainable_variables => returns [w0, b0, ...]

Las capas / modelos de Keras se heredan tf.train.Checkpointabley se @tf.functionintegran con, lo que hace posible el punto de control o la exportación de modelos guardados directamente desde los objetos de Keras. No es necesario que utilice .fit()la .fit()API para aprovechar estas integraciones.

Este es un ejemplo de aprendizaje por transferencia que demuestra cómo Keras facilita la recopilación de un subconjunto de variables relacionadas. Suponga que está utilizando una red troncal compartida para entrenar un modelo de múltiples cabezales:

trunk = tf.keras.Sequential([...])
head1 = tf.keras.Sequential([...])
head2 = tf.keras.Sequential([...])

path1 = tf.keras.Sequential([trunk, head1])
path2 = tf.keras.Sequential([trunk, head2])

# Train on primary dataset
for x, y in main_dataset:
  with tf.GradientTape() as tape:
    # training=True is only needed if there are layers with different
    # behavior during training versus inference (e.g. Dropout).
    prediction = path1(x, training=True)
    loss = loss_fn_head1(prediction, y)
  # Simultaneously optimize trunk and head1 weights.
  gradients = tape.gradient(loss, path1.trainable_variables)
  optimizer.apply_gradients(zip(gradients, path1.trainable_variables))

# Fine-tune second head, reusing the trunk
for x, y in small_dataset:
  with tf.GradientTape() as tape:
    # training=True is only needed if there are layers with different
    # behavior during training versus inference (e.g. Dropout).
    prediction = path2(x, training=True)
    loss = loss_fn_head2(prediction, y)
  # Only optimize head2 weights, not trunk weights
  gradients = tape.gradient(loss, head2.trainable_variables)
  optimizer.apply_gradients(zip(gradients, head2.trainable_variables))

# You can publish just the trunk computation for other people to reuse.
tf.saved_model.save(trunk, output_path)

Combinar tf.data.Datasets y @ tf.function

Al iterar a través de datos de entrenamiento que quepan en la memoria, no dude en usar iteraciones regulares de Python. De lo contrario, tf.data.Datasetes la mejor manera de transmitir datos de entrenamiento desde el disco. Los conjuntos de datos son iterables (no iteradores) , al igual que otros iterables de Python en el modo Eager. Al incluir el código tf.function(), puede aprovechar al máximo la función de captura previa / transmisión asíncrona del conjunto de datos, que reemplaza la iteración de Python con la operación de gráfico equivalente usando AutoGraph.

@tf.function
def train(model, dataset, optimizer):
  for x, y in dataset:
    with tf.GradientTape() as tape:
      # training=True is only needed if there are layers with different
      # behavior during training versus inference (e.g. Dropout).
      prediction = model(x, training=True)
      loss = loss_fn(prediction, y)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

Si usa la .fit()API, no tiene que preocuparse por la iteración del conjunto de datos.

model.compile(optimizer=optimizer, loss=loss_fn)
model.fit(dataset)

Utilice AutoGraph con el flujo de control de Python

AutoGraph proporciona una forma de convertir el flujo de control dependiente de los datos en un modo equivalente tf.condy tf.while_loopgráfico tf.while_loop.

Un lugar común donde aparece el flujo de control dependiente de los datos es el modelo de secuencia. tf.keras.layers.RNNEmpaquete una unidad RNN para que pueda expandir la repetición de forma estática o dinámica. Para fines de demostración, puede volver a implementar la expansión dinámica de la siguiente manera:

class DynamicRNN(tf.keras.Model):

  def __init__(self, rnn_cell):
    super(DynamicRNN, self).__init__(self)
    self.cell = rnn_cell

  def call(self, input_data):
    # [batch, time, features] -> [time, batch, features]
    input_data = tf.transpose(input_data, [1, 0, 2])
    outputs = tf.TensorArray(tf.float32, input_data.shape[0])
    state = self.cell.zero_state(input_data.shape[1], dtype=tf.float32)
    for i in tf.range(input_data.shape[0]):
      output, state = self.cell(input_data[i], state)
      outputs = outputs.write(i, output)
    return tf.transpose(outputs.stack(), [1, 0, 2]), state

Para obtener una descripción general más detallada de las funciones de AutoGraph, consulte la guía .

tf.metrics resume los datos y tf.summary los registra

Para grabar un resumen, use tf.summary.(scalar|histogram|...)y luego use el administrador de contexto para redirigirlo al autor. (Si se omite el administrador de contexto, no sucede nada). A diferencia de TF 1.x, el resumen se envía directamente al escritor; no hay una operación de "fusión" separada add_summary(), ni una llamada separada , lo que significa que debe estar en el sitio de llamada Aporta stepvalor.

summary_writer = tf.summary.create_file_writer('/tmp/summaries')
with summary_writer.as_default():
  tf.summary.scalar('loss', 0.1, step=42)

Para agregar datos antes de registrarlos como resumen, utilice tf.metrics. Los indicadores tienen estado: cuando llama .result(), acumulan valores y devuelven el resultado acumulado. Use para .reset_states()borrar el valor acumulado.

def train(model, optimizer, dataset, log_freq=10):
  avg_loss = tf.keras.metrics.Mean(name='loss', dtype=tf.float32)
  for images, labels in dataset:
    loss = train_step(model, optimizer, images, labels)
    avg_loss.update_state(loss)
    if tf.equal(optimizer.iterations % log_freq, 0):
      tf.summary.scalar('loss', avg_loss.result(), step=optimizer.iterations)
      avg_loss.reset_states()

def test(model, test_x, test_y, step_num):
  # training=False is only needed if there are layers with different
  # behavior during training versus inference (e.g. Dropout).
  loss = loss_fn(model(test_x, training=False), test_y)
  tf.summary.scalar('loss', loss, step=step_num)

train_summary_writer = tf.summary.create_file_writer('/tmp/summaries/train')
test_summary_writer = tf.summary.create_file_writer('/tmp/summaries/test')

with train_summary_writer.as_default():
  train(model, optimizer, dataset)

with test_summary_writer.as_default():
  test(model, test_x, test_y, optimizer.iterations)

Visualice el resumen generado apuntando TensorBoard al directorio de registro de resumen:

tensorboard --logdir /tmp/summaries

Utilice tf.config.experimental_run_functions_eagerly () al depurar

En TensorFlow 2.0, la ejecución ansiosa le permite ejecutar código paso a paso para verificar formas, tipos de datos y valores. Ciertas API (por ejemplo tf.function, tf.kerasetc.) están diseñadas para ejecutarse utilizando Graph para mejorar el rendimiento y la portabilidad. Al depurar, tf.config.experimental_run_functions_eagerly(True)use Eager para ejecutar dentro de este código.

P.ej:

@tf.function 
def f(x): 
	if x > 0:  
		import pdb  
		pdb.set_trace()  
		x = x + 1 
		return x
tf.config.experimental_run_functions_eagerly(True)
f(tf.constant(1))
>>> f()
-> x = x + 1
(Pdb) l 
6   @tf.function 
7   def f(x): 
8    if x > 0: 
9     import pdb 
10     pdb.set_trace() 
11  ->   x = x + 1 
12    return x 
13 
14   tf.config.experimental_run_functions_eagerly(True) 
15   f(tf.constant(1))[EOF]

Esto también se puede usar en modelos de Keras y otras API que admiten la ejecución Eager:

class CustomModel(tf.keras.models.Model): 
	@tf.function 
	def call(self, input_data):  
		if tf.reduce_mean(input_data) > 0:   
			return input_data  
		else:   
			import pdb   
			pdb.set_trace()   
			return input_data // 2
tf.config.experimental_run_functions_eagerly(True)
model = CustomModel()
model(tf.constant([-2, -4]))
>>> call()-> return input_data // 2
(Pdb) l 
10     if tf.reduce_mean(input_data) > 0: 
11      return input_data 
12     else: 
13      import pdb 
14      pdb.set_trace() 
15  ->    return input_data // 2 
16 
17 
18   tf.config.experimental_run_functions_eagerly(True) 
19   model = CustomModel() 
20   model(tf.constant([-2, -4]))

Fuente: Effective TensorFlow 2

Supongo que te gusta

Origin blog.csdn.net/weixin_43655282/article/details/109093628
Recomendado
Clasificación