Yardım Kaggle üzerinde TensorFlow ile Büyük Bariyer Resifi korumak Meydan Üyelik

tf.distribute.Strategy ile özel eğitim

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

Bu eğitimde nasıl kullanılacağını göstermektedir tf.distribute.Strategy özel eğitim döngüler ile. Moda MNIST veri seti üzerinde basit bir CNN modeli eğiteceğiz. Moda MNIST veri seti, 28 x 28 boyutunda 60000 tren görüntüsü ve 28 x 28 boyutunda 10000 test görüntüsü içerir.

Modelimizi eğitmek için özel eğitim döngüleri kullanıyoruz çünkü bunlar bize eğitim üzerinde esneklik ve daha fazla kontrol sağlıyor. Ayrıca, modelde ve eğitim döngüsünde hata ayıklamak daha kolaydır.

# Import TensorFlow
import tensorflow as tf

# Helper libraries
import numpy as np
import os

print(tf.__version__)
2.5.0

Moda MNIST veri setini indirin

fashion_mnist = tf.keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

# Adding a dimension to the array -> new shape == (28, 28, 1)
# We are doing this because the first layer in our model is a convolutional
# layer and it requires a 4D input (batch_size, height, width, channels).
# batch_size dimension will be added later on.
train_images = train_images[..., None]
test_images = test_images[..., None]

# Getting the images in [0, 1] range.
train_images = train_images / np.float32(255)
test_images = test_images / np.float32(255)

Değişkenleri ve grafiği dağıtmak için bir strateji oluşturun

Nasıl tf.distribute.MirroredStrategy strateji çalışması?

  • Tüm değişkenler ve model grafiği, kopyalarda çoğaltılır.
  • Giriş, kopyalar arasında eşit olarak dağıtılır.
  • Her kopya, aldığı girdi için kaybı ve gradyanları hesaplar.
  • Degradeler, toplanarak tüm kopyalar arasında eşitlenir.
  • Eşitlemeden sonra, her replikadaki değişkenlerin kopyalarına aynı güncelleme yapılır.
# If the list of devices is not specified in the
# `tf.distribute.MirroredStrategy` constructor, it will be auto-detected.
strategy = tf.distribute.MirroredStrategy()
WARNING:tensorflow:Collective ops is not configured at program startup. Some performance features may not be enabled.
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
print ('Number of devices: {}'.format(strategy.num_replicas_in_sync))
Number of devices: 1

Giriş ardışık düzenini ayarla

Grafiği ve değişkenleri platformdan bağımsız SavedModel biçimine aktarın. Modeliniz kaydedildikten sonra dürbünlü veya dürbünsüz olarak yükleyebilirsiniz.

BUFFER_SIZE = len(train_images)

BATCH_SIZE_PER_REPLICA = 64
GLOBAL_BATCH_SIZE = BATCH_SIZE_PER_REPLICA * strategy.num_replicas_in_sync

EPOCHS = 10

Veri kümelerini oluşturun ve bunları dağıtın:

train_dataset = tf.data.Dataset.from_tensor_slices((train_images, train_labels)).shuffle(BUFFER_SIZE).batch(GLOBAL_BATCH_SIZE) 
test_dataset = tf.data.Dataset.from_tensor_slices((test_images, test_labels)).batch(GLOBAL_BATCH_SIZE) 

train_dist_dataset = strategy.experimental_distribute_dataset(train_dataset)
test_dist_dataset = strategy.experimental_distribute_dataset(test_dataset)

modeli oluştur

Kullanarak bir model oluşturma tf.keras.Sequential . Bunu yapmak için Model Alt Sınıflandırma API'sini de kullanabilirsiniz.

def create_model():
  model = tf.keras.Sequential([
      tf.keras.layers.Conv2D(32, 3, activation='relu'),
      tf.keras.layers.MaxPooling2D(),
      tf.keras.layers.Conv2D(64, 3, activation='relu'),
      tf.keras.layers.MaxPooling2D(),
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(64, activation='relu'),
      tf.keras.layers.Dense(10)
    ])

  return model
