मिश्रित परिशुद्धता

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

अवलोकन

मिश्रित परिशुद्धता प्रशिक्षण के दौरान एक मॉडल में 16-बिट और 32-बिट फ़्लोटिंग-पॉइंट दोनों प्रकारों का उपयोग है ताकि इसे तेज़ी से चलाया जा सके और कम मेमोरी का उपयोग किया जा सके। संख्यात्मक स्थिरता के लिए मॉडल के कुछ हिस्सों को 32-बिट प्रकारों में रखने से, मॉडल का चरण कम होगा और मूल्यांकन मेट्रिक्स जैसे सटीकता के संदर्भ में समान रूप से प्रशिक्षित होगा। यह मार्गदर्शिका बताती है कि अपने मॉडलों को गति देने के लिए केरस मिश्रित सटीक एपीआई का उपयोग कैसे करें। इस एपीआई का उपयोग करने से आधुनिक जीपीयू पर 3 गुना से अधिक और टीपीयू पर 60% से अधिक प्रदर्शन में सुधार हो सकता है।

आज, अधिकांश मॉडल फ्लोट32 डीटाइप का उपयोग करते हैं, जो 32 बिट मेमोरी लेता है। हालाँकि, दो निम्न-सटीक dtypes, float16 और bfloat16 हैं, जिनमें से प्रत्येक के बजाय 16 बिट मेमोरी लेते हैं। आधुनिक त्वरक 16-बिट dtypes में तेजी से संचालन चला सकते हैं, क्योंकि उनके पास 16-बिट कंप्यूटेशंस चलाने के लिए विशेष हार्डवेयर है और 16-बिट dtypes को मेमोरी से तेजी से पढ़ा जा सकता है।

एनवीआईडीआईए जीपीयू फ्लोट16 में फ्लोट32 की तुलना में तेजी से संचालन कर सकते हैं, और टीपीयू फ्लोट32 की तुलना में बीफ्लोट16 में तेजी से संचालन कर सकते हैं। इसलिए, जब भी संभव हो उन उपकरणों पर इन कम-सटीक dtypes का उपयोग किया जाना चाहिए। हालांकि, संख्यात्मक कारणों से चर और कुछ गणना अभी भी फ्लोट32 में होनी चाहिए ताकि मॉडल समान गुणवत्ता के लिए प्रशिक्षित हो। केरस मिश्रित सटीक एपीआई आपको फ्लोट16/बीफ्लोट16 से प्रदर्शन लाभ प्राप्त करने और फ्लोट32 से संख्यात्मक स्थिरता लाभ प्राप्त करने के लिए फ्लोट16 या बीफ्लोट16 के मिश्रण का उपयोग करने की अनुमति देता है।

सेट अप

import tensorflow as tf

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

समर्थित हार्डवेयर

जबकि मिश्रित परिशुद्धता अधिकांश हार्डवेयर पर चलेगी, यह केवल हाल के एनवीआईडीआईए जीपीयू और क्लाउड टीपीयू पर मॉडल को गति देगी। एनवीआईडीआईए जीपीयू फ्लोट16 और फ्लोट32 के मिश्रण का उपयोग करते हुए समर्थन करते हैं, जबकि टीपीयू बीफ्लोट16 और फ्लोट32 के मिश्रण का समर्थन करते हैं।

NVIDIA GPU के बीच, 7.0 या उससे अधिक की गणना क्षमता वाले लोग मिश्रित परिशुद्धता से सबसे बड़ा प्रदर्शन लाभ देखेंगे क्योंकि उनके पास विशेष हार्डवेयर इकाइयाँ हैं, जिन्हें Tensor Cores कहा जाता है, ताकि फ्लोट16 मैट्रिक्स गुणन और कनवल्शन में तेजी लाई जा सके। पुराने GPU मिश्रित परिशुद्धता का उपयोग करने के लिए कोई गणित प्रदर्शन लाभ प्रदान नहीं करते हैं, हालांकि मेमोरी और बैंडविड्थ बचत कुछ स्पीडअप को सक्षम कर सकती है। आप NVIDIA के CUDA GPU वेब पेज पर अपने GPU के लिए गणना क्षमता देख सकते हैं। GPU के उदाहरण जो मिश्रित परिशुद्धता से सबसे अधिक लाभान्वित होंगे, उनमें RTX GPU, V100 और A100 शामिल हैं।

