کمک به حفاظت از دیواره بزرگ مرجانی با TensorFlow در Kaggle اضافه کردن چالش

دقت مخلوط

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub دانلود دفترچه یادداشت

بررسی اجمالی

دقت ترکیبی استفاده از هر دو نوع ممیز شناور 16 بیتی و 32 بیتی در یک مدل در طول آموزش است تا آن را سریعتر اجرا کند و از حافظه کمتری استفاده کند. با نگه‌داشتن بخش‌های خاصی از مدل در انواع 32 بیتی برای ثبات عددی، مدل زمان گام پایین‌تری خواهد داشت و از نظر معیارهای ارزیابی مانند دقت، به همان اندازه تمرین می‌کند. این راهنما نحوه استفاده از Keras را برای سرعت بخشیدن به مدل های خود شرح می دهد. استفاده از این API می تواند عملکرد را بیش از 3 برابر در GPU های مدرن و 60٪ در TPU ها بهبود بخشد.

امروزه اکثر مدل ها از float32 dtype استفاده می کنند که 32 بیت حافظه می گیرد. با این حال، دو نوع d با دقت کمتری وجود دارد، float16 و bfloat16، که هر کدام در عوض 16 بیت حافظه مصرف می کنند. شتاب دهنده های مدرن می توانند عملیات را در dtypes 16 بیتی سریعتر اجرا کنند، زیرا آنها دارای سخت افزار تخصصی برای اجرای محاسبات 16 بیتی هستند و dtypes 16 بیتی را می توان سریعتر از حافظه خواند.

پردازنده‌های گرافیکی NVIDIA می‌توانند عملیات‌ها را در float16 سریع‌تر از float32 و TPU‌ها در bfloat16 سریع‌تر از float32 اجرا کنند. بنابراین، این نوع d با دقت پایین‌تر باید تا حد امکان در آن دستگاه‌ها استفاده شود. با این حال، متغیرها و چند محاسبات به دلایل عددی همچنان باید در float32 باشند تا مدل با همان کیفیت آموزش ببیند. API دقیق مخلوط Keras به شما امکان می دهد از ترکیبی از float16 یا bfloat16 با float32 استفاده کنید تا از مزایای عملکرد float16/bfloat16 و مزایای ثبات عددی از float32 بهره مند شوید.

برپایی

import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import mixed_precision

سخت افزار پشتیبانی شده

در حالی که دقت ترکیبی روی اکثر سخت‌افزارها اجرا می‌شود، اما فقط سرعت مدل‌های پردازنده‌های گرافیکی اخیر NVIDIA و Cloud TPU را افزایش می‌دهد. پردازنده‌های گرافیکی NVIDIA از ترکیبی از float16 و float32 پشتیبانی می‌کنند، در حالی که TPU‌ها از ترکیبی از bfloat16 و float32 پشتیبانی می‌کنند.

در میان پردازنده‌های گرافیکی NVIDIA، آنهایی که دارای قابلیت محاسباتی 7.0 یا بالاتر هستند، بیشترین بهره را از دقت ترکیبی خواهند داشت، زیرا دارای واحدهای سخت‌افزاری ویژه به نام هسته‌های Tensor هستند که ضرب و کانولوشن ماتریس float16 را تسریع می‌کنند. پردازنده‌های گرافیکی قدیمی‌تر هیچ مزیتی برای عملکرد ریاضی برای استفاده از دقت مختلط ارائه نمی‌دهند، با این حال صرفه‌جویی در حافظه و پهنای باند می‌تواند برخی از سرعت‌ها را فعال کند. شما می توانید نگاه کردن قابلیت محاسبه برای GPU خود را در انویدیا صفحه وب CUDA GPU . نمونه‌هایی از پردازنده‌های گرافیکی که بیشترین بهره را از دقت ترکیبی می‌برند، شامل پردازنده‌های گرافیکی RTX، V100 و A100 می‌شوند.

