Lượng tử hóa float16 sau đào tạo

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Tổng quat

TensorFlow Lite bây giờ hỗ trợ chuyển đổi trọng các giá trị dấu chấm động 16-bit trong mô hình chuyển đổi từ TensorFlow sang định dạng đệm phẳng TensorFlow Lite. Điều này dẫn đến việc giảm kích thước mô hình xuống 2 lần. Một số phần cứng, như GPU, có thể tính toán nguyên bản trong số học có độ chính xác giảm này, giúp tăng tốc độ so với thực thi dấu phẩy động truyền thống. Có thể định cấu hình đại biểu GPU Tensorflow Lite để chạy theo cách này. Tuy nhiên, một mô hình được chuyển đổi thành trọng số float16 vẫn có thể chạy trên CPU mà không cần sửa đổi bổ sung: trọng số float16 được lấy mẫu bổ sung thành float32 trước suy luận đầu tiên. Điều này cho phép giảm đáng kể kích thước mô hình để đổi lấy tác động tối thiểu đến độ trễ và độ chính xác.

Trong hướng dẫn này, bạn đào tạo mô hình MNIST từ đầu, kiểm tra độ chính xác của nó trong TensorFlow, sau đó chuyển đổi mô hình thành bộ đệm phẳng Tensorflow Lite với lượng tử hóa float16. Cuối cùng, kiểm tra độ chính xác của mô hình đã chuyển đổi và so sánh với mô hình float32 ban đầu.

Xây dựng mô hình MNIST

Thành lập

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

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

Đào tạo và xuất mô hình

# 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
11501568/11490434 [==============================] - 0s 0us/step
1875/1875 [==============================] - 13s 2ms/step - loss: 0.2655 - accuracy: 0.9244 - val_loss: 0.1237 - val_accuracy: 0.9654
<keras.callbacks.History at 0x7f3f8428e6d0>

Ví dụ: bạn đã đào tạo mô hình chỉ trong một kỷ nguyên, vì vậy nó chỉ đào tạo đến độ chính xác ~ 96%.

Chuyển đổi sang mô hình TensorFlow Lite

Sử dụng Python TFLiteConverter , bây giờ bạn có thể chuyển đổi các mô hình đào tạo thành một mô hình TensorFlow Lite.

Bây giờ tải các mô hình sử dụng TFLiteConverter :

converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
2021-12-14 12:18:07.073783: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/tmpm1s3vkrd/assets
2021-12-14 12:18:07.876066: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-12-14 12:18:07.876112: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
WARNING:absl:Buffer deduplication procedure will be skipped when flatbuffer library is not properly loaded

Viết nó ra một .tflite file:

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)
84540

Để thay quantize mô hình để float16 về xuất khẩu, đầu tiên thiết lập optimizations cờ để tối ưu hóa sử dụng mặc định. Sau đó, chỉ định float16 là loại được hỗ trợ trên nền tảng đích:

converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]

Cuối cùng, chuyển đổi mô hình như bình thường. Lưu ý, theo mặc định, mô hình được chuyển đổi sẽ vẫn sử dụng đầu vào và đầu ra float để thuận tiện cho việc gọi.

tflite_fp16_model = converter.convert()
tflite_model_fp16_file = tflite_models_dir/"mnist_model_quant_f16.tflite"
tflite_model_fp16_file.write_bytes(tflite_fp16_model)
INFO:tensorflow:Assets written to: /tmp/tmpvjt9l68i/assets
INFO:tensorflow:Assets written to: /tmp/tmpvjt9l68i/assets
2021-12-14 12:18:08.810262: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-12-14 12:18:08.810303: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
WARNING:absl:Buffer deduplication procedure will be skipped when flatbuffer library is not properly loaded
44384

Lưu ý cách các tập tin kết quả là khoảng 1/2 kích thước.

ls -lh {tflite_models_dir}
total 128K
-rw-rw-r-- 1 kbuilder kbuilder 83K Dec 14 12:18 mnist_model.tflite
-rw-rw-r-- 1 kbuilder kbuilder 44K Dec 14 12:18 mnist_model_quant_f16.tflite

Chạy các mô hình TensorFlow Lite

Chạy mô hình TensorFlow Lite bằng Trình thông dịch Python TensorFlow Lite.

Tải mô hình vào trình thông dịch

interpreter = tf.lite.Interpreter(model_path=str(tflite_model_file))
interpreter.allocate_tensors()
interpreter_fp16 = tf.lite.Interpreter(model_path=str(tflite_model_fp16_file))
interpreter_fp16.allocate_tensors()

Kiểm tra các mô hình trên một hình ảnh

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_fp16.get_input_details()[0]["index"]
output_index = interpreter_fp16.get_output_details()[0]["index"]

interpreter_fp16.set_tensor(input_index, test_image)
interpreter_fp16.invoke()
predictions = interpreter_fp16.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

Đánh giá các mô hình

# 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.9654

Lặp lại đánh giá trên mô hình lượng tử float16 để thu được:

# NOTE: Colab runs on server CPUs. At the time of writing this, TensorFlow Lite
# doesn't have super optimized server CPU kernels. For this reason this may be
# slower than the above float interpreter. But for mobile CPUs, considerable
# speedup can be observed.
print(evaluate_model(interpreter_fp16))
0.9654

Trong ví dụ này, bạn đã lượng tử hóa một mô hình thành float16 mà không có sự khác biệt về độ chính xác.

Cũng có thể đánh giá mô hình lượng tử hóa fp16 trên GPU. Để thực hiện tất cả số học với các giá trị chính xác giảm, hãy chắc chắn để tạo ra các TfLiteGPUDelegateOptions struct trong ứng dụng và thiết lập của bạn precision_loss_allowed để 1 , như thế này:

//Prepare GPU delegate.
const TfLiteGpuDelegateOptions options = {
  .metadata = NULL,
  .compile_options = {
    .precision_loss_allowed = 1,  // FP16
    .preferred_gl_object_type = TFLITE_GL_OBJECT_TYPE_FASTEST,
    .dynamic_batch_enabled = 0,   // Not fully functional yet
  },
};

Tài liệu hướng dẫn chi tiết về các đại biểu TFLite GPU và làm thế nào để sử dụng nó trong ứng dụng của bạn có thể được tìm thấy ở đây