Aiuto proteggere la Grande Barriera Corallina con tensorflow sul Kaggle Join Sfida

Usa i TPU

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza la fonte su GitHub Scarica il taccuino

Prima di eseguire questo notebook Colab, assicuratevi che il vostro acceleratore hardware è un TPU controllando le impostazioni del notebook: Runtime> Cambia tipo runtime> acceleratore hardware> TPU.

Impostare

import tensorflow as tf

import os
import tensorflow_datasets as tfds
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/requests/__init__.py:104: RequestsDependencyWarning: urllib3 (1.26.7) or chardet (2.3.0)/charset_normalizer (2.0.8) doesn't match a supported version!
  RequestsDependencyWarning)

Inizializzazione TPU

Le TPU sono in genere lavoratori Cloud TPU, che sono diversi dal processo locale che esegue il programma Python dell'utente. Pertanto, è necessario eseguire alcune operazioni di inizializzazione per connettersi al cluster remoto e inizializzare le TPU. Si noti che il tpu argomento di tf.distribute.cluster_resolver.TPUClusterResolver è un indirizzo speciale solo per Colab. Se stai eseguendo il tuo codice su Google Compute Engine (GCE), dovresti invece trasmettere il nome della tua Cloud TPU.

resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='')
tf.config.experimental_connect_to_cluster(resolver)
# This is the TPU initialization code that has to be at the beginning.
tf.tpu.experimental.initialize_tpu_system(resolver)
print("All devices: ", tf.config.list_logical_devices('TPU'))
INFO:tensorflow:Clearing out eager caches
INFO:tensorflow:Clearing out eager caches
INFO:tensorflow:Initializing the TPU system: grpc://10.240.1.2:8470
INFO:tensorflow:Initializing the TPU system: grpc://10.240.1.2:8470
INFO:tensorflow:Finished initializing TPU system.
INFO:tensorflow:Finished initializing TPU system.
All devices:  [LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:0', device_type='TPU'), LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:1', device_type='TPU'), LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:2', device_type='TPU'), LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:3', device_type='TPU'), LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:4', device_type='TPU'), LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:5', device_type='TPU'), LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:6', device_type='TPU'), LogicalDevice(name='/job:worker/replica:0/task:0/device:TPU:7', device_type='TPU')]

Posizionamento manuale del dispositivo

Dopo che la TPU è stata inizializzata, puoi utilizzare il posizionamento manuale del dispositivo per posizionare il calcolo su un singolo dispositivo TPU:

a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])

with tf.device('/TPU:0'):
  c = tf.matmul(a, b)

print("c device: ", c.device)
print(c)
c device:  /job:worker/replica:0/task:0/device:TPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

Strategie di distribuzione

Di solito si esegue il modello su più TPU in modo parallelo ai dati. Per distribuire il tuo modello su più TPU (o altri acceleratori), TensorFlow offre diverse strategie di distribuzione. Puoi sostituire la tua strategia di distribuzione e il modello verrà eseguito su un determinato dispositivo (TPU). Controllare la guida di strategia di distribuzione per ulteriori informazioni.

Per dimostrare questo, creare un tf.distribute.TPUStrategy oggetto:

strategy = tf.distribute.TPUStrategy(resolver)
INFO:tensorflow:Found TPU system:
INFO:tensorflow:Found TPU system:
INFO:tensorflow:*** Num TPU Cores: 8
INFO:tensorflow:*** Num TPU Cores: 8
INFO:tensorflow:*** Num TPU Workers: 1
INFO:tensorflow:*** Num TPU Workers: 1
INFO:tensorflow:*** Num TPU Cores Per Worker: 8
INFO:tensorflow:*** Num TPU Cores Per Worker: 8
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:localhost/replica:0/task:0/device:CPU:0, CPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:localhost/replica:0/task:0/device:CPU:0, CPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:CPU:0, CPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:CPU:0, CPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:0, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:0, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:1, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:1, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:2, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:2, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:3, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:3, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:4, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:4, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:5, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:5, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:6, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:6, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:7, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU:7, TPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU_SYSTEM:0, TPU_SYSTEM, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:TPU_SYSTEM:0, TPU_SYSTEM, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:XLA_CPU:0, XLA_CPU, 0, 0)
INFO:tensorflow:*** Available Device: _DeviceAttributes(/job:worker/replica:0/task:0/device:XLA_CPU:0, XLA_CPU, 0, 0)