आप निम्न के साथ अपने GPU प्रकार की जांच कर सकते हैं। कमांड केवल तभी मौजूद है जब NVIDIA ड्राइवर स्थापित हैं, इसलिए निम्नलिखित एक त्रुटि उत्पन्न करेगा अन्यथा।

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

सभी क्लाउड टीपीयू bfloat16 को सपोर्ट करते हैं।

यहां तक ​​​​कि सीपीयू और पुराने जीपीयू पर, जहां कोई स्पीडअप अपेक्षित नहीं है, मिश्रित सटीक एपीआई का उपयोग अभी भी यूनिट परीक्षण, डिबगिंग या एपीआई को आज़माने के लिए किया जा सकता है। हालाँकि, CPU पर, मिश्रित परिशुद्धता काफी धीमी गति से चलेगी।

dtype नीति सेट करना

केरस में मिश्रित सटीकता का उपयोग करने के लिए, आपको एक tf.keras.mixed_precision.Policy बनाने की आवश्यकता है, जिसे आमतौर पर एक dtype नीति के रूप में संदर्भित किया जाता है। Dtype नीतियां निर्दिष्ट करती हैं कि dtypes परतें चलेंगी। इस गाइड में, आप 'mixed_float16' स्ट्रिंग से एक नीति बनाएंगे और इसे वैश्विक नीति के रूप में सेट करेंगे। यह बाद में बनाई गई परतों को फ्लोट16 और फ्लोट32 के मिश्रण के साथ मिश्रित परिशुद्धता का उपयोग करने का कारण बनेगा।

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' स्ट्रिंग को इसके कन्स्ट्रक्टर को पास करके बनाई गई है)। इस नीति के साथ, परतें फ्लोट16 संगणनाओं और फ्लोट32 चरों का उपयोग करती हैं। प्रदर्शन के लिए फ्लोट16 में गणना की जाती है, लेकिन संख्यात्मक स्थिरता के लिए चर को फ्लोट 32 में रखा जाना चाहिए। आप सीधे पॉलिसी के इन गुणों को क्वेरी कर सकते हैं।

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 पर कोई भी प्रदर्शन सुधार नगण्य हो जाता है। इसलिए, यदि GPU का उपयोग किया जाता है, तो प्रत्येक 4096 इकाइयों के साथ दो बड़ी Dense परतें बनाएं।

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
प्लेसहोल्डर17

प्रत्येक परत की एक नीति होती है और डिफ़ॉल्ट रूप से वैश्विक नीति का उपयोग करती है। इसलिए प्रत्येक Dense परत में mixed_float16 नीति होती है क्योंकि आपने वैश्विक नीति को पहले mixed_float16 पर सेट किया था। यह घने परतों को फ्लोट16 कंप्यूटेशंस करने का कारण बनेगा और इसमें फ्लोट32 वैरिएबल होंगे। उन्होंने फ्लोट16 कंप्यूटेशंस करने के लिए अपने इनपुट को फ्लोट16 में डाला, जिसके परिणामस्वरूप उनके आउटपुट फ्लोट16 हो गए। उनके चर फ्लोट 32 हैं और फ्लोट 16 में डाले जाएंगे जब परतों को डीटाइप बेमेल से त्रुटियों से बचने के लिए बुलाया जाता है।

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

इसके बाद, आउटपुट भविष्यवाणियां बनाएं। आम तौर पर, आप निम्नानुसार आउटपुट पूर्वानुमान बना सकते हैं, लेकिन यह हमेशा फ्लोट16 के साथ संख्यात्मक रूप से स्थिर नहीं होता है।

# 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

मॉडल के अंत में एक सॉफ्टमैक्स सक्रियण फ्लोट32 होना चाहिए। क्योंकि dtype नीति mixed_float16 है, सॉफ्टमैक्स सक्रियण में सामान्य रूप से एक float16 कंप्यूट dtype और आउटपुट float16 टेंसर होगा।

