प्रशिक्षण के बाद पूर्णांक परिमाणीकरण

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

अवलोकन

पूर्णांक परिमाणीकरण एक अनुकूलन रणनीति है जो 32-बिट फ्लोटिंग-पॉइंट नंबरों (जैसे वज़न और सक्रियण आउटपुट) को निकटतम 8-बिट फिक्स्ड-पॉइंट नंबरों में परिवर्तित करती है। और एक छोटे मॉडल में यह परिणाम में वृद्धि हुई inferencing गति है, जो इस तरह के रूप कम बिजली उपकरणों के लिए मूल्यवान है माइक्रोकंट्रोलर्स । यह डेटा स्वरूप भी के लिए आवश्यक है पूर्णांक केवल इस तरह के रूप त्वरक एज TPU

इस ट्यूटोरियल में, आप स्क्रैच से एक MNIST मॉडल को प्रशिक्षित करेंगे, यह एक Tensorflow लाइट फाइल में कनवर्ट करते हैं, और का उपयोग कर इसे quantize के बाद प्रशिक्षण परिमाणीकरण । अंत में, आप परिवर्तित मॉडल की सटीकता की जांच करेंगे और इसकी तुलना मूल फ्लोट मॉडल से करेंगे।

आपके पास वास्तव में कई विकल्प हैं कि आप किसी मॉडल को कितना मापना चाहते हैं। इस ट्यूटोरियल में, आप "पूर्ण पूर्णांक परिमाणीकरण" करेंगे, जो सभी वज़न और सक्रियण आउटपुट को 8-बिट पूर्णांक डेटा में परिवर्तित करता है - जबकि अन्य रणनीतियाँ फ़्लोटिंग-पॉइंट में कुछ मात्रा में डेटा छोड़ सकती हैं।

विभिन्न परिमाणीकरण रणनीतियों, के बारे में पढ़ा के बारे में अधिक जानने के लिए TensorFlow लाइट मॉडल अनुकूलन

सेट अप

इनपुट और आउटपुट टेंसर दोनों को परिमाणित करने के लिए, हमें TensorFlow r2.3 में जोड़े गए API का उपयोग करने की आवश्यकता है:

import logging
logging.getLogger("tensorflow").setLevel(logging.DEBUG)

import tensorflow as tf
import numpy as np
assert float(tf.__version__[:3]) >= 2.3

एक TensorFlow मॉडल उत्पन्न करें

हम से वर्गीकृत नंबरों के लिए एक साधारण मॉडल बनाएंगे MNIST डाटासेट

इस प्रशिक्षण में अधिक समय नहीं लगेगा क्योंकि आप मॉडल को केवल 5 युगों के लिए प्रशिक्षण दे रहे हैं, जो लगभग ~ 98% सटीकता के लिए प्रशिक्षण देता है।

# Load MNIST dataset
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# Normalize the input image so that each pixel value is between 0 to 1.
train_images = train_images.astype(np.float32) / 255.0
test_images = test_images.astype(np.float32) / 255.0

# Define the model architecture
model = tf.keras.Sequential([
  tf.keras.layers.InputLayer(input_shape=(28, 28)),
  tf.keras.layers.Reshape(target_shape=(28, 28, 1)),
  tf.keras.layers.Conv2D(filters=12, kernel_size=(3, 3), activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(10)
])

# Train the digit classification model
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(
                  from_logits=True),
              metrics=['accuracy'])
model.fit(
  train_images,
  train_labels,
  epochs=5,
  validation_data=(test_images, test_labels)
)
Epoch 1/5
1875/1875 [==============================] - 5s 2ms/step - loss: 0.2519 - accuracy: 0.9311 - val_loss: 0.1106 - val_accuracy: 0.9664
Epoch 2/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0984 - accuracy: 0.9724 - val_loss: 0.0828 - val_accuracy: 0.9743
Epoch 3/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0746 - accuracy: 0.9785 - val_loss: 0.0640 - val_accuracy: 0.9795
Epoch 4/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0620 - accuracy: 0.9814 - val_loss: 0.0620 - val_accuracy: 0.9793
Epoch 5/5
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0540 - accuracy: 0.9837 - val_loss: 0.0624 - val_accuracy: 0.9795
<keras.callbacks.History at 0x7fb44c988c90>