Per replicare un calcolo in modo che possa funzionare in tutti i core TPU, si può passare nella strategy.run API. Qui di seguito è un esempio che mostra tutti i nuclei ricezione degli stessi ingressi (a, b) ed eseguendo la moltiplicazione matriciale ogni core indipendente. Gli output saranno i valori di tutte le repliche.

@tf.function
def matmul_fn(x, y):
  z = tf.matmul(x, y)
  return z

z = strategy.run(matmul_fn, args=(a, b))
print(z)
PerReplica:{
  0: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32),
  1: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32),
  2: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32),
  3: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32),
  4: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32),
  5: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32),
  6: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32),
  7: tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)
}

Classificazione sui TPU

Dopo aver coperto i concetti di base, considera un esempio più concreto. In questa sezione viene illustrato come utilizzare la distribuzione strategia- tf.distribute.TPUStrategy -per formare un modello Keras su una nuvola in TPU.

Definire un modello Keras

Inizia con una definizione di un Sequential modello di Keras per la classificazione di immagini sul set di dati utilizzando MNIST Keras. Non è diverso da quello che useresti se ti allenassi su CPU o GPU. Nota che le esigenze di creazione di modello Keras essere dentro strategy.scope , in modo che le variabili possono essere create su ogni dispositivo TPU. Non è necessario che altre parti del codice rientrino nell'ambito della strategia.

def create_model():
  return tf.keras.Sequential(
      [tf.keras.layers.Conv2D(256, 3, activation='relu', input_shape=(28, 28, 1)),
       tf.keras.layers.Conv2D(256, 3, activation='relu'),
       tf.keras.layers.Flatten(),
       tf.keras.layers.Dense(256, activation='relu'),
       tf.keras.layers.Dense(128, activation='relu'),
       tf.keras.layers.Dense(10)])

Carica il set di dati

L'uso efficiente della tf.data.Dataset API è fondamentale quando si utilizza una nuvola TPU, come è impossibile utilizzare il cloud TPU a meno che non si può dar loro da mangiare i dati abbastanza velocemente. È possibile saperne di più su set di dati prestazioni nella guida di ingresso prestazioni gasdotto .

Per tutti, ma gli esperimenti più semplici (utilizzando tf.data.Dataset.from_tensor_slices o altri dati in-grafico), è necessario memorizzare tutti i file di dati letti dal set di dati in Google Cloud Storage (GCS) secchi.

Per la maggior parte dei casi d'uso, si consiglia di convertire i dati nel TFRecord formato e utilizzare un tf.data.TFRecordDataset per leggerlo. Controllare l' esercitazione TFRecord e tf.Example per i dettagli su come fare questo. E non è un requisito difficile ed è possibile utilizzare altri lettori del set di dati, come ad esempio tf.data.FixedLengthRecordDataset o tf.data.TextLineDataset .

È possibile caricare interi piccoli insiemi di dati in memoria, con tf.data.Dataset.cache .

Indipendentemente dal formato dei dati utilizzato, si consiglia vivamente di utilizzare file di grandi dimensioni dell'ordine di 100 MB. Ciò è particolarmente importante in questa impostazione di rete, poiché il sovraccarico dell'apertura di un file è significativamente maggiore.

Come mostrato nel seguente codice, è necessario utilizzare le tensorflow_datasets modulo per ottenere una copia della formazione MNIST e dati di test. Si noti che try_gcs è specificato di utilizzare una copia che è disponibile in un secchio GCS pubblica. Se non lo specifichi, la TPU non sarà in grado di accedere ai dati scaricati.

def get_dataset(batch_size, is_training=True):
  split = 'train' if is_training else 'test'
  dataset, info = tfds.load(name='mnist', split=split, with_info=True,
                            as_supervised=True, try_gcs=True)

  # Normalize the input data.
  def scale(image, label):
    image = tf.cast(image, tf.float32)
    image /= 255.0
    return image, label

  dataset = dataset.map(scale)

  # Only shuffle and repeat the dataset in training. The advantage of having an
  # infinite dataset for training is to avoid the potential last partial batch
  # in each epoch, so that you don't need to think about scaling the gradients
  # based on the actual batch size.
  if is_training:
    dataset = dataset.shuffle(10000)
    dataset = dataset.repeat()

  dataset = dataset.batch(batch_size)

  return dataset

Addestra il modello utilizzando le API di alto livello di Keras

È possibile addestrare il vostro modello con Keras fit e compile API. Non c'è nulla di TPU-specifica in questo passo si scrive il codice come se si stesse utilizzando GPU mutliple e un MirroredStrategy al posto del TPUStrategy . Potete saperne di più nella formazione distribuita con Keras tutorial.