इसे डेंस और सॉफ्टमैक्स लेयर्स को अलग करके और सॉफ्टमैक्स लेयर में dtype='float32' पास करके तय किया जा सकता है:

# 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' पास करना, लेयर की float32 पॉलिसी को फ्लोट32 पॉलिसी के रूप में ओवरराइड करता है, जो कंप्यूटेशन करता है और फ्लोट32 में वेरिएबल रखता है। समान रूप से, आप इसके बजाय dtype=mixed_precision.Policy('float32') पास कर सकते थे; परतें हमेशा dtype तर्क को नीति में परिवर्तित करती हैं। चूंकि Activation परत में कोई चर नहीं है, इसलिए नीति के चर प्रकार को नजरअंदाज कर दिया जाता है, लेकिन नीति की गणना फ्लोट32 के कारण सॉफ्टमैक्स और मॉडल आउटपुट फ्लोट32 हो जाता है।

मॉडल के बीच में फ्लोट16 सॉफ्टमैक्स जोड़ना ठीक है, लेकिन मॉडल के अंत में सॉफ्टमैक्स फ्लोट32 में होना चाहिए। इसका कारण यह है कि यदि सॉफ्टमैक्स से नुकसान की ओर बहने वाला मध्यवर्ती टेंसर फ्लोट16 या बीफ्लोट16 है, तो संख्यात्मक समस्याएँ हो सकती हैं।

यदि आपको लगता है कि यह फ्लोट16 गणनाओं के साथ संख्यात्मक रूप से स्थिर नहीं होगा, तो आप dtype='float32' पास करके किसी भी परत के dtype को float32 होने के लिए ओवरराइड कर सकते हैं। लेकिन आम तौर पर, यह केवल मॉडल की अंतिम परत पर आवश्यक है, क्योंकि अधिकांश परतों में mixed_float16 और mixed_bfloat16 16 के साथ पर्याप्त सटीकता होती है।

भले ही मॉडल सॉफ्टमैक्स में समाप्त न हो, फिर भी आउटपुट फ्लोट32 होना चाहिए। इस विशिष्ट मॉडल के लिए अनावश्यक होने पर, मॉडल आउटपुट को निम्नलिखित के साथ फ्लोट32 में डाला जा सकता है:

# 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 में डाला। आप फ्लोट16 पर कास्ट नहीं करते हैं क्योंकि 255 तक विभाजन सीपीयू पर है, जो फ्लोट16 ऑपरेशंस को फ्लोट32 ऑपरेशंस की तुलना में धीमी गति से चलाता है। इस मामले में, प्रदर्शन अंतर नगण्य है, लेकिन सामान्य तौर पर आपको सीपीयू पर चलने पर फ्लोट 32 में इनपुट प्रोसेसिंग गणित चलाना चाहिए। मॉडल की पहली परत इनपुट को फ्लोट 16 में डालेगी, क्योंकि प्रत्येक परत फ्लोटिंग-पॉइंट इनपुट को इसके कंप्यूट डीटाइप में डालेगी।

मॉडल के प्रारंभिक वजन पुनर्प्राप्त किए जाते हैं। यह वजन लोड करके फिर से खरोंच से प्रशिक्षण की अनुमति देगा।

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/कदम"। पहला युग धीमा हो सकता है क्योंकि TensorFlow मॉडल को अनुकूलित करने में कुछ समय व्यतीत करता है, लेकिन बाद में प्रति चरण समय स्थिर होना चाहिए।

यदि आप इस गाइड को Colab में चला रहे हैं, तो आप मिश्रित परिशुद्धता के प्रदर्शन की तुलना float32 से कर सकते हैं। ऐसा करने के लिए, "सेटिंग द टाइप पॉलिसी" सेक्शन में mixed_float16 से फ्लोट float32 में नीति बदलें, फिर इस बिंदु तक सभी कोशिकाओं को फिर से चलाएँ। कंप्यूट क्षमता 7.X वाले GPU पर, आपको प्रति चरण समय में उल्लेखनीय रूप से वृद्धि देखनी चाहिए, यह दर्शाता है कि मिश्रित सटीकता ने मॉडल को गति दी है। गाइड के साथ जारी रखने से पहले नीति को वापस mixed_float16 में बदलना सुनिश्चित करें और कोशिकाओं को फिर से चलाएँ।