एक TensorFlow लाइट मॉडल में कनवर्ट करें

अब आप का उपयोग कर TensorFlow लाइट प्रारूप करने के लिए प्रशिक्षित मॉडल में बदल सकते हैं TFLiteConverter API, और परिमाणीकरण की डिग्री बदलती लागू होते हैं।

सावधान रहें कि परिमाणीकरण के कुछ संस्करण कुछ डेटा को फ्लोट प्रारूप में छोड़ देते हैं। तो निम्न अनुभाग प्रत्येक विकल्प को परिमाणीकरण की बढ़ती मात्रा के साथ दिखाते हैं, जब तक कि हमें एक ऐसा मॉडल नहीं मिलता जो पूरी तरह से int8 या uint8 डेटा हो। (ध्यान दें कि हम प्रत्येक अनुभाग में कुछ कोड की नकल करते हैं ताकि आप प्रत्येक विकल्प के लिए सभी परिमाणीकरण चरण देख सकें।)

सबसे पहले, यहाँ एक परिवर्तित मॉडल है जिसमें कोई परिमाणीकरण नहीं है:

converter = tf.lite.TFLiteConverter.from_keras_model(model)

tflite_model = converter.convert()
2021-10-30 12:04:56.623151: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/tmp3os2tr3n/assets
2021-10-30 12:04:57.031317: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-10-30 12:04:57.031355: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.

यह अब एक TensorFlow लाइट मॉडल है, लेकिन यह अभी भी सभी पैरामीटर डेटा के लिए 32-बिट फ्लोट मानों का उपयोग कर रहा है।

डायनामिक रेंज क्वांटिज़ेशन का उपयोग करके कनवर्ट करें

आइए अब डिफ़ॉल्ट सक्षम optimizations (जैसे वजन के रूप में) सभी निश्चित मापदंडों प्रमात्रण करना झंडा:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]

tflite_model_quant = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmpi7xibvaj/assets
INFO:tensorflow:Assets written to: /tmp/tmpi7xibvaj/assets
2021-10-30 12:04:57.597982: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-10-30 12:04:57.598020: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.

मॉडल अब परिमाणित भार के साथ थोड़ा छोटा है, लेकिन अन्य चर डेटा अभी भी फ्लोट प्रारूप में है।

फ्लोट फ़ॉलबैक परिमाणीकरण का उपयोग करके कनवर्ट करें

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

def representative_data_gen():
  for input_value in tf.data.Dataset.from_tensor_slices(train_images).batch(1).take(100):
    # Model has only one input so each data point has one element.
    yield [input_value]

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_data_gen

tflite_model_quant = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmp3gwloj7n/assets
INFO:tensorflow:Assets written to: /tmp/tmp3gwloj7n/assets
2021-10-30 12:04:58.159142: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-10-30 12:04:58.159181: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0

अब सभी वज़न और परिवर्तनशील डेटा को परिमाणित किया गया है, और मॉडल मूल TensorFlow लाइट मॉडल की तुलना में काफी छोटा है।

हालांकि, उन अनुप्रयोगों के साथ संगतता बनाए रखने के लिए जो परंपरागत रूप से फ्लोट मॉडल इनपुट और आउटपुट टेंसर का उपयोग करते हैं, टेंसरफ्लो लाइट कन्वर्टर फ्लोट में मॉडल इनपुट और आउटपुट टेंसर छोड़ देता है:

interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)
input_type = interpreter.get_input_details()[0]['dtype']
print('input: ', input_type)
output_type = interpreter.get_output_details()[0]['dtype']
print('output: ', output_type)
input:  <class 'numpy.float32'>
output:  <class 'numpy.float32'>

यह आमतौर पर संगतता के लिए अच्छा है, लेकिन यह उन उपकरणों के साथ संगत नहीं होगा जो केवल पूर्णांक-आधारित संचालन करते हैं, जैसे कि एज टीपीयू।