# Create a checkpoint directory to store the checkpoints.
checkpoint_dir = './training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")

Kayıp fonksiyonunu tanımlayın

Normalde, 1 GPU/CPU'lu tek bir makinede kayıp, girdi grubundaki örnek sayısına bölünür.

Bir ürünün kullanımında, nasıl kaybı hesaplanmalıdır tf.distribute.Strategy ?

  • Örnek olarak, 4 GPU'nuz ve 64'lük bir toplu iş boyutunuz olduğunu varsayalım. Bir toplu girdi, çoğaltmalara (4 GPU) dağıtılır ve her çoğaltma, 16 boyutunda bir girdi alır.

  • Her kopyadaki model, ilgili girdisiyle ileriye doğru bir geçiş yapar ve kaybı hesaplar. Şimdi, kaybı ilgili girişindeki örnek sayısına bölmek yerine (BATCH_SIZE_PER_REPLICA = 16), kayıp GLOBAL_BATCH_SIZE'a (64) bölünmelidir.

Bunu neden yapıyorsun?

  • Bu geçişlerini her çoğaltma hesaplanır sonra, bunları toplayarak kopyaları arasında senkronize çünkü yapılması gereken.

Bunu TensorFlow'da nasıl yapabilirim?

  • Eğer bu eğitimde gibi özel bir eğitim döngü, yazıyorsanız, örneğin başına kayıpları toplamı ve GLOBAL_BATCH_SIZE tarafından toplam ikiye bölünür olmalıdır: scale_loss = tf.reduce_sum(loss) * (1. / GLOBAL_BATCH_SIZE) veya kullanabilirsiniz tf.nn.compute_average_loss argümanları ve geri dönüş ölçekli kaybı örneğin başına kaybı, isteğe bağlı numune ağırlıkları ve GLOBAL_BATCH_SIZE alır.

  • Modelinizde düzenlileştirme kayıpları kullanıyorsanız, kayıp değerini kopya sayısına göre ölçeklendirmeniz gerekir. Sen kullanarak bunu yapabilirsiniz tf.nn.scale_regularization_loss fonksiyonunu.

  • Kullanılması tf.reduce_mean önerilmez. Bunu yapmak, kaybı, adım adım değişebilen gerçek kopya başına toplu iş boyutuna böler.

  • Bu azalma ve ölçekleme keras içinde otomatik olarak yapılır model.compile ve model.fit

  • Kullanılıyorsa tf.keras.losses (aşağıdaki örnekte olduğu gibi) sınıfları, kayıp indirgeme açıkça biri olduğu belirtilmesi gerekir NONE veya SUM . AUTO ve SUM_OVER_BATCH_SIZE ile kullanıldığında izin verilmez tf.distribute.Strategy . AUTO Kullanıcı açık bir hale istediklerini azaltma düşünmek gerekir çünkü izin verilmeyen emin dağıtılmış durumda doğrudur. SUM_OVER_BATCH_SIZE anda yalnızca çoğaltma toplu boyut başına bölün ve kaçıran kolay olabilir kullanıcı için kopyaları sayısına göre bölünmesini bırakacaktı, çünkü izin verilmez. Bunun yerine kullanıcıdan indirgemeyi açıkça yapmasını istiyoruz.

  • Eğer labels çok boyutlu, daha sonra ortalama per_example_loss her numunede elemanların sayısı içinde. Örneğin, şekli ise predictions olan (batch_size, H, W, n_classes) ve labels olup (batch_size, H, W) , güncelleştirme gerekir per_example_loss : gibi per_example_loss /= tf.cast(tf.reduce_prod(tf.shape(labels)[1:]), tf.float32)