با موارد زیر می توانید نوع GPU خود را بررسی کنید. این فرمان تنها در صورتی وجود دارد که درایورهای NVIDIA نصب شده باشند، بنابراین در غیر این صورت خطای زیر ایجاد می شود.

nvidia-smi -L
GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-99e10c4d-de77-42ee-4524-6c41c4e5e47d)

تمام TPU های ابری از bfloat16 پشتیبانی می کنند.

حتی در CPUها و GPUهای قدیمی‌تر، جایی که انتظار افزایش سرعت وجود ندارد، APIهای دقیق ترکیبی همچنان می‌توانند برای آزمایش واحد، اشکال‌زدایی یا فقط برای آزمایش API استفاده شوند. با این حال، در CPU ها، دقت ترکیبی به طور قابل توجهی کندتر خواهد بود.

تنظیم خط مشی dtype

برای استفاده از دقت مخلوط در Keras، شما نیاز به ایجاد یک tf.keras.mixed_precision.Policy ، به طور معمول به عنوان یک سیاست dtype اشاره شده است. Dtype سیاست مشخص dtypes لایه ها در اجرا خواهد شد. در این راهنما، شما یک سیاست از رشته ساخت 'mixed_float16' و آن را به عنوان سیاست جهانی است. این باعث می شود که لایه های ایجاد شده بعدی از دقت ترکیبی با ترکیبی از float16 و float32 استفاده کنند.

policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_global_policy(policy)
INFO:tensorflow:Mixed precision compatibility check (mixed_float16): OK
Your GPU will likely run quickly with dtype policy mixed_float16 as it has compute capability of at least 7.0. Your GPU: Tesla V100-SXM2-16GB, compute capability 7.0

برای کوتاه مدت، شما به طور مستقیم می توانید یک رشته به تصویب set_global_policy ، که معمولا در عمل انجام می شود.

# Equivalent to the two lines above
mixed_precision.set_global_policy('mixed_float16')

این خط مشی دو جنبه مهم یک لایه را مشخص می کند: dtype محاسبات لایه در آن انجام می شود و dtype متغیرهای یک لایه. در عکس بالا، شما یک ایجاد mixed_float16 سیاست (یعنی یک mixed_precision.Policy ایجاد شده توسط عبور از رشته 'mixed_float16' به سازنده آن). با این خط مشی، لایه ها از محاسبات float16 و متغیرهای float32 استفاده می کنند. محاسبات در float16 برای عملکرد انجام می شود، اما متغیرها باید در float32 برای ثبات عددی نگهداری شوند. شما می توانید مستقیماً این ویژگی های خط مشی را پرس و جو کنید.

print('Compute dtype: %s' % policy.compute_dtype)
print('Variable dtype: %s' % policy.variable_dtype)
Compute dtype: float16
Variable dtype: float32

همانطور که پیش از ذکر شد، mixed_float16 سیاست مهمتر خواهد بهبود عملکرد در پردازندههای گرافیکی انویدیا با قابلیت محاسبه حداقل 7.0. این خط‌مشی روی دیگر GPUها و CPUها اجرا می‌شود اما ممکن است عملکرد را بهبود نبخشد. برای TPU ها از mixed_bfloat16 سیاست باید به جای استفاده می شود.

ساخت مدل

بعد، بیایید شروع به ساخت یک مدل ساده کنیم. مدل‌های اسباب‌بازی بسیار کوچک معمولاً از دقت ترکیبی بهره نمی‌برند، زیرا سربار ناشی از زمان اجرا TensorFlow معمولاً بر زمان اجرا غالب است و هر گونه بهبود عملکرد در GPU را ناچیز می‌سازد. بنابراین، اجازه دهید ساخت دو بزرگ Dense هر لایه را با 4096 واحد اگر یک GPU استفاده شده است.

inputs = keras.Input(shape=(784,), name='digits')
if tf.config.list_physical_devices('GPU'):
  print('The model will run with 4096 units on a GPU')
  num_units = 4096
