روز جامعه ML 9 نوامبر است! برای به روز رسانی از TensorFlow، JAX به ما بپیوندید، و بیشتر بیشتر بدانید

دقت مخلوط

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

بررسی اجمالی

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

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

پردازنده های گرافیکی NVIDIA می توانند عملیات در float16 را سریعتر از float32 اجرا کنند و TPU ها می توانند عملیات را در bfloat16 سریعتر از float32 اجرا کنند. بنابراین ، در صورت امکان در این دستگاه ها باید از این نوع با دقت پایین استفاده شود. با این حال ، متغیرها و چند محاسبه هنوز باید به دلایل عددی در 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 و TPU های ابری می شود. پردازنده های گرافیکی NVIDIA از ترکیب float16 و float32 پشتیبانی می کنند ، در حالی که TPU ها ترکیبی از bfloat16 و float32 را پشتیبانی می کنند.

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

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

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

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

حتی در پردازنده های گرافیکی و پردازنده های گرافیکی قدیمی تر ، جایی که انتظار افزایش سرعت وجود ندارد ، می توان از 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')

این خط مشی دو جنبه مهم یک لایه را مشخص می کند: نوع نوع محاسبات لایه و نوع متغیرهای لایه. در عکس بالا، شما یک ایجاد 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. این خط مشی روی سایر پردازنده های گرافیکی و 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.

افزودن softmax float16 در وسط یک مدل خوب است ، اما softmax در انتهای مدل باید در 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 می گذارد ، زیرا هر لایه ورودی های نقطه شناور را به نوع محاسبه خود می اندازد.

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

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 (پردازنده های گرافیکی آمپر و بالاتر) ، هنگام استفاده از دقت مختلط در مقایسه با float32 ، به احتمال زیاد در مدل راهنمای اسباب بازی هیچ بهبود عملکردی مشاهده نخواهید کرد. این به خاطر استفاده از TensorFloat-32 ، که به طور خودکار با استفاده از ریاضی با دقت کمتر در عملیات float32 خاص مانند tf.linalg.matmul . TensorFloat-32 برخی از مزایای عملکرد دقت مختلط را هنگام استفاده از float32 ارائه می دهد. با این حال ، در مدل های دنیای واقعی ، به طور معمول ، به دلیل صرفه جویی در پهنای باند حافظه و گزینه هایی که TensorFloat-32 از آنها پشتیبانی نمی کند ، به طور قابل توجهی بهبود عملکرد را از دقت مختلط مشاهده خواهید کرد.

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

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

پوسته پوسته شدن ضرر

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

زیر آب و سرریز

نوع داده float16 در مقایسه با float32 محدوده دینامیکی محدودی دارد. این بدان معناست که مقادیر بالای $ 65504 $ بی نهایت و ارزش های زیر $ 6.0 \ بار 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

در اینجا چند نکته در مورد عملکرد هنگام استفاده از دقت ترکیبی در 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)

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

XLA

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

نکات عملکرد TPU ابری

مانند GPU ها ، هنگام استفاده از Cloud TPU ها باید اندازه دسته خود را دو برابر کنید زیرا bfloat16 tensors از نیمی از حافظه استفاده می کنند. دو برابر شدن حجم دسته ممکن است توان تمرین را افزایش دهد.

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 شیب.

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

  • در پردازنده های گرافیکی ، اطمینان حاصل کنید که بیشتر ابعاد تانسور مضربی از 8 دلار است تا حداکثر عملکرد را داشته باشید

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