Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Pelatihan yang didistribusikan dengan TensorFlow

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Gambaran

tf.distribute.Strategy adalah TensorFlow API untuk mendistribusikan pelatihan di beberapa GPU, beberapa mesin atau TPU. Dengan menggunakan API ini, Anda dapat mendistribusikan model dan kode pelatihan yang ada dengan perubahan kode minimal.

tf.distribute.Strategy telah dirancang dengan mempertimbangkan tujuan-tujuan utama ini:

  • Mudah digunakan dan mendukung berbagai segmen pengguna, termasuk peneliti, insinyur ML, dll.
  • Memberikan kinerja yang baik di luar kotak.
  • Perpindahan antar strategi dengan mudah.

tf.distribute.Strategy dapat digunakan dengan API tingkat tinggi seperti Keras , dan juga dapat digunakan untuk mendistribusikan loop pelatihan khusus (dan, secara umum, setiap perhitungan menggunakan TensorFlow).

Di TensorFlow 2.x, Anda dapat menjalankan program dengan penuh semangat, atau dalam grafik menggunakan tf.function . tf.distribute.Strategy bermaksud mendukung kedua mode eksekusi ini, tetapi berfungsi paling baik dengan tf.function . Mode bersemangat hanya disarankan untuk tujuan debugging dan tidak didukung untuk TPUStrategy . Meskipun kami sering membahas pelatihan dalam panduan ini, API ini juga dapat digunakan untuk mendistribusikan evaluasi dan prediksi pada berbagai platform.

Anda dapat menggunakan tf.distribute.Strategy dengan sedikit perubahan pada kode Anda, karena kami telah mengubah komponen mendasar TensorFlow menjadi sadar strategi. Ini termasuk variabel, layer, model, pengoptimal, metrik, ringkasan, dan pos pemeriksaan.

Dalam panduan ini, kami menjelaskan berbagai jenis strategi dan bagaimana Anda dapat menggunakannya dalam situasi yang berbeda.

 # Import TensorFlow
import tensorflow as tf
 

Jenis strategi

tf.distribute.Strategy bermaksud untuk mencakup sejumlah kasus penggunaan di sepanjang sumbu yang berbeda. Beberapa kombinasi ini saat ini didukung dan yang lainnya akan ditambahkan di masa mendatang. Beberapa sumbu ini adalah:

  • Pelatihan sinkron vs asinkron: Ini adalah dua cara umum untuk mendistribusikan pelatihan dengan paralelisme data. Dalam pelatihan sinkronisasi, semua pekerja melatih berbagai irisan data input dalam sinkronisasi, dan mengagregasi gradien pada setiap langkah. Dalam pelatihan async, semua pekerja secara terpisah berlatih atas input data dan memperbarui variabel secara tidak sinkron. Pelatihan sinkronisasi biasanya didukung melalui all-reduction dan async melalui arsitektur server parameter.
  • Platform perangkat keras: Anda mungkin ingin mengukur pelatihan Anda ke beberapa GPU pada satu mesin, atau beberapa mesin dalam jaringan (dengan masing-masing 0 atau lebih GPU), atau di Cloud TPUs.

Untuk mendukung kasus penggunaan ini, ada enam strategi yang tersedia. Pada bagian selanjutnya kami menjelaskan skenario mana yang didukung dalam skenario mana dalam TF 2.2 saat ini. Berikut ini ikhtisar singkat:

API Pelatihan Strategi Mirrored Strategi TPUS Strategi MultiWorkerMirrored CentralStorageStrategy ParameterServerStrategy
API Keras Didukung Didukung Dukungan eksperimental Dukungan eksperimental Pos terencana yang didukung 2.3
Lingkaran pelatihan khusus Didukung Didukung Dukungan eksperimental Dukungan eksperimental Pos terencana yang didukung 2.3
API Pengukur Dukungan Terbatas Tidak didukung Dukungan Terbatas Dukungan Terbatas Dukungan Terbatas

Strategi Mirrored

tf.distribute.MirroredStrategy mendukung pelatihan didistribusikan secara sinkron pada beberapa GPU pada satu mesin. Ini menciptakan satu replika per perangkat GPU. Setiap variabel dalam model dicerminkan di semua replika. Bersama-sama, variabel-variabel ini membentuk variabel konseptual tunggal yang disebut MirroredVariable . Variabel-variabel ini tetap disinkronkan satu sama lain dengan menerapkan pembaruan yang identik.

Algoritma pengurangan semua efisien digunakan untuk mengkomunikasikan pembaruan variabel di seluruh perangkat. Semua-perkecil agregat tensor di semua perangkat dengan menambahkannya, dan membuatnya tersedia di setiap perangkat. Ini adalah algoritma yang menyatu yang sangat efisien dan dapat mengurangi overhead sinkronisasi secara signifikan. Ada banyak algoritme dan implementasi semua pengurangan yang tersedia, tergantung pada jenis komunikasi yang tersedia antar perangkat. Secara default, ini menggunakan NVIDIA NCCL sebagai implementasi semua-mengurangi. Anda dapat memilih dari beberapa opsi lain yang kami sediakan, atau menulis sendiri.

Inilah cara paling sederhana untuk membuat MirroredStrategy :

 mirrored_strategy = tf.distribute.MirroredStrategy()
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)

Ini akan membuat instance MirroredStrategy yang akan menggunakan semua GPU yang terlihat oleh TensorFlow, dan menggunakan NCCL sebagai komunikasi lintas perangkat.