else:
  # Use fewer units on CPUs so the model finishes in a reasonable amount of time
  print('The model will run with 64 units on a CPU')
  num_units = 64
dense1 = layers.Dense(num_units, activation='relu', name='dense_1')
x = dense1(inputs)
dense2 = layers.Dense(num_units, activation='relu', name='dense_2')
x = dense2(x)
The model will run with 4096 units on a GPU

هر لایه دارای یک خط مشی است و به طور پیش فرض از سیاست جهانی استفاده می کند. هر یک از Dense لایه بنابراین باید mixed_float16 سیاست به دلیل شما در سیاست جهانی را به مجموعه mixed_float16 قبلا. این باعث می شود که لایه های متراکم محاسبات float16 را انجام دهند و دارای متغیرهای float32 باشند. آنها برای انجام محاسبات float16 ورودی های خود را به float16 می ریزند که در نتیجه خروجی های آنها float16 می شود. متغیرهای آن‌ها float32 هستند و زمانی که لایه‌ها فراخوانی شوند برای جلوگیری از خطاهای ناشی از عدم تطابق dtype به float16 فرستاده می‌شوند.

print(dense1.dtype_policy)
print('x.dtype: %s' % x.dtype.name)
# 'kernel' is dense1's variable
print('dense1.kernel.dtype: %s' % dense1.kernel.dtype.name)
<Policy "mixed_float16">
x.dtype: float16
dense1.kernel.dtype: float32

بعد، پیش بینی های خروجی را ایجاد کنید. به طور معمول، شما می توانید پیش بینی های خروجی را به صورت زیر ایجاد کنید، اما این همیشه از نظر عددی با float16 پایدار نیست.

# INCORRECT: softmax and model output will be float16, when it should be float32
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)
print('Outputs dtype: %s' % outputs.dtype.name)
Outputs dtype: float16

یک فعال سازی softmax در انتهای مدل باید float32 باشد. از آنجا که سیاست dtype است mixed_float16 ، فعال شدن softmax به طور معمول یک float16 محاسبه dtype و تانسورها خروجی float16.

این را می توان با جدا کردن انبوه و لایه softmax، و با گذشت ثابت dtype='float32' به لایه softmax:

# CORRECT: softmax and model output are float32
x = layers.Dense(10, name='dense_logits')(x)
outputs = layers.Activation('softmax', dtype='float32', name='predictions')(x)
print('Outputs dtype: %s' % outputs.dtype.name)
Outputs dtype: float32

عبور dtype='float32' به سازنده لایه softmax لغو سیاست dtype لایه را به شود float32 سیاست، که نشانی از محاسبات و متغیرهای در float32 نگه می دارد. معادل، شما می توانید به جای گذشت dtype=mixed_precision.Policy('float32') ؛ لایه ها همیشه آرگومان dtype را به یک خط مشی تبدیل می کنند. از آنجا که Activation لایه دارای هیچ متغیر، متغیر dtype سیاست را نادیده گرفته شده است، اما dtype محاسبه سیاست از float32 علل softmax و خروجی مدل به float32.

افزودن سافت مکس float16 در وسط یک مدل خوب است، اما یک سافت مکس در انتهای مدل باید در float32 باشد. دلیل آن این است که اگر تانسور میانی که از Softmax به افت جریان می یابد float16 یا bfloat16 باشد، ممکن است مسائل عددی رخ دهد.

شما می توانید dtype از هر لایه را زیر پا بگذارند به float32 توان با عبور dtype='float32' اگر شما فکر می کنم آن را نمی خواهد عددی پایدار با float16 محاسبات باشد. اما به طور معمول، این است تنها در آخرین لایه از مدل لازم، به عنوان ترین لایه دقت کافی با mixed_float16 و mixed_bfloat16 .

حتی اگر مدل به softmax ختم نشود، خروجی ها باید همچنان float32 باشند. در حالی که برای این مدل خاص غیر ضروری است، خروجی های مدل را می توان با موارد زیر به float32 ریخت:

# The linear activation is an identity function. So this simply casts 'outputs'
# to float32. In this particular case, 'outputs' is already float32 so this is a
# no-op.
outputs = layers.Activation('linear', dtype='float32')(outputs)

سپس مدل را تکمیل و کامپایل کنید و داده های ورودی تولید کنید:

model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss='sparse_categorical_crossentropy',
              optimizer=keras.optimizers.RMSprop(),
              metrics=['accuracy'])

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

این مثال داده های ورودی را از int8 به float32 فرستاد. شما به float16 کست نمی کنید زیرا تقسیم بر 255 روی CPU است، که عملیات float16 را کندتر از عملیات float32 اجرا می کند. در این مورد، تفاوت عملکرد ناچیز است، اما به طور کلی باید ریاضی پردازش ورودی را در float32 اجرا کنید اگر روی CPU اجرا شود. لایه اول مدل، ورودی‌ها را به float16 می‌فرستد، زیرا هر لایه ورودی‌های ممیز شناور را به نوع d محاسبه می‌کند.

وزن های اولیه مدل بازیابی می شوند. این امکان تمرین مجدد از ابتدا را با بارگذاری وزنه ها فراهم می کند.

initial_weights = model.get_weights()

آموزش مدل با Model.fit

بعد، مدل را آموزش دهید:

history = model.fit(x_train, y_train,
                    batch_size=8192,
                    epochs=5,
                    validation_split=0.2)
test_scores = model.evaluate(x_test, y_test, verbose=2)
print('Test loss:', test_scores[0])
print('Test accuracy:', test_scores[1])
Epoch 1/5
6/6 [==============================] - 2s 78ms/step - loss: 4.9609 - accuracy: 0.4132 - val_loss: 0.6643 - val_accuracy: 0.8437
Epoch 2/5
6/6 [==============================] - 0s 34ms/step - loss: 0.7752 - accuracy: 0.7789 - val_loss: 0.3098 - val_accuracy: 0.9175
Epoch 3/5
6/6 [==============================] - 0s 34ms/step - loss: 0.3620 - accuracy: 0.8848 - val_loss: 0.3149 - val_accuracy: 0.8969
Epoch 4/5
6/6 [==============================] - 0s 34ms/step - loss: 0.2998 - accuracy: 0.9066 - val_loss: 0.2988 - val_accuracy: 0.9068
Epoch 5/5
6/6 [==============================] - 0s 33ms/step - loss: 0.2298 - accuracy: 0.9285 - val_loss: 0.5062 - val_accuracy: 0.8414
313/313 - 0s - loss: 0.5163 - accuracy: 0.8392
Test loss: 0.5163048505783081
Test accuracy: 0.8392000198364258

توجه داشته باشید که مدل زمان هر مرحله را در گزارش ها چاپ می کند: به عنوان مثال، "25ms/step". ممکن است دوره اول کندتر باشد زیرا TensorFlow مدتی را صرف بهینه سازی مدل می کند، اما پس از آن زمان هر مرحله باید تثبیت شود.

اگر این راهنما را در Colab اجرا می کنید، می توانید عملکرد دقت ترکیبی را با float32 مقایسه کنید. برای این کار، تغییر سیاست از mixed_float16 به float32 در بخش "تنظیم خط مشی dtype» است، پس از آن دوباره تمام سلول تا به این نقطه. در پردازنده‌های گرافیکی با قابلیت محاسباتی 7.X، باید شاهد افزایش قابل‌توجه زمان در هر مرحله باشید که نشان‌دهنده افزایش دقت ترکیبی مدل است. اطمینان حاصل کنید که برای تغییر سیاست تماس به mixed_float16 و دوباره سلول های قبل از ادامه راهنمای.