with strategy.scope():
  # Set reduction to `none` so we can do the reduction afterwards and divide by
  # global batch size.
  loss_object = tf.keras.losses.SparseCategoricalCrossentropy(
      from_logits=True,
      reduction=tf.keras.losses.Reduction.NONE)
  def compute_loss(labels, predictions):
    per_example_loss = loss_object(labels, predictions)
    return tf.nn.compute_average_loss(per_example_loss, global_batch_size=GLOBAL_BATCH_SIZE)

Kaybı ve doğruluğu izlemek için metrikleri tanımlayın

Bu metrikler, test kaybını, eğitimi ve test doğruluğunu izler. Sen kullanabilirsiniz .result() herhangi bir zamanda birikmiş istatistikleri almak.

with strategy.scope():
  test_loss = tf.keras.metrics.Mean(name='test_loss')

  train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(
      name='train_accuracy')
  test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(
      name='test_accuracy')
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).

Eğitim döngüsü

# model, optimizer, and checkpoint must be created under `strategy.scope`.
with strategy.scope():
  model = create_model()

  optimizer = tf.keras.optimizers.Adam()

  checkpoint = tf.train.Checkpoint(optimizer=optimizer, model=model)
def train_step(inputs):
  images, labels = inputs

  with tf.GradientTape() as tape:
    predictions = model(images, training=True)
    loss = compute_loss(labels, predictions)

  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

  train_accuracy.update_state(labels, predictions)
  return loss 

def test_step(inputs):
  images, labels = inputs

  predictions = model(images, training=False)
  t_loss = loss_object(labels, predictions)

  test_loss.update_state(t_loss)
  test_accuracy.update_state(labels, predictions)
# `run` replicates the provided computation and runs it
# with the distributed input.
@tf.function
def distributed_train_step(dataset_inputs):
  per_replica_losses = strategy.run(train_step, args=(dataset_inputs,))
  return strategy.reduce(tf.distribute.ReduceOp.SUM, per_replica_losses,
                         axis=None)

@tf.function
def distributed_test_step(dataset_inputs):
  return strategy.run(test_step, args=(dataset_inputs,))

for epoch in range(EPOCHS):
  # TRAIN LOOP
  total_loss = 0.0
  num_batches = 0
  for x in train_dist_dataset:
    total_loss += distributed_train_step(x)
    num_batches += 1
  train_loss = total_loss / num_batches

  # TEST LOOP
  for x in test_dist_dataset:
    distributed_test_step(x)

  if epoch % 2 == 0:
    checkpoint.save(checkpoint_prefix)

  template = ("Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, "
              "Test Accuracy: {}")
  print (template.format(epoch+1, train_loss,
                         train_accuracy.result()*100, test_loss.result(),
                         test_accuracy.result()*100))

  test_loss.reset_states()
  train_accuracy.reset_states()
  test_accuracy.reset_states()
Epoch 1, Loss: 0.5044084787368774, Accuracy: 81.87333679199219, Test Loss: 0.3816865086555481, Test Accuracy: 86.5999984741211
Epoch 2, Loss: 0.3375805616378784, Accuracy: 87.8566665649414, Test Loss: 0.3369813859462738, Test Accuracy: 87.76000213623047
Epoch 3, Loss: 0.2896445095539093, Accuracy: 89.50499725341797, Test Loss: 0.299490362405777, Test Accuracy: 89.22000122070312
Epoch 4, Loss: 0.259074866771698, Accuracy: 90.58833312988281, Test Loss: 0.2881558835506439, Test Accuracy: 89.33000183105469
Epoch 5, Loss: 0.2341146171092987, Accuracy: 91.38999938964844, Test Loss: 0.2916182577610016, Test Accuracy: 89.61000061035156
Epoch 6, Loss: 0.21513047814369202, Accuracy: 92.02333068847656, Test Loss: 0.2755740284919739, Test Accuracy: 89.85000610351562
Epoch 7, Loss: 0.1952667236328125, Accuracy: 92.88333129882812, Test Loss: 0.27464523911476135, Test Accuracy: 90.36000061035156
Epoch 8, Loss: 0.17831537127494812, Accuracy: 93.3566665649414, Test Loss: 0.26432710886001587, Test Accuracy: 90.19000244140625
Epoch 9, Loss: 0.16429665684700012, Accuracy: 93.85333251953125, Test Loss: 0.2659859359264374, Test Accuracy: 91.0999984741211
Epoch 10, Loss: 0.1503313183784485, Accuracy: 94.42166900634766, Test Loss: 0.2602477967739105, Test Accuracy: 91.06999969482422