Jika Anda ingin menggunakan hanya beberapa GPU pada mesin Anda, Anda dapat melakukannya seperti ini:

 mirrored_strategy = tf.distribute.MirroredStrategy(devices=["/gpu:0", "/gpu:1"])
 
WARNING:tensorflow:Some requested devices in `tf.distribute.Strategy` are not visible to TensorFlow: /job:localhost/replica:0/task:0/device:GPU:0,/job:localhost/replica:0/task:0/device:GPU:1
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0', '/job:localhost/replica:0/task:0/device:GPU:1')

Jika Anda ingin mengganti komunikasi lintas perangkat, Anda dapat melakukannya dengan menggunakan argumen cross_device_ops dengan memasok turunan dari tf.distribute.CrossDeviceOps . Saat ini, tf.distribute.HierarchicalCopyAllReduce dan tf.distribute.ReductionToOneDevice adalah dua opsi selain tf.distribute.NcclAllReduce yang merupakan default.

 mirrored_strategy = tf.distribute.MirroredStrategy(
    cross_device_ops=tf.distribute.HierarchicalCopyAllReduce())
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)

Strategi TPUS

tf.distribute.TPUStrategy memungkinkan Anda menjalankan pelatihan TensorFlow di Tensor Processing Units (TPUs). TPU adalah ASIC khusus Google yang dirancang untuk secara dramatis mempercepat beban kerja pembelajaran mesin. Mereka tersedia di Google Colab, TensorFlow Research Cloud dan Cloud TPU .

Dalam hal arsitektur pelatihan terdistribusi, TPUStrategy adalah MirroredStrategy sama - itu mengimplementasikan pelatihan terdistribusi sinkron. TPU menyediakan implementasi sendiri untuk semua pengurangan yang efisien dan operasi kolektif lainnya di beberapa inti TPU, yang digunakan dalam TPUStrategy .

Inilah cara Anda membuat TPUStrategy :

 cluster_resolver = tf.distribute.cluster_resolver.TPUClusterResolver(
    tpu=tpu_address)
tf.config.experimental_connect_to_cluster(cluster_resolver)
tf.tpu.experimental.initialize_tpu_system(cluster_resolver)
tpu_strategy = tf.distribute.TPUStrategy(cluster_resolver)
 

Contoh TPUClusterResolver membantu menemukan TPU. Di Colab, Anda tidak perlu menentukan argumen apa pun untuknya.

Jika Anda ingin menggunakan ini untuk Cloud TPUs:

  • Anda harus menentukan nama sumber daya TPU Anda dalam argumen tpu .
  • Anda harus menginisialisasi sistem TPU secara eksplisit di awal program. Ini diperlukan sebelum TPU dapat digunakan untuk perhitungan. Menginisialisasi sistem TPU juga menghapus memori TPU, jadi penting untuk menyelesaikan langkah ini terlebih dahulu untuk menghindari kehilangan status.

Strategi MultiWorkerMirrored

tf.distribute.experimental.MultiWorkerMirroredStrategy sangat mirip dengan MirroredStrategy . Ini mengimplementasikan pelatihan terdistribusi sinkron di beberapa pekerja, masing-masing dengan beberapa GPU berpotensi. Mirip dengan MirroredStrategy , ini menciptakan salinan semua variabel dalam model pada setiap perangkat di semua pekerja.

Ini menggunakan CollectiveOps sebagai metode komunikasi multi-pengurangan semua pekerja yang digunakan untuk menjaga variabel tetap sinkron. Operasi kolektif adalah operasi tunggal dalam grafik TensorFlow yang dapat secara otomatis memilih algoritma semua-pengurangan dalam runtime TensorFlow sesuai dengan perangkat keras, topologi jaringan dan ukuran tensor.

Ini juga mengimplementasikan optimasi kinerja tambahan. Sebagai contoh, itu termasuk optimasi statis yang mengubah beberapa semua-pengurangan pada tensor kecil menjadi lebih sedikit semua-pengurangan pada tensor yang lebih besar. Selain itu, kami sedang mendesainnya untuk memiliki arsitektur plugin - sehingga di masa depan, Anda akan dapat menambahkan algoritme plugin yang lebih baik untuk perangkat keras Anda. Perhatikan bahwa operasi kolektif juga menerapkan operasi kolektif lainnya seperti siaran dan pengumpulan semua.

Berikut adalah cara paling sederhana untuk membuat MultiWorkerMirroredStrategy :

 multiworker_strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy()
 
WARNING:tensorflow:Collective ops is not configured at program startup. Some performance features may not be enabled.
INFO:tensorflow:Using MirroredStrategy with devices ('/device:GPU:0',)
INFO:tensorflow:Single-worker MultiWorkerMirroredStrategy with local_devices = ('/device:GPU:0',), communication = CollectiveCommunication.AUTO

MultiWorkerMirroredStrategy saat ini memungkinkan Anda untuk memilih antara dua implementasi operasi kolektif yang berbeda. CollectiveCommunication.RING mengimplementasikan kolektif berbasis cincin menggunakan gRPC sebagai lapisan komunikasi. CollectiveCommunication.NCCL menggunakan NCCL Nvidia untuk mengimplementasikan kolektif. Komunikasi CollectiveCommunication.AUTO ANUTO menolak opsi untuk runtime. Pilihan terbaik implementasi kolektif tergantung pada jumlah dan jenis GPU, dan interkoneksi jaringan di cluster. Anda dapat menentukannya dengan cara berikut:

 multiworker_strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy(
    tf.distribute.experimental.CollectiveCommunication.NCCL)
 