इसके अतिरिक्त, यदि TensorFlow Lite में उस ऑपरेशन के लिए मात्रात्मक कार्यान्वयन शामिल नहीं है, तो उपरोक्त प्रक्रिया फ्लोट प्रारूप में एक ऑपरेशन छोड़ सकती है। यह रणनीति रूपांतरण को पूरा करने की अनुमति देती है ताकि आपके पास एक छोटा और अधिक कुशल मॉडल हो, लेकिन फिर से, यह केवल पूर्णांक हार्डवेयर के साथ संगत नहीं होगा। (इस एमएनआईएसटी मॉडल के सभी ऑप्स का परिमाणित कार्यान्वयन है।)

तो एक एंड-टू-एंड पूर्णांक-केवल मॉडल सुनिश्चित करने के लिए, आपको कुछ और पैरामीटर चाहिए ...

केवल पूर्णांक परिमाणीकरण का उपयोग करके कनवर्ट करें

इनपुट और आउटपुट टेंसर की मात्रा निर्धारित करने के लिए, और कनवर्टर को एक त्रुटि फेंकने के लिए यदि यह एक ऑपरेशन का सामना करता है जो इसे परिमाणित नहीं कर सकता है, तो कुछ अतिरिक्त मापदंडों के साथ मॉडल को फिर से परिवर्तित करें:

def representative_data_gen():
  for input_value in tf.data.Dataset.from_tensor_slices(train_images).batch(1).take(100):
    yield [input_value]

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_data_gen
# Ensure that if any ops can't be quantized, the converter throws an error
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
# Set the input and output tensors to uint8 (APIs added in r2.3)
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8

tflite_model_quant = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmp8ygc2_3y/assets
INFO:tensorflow:Assets written to: /tmp/tmp8ygc2_3y/assets
2021-10-30 12:04:59.308505: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-10-30 12:04:59.308542: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 3, output_inference_type: 3
WARNING:absl:For model inputs containing unsupported operations which cannot be quantized, the `inference_input_type` attribute will default to the original type.

आंतरिक परिमाणीकरण ऊपर जैसा ही रहता है, लेकिन आप देख सकते हैं कि इनपुट और आउटपुट टेंसर अब पूर्णांक प्रारूप हैं:

interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)
input_type = interpreter.get_input_details()[0]['dtype']
print('input: ', input_type)
output_type = interpreter.get_output_details()[0]['dtype']
print('output: ', output_type)
input:  <class 'numpy.uint8'>
output:  <class 'numpy.uint8'>

अब आप एक पूर्णांक quantized मॉडल है कि मॉडल के इनपुट और आउटपुट tensors के लिए डेटा पूर्णांक का उपयोग करता है, तो यह इस तरह के रूप पूर्णांक केवल हार्डवेयर के साथ संगत है एज TPU

मॉडल को फाइलों के रूप में सहेजें

तुम एक की आवश्यकता होगी .tflite अन्य उपकरणों पर अपने मॉडल को तैनात करने के लिए फ़ाइल। तो चलिए कनवर्ट किए गए मॉडल को फाइलों में सेव करते हैं और जब हम नीचे इंफेक्शन चलाते हैं तो उन्हें लोड करते हैं।

import pathlib

tflite_models_dir = pathlib.Path("/tmp/mnist_tflite_models/")
tflite_models_dir.mkdir(exist_ok=True, parents=True)

# Save the unquantized/float model:
tflite_model_file = tflite_models_dir/"mnist_model.tflite"
tflite_model_file.write_bytes(tflite_model)
# Save the quantized model:
tflite_model_quant_file = tflite_models_dir/"mnist_model_quant.tflite"
tflite_model_quant_file.write_bytes(tflite_model_quant)
24280

TensorFlow Lite मॉडल चलाएँ

अब हम TensorFlow लाइट का उपयोग कर अनुमान चलाएँगे Interpreter मॉडल सत्यता तुलना करने के लिए।

सबसे पहले, हमें एक फ़ंक्शन की आवश्यकता होती है जो किसी दिए गए मॉडल और छवियों के साथ अनुमान लगाता है, और फिर भविष्यवाणियां लौटाता है:

