মিশ্রিত নির্ভুলতা

TensorFlow.org-এ দেখুন Google Colab-এ চালান GitHub-এ উৎস দেখুন নোটবুক ডাউনলোড করুন

ওভারভিউ

মিশ্র নির্ভুলতা হল প্রশিক্ষণের সময় মডেলটিতে 16-বিট এবং 32-বিট ফ্লোটিং-পয়েন্ট উভয় প্রকারের ব্যবহার যাতে এটি দ্রুত চালানো যায় এবং কম মেমরি ব্যবহার করা যায়। সাংখ্যিক স্থিতিশীলতার জন্য মডেলের নির্দিষ্ট অংশগুলিকে 32-বিট প্রকারে রেখে, মডেলটির ধাপে ধাপে কম সময় থাকবে এবং নির্ভুলতার মতো মূল্যায়ন মেট্রিক্সের ক্ষেত্রেও সমানভাবে প্রশিক্ষণ পাবে। আপনার মডেলের গতি বাড়ানোর জন্য কেরাস মিশ্রিত নির্ভুলতা API কীভাবে ব্যবহার করবেন তা এই নির্দেশিকাটি বর্ণনা করে। এই API ব্যবহার করলে আধুনিক GPU-তে 3 গুণের বেশি এবং TPU-তে 60% কর্মক্ষমতা উন্নত হতে পারে।

আজ, বেশিরভাগ মডেল float32 dtype ব্যবহার করে, যা 32 বিট মেমরি নেয়। যাইহোক, দুটি নিম্ন-নির্ভুলতা টাইপ আছে, float16 এবং bfloat16, প্রতিটির পরিবর্তে 16 বিট মেমরি লাগে। আধুনিক অ্যাক্সিলারেটরগুলি 16-বিট ডিটাইপগুলিতে দ্রুত কাজ চালাতে পারে, কারণ তাদের কাছে 16-বিট কম্পিউটেশন চালানোর জন্য বিশেষ হার্ডওয়্যার রয়েছে এবং 16-বিট ডিটাইপগুলি মেমরি থেকে দ্রুত পড়া যায়।

NVIDIA GPU গুলি float32-এর চেয়ে দ্রুত float16-এ কাজ চালাতে পারে, এবং TPUগুলি float32-এর চেয়ে দ্রুত bfloat16-এ কাজ চালাতে পারে। অতএব, এই নিম্ন-নির্ভুলতা টাইপগুলি যখনই সম্ভব সেই ডিভাইসগুলিতে ব্যবহার করা উচিত৷ যাইহোক, ভেরিয়েবল এবং কয়েকটি গণনা এখনও সংখ্যাগত কারণে float32-এ থাকা উচিত যাতে মডেলটি একই মানের প্রশিক্ষণ দেয়। Keras মিক্সড প্রিসিশন API আপনাকে float16/bfloat16 থেকে পারফরম্যান্স সুবিধা এবং float32 থেকে সাংখ্যিক স্থিতিশীলতার সুবিধা পেতে float32 এর সাথে float16 বা bfloat16 এর মিশ্রণ ব্যবহার করতে দেয়।

সেটআপ

import tensorflow as tf

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

সমর্থিত হার্ডওয়্যার

যদিও মিশ্র নির্ভুলতা বেশিরভাগ হার্ডওয়্যারে চলবে, এটি শুধুমাত্র সাম্প্রতিক NVIDIA GPU এবং ক্লাউড TPU-তে মডেলগুলির গতি বাড়াবে। NVIDIA GPUs float16 এবং float32 এর মিশ্রণ ব্যবহার করে সমর্থন করে, যখন TPUs bfloat16 এবং float32 এর মিশ্রণ সমর্থন করে।

NVIDIA GPU-এর মধ্যে, যাদের কম্পিউট ক্ষমতা 7.0 বা তার বেশি তারা মিশ্র নির্ভুলতা থেকে সর্বাধিক কার্যক্ষমতার সুবিধা দেখতে পাবে কারণ তাদের ফ্লোট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 এবং পুরানো GPU-তে, যেখানে কোনো গতি প্রত্যাশিত নয়, মিশ্র নির্ভুল APIগুলি এখনও ইউনিট টেস্টিং, ডিবাগিং বা শুধুমাত্র API চেষ্টা করার জন্য ব্যবহার করা যেতে পারে। CPU-তে, মিশ্র নির্ভুলতা উল্লেখযোগ্যভাবে ধীর গতিতে চলবে।

dtype নীতি সেট করা হচ্ছে