WARNING:tensorflow:Collective ops is not configured at program startup. Some performance features may not be enabled.
INFO:tensorflow:Using MirroredStrategy with devices ('/device:GPU:0',)
INFO:tensorflow:Single-worker MultiWorkerMirroredStrategy with local_devices = ('/device:GPU:0',), communication = CollectiveCommunication.NCCL

Salah satu perbedaan utama untuk menjalankan pelatihan multi-pekerja, dibandingkan dengan pelatihan multi-GPU, adalah pengaturan multi-pekerja. TF_CONFIG lingkungan TF_CONFIG adalah cara standar di TensorFlow untuk menentukan konfigurasi cluster untuk setiap pekerja yang merupakan bagian dari cluster. Pelajari lebih lanjut tentang menyiapkan TF_CONFIG .

CentralStorageStrategy

tf.distribute.experimental.CentralStorageStrategy juga melakukan pelatihan sinkron. Variabel tidak dicerminkan, melainkan ditempatkan pada CPU dan operasi direplikasi di semua GPU lokal. Jika hanya ada satu GPU, semua variabel dan operasi akan ditempatkan pada GPU itu.

Buat instance CentralStorageStrategy dengan:

 central_storage_strategy = tf.distribute.experimental.CentralStorageStrategy()
 
INFO:tensorflow:ParameterServerStrategy (CentralStorageStrategy if you are using a single machine) with compute_devices = ['/job:localhost/replica:0/task:0/device:GPU:0'], variable_device = '/job:localhost/replica:0/task:0/device:GPU:0'

Ini akan membuat instance CentralStorageStrategy yang akan menggunakan semua GPU dan CPU yang terlihat. Pembaruan ke variabel pada replika akan dikumpulkan sebelum diterapkan ke variabel.

ParameterServerStrategy

tf.distribute.experimental.ParameterServerStrategy mendukung pelatihan server parameter pada banyak mesin. Dalam pengaturan ini, beberapa mesin ditetapkan sebagai pekerja dan beberapa sebagai server parameter. Setiap variabel model ditempatkan pada satu server parameter. Komputasi direplikasi di semua GPU dari semua pekerja.

Dalam hal kode, tampilannya mirip dengan strategi lain:

 ps_strategy = tf.distribute.experimental.ParameterServerStrategy()
 

Untuk pelatihan multi-pekerja, TF_CONFIG perlu menentukan konfigurasi server parameter dan pekerja di cluster Anda, yang dapat Anda baca lebih lanjut di TF_CONFIG di bawah ini .

Strategi lainnya

Selain strategi di atas, ada dua strategi lain yang mungkin berguna untuk membuat prototipe dan debugging saat menggunakan tf.distribute APIs.

Strategi Default

Strategi default adalah strategi distribusi yang hadir ketika tidak ada strategi distribusi eksplisit dalam ruang lingkup. Ini mengimplementasikan antarmuka tf.distribute.Strategy tetapi merupakan pass-through dan tidak memberikan distribusi aktual. Misalnya, strategy.run(fn) cukup memanggil fn . Kode yang ditulis menggunakan strategi ini harus berperilaku persis seperti kode yang ditulis tanpa strategi apa pun. Anda dapat menganggapnya sebagai strategi "tidak-op".

Strategi default adalah tunggal - dan seseorang tidak dapat membuat lebih banyak contoh. Itu dapat diperoleh dengan menggunakan tf.distribute.get_strategy() luar ruang lingkup strategi eksplisit apa pun (API yang sama yang dapat digunakan untuk memasukkan strategi saat ini di dalam ruang lingkup strategi eksplisit).

 default_strategy = tf.distribute.get_strategy()
 

Strategi ini melayani dua tujuan utama:

  • Hal ini memungkinkan penulisan kode perpustakaan distribusi sadar tanpa syarat. Misalnya, dalam pengoptimal, kita dapat melakukan tf.distribute.get_strategy() dan menggunakan strategi itu untuk mengurangi gradien - itu akan selalu mengembalikan objek strategi yang dapat kita sebut API pengurangan.
 # In optimizer or other library code
# Get currently active strategy
strategy = tf.distribute.get_strategy()
strategy.reduce("SUM", 1., axis=None)  # reduce some values
 
1.0
  • Mirip dengan kode perpustakaan, dapat digunakan untuk menulis program pengguna akhir untuk bekerja dengan dan tanpa strategi distribusi, tanpa memerlukan logika kondisional. Cuplikan kode contoh yang menggambarkan ini:
 if tf.config.list_physical_devices('gpu'):
  strategy = tf.distribute.MirroredStrategy()
else:  # use default strategy
  strategy = tf.distribute.get_strategy() 

with strategy.scope():
  # do something interesting
  print(tf.Variable(1.))
 
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>

OneDeviceStrategy

tf.distribute.OneDeviceStrategy adalah strategi untuk menempatkan semua variabel dan komputasi pada satu perangkat tertentu.

 strategy = tf.distribute.OneDeviceStrategy(device="/gpu:0")
 

Strategi ini berbeda dari strategi default dalam beberapa cara. Dalam strategi default, logika penempatan variabel tetap tidak berubah bila dibandingkan dengan menjalankan TensorFlow tanpa strategi distribusi apa pun. Tetapi ketika menggunakan OneDeviceStrategy , semua variabel yang dibuat dalam cakupannya secara eksplisit ditempatkan pada perangkat yang ditentukan. Selain itu, fungsi apa pun yang dipanggil melalui OneDeviceStrategy.run juga akan ditempatkan pada perangkat yang ditentukan.