कम से कम 8.0 (एम्पीयर जीपीयू और ऊपर) की गणना क्षमता वाले जीपीयू पर, फ्लोट 32 की तुलना में मिश्रित परिशुद्धता का उपयोग करते समय आपको इस गाइड में खिलौना मॉडल में कोई प्रदर्शन सुधार नहीं दिखाई देगा। यह TensorFloat-32 के उपयोग के कारण है, जो tf.linalg.matmul जैसे कुछ फ्लोट32 ऑप्स में स्वचालित रूप से कम सटीक गणित का उपयोग करता है। TensorFloat-32 फ्लोट32 का उपयोग करते समय मिश्रित परिशुद्धता के कुछ प्रदर्शन लाभ देता है। हालाँकि, वास्तविक दुनिया के मॉडल में, आप अभी भी आम तौर पर मेमोरी बैंडविड्थ बचत और ऑप्स के कारण मिश्रित परिशुद्धता से महत्वपूर्ण प्रदर्शन सुधार देखेंगे जो TensorFloat-32 का समर्थन नहीं करता है।

यदि टीपीयू पर मिश्रित परिशुद्धता चल रही है, तो आप जीपीयू, विशेष रूप से प्री-एम्पीयर जीपीयू पर मिश्रित परिशुद्धता चलाने की तुलना में अधिक प्रदर्शन लाभ नहीं देखेंगे। ऐसा इसलिए है क्योंकि टीपीयू फ्लोट 32 की डिफ़ॉल्ट डीटाइप नीति के साथ भी हुड के तहत bfloat16 में कुछ ऑप्स करते हैं। यह ठीक उसी तरह है जैसे एम्पीयर जीपीयू डिफ़ॉल्ट रूप से TensorFloat-32 का उपयोग करते हैं। एम्पीयर जीपीयू की तुलना में, टीपीयू आमतौर पर वास्तविक दुनिया के मॉडल पर मिश्रित सटीकता के साथ कम प्रदर्शन लाभ देखते हैं।

कई वास्तविक दुनिया के मॉडल के लिए, मिश्रित परिशुद्धता आपको मेमोरी से बाहर निकले बिना बैच आकार को दोगुना करने की अनुमति देती है, क्योंकि फ्लोट16 टेंसर आधी मेमोरी लेते हैं। हालांकि यह खिलौना मॉडल पर लागू नहीं होता है, क्योंकि आप मॉडल को किसी भी प्रकार में चला सकते हैं जहां प्रत्येक बैच में 60,000 छवियों के पूरे एमएनआईएसटी डेटासेट होते हैं।

हानि स्केलिंग

लॉस स्केलिंग एक ऐसी तकनीक है जो संख्यात्मक अंडरफ्लो से बचने के लिए tf.keras.Model.fit स्वचालित रूप से mixed_float16 नीति के साथ प्रदर्शन करती है। यह खंड बताता है कि नुकसान स्केलिंग क्या है और अगला खंड वर्णन करता है कि इसे कस्टम प्रशिक्षण लूप के साथ कैसे उपयोग किया जाए।

अंडरफ्लो और ओवरफ्लो

फ्लोट 16 डेटा प्रकार में फ्लोट 32 की तुलना में एक संकीर्ण गतिशील सीमा होती है। इसका मतलब है कि \(65504\) से ऊपर के मान अनंत तक ओवरफ़्लो हो जाएंगे और \(6.0 \times 10^{-8}\) से नीचे के मान शून्य से कम हो जाएंगे। फ्लोट 32 और बीफ्लोट 16 में बहुत अधिक गतिशील रेंज है ताकि अतिप्रवाह और अंडरफ्लो कोई समस्या न हो।

उदाहरण के लिए:

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

व्यवहार में, फ्लोट16 के साथ अतिप्रवाह शायद ही कभी होता है। इसके अतिरिक्त, फॉरवर्ड पास के दौरान अंडरफ्लो भी शायद ही कभी होता है। हालांकि, बैकवर्ड पास के दौरान, ग्रेडिएंट शून्य से नीचे आ सकते हैं। लॉस स्केलिंग इस अंडरफ्लो को रोकने की एक तकनीक है।