কেরাসে মিশ্র নির্ভুলতা ব্যবহার করতে, আপনাকে একটি 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')

নীতিটি একটি স্তরের দুটি গুরুত্বপূর্ণ দিক নির্দিষ্ট করে: যে টাইপটিতে স্তরের গণনা করা হয় এবং একটি স্তরের ভেরিয়েবলের dটাইপ৷ উপরে, আপনি একটি mixed_float16 নীতি তৈরি করেছেন (অর্থাৎ, একটি mixed_precision.Policy । নীতি 'mixed_float16' স্ট্রিংটি তার কন্সট্রাকটরকে পাস করে তৈরি করা হয়েছে)। এই নীতির সাথে, স্তরগুলি float16 গণনা এবং float32 ভেরিয়েবল ব্যবহার করে। পারফরম্যান্সের জন্য ফ্লোট16-এ গণনা করা হয়, তবে সংখ্যাগত স্থিতিশীলতার জন্য ভেরিয়েবলগুলি অবশ্যই 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 এর কম্পিউট ক্ষমতা সহ NVIDIA GPU-এর কর্মক্ষমতাকে উল্লেখযোগ্যভাবে উন্নত করবে। নীতিটি অন্যান্য GPU এবং CPU-তে চলবে কিন্তু কর্মক্ষমতা উন্নত নাও হতে পারে। TPU-এর জন্য, এর পরিবর্তে mixed_bfloat16 নীতি ব্যবহার করা উচিত।

মডেল নির্মাণ

এর পরে, আসুন একটি সাধারণ মডেল তৈরি করা শুরু করি। খুব ছোট খেলনা মডেলগুলি সাধারণত মিশ্র নির্ভুলতা থেকে উপকৃত হয় না, কারণ টেনসরফ্লো রানটাইম থেকে ওভারহেড সাধারণত এক্সিকিউশন টাইমকে প্রাধান্য দেয়, যা 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

প্রতিটি স্তরের একটি নীতি আছে এবং ডিফল্টরূপে বৈশ্বিক নীতি ব্যবহার করে। প্রতিটি 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 টেনসর থাকে।

এটি ঘন এবং সফ্টম্যাক্স স্তরগুলিকে পৃথক করে এবং 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' পাস করা লেয়ারের dtype পলিসিকে float32 নীতিতে ওভাররাইড করে, যা গণনা করে এবং ভেরিয়েবলগুলিকে float32-এ রাখে। সমানভাবে, আপনি পরিবর্তে dtype=mixed_precision.Policy('float32') ; স্তরগুলি সর্বদা dtype আর্গুমেন্টকে একটি নীতিতে রূপান্তর করে। যেহেতু Activation লেয়ারে কোনো ভেরিয়েবল নেই, তাই নীতির ভেরিয়েবল dtype উপেক্ষা করা হয়, কিন্তু float32-এর নীতির কম্পিউট dtype softmax এবং মডেলের আউটপুট float32 হয়৷

একটি মডেলের মাঝখানে একটি float16 softmax যোগ করা ঠিক আছে, কিন্তু মডেলের শেষে একটি softmax float32 এ থাকা উচিত। কারণ হল যে যদি সফ্টম্যাক্স থেকে ক্ষতির দিকে প্রবাহিত মধ্যবর্তী টেনসরটি float16 বা bfloat16 হয়, তাহলে সংখ্যাগত সমস্যা হতে পারে।

আপনি dtype='float32' পাস করে যেকোনো স্তরের dtype ওভাররাইড করতে পারেন যদি আপনি মনে করেন এটি float16 কম্পিউটেশনের সাথে সংখ্যাগতভাবে স্থিতিশীল হবে না। কিন্তু সাধারণত, এটি শুধুমাত্র মডেলের শেষ স্তরের জন্য প্রয়োজনীয়, কারণ বেশিরভাগ mixed_float16 এবং mixed_bfloat16 এর সাথে যথেষ্ট নির্ভুলতা রয়েছে।

এমনকি যদি মডেলটি সফটম্যাক্সে শেষ না হয়, তবুও আউটপুটগুলি 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"৷ প্রথম যুগটি ধীর হতে পারে কারণ টেনসরফ্লো মডেলটিকে অপ্টিমাইজ করার জন্য কিছু সময় ব্যয় করে, কিন্তু পরে প্রতি ধাপে সময় স্থিতিশীল হওয়া উচিত।