Input yang didistribusikan melalui strategi ini akan di-prefetch ke perangkat yang ditentukan. Dalam strategi default, tidak ada distribusi input.

Mirip dengan strategi default, strategi ini juga dapat digunakan untuk menguji kode Anda sebelum beralih ke strategi lain yang sebenarnya didistribusikan ke beberapa perangkat / mesin. Ini akan menjalankan mesin strategi distribusi agak lebih dari strategi default, tetapi tidak sepenuhnya menggunakan MirroredStrategy atau TPUStrategy dll. Jika Anda ingin kode yang berperilaku seolah-olah tidak ada strategi, maka gunakan strategi default.

Sejauh ini kita telah berbicara tentang apa saja strategi berbeda yang tersedia dan bagaimana Anda dapat membuat instantiate. Dalam beberapa bagian berikutnya, kami akan berbicara tentang berbagai cara di mana Anda dapat menggunakannya untuk mendistribusikan pelatihan Anda. Kami akan menampilkan cuplikan kode pendek dalam panduan ini dan menautkan ke tutorial lengkap yang dapat Anda jalankan ujung ke ujung.

Menggunakan tf.distribute.Strategy dengan tf.keras.Model.fit

Kami telah mengintegrasikan tf.distribute.Strategy ke tf.keras yang merupakan implementasi spesifikasi Keras API dari TensorFlow. tf.keras adalah API tingkat tinggi untuk membangun dan melatih model. Dengan mengintegrasikan ke backend tf.keras , kami membuatnya mulus bagi Anda untuk mendistribusikan pelatihan Anda yang ditulis dalam kerangka pelatihan Keras menggunakan model.fit .

Inilah yang perlu Anda ubah dalam kode Anda:

  1. Buat instance dari tf.distribute.Strategy sesuai.
  2. Pindahkan pembuatan model Keras, pengoptimal, dan metrik ke dalam strategy.scope .

Kami mendukung semua jenis model Keras - berurutan, fungsional, dan subklas.

Berikut adalah cuplikan kode untuk melakukan ini untuk model Keras yang sangat sederhana dengan satu lapisan padat:

 mirrored_strategy = tf.distribute.MirroredStrategy()

with mirrored_strategy.scope():
  model = tf.keras.Sequential([tf.keras.layers.Dense(1, input_shape=(1,))])

model.compile(loss='mse', optimizer='sgd')
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)

Dalam contoh ini kami menggunakan MirroredStrategy sehingga kami dapat menjalankan ini pada mesin dengan beberapa GPU. strategy.scope() menunjukkan kepada Keras strategi mana yang digunakan untuk mendistribusikan pelatihan. Membuat model / pengoptimal / metrik di dalam lingkup ini memungkinkan kami untuk membuat variabel terdistribusi alih-alih variabel biasa. Setelah ini diatur, Anda dapat menyesuaikan model Anda seperti biasanya. MirroredStrategy menangani replikasi pelatihan model pada GPU yang tersedia, agregasi gradien, dan banyak lagi.

 dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(100).batch(10)
model.fit(dataset, epochs=2)
model.evaluate(dataset)
 