# Helper function to run inference on a TFLite model
def run_tflite_model(tflite_file, test_image_indices):
  global test_images

  # Initialize the interpreter
  interpreter = tf.lite.Interpreter(model_path=str(tflite_file))
  interpreter.allocate_tensors()

  input_details = interpreter.get_input_details()[0]
  output_details = interpreter.get_output_details()[0]

  predictions = np.zeros((len(test_image_indices),), dtype=int)
  for i, test_image_index in enumerate(test_image_indices):
    test_image = test_images[test_image_index]
    test_label = test_labels[test_image_index]

    # Check if the input type is quantized, then rescale input data to uint8
    if input_details['dtype'] == np.uint8:
      input_scale, input_zero_point = input_details["quantization"]
      test_image = test_image / input_scale + input_zero_point

    test_image = np.expand_dims(test_image, axis=0).astype(input_details["dtype"])
    interpreter.set_tensor(input_details["index"], test_image)
    interpreter.invoke()
    output = interpreter.get_tensor(output_details["index"])[0]

    predictions[i] = output.argmax()

  return predictions

एक छवि पर मॉडल का परीक्षण करें

अब हम फ्लोट मॉडल और परिमाणित मॉडल के प्रदर्शन की तुलना करेंगे:

  • tflite_model_file फ्लोटिंग प्वाइंट डेटा के साथ मूल TensorFlow लाइट मॉडल है।
  • tflite_model_quant_file पिछले मॉडल हम पूर्णांक केवल परिमाणीकरण का उपयोग कर परिवर्तित है (यह इनपुट और आउटपुट के लिए uint8 डेटा का उपयोग करता)।

आइए हमारी भविष्यवाणियों को मुद्रित करने के लिए एक और फ़ंक्शन बनाएं:

import matplotlib.pylab as plt

# Change this to test a different image
test_image_index = 1

## Helper function to test the models on one image
def test_model(tflite_file, test_image_index, model_type):
  global test_labels

  predictions = run_tflite_model(tflite_file, [test_image_index])

  plt.imshow(test_images[test_image_index])
  template = model_type + " Model \n True:{true}, Predicted:{predict}"
  _ = plt.title(template.format(true= str(test_labels[test_image_index]), predict=str(predictions[0])))
  plt.grid(False)

अब फ्लोट मॉडल का परीक्षण करें:

test_model(tflite_model_file, test_image_index, model_type="Float")

पीएनजी

और परिमाणित मॉडल का परीक्षण करें:

test_model(tflite_model_quant_file, test_image_index, model_type="Quantized")

पीएनजी

सभी छवियों पर मॉडल का मूल्यांकन करें

अब इस ट्यूटोरियल की शुरुआत में लोड की गई सभी परीक्षण छवियों का उपयोग करके दोनों मॉडलों को चलाते हैं:

# Helper function to evaluate a TFLite model on all images
def evaluate_model(tflite_file, model_type):
  global test_images
  global test_labels

  test_image_indices = range(test_images.shape[0])
  predictions = run_tflite_model(tflite_file, test_image_indices)

  accuracy = (np.sum(test_labels== predictions) * 100) / len(test_images)

  print('%s model accuracy is %.4f%% (Number of test samples=%d)' % (
      model_type, accuracy, len(test_images)))

फ्लोट मॉडल का मूल्यांकन करें:

evaluate_model(tflite_model_file, model_type="Float")
Float model accuracy is 97.9500% (Number of test samples=10000)

परिमाणित मॉडल का मूल्यांकन करें:

evaluate_model(tflite_model_quant_file, model_type="Quantized")
Quantized model accuracy is 97.9300% (Number of test samples=10000)

तो अब आपके पास फ्लोट मॉडल की तुलना में सटीकता में लगभग कोई अंतर नहीं होने वाले मॉडल को एक पूर्णांक मात्राबद्ध किया गया है।

अन्य परिमाणीकरण रणनीतियों, के बारे में पढ़ा के बारे में अधिक जानने के लिए TensorFlow लाइट मॉडल अनुकूलन