עזרה להגן על שונית המחסום הגדולה עם TensorFlow על Kaggle הצטרפו אתגר

השתמש ב- TPU

הצג באתר TensorFlow.org הפעל בגוגל קולאב צפה במקור ב-GitHub הורד מחברת

לפני שתפעיל מחברת Colab הזה, לוודא כי מאיץ החומרה היא TPU ידי בדיקת ההגדרות המחברת שלך: Runtime> סוג ריצה שינוי> מאיץ חומרה> TPU.

להכין

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)

אתחול TPU

TPUs הם בדרך כלל עובדי Cloud TPU, אשר שונים מהתהליך המקומי המריץ את תוכנית Python של המשתמש. לפיכך, עליך לבצע עבודת אתחול כדי להתחבר לאשכול המרוחק ולאתחל את ה-TPUs. שים לב tpu הטיעון כדי tf.distribute.cluster_resolver.TPUClusterResolver היא כתובת מיוחדת רק עבור Colab. אם אתה מפעיל את הקוד שלך ב-Google Compute Engine (GCE), במקום זאת עליך להעביר את השם של 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.10:8470
INFO:tensorflow:Initializing the TPU system: grpc://10.240.1.10: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')]

מיקום המכשיר ידני

לאחר אתחול ה-TPU, תוכל להשתמש במיקום ידני של המכשיר כדי למקם את החישוב על התקן 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)

אסטרטגיות הפצה

בדרך כלל אתה מריץ את המודל שלך על מספר TPUs בצורה מקבילה לנתונים. כדי להפיץ את המודל שלך על מספר TPUs (או מאיצים אחרים), TensorFlow מציעה מספר אסטרטגיות הפצה. אתה יכול להחליף את אסטרטגיית ההפצה שלך והמודל יפעל על כל מכשיר נתון (TPU). בדוק את מדריך אסטרטגית הפצה למידע נוסף.

כדי להמחיש זאת, ליצור tf.distribute.TPUStrategy אובייקט:

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)

כדי לשכפל חישוב כך שזה יכול לרוץ בכל ליבות TPU, אתה יכול לעבור אותו לתוך strategy.run API. להלן דוגמה המציגה את כל ליבות זוכים לאותה תשומות (a, b) וביצוע כפל במטריצה על כל ליבה בנפרד. הפלטים יהיו הערכים מכל ההעתקים.

@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)
}

סיווג על TPUs

לאחר שכיסית את המושגים הבסיסיים, שקול דוגמה קונקרטית יותר. סעיף זה מדגים כיצד להשתמש בהתפלגות strategy- tf.distribute.TPUStrategy -כדי לאמן מודל Keras על ענן TPU.

הגדירו דגם של קרס

התחל עם ההגדרה של Sequential מודל Keras לסיווג תמונה על בסיס הנתונים MNIST באמצעות Keras. זה לא שונה ממה שהיית משתמש אם היית מתאמן על CPUs או GPUs. הערה כי הצרכים יצירת מודל Keras להיות בתוך strategy.scope , כך המשתנים יכול להיווצר על כל מכשיר TPU. חלקים אחרים של הקוד אינם נחוצים כדי להיות בטווח האסטרטגיה.

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)])

טען את מערך הנתונים

שימוש יעיל של tf.data.Dataset API הוא קריטי בעת שימוש קלאוד TPU, כפי שאי אפשר להשתמש בענן TPUs אלא אם אתה יכול להאכיל אותם נתונים מספיק מהר. אתה יכול ללמוד יותר על נתון וביצועי מדריך ביצועי צינור ההזנה .

מלבד עבור הניסויים הפשוטים (באמצעות tf.data.Dataset.from_tensor_slices או הנתונים-גרף אחרים), אתה צריך לאחסן את כל קבצי הנתונים לקרוא על ידי מערך הנתונים ב Google Cloud Storage (GCS) דליים.

ברוב המקרים השימוש, מומלץ להמיר את הנתונים שלך לתוך TFRecord בפורמט ולהשתמש tf.data.TFRecordDataset לקרוא אותו. בדוק את הדרכת TFRecord ו tf.Example לפרטים על איך לעשות את זה. זוהי אינה דרישה קשה ואתה יכול להשתמש הקוראים במערך אחרים, כגון tf.data.FixedLengthRecordDataset או tf.data.TextLineDataset .

אתה יכול לטעון מערכי נתונים קטנים כולו לתוך הזיכרון באמצעות tf.data.Dataset.cache .

ללא קשר לפורמט הנתונים בו נעשה שימוש, מומלץ מאוד להשתמש בקבצים גדולים בסדר גודל של 100MB. זה חשוב במיוחד בהגדרה זו ברשת, שכן התקורה של פתיחת קובץ גבוהה משמעותית.