Epoch 1/2
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/data/ops/multi_device_iterator_ops.py:601: get_next_as_optional (from tensorflow.python.data.ops.iterator_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Iterator.get_next_as_optional()` instead.
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',).
10/10 [==============================] - 0s 2ms/step - loss: 1.0035
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',).
Epoch 2/2
10/10 [==============================] - 0s 1ms/step - loss: 0.4436
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',).
10/10 [==============================] - 0s 1ms/step - loss: 0.2755

0.27546340227127075

Di sini kami menggunakan tf.data.Dataset untuk memberikan pelatihan dan input eval. Anda juga dapat menggunakan array numpy:

 import numpy as np
inputs, targets = np.ones((100, 1)), np.ones((100, 1))
model.fit(inputs, targets, epochs=2, batch_size=10)
 
Epoch 1/2
10/10 [==============================] - 0s 1ms/step - loss: 0.1961
Epoch 2/2
10/10 [==============================] - 0s 1ms/step - loss: 0.0867

<tensorflow.python.keras.callbacks.History at 0x7fa17808e240>

Dalam kedua kasus (dataset atau numpy), setiap kumpulan input yang diberikan dibagi rata di antara beberapa replika. Misalnya, jika menggunakan MirroredStrategy dengan 2 GPU, setiap batch ukuran 10 akan dibagi di antara 2 GPU, dengan masing-masing menerima 5 contoh input di setiap langkah. Setiap zaman kemudian akan berlatih lebih cepat saat Anda menambahkan lebih banyak GPU. Biasanya, Anda ingin menambah ukuran bets saat Anda menambahkan lebih banyak akselerator sehingga dapat memanfaatkan daya komputasi ekstra secara efektif. Anda juga perlu menyesuaikan tingkat belajar Anda, tergantung pada modelnya. Anda dapat menggunakan strategy.num_replicas_in_sync untuk mendapatkan jumlah replika.

 # Compute global batch size using number of replicas.
BATCH_SIZE_PER_REPLICA = 5
global_batch_size = (BATCH_SIZE_PER_REPLICA *
                     mirrored_strategy.num_replicas_in_sync)
dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(100)
dataset = dataset.batch(global_batch_size)

LEARNING_RATES_BY_BATCH_SIZE = {5: 0.1, 10: 0.15}
learning_rate = LEARNING_RATES_BY_BATCH_SIZE[global_batch_size]
 

Apa yang didukung sekarang?

API Pelatihan Strategi Mirrored Strategi TPUS Strategi MultiWorkerMirrored CentralStorageStrategy ParameterServerStrategy
API Keras Didukung Didukung Dukungan eksperimental Dukungan eksperimental Mendukung pos yang direncanakan 2.3

Contoh dan Tutorial

Berikut adalah daftar tutorial dan contoh yang menggambarkan integrasi di atas ujung ke ujung dengan Keras:

  1. Tutorial untuk melatih MNIST dengan MirroredStrategy .
  2. Tutorial untuk melatih MNIST menggunakan MultiWorkerMirroredStrategy .
  3. Panduan tentang pelatihan MNIST menggunakan TPUStrategy .
  4. TensorFlow Model Taman repositori yang berisi koleksi state-of-the-art model diimplementasikan menggunakan berbagai strategi.

Menggunakan tf.distribute.Strategy dengan loop pelatihan khusus

Seperti yang Anda lihat, menggunakan tf.distribute.Strategy dengan Keras model.fit hanya perlu mengubah beberapa baris kode Anda. Dengan sedikit usaha, Anda juga dapat menggunakan tf.distribute.Strategy dengan loop pelatihan khusus.

Jika Anda membutuhkan lebih banyak fleksibilitas dan kontrol atas loop pelatihan Anda daripada yang dimungkinkan dengan Estimator atau Keras, Anda dapat menulis loop pelatihan khusus. Misalnya, saat menggunakan GAN, Anda mungkin ingin mengambil langkah generator atau diskriminator yang berbeda di setiap putaran. Demikian pula, kerangka kerja tingkat tinggi tidak terlalu cocok untuk pelatihan Pembelajaran Penguatan.

Untuk mendukung loop pelatihan khusus, kami menyediakan serangkaian metode inti melalui kelas tf.distribute.Strategy . Menggunakan ini mungkin memerlukan sedikit restrukturisasi kode pada awalnya, tetapi setelah selesai, Anda harus dapat beralih antara GPU, TPU, dan beberapa mesin hanya dengan mengubah contoh strategi.

Di sini kita akan menunjukkan potongan singkat yang menggambarkan kasus penggunaan ini untuk contoh pelatihan sederhana menggunakan model Keras yang sama seperti sebelumnya.

Pertama, kami membuat model dan pengoptimal dalam lingkup strategi. Ini memastikan bahwa variabel apa pun yang dibuat dengan model dan pengoptimal adalah variabel cermin.

 with mirrored_strategy.scope():
  model = tf.keras.Sequential([tf.keras.layers.Dense(1, input_shape=(1,))])
  optimizer = tf.keras.optimizers.SGD()
 

Selanjutnya, kita membuat dataset input dan memanggil tf.distribute.Strategy.experimental_distribute_dataset untuk mendistribusikan dataset berdasarkan strategi.

 dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(100).batch(
    global_batch_size)
dist_dataset = mirrored_strategy.experimental_distribute_dataset(dataset)
 

Kemudian, kami mendefinisikan satu langkah pelatihan. Kami akan menggunakan tf.GradientTape untuk menghitung gradien dan optimizer untuk menerapkan gradien tersebut untuk memperbarui variabel model kami. Untuk mendistribusikan langkah pelatihan ini, kami memasukkan fungsi train_step dan meneruskannya ke tf.distrbute.Strategy.run bersama dengan input dataset yang kami dapatkan dari dist_dataset dibuat sebelumnya:

 loss_object = tf.keras.losses.BinaryCrossentropy(
  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)

def train_step(inputs):
  features, labels = inputs

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

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

@tf.function
def distributed_train_step(dist_inputs):
  per_replica_losses = mirrored_strategy.run(train_step, args=(dist_inputs,))
  return mirrored_strategy.reduce(tf.distribute.ReduceOp.SUM, per_replica_losses,
                         axis=None)
 

Beberapa hal lain yang perlu diperhatikan dalam kode di atas:

  1. Kami menggunakan tf.nn.compute_average_loss untuk menghitung kerugian. tf.nn.compute_average_loss menjumlahkan kerugian per contoh dan membagi jumlahnya dengan global_batch_size. Ini penting karena nanti setelah gradien dihitung pada setiap replika, mereka dikumpulkan di seluruh replika dengan menjumlahkannya .
  2. Kami menggunakan tf.distribute.Strategy.reduce API untuk mengagregasi hasil yang dikembalikan oleh tf.distribute.Strategy.run . tf.distribute.Strategy.run mengembalikan hasil dari setiap replika lokal dalam strategi, dan ada beberapa cara untuk mengkonsumsi hasil ini. Anda dapat reduce untuk mendapatkan nilai gabungan. Anda juga dapat melakukan tf.distribute.Strategy.experimental_local_results untuk mendapatkan daftar nilai yang terkandung dalam hasil, satu per replika lokal.
  3. Ketika apply_gradients dipanggil dalam lingkup strategi distribusi, perilakunya diubah. Secara khusus, sebelum menerapkan gradien pada setiap instance paralel selama pelatihan sinkron, ia melakukan penjumlahan dari seluruh gradien.

Akhirnya, setelah kita menentukan langkah pelatihan, kita bisa mengulanginya di atas dist_dataset dan menjalankan pelatihan dalam satu lingkaran:

 for dist_inputs in dist_dataset:
  print(distributed_train_step(dist_inputs))
 
tf.Tensor(0.4155251, shape=(), dtype=float32)
tf.Tensor(0.41321823, shape=(), dtype=float32)
tf.Tensor(0.4109319, shape=(), dtype=float32)
tf.Tensor(0.40866604, shape=(), dtype=float32)
tf.Tensor(0.40642032, shape=(), dtype=float32)
tf.Tensor(0.40419456, shape=(), dtype=float32)
tf.Tensor(0.4019885, shape=(), dtype=float32)
tf.Tensor(0.399802, shape=(), dtype=float32)
tf.Tensor(0.39763477, shape=(), dtype=float32)
tf.Tensor(0.3954866, shape=(), dtype=float32)
tf.Tensor(0.39335734, shape=(), dtype=float32)
tf.Tensor(0.3912467, shape=(), dtype=float32)
tf.Tensor(0.38915452, shape=(), dtype=float32)
tf.Tensor(0.38708064, shape=(), dtype=float32)
tf.Tensor(0.38502476, shape=(), dtype=float32)
tf.Tensor(0.38298675, shape=(), dtype=float32)
tf.Tensor(0.38096642, shape=(), dtype=float32)
tf.Tensor(0.3789635, shape=(), dtype=float32)
tf.Tensor(0.3769779, shape=(), dtype=float32)
tf.Tensor(0.37500936, shape=(), dtype=float32)

Pada contoh di atas, kami mengulangi dist_dataset untuk memberikan masukan ke pelatihan Anda. Kami juga menyediakan tf.distribute.Strategy.make_experimental_numpy_dataset untuk mendukung input numpy. Anda dapat menggunakan API ini untuk membuat dataset sebelum memanggil tf.distribute.Strategy.experimental_distribute_dataset .

Cara lain untuk mengulang data Anda adalah dengan menggunakan iterator secara eksplisit. Anda mungkin ingin melakukan ini ketika Anda ingin menjalankan untuk sejumlah langkah tertentu dan bukan mengulangi seluruh dataset. Iterasi di atas sekarang akan dimodifikasi untuk membuat iterator terlebih dahulu dan kemudian secara eksplisit memanggil next untuk mendapatkan data input.

 iterator = iter(dist_dataset)
for _ in range(10):
  print(distributed_train_step(next(iterator)))
 
tf.Tensor(0.37305772, shape=(), dtype=float32)
tf.Tensor(0.3711228, shape=(), dtype=float32)
tf.Tensor(0.3692044, shape=(), dtype=float32)
tf.Tensor(0.36730233, shape=(), dtype=float32)
tf.Tensor(0.3654165, shape=(), dtype=float32)
tf.Tensor(0.36354658, shape=(), dtype=float32)
tf.Tensor(0.36169255, shape=(), dtype=float32)
tf.Tensor(0.3598542, shape=(), dtype=float32)
tf.Tensor(0.35803124, shape=(), dtype=float32)
tf.Tensor(0.3562236, shape=(), dtype=float32)

Ini mencakup kasus paling sederhana menggunakan tf.distribute.Strategy API untuk mendistribusikan loop pelatihan khusus. Kami sedang dalam proses meningkatkan API ini. Karena kasus penggunaan ini membutuhkan lebih banyak pekerjaan untuk mengadaptasi kode Anda, kami akan menerbitkan panduan terperinci yang terpisah di masa depan.

Apa yang didukung sekarang?

API Pelatihan Strategi Mirrored Strategi TPUS Strategi MultiWorkerMirrored CentralStorageStrategy ParameterServerStrategy
Loop Pelatihan Kustom Didukung Didukung Dukungan eksperimental Dukungan eksperimental Mendukung pos yang direncanakan 2.3

Contoh dan Tutorial

Berikut adalah beberapa contoh untuk menggunakan strategi distribusi dengan loop pelatihan khusus:

  1. Tutorial untuk melatih MNIST menggunakan MirroredStrategy .
  2. Panduan tentang pelatihan MNIST menggunakan TPUStrategy .
  3. TensorFlow Model Taman repositori yang berisi koleksi state-of-the-art model diimplementasikan menggunakan berbagai strategi.

Menggunakan tf.distribute.Strategy dengan Estimator (Dukungan terbatas)

tf.estimator adalah pelatihan TensorFlow API yang didistribusikan yang awalnya mendukung pendekatan server parameter async. Seperti dengan Keras, kami telah mengintegrasikan tf.distribute.Strategy ke tf.Estimator . Jika Anda menggunakan Estimator untuk pelatihan Anda, Anda dapat dengan mudah mengubah pelatihan terdistribusi dengan sedikit perubahan pada kode Anda. Dengan ini, pengguna Estimator sekarang dapat melakukan pelatihan didistribusikan secara sinkron pada beberapa GPU dan beberapa pekerja, serta menggunakan TPU. Namun, dukungan dalam Pengestimasi ini terbatas. Lihat Apa yang didukung sekarang bagian di bawah untuk detail lebih lanjut.

Penggunaan tf.distribute.Strategy dengan Estimator sedikit berbeda dari kasus Keras. Alih-alih menggunakan strategy.scope , sekarang kita meneruskan objek strategi ke RunConfig untuk Pengukur.

Berikut ini adalah cuplikan kode yang menunjukkan ini dengan LinearRegressor Estimator LinearRegressor dan MirroredStrategy :

 mirrored_strategy = tf.distribute.MirroredStrategy()
config = tf.estimator.RunConfig(
    train_distribute=mirrored_strategy, eval_distribute=mirrored_strategy)
regressor = tf.estimator.LinearRegressor(
    feature_columns=[tf.feature_column.numeric_column('feats')],
    optimizer='SGD',
    config=config)
 
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
INFO:tensorflow:Initializing RunConfig with distribution strategies.
INFO:tensorflow:Not using Distribute Coordinator.
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmp2ack9oru
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp2ack9oru', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': <tensorflow.python.distribute.mirrored_strategy.MirroredStrategy object at 0x7fa124522b38>, '_device_fn': None, '_protocol': None, '_eval_distribute': <tensorflow.python.distribute.mirrored_strategy.MirroredStrategy object at 0x7fa124522b38>, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1, '_distribute_coordinator_mode': None}

Kami menggunakan Penaksir awal di sini, tetapi kode yang sama juga berfungsi dengan Penaksir khusus. train_distribute menentukan bagaimana pelatihan akan didistribusikan, dan eval_distribute menentukan bagaimana evaluasi akan didistribusikan. Ini adalah perbedaan lain dari Keras di mana kami menggunakan strategi yang sama untuk pelatihan dan evaluasi.

Sekarang kita dapat melatih dan mengevaluasi Estimator ini dengan fungsi input:

 def input_fn():
  dataset = tf.data.Dataset.from_tensors(({"feats":[1.]}, [1.]))
  return dataset.repeat(1000).batch(10)
regressor.train(input_fn=input_fn, steps=10)
regressor.evaluate(input_fn=input_fn, steps=10)
 
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_estimator/python/estimator/canned/linear.py:1481: Layer.add_variable (from tensorflow.python.keras.engine.base_layer_v1) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.add_weight` method instead.
INFO:tensorflow:Done calling model_fn.
WARNING:tensorflow:AutoGraph could not transform <function _combine_distributed_scaffold.<locals>.<lambda> at 0x7fa12452cb70> and will run it as-is.
Cause: could not parse the source code:

      lambda scaffold: scaffold.ready_op, args=(grouped_scaffold,))

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function _combine_distributed_scaffold.<locals>.<lambda> at 0x7fa12452cb70> and will run it as-is.
Cause: could not parse the source code:

      lambda scaffold: scaffold.ready_op, args=(grouped_scaffold,))

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
INFO:tensorflow:Create CheckpointSaverHook.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_estimator/python/estimator/util.py:96: DistributedIteratorV1.initialize (from tensorflow.python.distribute.input_lib) is deprecated and will be removed in a future version.
Instructions for updating:
Use the iterator's `initializer` property instead.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...
INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp2ack9oru/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...
INFO:tensorflow:loss = 1.0, step = 0
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 10...
INFO:tensorflow:Saving checkpoints for 10 into /tmp/tmp2ack9oru/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 10...
INFO:tensorflow:Loss for final step: 2.877698e-13.
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
WARNING:tensorflow:AutoGraph could not transform <function _combine_distributed_scaffold.<locals>.<lambda> at 0x7fa1e9768d08> and will run it as-is.
Cause: could not parse the source code:

      lambda scaffold: scaffold.ready_op, args=(grouped_scaffold,))

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function _combine_distributed_scaffold.<locals>.<lambda> at 0x7fa1e9768d08> and will run it as-is.
Cause: could not parse the source code:

      lambda scaffold: scaffold.ready_op, args=(grouped_scaffold,))

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
INFO:tensorflow:Starting evaluation at 2020-08-04T20:28:12Z
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmp2ack9oru/model.ckpt-10
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [1/10]
INFO:tensorflow:Evaluation [2/10]
INFO:tensorflow:Evaluation [3/10]
INFO:tensorflow:Evaluation [4/10]
INFO:tensorflow:Evaluation [5/10]
INFO:tensorflow:Evaluation [6/10]
INFO:tensorflow:Evaluation [7/10]
INFO:tensorflow:Evaluation [8/10]
INFO:tensorflow:Evaluation [9/10]
INFO:tensorflow:Evaluation [10/10]
INFO:tensorflow:Inference Time : 0.20350s
INFO:tensorflow:Finished evaluation at 2020-08-04-20:28:12
INFO:tensorflow:Saving dict for global step 10: average_loss = 1.4210855e-14, global_step = 10, label/mean = 1.0, loss = 1.4210855e-14, prediction/mean = 0.99999994
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 10: /tmp/tmp2ack9oru/model.ckpt-10