हानि स्केलिंग सिंहावलोकन

हानि स्केलिंग की मूल अवधारणा सरल है: बस कुछ बड़ी संख्या से हानि को गुणा करें, जैसे कि \(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 का उपयोग करना चाहिए। यह अगले भाग में वर्णित है।

एक कस्टम प्रशिक्षण लूप के साथ मॉडल का प्रशिक्षण

अब तक, आपने tf.keras.Model.fit का उपयोग करके मिश्रित परिशुद्धता के साथ एक Keras मॉडल को प्रशिक्षित किया है। इसके बाद, आप कस्टम प्रशिक्षण लूप के साथ मिश्रित परिशुद्धता का उपयोग करेंगे। यदि आप पहले से नहीं जानते हैं कि कस्टम प्रशिक्षण लूप क्या है, तो कृपया पहले कस्टम प्रशिक्षण मार्गदर्शिका पढ़ें।

मिश्रित परिशुद्धता के साथ एक कस्टम प्रशिक्षण लूप चलाने के लिए इसे फ्लोट 32 में चलाने पर दो बदलावों की आवश्यकता होती है:

  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 s को परिभाषित करें:

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) : इनपुट के रूप में स्केल किए गए ग्रेडिएंट्स की एक सूची लेता है, और प्रत्येक को नुकसान के पैमाने से विभाजित करने के लिए उन्हें अनस्केल करता है

ग्रेडिएंट में अंडरफ्लो को रोकने के लिए इन कार्यों का उपयोग किया जाना चाहिए। LossScaleOptimizer.apply_gradients तब ग्रेडिएंट लागू करेंगे यदि उनमें से किसी में भी Inf s या NaN s नहीं है। यह नुकसान के पैमाने को भी अपडेट करेगा, इसे आधा कर देगा यदि ग्रेडिएंट में Inf s या NaN s हैं और संभावित रूप से इसे अन्यथा बढ़ा रहे हैं।

@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 पर मिश्रित सटीकता का उपयोग करते समय यहां कुछ प्रदर्शन युक्तियां दी गई हैं।

अपने बैच का आकार बढ़ाना

यदि यह मॉडल की गुणवत्ता को प्रभावित नहीं करता है, तो मिश्रित परिशुद्धता का उपयोग करते समय बैच आकार को दोगुना करने का प्रयास करें। चूंकि फ्लोट16 टेंसर आधी मेमोरी का उपयोग करते हैं, यह अक्सर आपको मेमोरी खत्म किए बिना अपने बैच के आकार को दोगुना करने की अनुमति देता है। बैच का आकार बढ़ाना आमतौर पर प्रशिक्षण थ्रूपुट को बढ़ाता है, अर्थात प्रति सेकंड प्रशिक्षण तत्व जिस पर आपका मॉडल चल सकता है।

यह सुनिश्चित करना कि GPU Tensor Core का उपयोग किया जाता है

जैसा कि पहले उल्लेख किया गया है, आधुनिक NVIDIA GPU Tensor Cores नामक एक विशेष हार्डवेयर इकाई का उपयोग करते हैं जो कि फ्लोट16 मैट्रिक्स को बहुत तेज़ी से गुणा कर सकता है। हालांकि, टेंसर कोर को 8 के गुणक के लिए टेंसर के कुछ आयामों की आवश्यकता होती है। नीचे दिए गए उदाहरणों में, एक तर्क बोल्ड है यदि केवल और यदि इसे उपयोग करने के लिए टेन्सर कोर के लिए 8 का गुणक होना चाहिए।

  • tf.keras.layers.Dense( इकाइयाँ=64 )
  • tf.keras.layers.Conv2d ( फ़िल्टर = 48 , कर्नेल_साइज़ = 7, स्ट्राइड = 3)
    • और इसी तरह अन्य दृढ़ परतों के लिए, जैसे tf.keras.layers.Conv3d
  • tf.keras.layers.LSTM ( इकाइयाँ = 64 )
    • और अन्य आरएनएन के लिए समान, जैसे tf.keras.layers.GRU
  • tf.keras.Model.fit (युग = 2, बैच_साइज = 128 )

