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 öğretici, özel eğitim döngüleriyle tf.distribute.Strategy nasıl kullanılacağını gösterir. 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__)
tutucu1 l10n-yer
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

tf.distribute.MirroredStrategy stratejisi nasıl çalışır?

  • 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',)
yer tutucu5 l10n-yer
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

tf.keras.Sequential kullanarak bir model oluşturun. 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
tutucu10 l10n-yer
# 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.

Peki, bir tf.distribute.Strategy kullanırken kayıp nasıl hesaplanmalıdır?

  • Ö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?

  • Bunun yapılması gerekir, çünkü her replikadaki degradeler hesaplandıktan sonra, bunlar toplanarak replikalar arasında eşitlenir.

Bunu TensorFlow'da nasıl yapabilirim?

  • Bu öğreticide olduğu gibi özel bir eğitim döngüsü yazıyorsanız, örnek başına kayıpları toplamalı ve toplamı GLOBAL_BATCH_SIZE'a bölmelisiniz: scale_loss = tf.reduce_sum(loss) * (1. / GLOBAL_BATCH_SIZE) veya tf.nn.compute_average_loss kullanabilirsiniz Örnek başına kaybı, isteğe bağlı örnek ağırlıklarını ve tf.nn.compute_average_loss bağımsız değişken olarak alan ve ölçeklenmiş kaybı döndüren .nn.compute_average_loss.

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

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

  • Bu küçültme ve ölçekleme, keras model.compile ve model.fit otomatik olarak yapılır.

  • tf.keras.losses sınıfları kullanılıyorsa (aşağıdaki örnekte olduğu gibi), kayıp azaltmanın açıkça NONE veya SUM olarak belirtilmesi gerekir. tf.distribute.Strategy ile kullanıldığında AUTO ve SUM_OVER_BATCH_SIZE izin tf.distribute.Strategy . AUTO izin verilmez, çünkü kullanıcının dağıtılmış durumda doğru olduğundan emin olmak için hangi azaltmayı istediğini açıkça düşünmesi gerekir. SUM_OVER_BATCH_SIZE şu anda yalnızca kopya parti boyutuna göre bölüneceği ve kopya sayısına göre bölmeyi kullanıcıya bırakacağı için izin verilmemektedir, bu da gözden kaçırılması kolay olabilir. Bunun yerine kullanıcıdan indirgemeyi açıkça yapmasını istiyoruz.

  • labels çok boyutluysa, her örnekteki öğe sayısı boyunca per_example_loss ortalamasını alın. Örneğin, predictions şekli (batch_size, H, W, n_classes) ve labels (batch_size, H, W) ise, per_example_loss şekilde güncellemeniz gerekir: 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. Birikmiş istatistikleri istediğiniz zaman almak için .result() 'u kullanabilirsiniz.

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')
tutucu13 l10n-yer
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)
yer tutucu16 l10n-yer
# `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

tf.distribute.Strategy ile kontrol noktası olan bir model, stratejili veya stratejisiz olarak 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)
yer tutucu20 l10n-yer
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

Tüm veri kümesi boyunca değil, belirli bir sayıda adım üzerinde yineleme yapmak istiyorsanız, yineleyicide next iter çağrısını ve açık çağrıyı kullanarak bir yineleyici oluşturabilirsiniz. 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()
tutucu23 l10n-yer
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, for x in ... yapısını kullanarak veya yukarıda yaptığımız gibi yineleyiciler oluşturarak bir train_dist_dataset içindeki bütün train_dist_dataset girdisini yineleyebilirsiniz. Aşağıdaki örnek, bir eğitim dönemini bir tf.function içine sarmayı ve işlevin içinde train_dist_dataset üzerinde yinelemeyi gösterir.

@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()
tutucu25 l10n-yer
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

Gerçekleştirilen kayıp ölçeklendirme hesaplaması nedeniyle, farklı kopyalarda eğitim kaybını izlemek için tf.metrics.Mean kullanılmasını önermiyoruz .

Ö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 .

İki replikadaki kaybı izlemek için tf.metrics.Mean kullanırsanız, sonuç farklıdır. Bu örnekte, total 3,50 ve 2 count elde edersiniz, bu da metrikte result() çağrıldığında total / count = 1,75 ile sonuçlanır. tf.keras.Metrics ile hesaplanan kayıp, eşitlemedeki kopya sayısına eşit olan ek bir faktörle ö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. MirroredStrategy kullanan DenseNet örneği.
  3. MirroredStrategy ve TPUStrategy kullanılarak eğitilmiş BERT örneği. Bu örnek, bir kontrol noktasından nasıl yükleneceğini ve dağıtılmış eğitim vb. sırasında periyodik kontrol noktalarının nasıl oluşturulacağını anlamak için özellikle yararlıdır.
  4. keras_use_ctl bayrağı kullanılarak etkinleştirilebilen MirroredStrategy kullanılarak eğitilmiş NCF örneği.
  5. MirroredStrategy kullanılarak eğitilmiş NMT örneği.

Dağıtım stratejisi kılavuzunda listelenen daha fazla örnek.

Sonraki adımlar

  • Modellerinizde yeni tf.distribute.Strategy API'sini deneyin.
  • TensorFlow modellerinizin performansını optimize etmek için kullanabileceğiniz diğer stratejiler ve araçlar hakkında daha fazla bilgi edinmek için kılavuzdaki Performans bölümünü ziyaret edin.