{'average_loss': 1.4210855e-14,
 'label/mean': 1.0,
 'loss': 1.4210855e-14,
 'prediction/mean': 0.99999994,
 'global_step': 10}

Perbedaan lain yang disoroti di sini antara Estimator dan Keras adalah penanganan input. Dalam Keras, kami menyebutkan bahwa setiap kumpulan dataset dibagi secara otomatis di beberapa replika. Namun, dalam Estimator, kami tidak melakukan pemisahan secara otomatis, juga tidak secara otomatis membuang data di antara pekerja yang berbeda. Anda memiliki kendali penuh atas bagaimana Anda ingin data Anda didistribusikan di antara pekerja dan perangkat, dan Anda harus memberikan input_fn untuk menentukan cara mendistribusikan data Anda.

input_fn Anda dipanggil sekali per pekerja, sehingga memberikan satu dataset per pekerja. Kemudian satu batch dari dataset tersebut diumpankan ke satu replika pada pekerja itu, sehingga mengkonsumsi N batch untuk replika N pada 1 pekerja. Dengan kata lain, dataset yang dikembalikan oleh input_fn harus menyediakan kumpulan ukuran PER_REPLICA_BATCH_SIZE . Dan ukuran kumpulan global untuk satu langkah dapat diperoleh sebagai PER_REPLICA_BATCH_SIZE * strategy.num_replicas_in_sync .