כפי שניתן לראות בקוד שלהלן, עליך להשתמש tensorflow_datasets מודול כדי לקבל עותק של אימונים MNIST ואת נתוני הבדיקה. הערה כי try_gcs המצוין להשתמש עותק זמין בתוך דלי GCS הציבור. אם לא תציין זאת, ה-TPU לא יוכל לגשת לנתונים שהורדת.

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

אמן את המודל באמצעות ממשקי API ברמה גבוהה של Keras

אתה יכול לאמן את המודל עם Keras fit ו compile APIs. אין דבר TPU ספציפי זה של שלב אתה כותב את הקוד כאילו השתמשת GPUs mutliple וכן MirroredStrategy במקום TPUStrategy . אתה יכול ללמוד עוד על אימון מבוזרת עם Keras הדרכה.

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 [==============================] - 17s 32ms/step - loss: 0.1268 - sparse_categorical_accuracy: 0.9611 - val_loss: 0.0398 - val_sparse_categorical_accuracy: 0.9872
Epoch 2/5
300/300 [==============================] - 6s 21ms/step - loss: 0.0332 - sparse_categorical_accuracy: 0.9896 - val_loss: 0.0505 - val_sparse_categorical_accuracy: 0.9849
Epoch 3/5
300/300 [==============================] - 6s 21ms/step - loss: 0.0204 - sparse_categorical_accuracy: 0.9934 - val_loss: 0.0409 - val_sparse_categorical_accuracy: 0.9886
Epoch 4/5
300/300 [==============================] - 6s 21ms/step - loss: 0.0129 - sparse_categorical_accuracy: 0.9957 - val_loss: 0.0541 - val_sparse_categorical_accuracy: 0.9848
Epoch 5/5
300/300 [==============================] - 6s 21ms/step - loss: 0.0106 - sparse_categorical_accuracy: 0.9965 - val_loss: 0.0492 - val_sparse_categorical_accuracy: 0.9855
<keras.callbacks.History at 0x7fc7180734e0>

כדי לצמצם תקורה Python ו למקסם את הביצועים של TPU שלך, לעבור את argument- steps_per_execution -כדי Model.compile . בדוגמה זו, הוא מגדיל את התפוקה בכ-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 [==============================] - 12s 42ms/step - loss: 0.1235 - sparse_categorical_accuracy: 0.9610 - val_loss: 0.0423 - val_sparse_categorical_accuracy: 0.9858
Epoch 2/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0329 - sparse_categorical_accuracy: 0.9894 - val_loss: 0.0405 - val_sparse_categorical_accuracy: 0.9869
Epoch 3/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0179 - sparse_categorical_accuracy: 0.9941 - val_loss: 0.0475 - val_sparse_categorical_accuracy: 0.9870
Epoch 4/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0136 - sparse_categorical_accuracy: 0.9956 - val_loss: 0.0404 - val_sparse_categorical_accuracy: 0.9888
Epoch 5/5
300/300 [==============================] - 3s 10ms/step - loss: 0.0095 - sparse_categorical_accuracy: 0.9967 - val_loss: 0.0478 - val_sparse_categorical_accuracy: 0.9878
<keras.callbacks.History at 0x7fc690143dd8>

אימון הדגם באמצעות לולאת אימון מותאמת אישית

ניתן גם ליצור ולאמן המודל שלך באמצעות tf.function ו tf.distribute APIs ישירות. אתה יכול להשתמש strategy.experimental_distribute_datasets_from_function API כדי להפיץ את הנתונים נתון פונקציה במערך. שים לב שבדוגמה למטה גודל האצווה המועבר למערך הנתונים הוא גודל האצווה לכל העתק במקום גודל האצווה העולמי. כדי ללמוד עוד, לבדוק את האימון מותאם אישית עם tf.distribute.Strategy הדרכה.

ראשית, צור את המודל, מערכי הנתונים ו-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

לאחר מכן, הפעל את לולאת האימון:

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.1315, accuracy: 95.77%
Epoch: 1/5
Current step: 600, training loss: 0.0354, accuracy: 98.92%
Epoch: 2/5
Current step: 900, training loss: 0.0204, accuracy: 99.31%
Epoch: 3/5
Current step: 1200, training loss: 0.0151, accuracy: 99.48%
Epoch: 4/5
Current step: 1500, training loss: 0.0096, accuracy: 99.69%

שיפור ביצועים עם שלבים מרובים בתוך tf.function

אתה יכול לשפר את הביצועים על ידי הפעלת צעדים מרובים בתוך tf.function . זו מושגת על ידי עטיפת strategy.run השיחה עם tf.range בתוך tf.function , ואת החתימות יהיה להמיר אותו tf.while_loop על העובד TPU.

למרות הביצועים המשופרים, יש פשרות עם שיטה זו לעומת ריצה צעד אחד פנימה tf.function . Running שלבים מרובים tf.function הוא פחות גמיש-אתה לא יכול לנהל את העניינים בשקיקה או קוד פיתון שרירותי בתוך השלבים.

@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.0081, accuracy: 99.73%

הצעדים הבאים