کمی سازی عدد صحیح پس از آموزش

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

بررسی اجمالی

کوانتیزاسیون صحیح یک استراتژی بهینه سازی است که اعداد نقطه شناور 32 بیتی (مانند وزن و خروجی فعالسازی) را به نزدیکترین اعداد نقطه ثابت 8 بیتی تبدیل می کند. این نتایج در یک مدل کوچک تر و افزایش سرعت استنتاج، برای دستگاه های کم قدرت با ارزش است که مانند میکروکنترلرها . این فرمت داده نیز توسط مورد نیاز عدد صحیح فقط مانند شتاب دهنده لبه TPU .

در این آموزش، شما یک مدل MNIST از ابتدا آموزش، آن را تبدیل به یک فایل Tensorflow مطلب، و فرمول اندازهگیری آن با استفاده از کوانتیزاسیون پس از آموزش . در نهایت ، شما دقت مدل تبدیل شده را بررسی کرده و آن را با مدل شناور اصلی مقایسه می کنید.

در واقع شما چندین گزینه برای تعیین مقدار یک مدل دارید. در این آموزش ، شما "کوانتیزاسیون صحیح کامل" را انجام می دهید ، که همه وزن ها و خروجی های فعال سازی را به داده های صحیح 8 بیتی تبدیل می کند-در حالی که سایر استراتژی ها ممکن است مقداری داده را در نقطه شناور باقی بگذارند.

برای کسب اطلاعات بیشتر در مورد استراتژی های تدریج مختلف، خواندن در مورد بهینه سازی مدل TensorFlow بازگشت به محتوا | .

برپایی

برای اندازه گیری هر دو کشنده ورودی و خروجی ، باید از API های اضافه شده در TensorFlow r2.3 استفاده کنیم:

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 accuracy دقت را آموزش می دهد.

# 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)
)
2021-09-12 11:12:32.819553: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_SYSTEM_DRIVER_MISMATCH: system has unsupported display driver / cuda driver combination
2021-09-12 11:12:32.819712: E tensorflow/stream_executor/cuda/cuda_diagnostics.cc:313] kernel version 470.57.2 does not match DSO version 470.63.1 -- cannot find working devices in this configuration
Epoch 1/5
1875/1875 [==============================] - 10s 5ms/step - loss: 0.2801 - accuracy: 0.9208 - val_loss: 0.1311 - val_accuracy: 0.9640
Epoch 2/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.1110 - accuracy: 0.9684 - val_loss: 0.0896 - val_accuracy: 0.9730
Epoch 3/5
1875/1875 [==============================] - 10s 5ms/step - loss: 0.0814 - accuracy: 0.9768 - val_loss: 0.0708 - val_accuracy: 0.9765
Epoch 4/5
1875/1875 [==============================] - 10s 5ms/step - loss: 0.0678 - accuracy: 0.9803 - val_loss: 0.0619 - val_accuracy: 0.9790
Epoch 5/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0590 - accuracy: 0.9826 - val_loss: 0.0594 - val_accuracy: 0.9799
<keras.callbacks.History at 0x7fe418a28ed0>

تبدیل به مدل TensorFlow Lite

در حال حاضر شما می توانید مدل آموزش دیده را به فرمت TensorFlow آرشیو با استفاده از تبدیل TFLiteConverter API، و اعمال درجات مختلفی از تدریج.

مراقب باشید که برخی از نسخه های کوانتیزاسیون برخی از داده ها را در قالب شناور قرار می دهند. بنابراین بخش های زیر هر یک از گزینه ها را با افزایش مقدار کوانتیزاسیون نشان می دهد ، تا زمانی که مدلی را دریافت کنیم که کاملاً داده int8 یا uint8 باشد. (توجه داشته باشید که ما در هر بخش تعدادی کد را تکراری می کنیم تا بتوانید تمام مراحل کوانتاسیون برای هر گزینه را مشاهده کنید.)

اول ، در اینجا یک مدل تبدیل شده بدون کوانتیزه است:

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

tflite_model = converter.convert()
2021-09-12 11:13:21.390430: 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/tmpcxslls_y/assets
2021-09-12 11:13:21.805193: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-09-12 11:13:21.805239: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.

در حال حاضر یک مدل TensorFlow Lite است ، اما هنوز از مقادیر شناور 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/tmpz_srxxsd/assets
INFO:tensorflow:Assets written to: /tmp/tmpz_srxxsd/assets
2021-09-12 11:13:22.372952: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-09-12 11:13:22.372999: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.

مدل در حال حاضر کمی کوچکتر با وزن های کمی شده است ، اما سایر داده های متغیر هنوز در قالب شناور هستند.

با استفاده از کوانتیزاسیون float float تبدیل کنید

برای فرمول اندازهگیری داده های متغیر (مانند ورودی مدل / خروجی و واسطه بین لایه)، شما نیاز به ارائه یک 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/tmpao6f2zfk/assets
INFO:tensorflow:Assets written to: /tmp/tmpao6f2zfk/assets
2021-09-12 11:13:22.933640: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-09-12 11:13:22.933678: 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 Lite به طور قابل توجهی کوچکتر است.

با این حال ، برای حفظ سازگاری با برنامه های کاربردی که به طور سنتی از کشنده های ورودی و خروجی مدل float استفاده می کنند ، TensorFlow Lite Converter مدل های کششی ورودی و خروجی مدل را در float قرار می دهد:

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'>

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

علاوه بر این ، اگر TensorFlow Lite یک پیاده سازی کوانتیزه برای آن عملیات را شامل نشود ، ممکن است یک فرایند فوق یک عملیات را در قالب float ترک کند. این استراتژی اجازه می دهد تا تبدیل کامل شود بنابراین شما یک مدل کوچکتر و کارآمدتر دارید ، اما باز هم ، با سخت افزارهای صحیح سازگار نخواهد بود. (همه گزینه های موجود در این مدل MNIST دارای پیاده سازی کمی هستند.)

بنابراین برای اطمینان از یک مدل انتهای به انتهای عدد صحیح ، به چند پارامتر دیگر نیاز دارید ...

تبدیل با استفاده از کوانتیزه فقط برای عدد صحیح

برای کمی کردن کشنده های ورودی و خروجی و ایجاد خطا در مبدل در صورت مواجه شدن با عملیاتی که نمی تواند آن را اندازه گیری کند ، مدل را با پارامترهای اضافی دوباره تبدیل کنید:

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/tmpfu_lr0lq/assets
INFO:tensorflow:Assets written to: /tmp/tmpfu_lr0lq/assets
2021-09-12 11:13:24.044232: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-09-12 11:13:24.044271: 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'>

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

png

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

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

png

مدل ها را روی همه تصاویر ارزیابی کنید

حالا بیایید هر دو مدل را با استفاده از تمام تصاویر آزمایشی که در ابتدای این آموزش بارگذاری کرده ایم اجرا کنیم:

# 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.9900% (Number of test samples=10000)

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

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

بنابراین شما در حال حاضر یک عدد صحیح را در مقایسه با مدل شناور تقریباً بدون دقت در دقت ، اندازه گیری کرده اید.

برای کسب اطلاعات بیشتر در مورد دیگر استراتژی های تدریج، به عنوان خوانده شده در مورد بهینه سازی مدل TensorFlow بازگشت به محتوا | .