Saat melakukan pelatihan multi-pekerja, Anda harus membagi data Anda di antara para pekerja, atau mengacak dengan seed acak pada masing-masing. Anda dapat melihat contoh bagaimana melakukan ini di Pelatihan Multi-pekerja dengan Pengukur .

Dan juga, Anda dapat menggunakan strategi multi-pekerja dan parameter server juga. Kode tetap sama, tetapi Anda perlu menggunakan tf.estimator.train_and_evaluate , dan mengatur variabel lingkungan TF_CONFIG untuk setiap biner yang berjalan di cluster Anda.

Apa yang didukung sekarang?

Ada dukungan terbatas untuk pelatihan dengan Estimator menggunakan semua strategi kecuali Strategi TPUStrategy . Pelatihan dan evaluasi dasar harus berhasil, tetapi sejumlah fitur canggih seperti perancah belum berfungsi. Mungkin juga ada sejumlah bug dalam integrasi ini. Saat ini, kami tidak berencana untuk secara aktif meningkatkan dukungan ini, dan sebaliknya berfokus pada Keras dan dukungan loop pelatihan khusus. Jika memungkinkan, Anda sebaiknya menggunakan tf.distribute dengan API tersebut.

API Pelatihan Strategi Mirrored Strategi TPUS Strategi MultiWorkerMirrored CentralStorageStrategy ParameterServerStrategy
API Pengukur Dukungan Terbatas Tidak didukung Dukungan Terbatas Dukungan Terbatas Dukungan Terbatas

