İnt16 aktivasyonlu eğitim sonrası tamsayı niceleme

TensorFlow.org'da görüntüleyin Google Colab'de çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

Genel Bakış

TensorFlow Lite , TensorFlow'dan TensorFlow Lite'ın düz arabellek formatına model dönüşümü sırasında artık etkinleştirmeleri 16 bitlik tam sayı değerlerine ve ağırlıkları 8 bitlik tam sayı değerlerine dönüştürmeyi destekliyor. Bu moda "16x8 nicemleme modu" diyoruz. Bu mod, etkinleştirmeler nicemlemeye duyarlı olduğunda nicelenmiş modelin doğruluğunu önemli ölçüde artırabilirken, yine de model boyutunda neredeyse 3-4 kat azalma sağlar. Dahası, bu tamamen nicelleştirilmiş model, yalnızca tam sayı donanım hızlandırıcıları tarafından tüketilebilir.

Eğitim sonrası nicelemenin bu modundan yararlanan bazı model örnekleri şunları içerir:

  • süper çözünürlük,
  • gürültü engelleme ve hüzmeleme gibi ses sinyali işleme,
  • görüntü gürültü giderme,
  • Tek bir görüntüden HDR rekonstrüksiyonu

Bu eğitimde, bir MNIST modelini sıfırdan eğitiyor, TensorFlow'da doğruluğunu kontrol ediyor ve ardından bu modu kullanarak modeli bir Tensorflow Lite düz arabelleğe dönüştürüyorsunuz. Sonunda, dönüştürülen modelin doğruluğunu kontrol eder ve orijinal float32 modeliyle karşılaştırırsınız. Bu örneğin, bu modun kullanımını gösterdiğini ve TensorFlow Lite'taki diğer mevcut niceleme tekniklerine göre faydalar göstermediğini unutmayın.

MNIST modeli oluşturun

Kurulum

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

import tensorflow as tf
from tensorflow import keras
import numpy as np
import pathlib

16x8 niceleme modunun mevcut olup olmadığını kontrol edin

tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8
<OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8: 'EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8'>

Modeli eğitin ve dışa aktarın

# Load MNIST dataset
mnist = 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 / 255.0
test_images = test_images / 255.0

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

# Train the digit classification model
model.compile(optimizer='adam',
              loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(
  train_images,
  train_labels,
  epochs=1,
  validation_data=(test_images, test_labels)
)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
1875/1875 [==============================] - 13s 2ms/step - loss: 0.2827 - accuracy: 0.9209 - val_loss: 0.1246 - val_accuracy: 0.9664
<tensorflow.python.keras.callbacks.History at 0x7fc6d432cd50>

Örneğin, modeli yalnızca tek bir dönem için eğittiniz, bu nedenle model yalnızca ~% 96 doğrulukla eğitilir.

TensorFlow Lite modeline dönüştürme

Python TFLiteConverter'ı kullanarak artık eğitilmiş modeli bir TensorFlow Lite modeline dönüştürebilirsiniz.

Şimdi, TFliteConverter kullanarak modeli varsayılan float32 biçimine dönüştürün:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmpsw317yw_/assets

Bir .tflite dosyasına yazın:

tflite_models_dir = pathlib.Path("/tmp/mnist_tflite_models/")
tflite_models_dir.mkdir(exist_ok=True, parents=True)
tflite_model_file = tflite_models_dir/"mnist_model.tflite"
tflite_model_file.write_bytes(tflite_model)
84552

Bunun yerine modeli 16x8 niceleme moduna nicelendirmek için, önce optimizations bayrağını varsayılan optimizasyonları kullanacak şekilde ayarlayın. Ardından, hedef spesifikasyonunda 16x8 niceleme modunun gerekli desteklenen işlem olduğunu belirtin:

converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]

İnt8 eğitim sonrası niceleme durumunda olduğu gibi, dönüştürücü seçeneklerini inference_input(output)_type olarak ayarlayarak tam sayı nicemlenmiş bir model üretmek mümkündür.

Kalibrasyon verilerini ayarlayın:

mnist_train, _ = tf.keras.datasets.mnist.load_data()
images = tf.cast(mnist_train[0], tf.float32) / 255.0
mnist_ds = tf.data.Dataset.from_tensor_slices((images)).batch(1)
def representative_data_gen():
  for input_value in mnist_ds.take(100):
    # Model has only one input so each data point has one element.
    yield [input_value]