जब भी संभव हो आपको Tensor Cores का उपयोग करने का प्रयास करना चाहिए। यदि आप अधिक जानना चाहते हैं, तो NVIDIA डीप लर्निंग परफॉर्मेंस गाइड Tensor Cores के साथ-साथ अन्य Tensor Core-संबंधित प्रदर्शन जानकारी का उपयोग करने के लिए सटीक आवश्यकताओं का वर्णन करता है।

एक्सएलए

XLA एक कंपाइलर है जो मिश्रित सटीक प्रदर्शन को और बढ़ा सकता है, साथ ही साथ फ्लोट32 प्रदर्शन को कुछ हद तक बढ़ा सकता है। विवरण के लिए XLA गाइड देखें।

क्लाउड टीपीयू प्रदर्शन युक्तियाँ

GPU के साथ, आपको क्लाउड TPU का उपयोग करते समय अपने बैच के आकार को दोगुना करने का प्रयास करना चाहिए क्योंकि bfloat16 टेंसर आधी मेमोरी का उपयोग करते हैं। बैच के आकार को दोगुना करने से प्रशिक्षण थ्रूपुट बढ़ सकता है।

इष्टतम प्रदर्शन प्राप्त करने के लिए टीपीयू को किसी अन्य मिश्रित सटीक-विशिष्ट ट्यूनिंग की आवश्यकता नहीं होती है। उन्हें पहले से ही XLA के उपयोग की आवश्यकता है। टीपीयू को कुछ आयामों के \(128\)के गुणक होने से लाभ होता है, लेकिन यह फ्लोट32 प्रकार पर समान रूप से लागू होता है जैसा कि मिश्रित परिशुद्धता के लिए होता है। सामान्य टीपीयू प्रदर्शन युक्तियों के लिए क्लाउड टीपीयू प्रदर्शन मार्गदर्शिका देखें, जो मिश्रित परिशुद्धता के साथ-साथ फ्लोट32 टेंसर पर भी लागू होती है।

सारांश

  • यदि आप कम से कम गणना क्षमता 7.0 के साथ टीपीयू या एनवीआईडीआईए जीपीयू का उपयोग करते हैं तो आपको मिश्रित परिशुद्धता का उपयोग करना चाहिए, क्योंकि यह 3x तक प्रदर्शन में सुधार करेगा।
  • आप निम्न पंक्तियों के साथ मिश्रित परिशुद्धता का उपयोग कर सकते हैं:

    # On TPUs, use 'mixed_bfloat16' instead
    mixed_precision.set_global_policy('mixed_float16')
    
  • यदि आपका मॉडल सॉफ्टमैक्स में समाप्त होता है, तो सुनिश्चित करें कि यह फ्लोट32 है। और इस बात की परवाह किए बिना कि आपका मॉडल किस पर समाप्त होता है, सुनिश्चित करें कि आउटपुट फ्लोट32 है।

  • यदि आप उपरोक्त पंक्तियों के अलावा, mixed_float16 के साथ एक कस्टम प्रशिक्षण लूप का उपयोग करते हैं, तो आपको अपने अनुकूलक को tf.keras.mixed_precision.LossScaleOptimizer के साथ लपेटना होगा। फिर नुकसान को मापने के लिए optimizer.get_scaled_loss .get_scaled_loss को कॉल करें, और ग्रैडिएंट को अनस्केल करने के लिए optimizer.get_unscaled_gradients .get_unscaled_gradients को कॉल करें।

  • यदि मूल्यांकन सटीकता कम नहीं होती है, तो प्रशिक्षण बैच का आकार दोगुना करें

  • GPU पर, सुनिश्चित करें कि अधिकांश टेंसर आयाम प्रदर्शन को अधिकतम करने के लिए \(8\) के गुणक हैं

tf.keras.mixed_precision API का उपयोग करके मिश्रित परिशुद्धता के अधिक उदाहरणों के लिए, आधिकारिक मॉडल रिपॉजिटरी देखें। अधिकांश आधिकारिक मॉडल, जैसे कि ResNet और Transformer , मिश्रित परिशुद्धता का उपयोग करके --dtype=fp16 पास करके चलेंगे।