در پردازنده‌های گرافیکی با قابلیت محاسباتی حداقل 8.0 (GPUهای آمپر و بالاتر)، احتمالاً هنگام استفاده از دقت ترکیبی در مقایسه با float32، هیچ بهبود عملکردی در مدل اسباب‌بازی در این راهنما مشاهده نخواهید کرد. این به خاطر استفاده از TensorFloat-32 ، که به طور خودکار با استفاده از ریاضی با دقت کمتر در عملیات float32 خاص مانند tf.linalg.matmul . TensorFloat-32 برخی از مزایای عملکرد دقت مخلوط را هنگام استفاده از float32 ارائه می دهد. با این حال، در مدل‌های دنیای واقعی، به دلیل صرفه‌جویی در پهنای باند حافظه و عملیات‌هایی که TensorFloat-32 از آن‌ها پشتیبانی نمی‌کند، معمولاً شاهد بهبود عملکرد قابل توجهی از دقت ترکیبی خواهید بود.

اگر دقت ترکیبی را بر روی یک TPU اجرا کنید، در مقایسه با اجرای دقیق ترکیبی روی پردازنده‌های گرافیکی، به‌ویژه پردازنده‌های گرافیکی قبل از آمپر، افزایش عملکرد چندانی نخواهید داشت. این به این دلیل است که TPU ها عملیات خاصی را در bfloat16 در زیر هود انجام می دهند حتی با سیاست پیش فرض dtype float32. این شبیه به نحوه استفاده پردازنده های گرافیکی Ampere از TensorFloat-32 به طور پیش فرض است. در مقایسه با پردازنده‌های گرافیکی Ampere، TPUها معمولاً با دقت ترکیبی در مدل‌های واقعی، عملکرد کمتری دارند.

برای بسیاری از مدل‌های دنیای واقعی، دقت ترکیبی همچنین به شما امکان می‌دهد تا اندازه دسته‌ای را بدون تمام شدن حافظه دو برابر کنید، زیرا تانسورهای float16 نیمی از حافظه را می‌گیرند. اما این در مورد این مدل اسباب‌بازی صدق نمی‌کند، زیرا احتمالاً می‌توانید مدل را در هر نوع d اجرا کنید که در آن هر دسته شامل کل مجموعه داده MNIST از 60000 تصویر باشد.

جرم گیری از دست دادن

پوسته پوسته شدن دست دادن یک تکنیک که است که tf.keras.Model.fit به طور خودکار انجام با mixed_float16 سیاست برای جلوگیری از سرریز عددی. این بخش توضیح می‌دهد که مقیاس‌گذاری ضرر چیست و بخش بعدی نحوه استفاده از آن را با یک حلقه آموزشی سفارشی توضیح می‌دهد.

زیر آب و سرریز

نوع داده float16 دارای محدوده دینامیکی باریکی در مقایسه با float32 است. این به معنی ارزش بالا \(65504\) به بی نهایت و مقادیر زیر را لبریز خواهد شد \(6.0 \times 10^{-8}\) به صفر پاریز خواهد شد. float32 و bfloat16 دامنه دینامیکی بسیار بالاتری دارند به طوری که سرریز و زیر جریان مشکلی ندارند.

مثلا:

x = tf.constant(256, dtype='float16')
(x ** 2).numpy()  # Overflow
inf
x = tf.constant(1e-5, dtype='float16')
(x ** 2).numpy()  # Underflow
0.0

در عمل سرریز با float16 به ندرت اتفاق می افتد. علاوه بر این، جریان زیرین نیز به ندرت در طول پاس رو به جلو رخ می دهد. با این حال، در طول گذر به عقب، گرادیان ها می توانند به صفر برسند. جرم گیری از دست دادن تکنیکی برای جلوگیری از این زیرریزی است.

نمای کلی مقیاس بندی از دست دادن

مفهوم اساسی از پوسته پوسته شدن دست دادن ساده است: به سادگی ضرب از دست دادن با برخی تعداد زیادی، می گویند \(1024\)، و شما ارزش مقیاس از دست دادن است. این شیب به مقیاس های باعث \(1024\) و همچنین، تا حد زیادی کاهش شانس سرریز. هنگامی که شیب نهایی محاسبه می شوند، آنها را تقسیم \(1024\) به آنها را به ارزش صحیح خود.