with strategy.scope():
  model = create_model()
  model.compile(optimizer='adam',
                loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                metrics=['sparse_categorical_accuracy'])

batch_size = 200
steps_per_epoch = 60000 // batch_size
validation_steps = 10000 // batch_size

train_dataset = get_dataset(batch_size, is_training=True)
test_dataset = get_dataset(batch_size, is_training=False)

model.fit(train_dataset,
          epochs=5,
          steps_per_epoch=steps_per_epoch,
          validation_data=test_dataset, 
          validation_steps=validation_steps)
Epoch 1/5
300/300 [==============================] - 18s 32ms/step - loss: 0.1291 - sparse_categorical_accuracy: 0.9590 - val_loss: 0.0410 - val_sparse_categorical_accuracy: 0.9871
Epoch 2/5
300/300 [==============================] - 6s 22ms/step - loss: 0.0335 - sparse_categorical_accuracy: 0.9892 - val_loss: 0.0492 - val_sparse_categorical_accuracy: 0.9847
Epoch 3/5
300/300 [==============================] - 6s 21ms/step - loss: 0.0205 - sparse_categorical_accuracy: 0.9941 - val_loss: 0.0457 - val_sparse_categorical_accuracy: 0.9868
Epoch 4/5
300/300 [==============================] - 7s 22ms/step - loss: 0.0115 - sparse_categorical_accuracy: 0.9960 - val_loss: 0.0428 - val_sparse_categorical_accuracy: 0.9891
Epoch 5/5
300/300 [==============================] - 6s 21ms/step - loss: 0.0110 - sparse_categorical_accuracy: 0.9965 - val_loss: 0.0592 - val_sparse_categorical_accuracy: 0.9853
<keras.callbacks.History at 0x7f25fc108a58>

Per ridurre Python sovraccarico e massimizzare le prestazioni del vostro TPU, passare l'argument- steps_per_execution -per Model.compile . In questo esempio, aumenta il throughput di circa il 50%:

with strategy.scope():
  model = create_model()
  model.compile(optimizer='adam',
                # Anything between 2 and `steps_per_epoch` could help here.
                steps_per_execution = 50,
                loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                metrics=['sparse_categorical_accuracy'])

model.fit(train_dataset,
          epochs=5,
          steps_per_epoch=steps_per_epoch,
          validation_data=test_dataset,
          validation_steps=validation_steps)
Epoch 1/5
300/300 [==============================] - 13s 42ms/step - loss: 0.1343 - sparse_categorical_accuracy: 0.9594 - val_loss: 0.0487 - val_sparse_categorical_accuracy: 0.9837
Epoch 2/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0348 - sparse_categorical_accuracy: 0.9891 - val_loss: 0.0401 - val_sparse_categorical_accuracy: 0.9876
Epoch 3/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0187 - sparse_categorical_accuracy: 0.9940 - val_loss: 0.0517 - val_sparse_categorical_accuracy: 0.9844
Epoch 4/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0123 - sparse_categorical_accuracy: 0.9963 - val_loss: 0.0506 - val_sparse_categorical_accuracy: 0.9860
Epoch 5/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0080 - sparse_categorical_accuracy: 0.9974 - val_loss: 0.0456 - val_sparse_categorical_accuracy: 0.9878
<keras.callbacks.History at 0x7f23ac7782b0>

Addestrare il modello utilizzando un ciclo di addestramento personalizzato

È inoltre possibile creare e addestrare il vostro modello utilizzando tf.function e tf.distribute direttamente le API. È possibile utilizzare l' strategy.experimental_distribute_datasets_from_function API per distribuire il dataset data una funzione set di dati. Si noti che nell'esempio seguente la dimensione batch passata al set di dati è la dimensione batch per replica anziché la dimensione batch globale. Per ulteriori informazioni, visitate il training personalizzata con tf.distribute.Strategy tutorial.

Innanzitutto, crea il modello, i set di dati e tf.functions:

# Create the model, optimizer and metrics inside the strategy scope, so that the
# variables can be mirrored on each device.
with strategy.scope():
  model = create_model()
  optimizer = tf.keras.optimizers.Adam()
  training_loss = tf.keras.metrics.Mean('training_loss', dtype=tf.float32)
  training_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(
      'training_accuracy', dtype=tf.float32)