Yukarıdaki örnekte dikkat edilmesi gerekenler:

En son kontrol noktasını geri yükleyin ve test edin

Bir ile checkpointed bir model tf.distribute.Strategy ile veya bir strateji olmadan geri yüklenebilir.

eval_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(
      name='eval_accuracy')

new_model = create_model()
new_optimizer = tf.keras.optimizers.Adam()

test_dataset = tf.data.Dataset.from_tensor_slices((test_images, test_labels)).batch(GLOBAL_BATCH_SIZE)
@tf.function
def eval_step(images, labels):
  predictions = new_model(images, training=False)
  eval_accuracy(labels, predictions)
checkpoint = tf.train.Checkpoint(optimizer=new_optimizer, model=new_model)
checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))

for images, labels in test_dataset:
  eval_step(images, labels)

print ('Accuracy after restoring the saved model without strategy: {}'.format(
    eval_accuracy.result()*100))
Accuracy after restoring the saved model without strategy: 91.0999984741211

Bir veri kümesi üzerinde yineleme yapmanın alternatif yolları

Yineleyicileri kullanma

Eğer tüm veri kümesi içinden verilen bir adım sayısını değil, üzerinde yineleme yapmak istiyorsanız kullandığınız bir yineleyici oluşturabilir iter çağrısı ve açıkça çağrı next yineleyici üzerinde. tf.function içinde ve dışında veri kümesi üzerinde yineleme yapmayı seçebilirsiniz. İşte bir yineleyici kullanarak tf.function dışında veri kümesinin yinelemesini gösteren küçük bir pasaj.

for _ in range(EPOCHS):
  total_loss = 0.0
  num_batches = 0
  train_iter = iter(train_dist_dataset)

  for _ in range(10):
    total_loss += distributed_train_step(next(train_iter))
    num_batches += 1
  average_train_loss = total_loss / num_batches

  template = ("Epoch {}, Loss: {}, Accuracy: {}")
  print (template.format(epoch+1, average_train_loss, train_accuracy.result()*100))
  train_accuracy.reset_states()
Epoch 10, Loss: 0.14126229286193848, Accuracy: 95.0
Epoch 10, Loss: 0.1343936026096344, Accuracy: 95.0
Epoch 10, Loss: 0.12443388998508453, Accuracy: 94.84375
Epoch 10, Loss: 0.1607474684715271, Accuracy: 94.21875
Epoch 10, Loss: 0.10524413734674454, Accuracy: 96.71875
Epoch 10, Loss: 0.11492376029491425, Accuracy: 96.71875
Epoch 10, Loss: 0.16041627526283264, Accuracy: 94.21875
Epoch 10, Loss: 0.13022005558013916, Accuracy: 94.6875
Epoch 10, Loss: 0.17113295197486877, Accuracy: 93.28125
Epoch 10, Loss: 0.12315043061971664, Accuracy: 95.625

Bir tf.function içinde yineleme

Ayrıca yinelerler tüm giriş üzerinde olabilir train_dist_dataset kullanarak bir tf.function içeride for x in ... yukarıda yaptığımız gibi yapı veya tarafından yineleyiciler oluşturmak. Aşağıdaki örnek tf.function eğitim zamanında bir devre sarma ve yineleme gösteren train_dist_dataset işlevi içinde.