আপনি যদি Colab-এ এই গাইডটি চালান, তাহলে আপনি float32-এর সাথে মিশ্র নির্ভুলতার পারফরম্যান্সের তুলনা করতে পারেন। এটি করার জন্য, "dtype নীতি নির্ধারণ করা" বিভাগে float32 16 থেকে mixed_float16 -এ নীতি পরিবর্তন করুন, তারপর এই বিন্দু পর্যন্ত সমস্ত কক্ষ পুনরায় চালু করুন। কম্পিউট ক্ষমতা 7.X সহ GPUগুলিতে, আপনি প্রতি ধাপে সময় উল্লেখযোগ্যভাবে বৃদ্ধি দেখতে পাবেন, মিশ্র নির্ভুলতা মডেলের গতি বাড়িয়েছে। নীতিটি mixed_float16 এ পরিবর্তন করা নিশ্চিত করুন এবং গাইডের সাথে চালিয়ে যাওয়ার আগে ঘরগুলি পুনরায় চালু করুন।

কমপক্ষে 8.0 (অ্যাম্পিয়ার জিপিইউ এবং তার উপরে) কম্পিউট ক্ষমতা সহ GPU-তে, float32 এর তুলনায় মিশ্র নির্ভুলতা ব্যবহার করার সময় আপনি সম্ভবত এই নির্দেশিকায় খেলনা মডেলে কোনও কর্মক্ষমতা উন্নতি দেখতে পাবেন না। এটি TensorFloat-32 ব্যবহারের কারণে, যা স্বয়ংক্রিয়ভাবে নির্দিষ্ট float32 ops যেমন tf.linalg.matmul এ নিম্ন নির্ভুল গণিত ব্যবহার করে। TensorFloat-32 float32 ব্যবহার করার সময় মিশ্র নির্ভুলতার কিছু কর্মক্ষমতা সুবিধা দেয়। যাইহোক, বাস্তব-বিশ্বের মডেলগুলিতে, আপনি এখনও সাধারণত মেমরি ব্যান্ডউইথ সঞ্চয় এবং অপস যা TensorFloat-32 সমর্থন করে না কারণে মিশ্র নির্ভুলতা থেকে উল্লেখযোগ্যভাবে কর্মক্ষমতা উন্নতি দেখতে পাবেন।

টিপিইউতে মিশ্র নির্ভুলতা চালানো হলে, আপনি জিপিইউ, বিশেষ করে প্রি-অ্যাম্পিয়ার জিপিইউতে মিশ্র নির্ভুলতা চালানোর তুলনায় ততটা পারফরম্যান্স লাভ দেখতে পাবেন না। এর কারণ হল TPU গুলি float32-এর ডিফল্ট dtype নীতির সাথেও হুডের নিচে bfloat16-এ নির্দিষ্ট কিছু অপারেশন করে। এটি ডিফল্টরূপে অ্যাম্পিয়ার জিপিইউগুলি TensorFloat-32 ব্যবহার করার অনুরূপ। অ্যাম্পিয়ার জিপিইউ-এর তুলনায়, টিপিইউ সাধারণত বাস্তব-বিশ্বের মডেলগুলিতে মিশ্র নির্ভুলতার সাথে কম কর্মক্ষমতা লাভ দেখতে পায়।

অনেক বাস্তব-বিশ্বের মডেলের জন্য, মিশ্র নির্ভুলতা আপনাকে মেমরি ফুরিয়ে না গিয়ে ব্যাচের আকার দ্বিগুণ করতে দেয়, কারণ float16 টেনসর অর্ধেক মেমরি নেয়। যদিও এটি এই খেলনা মডেলের ক্ষেত্রে প্রযোজ্য নয়, কারণ আপনি সম্ভবত যে কোনো dtype মডেলটি চালাতে পারেন যেখানে প্রতিটি ব্যাচে 60,000 চিত্রের সম্পূর্ণ MNIST ডেটাসেট থাকে।

লস স্কেলিং

লস স্কেলিং হল একটি কৌশল যা 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 ব্যবহার করতে হবে। এটি পরবর্তী বিভাগে বর্ণিত হয়েছে।

একটি কাস্টম প্রশিক্ষণ লুপ সঙ্গে মডেল প্রশিক্ষণ