شبه کد این فرآیند عبارت است از:

loss_scale = 1024
loss = model(inputs)
loss *= loss_scale
# Assume `grads` are float32. You do not want to divide float16 gradients.
grads = compute_gradient(loss, model.trainable_variables)
grads /= loss_scale

انتخاب مقیاس ضرر می تواند مشکل باشد. اگر مقیاس تلفات خیلی کم باشد، ممکن است شیب ها همچنان به صفر برسند. اگر خیلی زیاد باشد، مشکل برعکس رخ می دهد: گرادیان ها ممکن است تا بی نهایت سرریز شوند.

برای حل این مشکل، TensorFlow به صورت پویا مقیاس تلفات را تعیین می کند، بنابراین نیازی به انتخاب دستی ندارید. اگر شما استفاده از tf.keras.Model.fit ، پوسته پوسته شدن دست دادن است را برای شما انجام می شود بنابراین شما لازم نیست که برای انجام هر گونه کار اضافی است. اگر شما یک حلقه آموزش سفارشی استفاده کنید، باید به صراحت بهینه ساز های ویژه لفاف بسته بندی استفاده tf.keras.mixed_precision.LossScaleOptimizer به پوسته پوسته شدن دست دادن استفاده را به منظور. این در بخش بعدی توضیح داده شده است.

آموزش مدل با یک حلقه آموزشی سفارشی

تا کنون، شما یک مدل Keras با دقت مخلوط با استفاده از آموزش دیده اند tf.keras.Model.fit . در مرحله بعد، از دقت ترکیبی با یک حلقه آموزشی سفارشی استفاده خواهید کرد. اگر شما در حال حاضر می دانیم که چه حلقه آموزش سفارشی است، لطفا مطالعه راهنمای آموزشی سفارشی برای اولین بار.

اجرای یک حلقه آموزشی سفارشی با دقت ترکیبی به دو تغییر نسبت به اجرای آن در float32 نیاز دارد:

  1. مدل را با دقت ترکیبی بسازید (شما قبلاً این کار را انجام داده اید)
  2. به صراحت استفاده از پوسته پوسته شدن دست دادن اگر mixed_float16 استفاده شده است.

برای مرحله (2)، شما را به استفاده از tf.keras.mixed_precision.LossScaleOptimizer کلاس، که کاری ادامه داده اند بهینه ساز و پوسته پوسته شدن دست دادن اعمال می شود. به طور پیش فرض، به صورت پویا مقیاس ضرر را تعیین می کند، بنابراین مجبور نیستید یکی را انتخاب کنید. ساخت یک LossScaleOptimizer شرح زیر است.

optimizer = keras.optimizers.RMSprop()
optimizer = mixed_precision.LossScaleOptimizer(optimizer)

اگر بخواهید، می‌توانید یک مقیاس تلفات صریح را انتخاب کنید یا رفتار مقیاس‌بندی ضرر را سفارشی کنید، اما به شدت توصیه می‌شود که رفتار مقیاس‌بندی تلفات پیش‌فرض را حفظ کنید، زیرا مشخص شده است که در همه مدل‌های شناخته‌شده به خوبی کار می‌کند. مشاهده tf.keras.mixed_precision.LossScaleOptimizer اسناد اگر شما می خواهید برای سفارشی کردن رفتار پوسته پوسته شدن دست دادن.

بعد، تعریف شی از دست دادن و tf.data.Dataset بازدید کنندگان:

loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
train_dataset = (tf.data.Dataset.from_tensor_slices((x_train, y_train))
                 .shuffle(10000).batch(8192))
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(8192)

سپس تابع مرحله آموزش را تعریف کنید. شما از دو روش جدید از بهینه‌ساز مقیاس ضرر برای مقیاس‌سازی ضرر و کاهش مقیاس گرادیان استفاده خواهید کرد:

  • get_scaled_loss(loss) : ضرب از دست دادن با مقیاس از دست دادن
  • get_unscaled_gradients(gradients) : طول می کشد در یک لیست از شیب کوچک به عنوان ورودی، و تقسیم هر یک با مقیاس از دست دادن به آنها unscale