converter.representative_dataset = representative_data_gen

Son olarak, modeli her zamanki gibi dönüştürün. Varsayılan olarak, dönüştürülmüş modelin çağrı kolaylığı için yine de kayan giriş ve çıkışlar kullanacağını unutmayın.

tflite_16x8_model = converter.convert()
tflite_model_16x8_file = tflite_models_dir/"mnist_model_quant_16x8.tflite"
tflite_model_16x8_file.write_bytes(tflite_16x8_model)
INFO:tensorflow:Assets written to: /tmp/tmpaq8qqppx/assets
INFO:tensorflow:Assets written to: /tmp/tmpaq8qqppx/assets
24832

Elde edilen dosyanın boyutunun yaklaşık 1/3 olduğuna dikkat edin.

ls -lh {tflite_models_dir}
total 112K
-rw-rw-r-- 1 kbuilder kbuilder 83K May 15 11:12 mnist_model.tflite
-rw-rw-r-- 1 kbuilder kbuilder 25K May 15 11:12 mnist_model_quant_16x8.tflite

TensorFlow Lite modellerini çalıştırın

Python TensorFlow Lite Yorumlayıcı'yı kullanarak TensorFlow Lite modelini çalıştırın.

Modeli yorumlayıcılara yükleyin

interpreter = tf.lite.Interpreter(model_path=str(tflite_model_file))
interpreter.allocate_tensors()
interpreter_16x8 = tf.lite.Interpreter(model_path=str(tflite_model_16x8_file))
interpreter_16x8.allocate_tensors()

Modelleri tek bir görüntü üzerinde test edin

test_image = np.expand_dims(test_images[0], axis=0).astype(np.float32)

input_index = interpreter.get_input_details()[0]["index"]
output_index = interpreter.get_output_details()[0]["index"]

interpreter.set_tensor(input_index, test_image)
interpreter.invoke()
predictions = interpreter.get_tensor(output_index)
import matplotlib.pylab as plt

plt.imshow(test_images[0])
template = "True:{true}, predicted:{predict}"
_ = plt.title(template.format(true= str(test_labels[0]),
                              predict=str(np.argmax(predictions[0]))))
plt.grid(False)

png

test_image = np.expand_dims(test_images[0], axis=0).astype(np.float32)

input_index = interpreter_16x8.get_input_details()[0]["index"]
output_index = interpreter_16x8.get_output_details()[0]["index"]

interpreter_16x8.set_tensor(input_index, test_image)
interpreter_16x8.invoke()
predictions = interpreter_16x8.get_tensor(output_index)
plt.imshow(test_images[0])
template = "True:{true}, predicted:{predict}"
_ = plt.title(template.format(true= str(test_labels[0]),
                              predict=str(np.argmax(predictions[0]))))
plt.grid(False)

png

Modelleri değerlendirin

# A helper function to evaluate the TF Lite model using "test" dataset.
def evaluate_model(interpreter):
  input_index = interpreter.get_input_details()[0]["index"]
  output_index = interpreter.get_output_details()[0]["index"]

  # Run predictions on every image in the "test" dataset.
  prediction_digits = []
  for test_image in test_images:
    # Pre-processing: add batch dimension and convert to float32 to match with
    # the model's input data format.
    test_image = np.expand_dims(test_image, axis=0).astype(np.float32)
    interpreter.set_tensor(input_index, test_image)

    # Run inference.
    interpreter.invoke()

    # Post-processing: remove batch dimension and find the digit with highest
    # probability.
    output = interpreter.tensor(output_index)
    digit = np.argmax(output()[0])
    prediction_digits.append(digit)

  # Compare prediction results with ground truth labels to calculate accuracy.
  accurate_count = 0
  for index in range(len(prediction_digits)):
    if prediction_digits[index] == test_labels[index]:
      accurate_count += 1
  accuracy = accurate_count * 1.0 / len(prediction_digits)

  return accuracy
print(evaluate_model(interpreter))
0.9664

16x8 nicemlenmiş modelde değerlendirmeyi tekrarlayın:

# NOTE: This quantization mode is an experimental post-training mode,
# it does not have any optimized kernels implementations or
# specialized machine learning hardware accelerators. Therefore,
# it could be slower than the float interpreter.
print(evaluate_model(interpreter_16x8))
0.9662

Bu örnekte, doğrulukta bir fark olmadan, ancak 3x küçültülmüş boyutla bir modeli 16x8 olarak nicelendirdiniz.