# Calculate per replica batch size, and distribute the datasets on each TPU
# worker.
per_replica_batch_size = batch_size // strategy.num_replicas_in_sync

train_dataset = strategy.experimental_distribute_datasets_from_function(
    lambda _: get_dataset(per_replica_batch_size, is_training=True))

@tf.function
def train_step(iterator):
  """The step function for one training step."""

  def step_fn(inputs):
    """The computation to run on each TPU device."""
    images, labels = inputs
    with tf.GradientTape() as tape:
      logits = model(images, training=True)
      loss = tf.keras.losses.sparse_categorical_crossentropy(
          labels, logits, from_logits=True)
      loss = tf.nn.compute_average_loss(loss, global_batch_size=batch_size)
    grads = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(list(zip(grads, model.trainable_variables)))
    training_loss.update_state(loss * strategy.num_replicas_in_sync)
    training_accuracy.update_state(labels, logits)

  strategy.run(step_fn, args=(next(iterator),))
WARNING:tensorflow:From <ipython-input-1-5625c2a14441>:15: StrategyBase.experimental_distribute_datasets_from_function (from tensorflow.python.distribute.distribute_lib) is deprecated and will be removed in a future version.
Instructions for updating:
rename to distribute_datasets_from_function
WARNING:tensorflow:From <ipython-input-1-5625c2a14441>:15: StrategyBase.experimental_distribute_datasets_from_function (from tensorflow.python.distribute.distribute_lib) is deprecated and will be removed in a future version.
Instructions for updating:
rename to distribute_datasets_from_function

Quindi, esegui il ciclo di allenamento:

steps_per_eval = 10000 // batch_size

train_iterator = iter(train_dataset)
for epoch in range(5):
  print('Epoch: {}/5'.format(epoch))

  for step in range(steps_per_epoch):
    train_step(train_iterator)
  print('Current step: {}, training loss: {}, accuracy: {}%'.format(
      optimizer.iterations.numpy(),
      round(float(training_loss.result()), 4),
      round(float(training_accuracy.result()) * 100, 2)))
  training_loss.reset_states()
  training_accuracy.reset_states()
Epoch: 0/5
Current step: 300, training loss: 0.1436, accuracy: 95.42%
Epoch: 1/5
Current step: 600, training loss: 0.0342, accuracy: 98.94%
Epoch: 2/5
Current step: 900, training loss: 0.0205, accuracy: 99.36%
Epoch: 3/5
Current step: 1200, training loss: 0.0123, accuracy: 99.59%
Epoch: 4/5
Current step: 1500, training loss: 0.0089, accuracy: 99.68%

Miglioramento delle prestazioni con più passaggi all'interno tf.function

È possibile migliorare le prestazioni per l'esecuzione di più passaggi all'interno di una tf.function . Questo risultato è ottenuto avvolgendo lo strategy.run chiamata con un tf.range all'interno tf.function , e AutoGraph verrà convertito in un tf.while_loop del lavoratore TPU.

Nonostante il miglioramento delle prestazioni, ci sono dei compromessi con questo metodo rispetto alla corsa un singolo passo all'interno tf.function . L'esecuzione di più passaggi in un tf.function è meno flessibile, non si può eseguire le cose con entusiasmo o codice Python arbitrario all'interno dei passaggi.

@tf.function
def train_multiple_steps(iterator, steps):
  """The step function for one training step."""

  def step_fn(inputs):
    """The computation to run on each TPU device."""
    images, labels = inputs
    with tf.GradientTape() as tape:
      logits = model(images, training=True)
      loss = tf.keras.losses.sparse_categorical_crossentropy(
          labels, logits, from_logits=True)
      loss = tf.nn.compute_average_loss(loss, global_batch_size=batch_size)
    grads = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(list(zip(grads, model.trainable_variables)))
    training_loss.update_state(loss * strategy.num_replicas_in_sync)
    training_accuracy.update_state(labels, logits)

  for _ in tf.range(steps):
    strategy.run(step_fn, args=(next(iterator),))

# Convert `steps_per_epoch` to `tf.Tensor` so the `tf.function` won't get 
# retraced if the value changes.
train_multiple_steps(train_iterator, tf.convert_to_tensor(steps_per_epoch))

print('Current step: {}, training loss: {}, accuracy: {}%'.format(
      optimizer.iterations.numpy(),
      round(float(training_loss.result()), 4),
      round(float(training_accuracy.result()) * 100, 2)))
Current step: 1800, training loss: 0.0093, accuracy: 99.68%

Prossimi passi