این توابع باید به منظور جلوگیری از جریان زیر در شیب استفاده شوند. LossScaleOptimizer.apply_gradients خواهد پس از آن اعمال شیب اگر هیچ یک از آنها Inf بازدید کنندگان و یا NaN است. آن را نیز به مقیاس از دست دادن رسانی، نصف آن را اگر شیب حال Inf بازدید کنندگان و یا NaN و به طور بالقوه آن افزایش غیر این صورت.

@tf.function
def train_step(x, y):
  with tf.GradientTape() as tape:
    predictions = model(x)
    loss = loss_object(y, predictions)
    scaled_loss = optimizer.get_scaled_loss(loss)
  scaled_gradients = tape.gradient(scaled_loss, model.trainable_variables)
  gradients = optimizer.get_unscaled_gradients(scaled_gradients)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))
  return loss

LossScaleOptimizer به احتمال زیاد چند قدم اول در شروع آموزش جست و خیز. مقیاس ضرر از بالا شروع می شود تا بتوان مقیاس بهینه ضرر را به سرعت تعیین کرد. پس از چند مرحله، مقیاس ضرر تثبیت می شود و تعداد بسیار کمی از مراحل رد می شوند. این فرآیند به صورت خودکار اتفاق می افتد و بر کیفیت تمرین تاثیری نمی گذارد.

حالا مرحله تست را تعریف کنید:

@tf.function
def test_step(x):
  return model(x, training=False)

وزن های اولیه مدل را بارگیری کنید تا بتوانید از ابتدا دوباره آموزش دهید:

model.set_weights(initial_weights)

در نهایت حلقه آموزش سفارشی را اجرا کنید:

for epoch in range(5):
  epoch_loss_avg = tf.keras.metrics.Mean()
  test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(
      name='test_accuracy')
  for x, y in train_dataset:
    loss = train_step(x, y)
    epoch_loss_avg(loss)
  for x, y in test_dataset:
    predictions = test_step(x)
    test_accuracy.update_state(y, predictions)
  print('Epoch {}: loss={}, test accuracy={}'.format(epoch, epoch_loss_avg.result(), test_accuracy.result()))
Epoch 0: loss=4.869325160980225, test accuracy=0.7221999764442444
Epoch 1: loss=0.4893573224544525, test accuracy=0.878000020980835
Epoch 2: loss=0.36011582612991333, test accuracy=0.9440000057220459
Epoch 3: loss=0.27391332387924194, test accuracy=0.9318000078201294
Epoch 4: loss=0.247697651386261, test accuracy=0.933899998664856

نکات عملکرد GPU

در اینجا نکاتی در مورد عملکرد هنگام استفاده از دقت ترکیبی در پردازنده‌های گرافیکی آورده شده است.

حجم دسته خود را افزایش دهید

اگر کیفیت مدل را تحت تأثیر قرار نمی دهد، هنگام استفاده از دقت ترکیبی، سعی کنید با دو برابر اندازه دسته اجرا کنید. از آنجایی که تانسورهای float16 از نیمی از حافظه استفاده می‌کنند، این اغلب به شما امکان می‌دهد تا اندازه دسته خود را بدون تمام شدن حافظه دو برابر کنید. افزایش اندازه دسته به طور معمول باعث افزایش توان عملیاتی می شود، یعنی عناصر آموزشی در هر ثانیه که مدل شما می تواند روی آنها اجرا شود.

اطمینان از استفاده از هسته های تانسور GPU