@tf.function
def distributed_train_epoch(dataset):
  total_loss = 0.0
  num_batches = 0
  for x in dataset:
    per_replica_losses = strategy.run(train_step, args=(x,))
    total_loss += strategy.reduce(
      tf.distribute.ReduceOp.SUM, per_replica_losses, axis=None)
    num_batches += 1
  return total_loss / tf.cast(num_batches, dtype=tf.float32)

for epoch in range(EPOCHS):
  train_loss = distributed_train_epoch(train_dist_dataset)

  template = ("Epoch {}, Loss: {}, Accuracy: {}")
  print (template.format(epoch+1, train_loss, train_accuracy.result()*100))

  train_accuracy.reset_states()
Epoch 1, Loss: 0.13766956329345703, Accuracy: 94.89666748046875
Epoch 2, Loss: 0.12510614097118378, Accuracy: 95.35166931152344
Epoch 3, Loss: 0.11464647948741913, Accuracy: 95.70333099365234
Epoch 4, Loss: 0.10295023769140244, Accuracy: 96.12000274658203
Epoch 5, Loss: 0.09352775663137436, Accuracy: 96.49666595458984
Epoch 6, Loss: 0.08494547754526138, Accuracy: 96.87166595458984
Epoch 7, Loss: 0.07917638123035431, Accuracy: 97.09166717529297
Epoch 8, Loss: 0.07128290832042694, Accuracy: 97.37833404541016
Epoch 9, Loss: 0.06662175804376602, Accuracy: 97.47999572753906
Epoch 10, Loss: 0.06016768515110016, Accuracy: 97.82833099365234

Replikalar arasında eğitim kaybını izleme

Biz kullanılmasını önermiyoruz tf.metrics.Mean çünkü gerçekleştirilir kaybı ölçekleme hesaplama, farklı kopyaları çeşitli yerlerindeki eğitim kaybını izlemek için.

Örneğin, aşağıdaki özelliklere sahip bir eğitim işi yürütürseniz:

  • iki kopya
  • Her kopyada iki numune işlenir
  • Ortaya çıkan kayıp değerleri: [2, 3] ve [4, 5] her replikada
  • Genel parti boyutu = 4

Kayıp ölçekleme ile, kayıp değerlerini toplayarak ve ardından genel parti boyutuna bölerek her bir replikadaki kaybın örnek başına değerini hesaplarsınız. Bu durumda: (2 + 3) / 4 = 1.25 ve (4 + 5) / 4 = 2.25 .

Eğer kullanırsanız tf.metrics.Mean iki yineleme arasında kaybını izlemek için, sonuç farklıdır. Bu örnekte, bir ile son total 3.50 ve count , 2 hangi sonuçları total / count zaman = 1.75 result() metrik olarak adlandırılır. Hesaplanan kaybı tf.keras.Metrics senkronize yinelemeler sayısına eşit bir ek faktör ile ölçeklenir.

Kılavuz ve örnekler

Özel eğitim döngüleriyle dağıtım stratejisini kullanmaya ilişkin bazı örnekler:

  1. Dağıtılmış eğitim kılavuzu
  2. DenseNet kullanılarak, örnek MirroredStrategy .
  3. Bert örneği kullanılarak eğitimli MirroredStrategy ve TPUStrategy . Bu örnek, dağıtılmış eğitim vb. sırasında bir kontrol noktasından nasıl yükleneceğini ve periyodik kontrol noktalarının nasıl oluşturulacağını anlamak için özellikle yararlıdır.
  4. KDK örneği kullanılarak eğitimli MirroredStrategy kullanılarak etkinleştirilebilir keras_use_ctl bayrağı.
  5. NMT örneği kullanılarak eğitimli MirroredStrategy .

Listelenen fazla örnek Dağıtım strateji rehberi .

Sonraki adımlar