এখন পর্যন্ত, আপনি 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 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 না থাকে। এটি ক্ষতির স্কেলও আপডেট করবে, গ্রেডিয়েন্টে Inf s বা 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 GPU গুলি টেনসর কোর নামক একটি বিশেষ হার্ডওয়্যার ইউনিট ব্যবহার করে যা খুব দ্রুত float16 ম্যাট্রিক্সকে গুণ করতে পারে। যাইহোক, টেনসর কোর-এর জন্য টেনসরের নির্দিষ্ট মাত্রা 8-এর গুণিতক হওয়া প্রয়োজন। নীচের উদাহরণগুলিতে, একটি যুক্তি যদি টেনসর কোর ব্যবহার করার জন্য 8-এর গুণিতক হওয়া প্রয়োজন তবেই সাহসী হয়।

  • tf.keras.layers.Dense( ইউনিট=64 )
  • tf.keras.layers.Conv2d( filters=48 , kernel_size=7, stride=3)
    • এবং একইভাবে অন্যান্য পরিবর্তনমূলক স্তরগুলির জন্য, যেমন tf.keras.layers.Conv3d
  • tf.keras.layers.LSTM( ইউনিট=64 )
    • এবং অন্যান্য RNN-এর জন্য অনুরূপ, যেমন tf.keras.layers.GRU
  • tf.keras.Model.fit(epochs=2, batch_size=128 )

আপনার যখন সম্ভব টেনসর কোর ব্যবহার করার চেষ্টা করা উচিত। আপনি যদি আরও জানতে চান, NVIDIA ডিপ লার্নিং পারফরম্যান্স গাইড টেনসর কোর এবং সেইসাথে অন্যান্য টেনসর কোর-সম্পর্কিত পারফরম্যান্স তথ্য ব্যবহার করার জন্য সঠিক প্রয়োজনীয়তা বর্ণনা করে।

এক্সএলএ

XLA হল একটি কম্পাইলার যা আরও মিশ্র নির্ভুলতা কর্মক্ষমতা বাড়াতে পারে, সেইসাথে float32 কর্মক্ষমতাও কিছুটা কম। বিস্তারিত জানার জন্য XLA গাইড পড়ুন।

ক্লাউড TPU কর্মক্ষমতা টিপস

জিপিইউগুলির মতো, ক্লাউড টিপিইউ ব্যবহার করার সময় আপনার ব্যাচের আকার দ্বিগুণ করার চেষ্টা করা উচিত কারণ bfloat16 টেনসর অর্ধেক মেমরি ব্যবহার করে। ব্যাচের আকার দ্বিগুণ করা প্রশিক্ষণ থ্রুপুট বৃদ্ধি করতে পারে।

সর্বোত্তম পারফরম্যান্স পেতে TPU-গুলির অন্য কোন মিশ্র নির্ভুলতা-নির্দিষ্ট টিউনিংয়ের প্রয়োজন হয় না। তারা ইতিমধ্যে XLA ব্যবহার প্রয়োজন. TPU গুলি \(128\)এর গুণিতক হওয়ার জন্য নির্দিষ্ট মাত্রার দ্বারা উপকৃত হয়, তবে এটি float32 প্রকারের ক্ষেত্রে সমানভাবে প্রযোজ্য যেমন এটি মিশ্র নির্ভুলতার জন্য করে। সাধারণ TPU পারফরম্যান্স টিপসের জন্য ক্লাউড TPU পারফরম্যান্স গাইড দেখুন, যা মিশ্র নির্ভুলতার পাশাপাশি float32 টেনসরগুলিতে প্রযোজ্য।

সারসংক্ষেপ

  • আপনি যদি অন্তত কম্পিউট ক্ষমতা 7.0 সহ TPUs বা NVIDIA GPU ব্যবহার করেন তাহলে আপনার মিশ্র নির্ভুলতা ব্যবহার করা উচিত, কারণ এটি কার্যক্ষমতা 3x পর্যন্ত উন্নত করবে।
  • আপনি নিম্নলিখিত লাইনগুলির সাথে মিশ্র নির্ভুলতা ব্যবহার করতে পারেন:

    # 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_unscaled_gradients এবং গ্রেডিয়েন্ট আনস্কেল করতে optimizer.get_scaled_loss কল করুন।

  • প্রশিক্ষণ ব্যাচের আকার দ্বিগুণ করুন যদি এটি মূল্যায়নের নির্ভুলতা হ্রাস না করে

  • GPU-তে, কর্মক্ষমতা সর্বাধিক করার জন্য বেশিরভাগ টেনসরের মাত্রাগুলি \(8\) এর একাধিক হয় তা নিশ্চিত করুন

tf.keras.mixed_precision API ব্যবহার করে মিশ্র নির্ভুলতার আরও উদাহরণের জন্য, অফিসিয়াল মডেল রিপোজিটরি দেখুন। বেশিরভাগ অফিসিয়াল মডেল, যেমন ResNet এবং ট্রান্সফরমার , --dtype=fp16 পাস করে মিশ্র নির্ভুলতা ব্যবহার করে চলবে।