همانطور که قبلا ذکر شد، پردازنده‌های گرافیکی مدرن NVIDIA از یک واحد سخت‌افزاری به نام Tensor Cores استفاده می‌کنند که می‌تواند ماتریس‌های float16 را خیلی سریع ضرب کند. با این حال، هسته‌های تانسور نیاز دارند که ابعاد خاصی از تانسورها مضرب 8 باشند. در مثال‌های زیر، یک آرگومان پررنگ است اگر و فقط اگر لازم باشد برای هسته‌های تانسور مضرب 8 باشد.

  • tf.keras.layers.Dense (واحد = 64)
  • tf.keras.layers.Conv2d (فیلتر = 48، kernel_size = 7، گام = 3)
    • و به طور مشابه برای سایر لایه های کانولوشن، مانند tf.keras.layers.Conv3d
  • tf.keras.layers.LSTM (واحد = 64)
    • و مشابه برای RNN های دیگر، مانند tf.keras.layers.GRU
  • tf.keras.Model.fit (دوره = 2، batch_size = 128)

باید سعی کنید در صورت امکان از Tensor Cores استفاده کنید. اگر شما می خواهید برای کسب اطلاعات بیشتر، NVIDIA عمیق راهنمای یادگیری و عملکرد توصیف دقیق مورد نیاز برای استفاده از تانسور هسته و همچنین دیگر اطلاعات عملکرد تانسور هسته مرتبط است.

XLA

XLA کامپایلری است که می تواند عملکرد دقیق ترکیبی و همچنین عملکرد float32 را به میزان کمتری افزایش دهد. به مراجعه راهنمای XLA برای جزئیات بیشتر.

نکات عملکرد Cloud TPU

همانند پردازنده‌های گرافیکی، هنگام استفاده از Cloud TPU باید اندازه دسته خود را دو برابر کنید زیرا تانسورهای bfloat16 نیمی از حافظه را مصرف می‌کنند. دوبرابر کردن اندازه دسته ممکن است باعث افزایش توان آموزشی شود.

TPU ها برای دستیابی به عملکرد بهینه نیازی به تنظیم دقیق ترکیبی دیگر ندارند. آنها قبلاً به استفاده از XLA نیاز دارند. سود TPU ها از داشتن ابعاد خاص بودن تقسیم عددی بر مضرب \(128\)، اما این امر به همان اندازه به نوع float32 عنوان آن را برای دقت مخلوط می کند. را بررسی کنید راهنمای عملکرد ابر TPU برای TPU کلی عملکرد راهنمایی، که به دقت مخلوط و همچنین float32 تانسورها اعمال می شود.

خلاصه

  • اگر از TPU یا GPU های NVIDIA با حداقل قابلیت محاسبه 7.0 استفاده می کنید، باید از دقت ترکیبی استفاده کنید، زیرا عملکرد را تا 3 برابر بهبود می بخشد.
  • می توانید از دقت ترکیبی با خطوط زیر استفاده کنید:

    # On TPUs, use 'mixed_bfloat16' instead
    mixed_precision.set_global_policy('mixed_float16')
    
  • اگر مدل شما به softmax ختم می شود، مطمئن شوید که float32 است. و صرف نظر از اینکه مدل شما به چه پایانی می رسد، مطمئن شوید که خروجی float32 است.

  • اگر شما استفاده از یک حلقه آموزش سفارشی با mixed_float16 ، علاوه بر خطوط فوق، شما نیاز به بسته بندی کردن بهینه ساز خود را با یک tf.keras.mixed_precision.LossScaleOptimizer . سپس پاسخ optimizer.get_scaled_loss به مقیاس از دست دادن، و optimizer.get_unscaled_gradients به unscale شیب.

  • اگر دقت ارزیابی را کاهش ندهد، اندازه دسته آموزشی را دو برابر کنید

  • در GPU ها، اطمینان حاصل شود بسیاری از ابعاد تانسور می مضربی از \(8\) به عملکرد حداکثر

برای مثال بیشتر از دقت مخلوط با استفاده از tf.keras.mixed_precision API، بررسی مدل های مخزن رسمی . اکثر مدل های رسمی، مانند RESNET و ترانسفورماتور ، اجرا خواهد شد با استفاده از دقت مخلوط با عبور --dtype=fp16 .