Contoh dan Tutorial

Berikut adalah beberapa contoh yang menunjukkan penggunaan ujung ke ujung dari berbagai strategi dengan Estimator:

  1. Pelatihan Multi-pekerja dengan Estimator untuk melatih MNIST dengan beberapa pekerja menggunakan MultiWorkerMirroredStrategy .
  2. Contoh ujung ke ujung untuk pelatihan multi-pekerja dalam tensorflow / ekosistem menggunakan templat Kubernetes. Contoh ini dimulai dengan model Keras dan mengubahnya menjadi Pengukur menggunakan API tf.keras.estimator.model_to_estimator .
  3. Model ResNet50 resmi, yang dapat dilatih menggunakan MirroredStrategy atau MultiWorkerMirroredStrategy .

Topik lainnya

Di bagian ini, kami akan membahas beberapa topik yang relevan dengan beberapa kasus penggunaan.

Menyiapkan variabel lingkungan TF_CONFIG

Untuk pelatihan multi-pekerja, seperti yang disebutkan sebelumnya, Anda perlu mengatur variabel lingkungan TF_CONFIG untuk setiap biner yang berjalan di cluster Anda. TF_CONFIG lingkungan TF_CONFIG adalah string JSON yang menentukan tugas apa yang merupakan gugus, alamatnya dan peran masing-masing tugas dalam gugus. Kami menyediakan templat Kubernetes di repo tensorflow / ekosistem yang menetapkan TF_CONFIG untuk tugas pelatihan Anda.

Ada dua komponen TF_CONFIG: cluster dan tugas. klaster memberikan informasi tentang klaster pelatihan, yang merupakan dikte yang terdiri dari berbagai jenis pekerjaan seperti pekerja. Dalam pelatihan multi-pekerja, biasanya ada satu pekerja yang mengambil sedikit lebih banyak tanggung jawab seperti menyimpan pos pemeriksaan dan menulis file ringkasan untuk TensorBoard di samping apa yang pekerja biasa lakukan. Pekerja tersebut disebut sebagai pekerja 'kepala', dan merupakan kebiasaan bahwa pekerja dengan indeks 0 ditunjuk sebagai pekerja kepala (sebenarnya inilah bagaimana tf. Mendistribusikan.Strategi diimplementasikan). tugas di sisi lain memberikan informasi tentang tugas saat ini. Cluster komponen pertama adalah sama untuk semua pekerja, dan tugas komponen kedua berbeda pada setiap pekerja dan menentukan jenis dan indeks pekerja itu.

Salah satu contoh TF_CONFIG adalah:

 os.environ["TF_CONFIG"] = json.dumps({
    "cluster": {
        "worker": ["host1:port", "host2:port", "host3:port"],
        "ps": ["host4:port", "host5:port"]
    },
   "task": {"type": "worker", "index": 1}
})
 

TF_CONFIG ini menetapkan bahwa ada tiga pekerja dan dua tugas ps di kluster bersama dengan host dan port mereka. Bagian "tugas" menentukan bahwa peran tugas saat ini di cluster, pekerja 1 (pekerja kedua). Peran yang valid dalam sebuah cluster adalah "kepala", "pekerja", "ps" dan "evaluator". Seharusnya tidak ada pekerjaan "ps" kecuali ketika menggunakan tf.distribute.experimental.ParameterServerStrategy .

Apa berikutnya?

tf.distribute.Strategy aktif dalam pengembangan. Kami menyambut Anda untuk mencobanya dan memberikan tanggapan Anda menggunakan masalah GitHub .