Kuantisasi pasca-pelatihan

Kuantisasi pasca-pelatihan adalah teknik konversi yang dapat mengurangi ukuran model sekaligus meningkatkan latensi CPU dan akselerator perangkat keras, dengan sedikit penurunan akurasi model. Anda dapat mengkuantisasi model float TensorFlow yang sudah dilatih saat mengonversinya ke format TensorFlow Lite menggunakan TensorFlow Lite Converter .

Metode Optimasi

Ada beberapa opsi kuantisasi pasca pelatihan yang dapat dipilih. Berikut tabel ringkasan pilihan dan manfaat yang diberikannya:

Teknik Manfaat Perangkat keras
Kuantisasi rentang dinamis 4x lebih kecil, kecepatan 2x-3x CPU
Kuantisasi bilangan bulat penuh 4x lebih kecil, 3x+ percepatan CPU, Edge TPU, Mikrokontroler
Kuantisasi Float16 2x lebih kecil, akselerasi GPU CPU, GPU

Pohon keputusan berikut dapat membantu menentukan metode kuantisasi pasca pelatihan mana yang terbaik untuk kasus penggunaan Anda:

opsi pengoptimalan pasca pelatihan

Kuantisasi rentang dinamis

Kuantisasi rentang dinamis adalah titik awal yang direkomendasikan karena memberikan pengurangan penggunaan memori dan komputasi yang lebih cepat tanpa Anda harus menyediakan kumpulan data yang representatif untuk kalibrasi. Jenis kuantisasi ini, secara statis hanya mengkuantisasi bobot dari floating point ke integer pada waktu konversi, yang memberikan presisi 8-bit:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

Untuk lebih mengurangi latensi selama inferensi, operator "rentang dinamis" secara dinamis mengkuantifikasi aktivasi berdasarkan rentangnya hingga 8-bit dan melakukan komputasi dengan bobot dan aktivasi 8-bit. Pengoptimalan ini memberikan latensi yang mendekati kesimpulan titik tetap sepenuhnya. Namun, keluarannya masih disimpan menggunakan titik mengambang sehingga peningkatan kecepatan operasi rentang dinamis kurang dari komputasi titik tetap penuh.

Kuantisasi bilangan bulat penuh

Anda bisa mendapatkan peningkatan latensi lebih lanjut, pengurangan penggunaan memori puncak, dan kompatibilitas dengan perangkat keras atau akselerator bilangan bulat saja dengan memastikan semua matematika model dikuantisasi bilangan bulat.

Untuk kuantisasi bilangan bulat penuh, Anda perlu mengkalibrasi atau memperkirakan rentang, yaitu (min, maks) semua tensor floating-point dalam model. Tidak seperti tensor konstan seperti bobot dan bias, tensor variabel seperti masukan model, aktivasi (keluaran lapisan perantara), dan keluaran model tidak dapat dikalibrasi kecuali kita menjalankan beberapa siklus inferensi. Akibatnya, konverter memerlukan kumpulan data yang representatif untuk mengkalibrasinya. Kumpulan data ini dapat berupa sebagian kecil (sekitar ~100-500 sampel) dari data pelatihan atau validasi. Lihat fungsi representative_dataset() di bawah.

Dari TensorFlow versi 2.7, Anda dapat menentukan kumpulan data perwakilan melalui tanda tangan seperti contoh berikut:

def representative_dataset():
  for data in dataset:
    yield {
      "image": data.image,
      "bias": data.bias,
    }

Jika ada lebih dari satu tanda tangan dalam model TensorFlow yang diberikan, Anda dapat menentukan beberapa set data dengan menentukan kunci tanda tangan:

def representative_dataset():
  # Feed data set for the "encode" signature.
  for data in encode_signature_dataset:
    yield (
      "encode", {
        "image": data.image,
        "bias": data.bias,
      }
    )

  # Feed data set for the "decode" signature.
  for data in decode_signature_dataset:
    yield (
      "decode", {
        "image": data.image,
        "hint": data.hint,
      },
    )

Anda dapat menghasilkan kumpulan data representatif dengan memberikan daftar tensor masukan:

def representative_dataset():
  for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100):
    yield [tf.dtypes.cast(data, tf.float32)]

Sejak TensorFlow versi 2.7, sebaiknya gunakan pendekatan berbasis tanda tangan dibandingkan pendekatan berbasis daftar tensor masukan karena urutan tensor masukan dapat dengan mudah dibalik.

Untuk tujuan pengujian, Anda dapat menggunakan kumpulan data dummy sebagai berikut:

def representative_dataset():
    for _ in range(100):
      data = np.random.rand(1, 244, 244, 3)
      yield [data.astype(np.float32)]
 

Integer dengan float fallback (menggunakan input/output float default)

Untuk mengkuantisasi model secara integer sepenuhnya, namun menggunakan operator float ketika operator tersebut tidak memiliki implementasi integer (untuk memastikan konversi terjadi dengan lancar), gunakan langkah-langkah berikut:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
tflite_quant_model = converter.convert()

Hanya bilangan bulat

Membuat model bilangan bulat saja adalah kasus penggunaan umum TensorFlow Lite untuk Mikrokontroler dan TPU Coral Edge .

Selain itu, untuk memastikan kompatibilitas dengan perangkat integer saja (seperti mikrokontroler 8-bit) dan akselerator (seperti Coral Edge TPU), Anda dapat menerapkan kuantisasi integer penuh untuk semua operasi termasuk input dan output, dengan menggunakan langkah-langkah berikut:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8
tflite_quant_model = converter.convert()

Kuantisasi Float16

Anda dapat mengurangi ukuran model floating point dengan mengkuantisasi bobotnya menjadi float16, standar IEEE untuk angka floating point 16-bit. Untuk mengaktifkan kuantisasi bobot float16, gunakan langkah-langkah berikut:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

Keuntungan kuantisasi float16 adalah sebagai berikut:

  • Ini mengurangi ukuran model hingga setengahnya (karena semua bobot menjadi setengah dari ukuran aslinya).
  • Ini menyebabkan hilangnya akurasi yang minimal.
  • Ini mendukung beberapa delegasi (misalnya delegasi GPU) yang dapat beroperasi secara langsung pada data float16, sehingga menghasilkan eksekusi yang lebih cepat daripada komputasi float32.

Kerugian dari kuantisasi float16 adalah sebagai berikut:

  • Itu tidak mengurangi latensi sebanyak kuantisasi ke matematika titik tetap.
  • Secara default, model terkuantisasi float16 akan "mendekuantisasi" nilai bobot menjadi float32 saat dijalankan di CPU. (Perhatikan bahwa delegasi GPU tidak akan melakukan dekuantisasi ini, karena dapat beroperasi pada data float16.)

Hanya bilangan bulat: aktivasi 16-bit dengan bobot 8-bit (eksperimental)

Ini adalah skema kuantisasi eksperimental. Ini mirip dengan skema "hanya bilangan bulat", tetapi aktivasi dikuantisasi berdasarkan rentangnya hingga 16-bit, bobot dikuantisasi dalam bilangan bulat 8-bit dan bias dikuantisasi menjadi bilangan bulat 64-bit. Ini lebih lanjut disebut sebagai kuantisasi 16x8.

Keuntungan utama kuantisasi ini adalah dapat meningkatkan akurasi secara signifikan, namun hanya sedikit meningkatkan ukuran model.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

Jika kuantisasi 16x8 tidak didukung untuk beberapa operator dalam model, maka model masih dapat dikuantisasi, namun operator yang tidak didukung tetap berada dalam float. Opsi berikut harus ditambahkan ke target_spec untuk memungkinkan hal ini.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

Contoh kasus penggunaan peningkatan akurasi yang diberikan oleh skema kuantisasi ini meliputi:

  • resolusi super,
  • pemrosesan sinyal audio seperti peredam bising dan beamforming,
  • menghilangkan kebisingan gambar,
  • Rekonstruksi HDR dari satu gambar.

Kerugian dari kuantisasi ini adalah:

  • Saat ini inferensi terasa lebih lambat dibandingkan bilangan bulat penuh 8-bit karena kurangnya implementasi kernel yang dioptimalkan.
  • Saat ini tidak kompatibel dengan delegasi TFLite yang dipercepat perangkat keras yang ada.

Tutorial untuk mode kuantisasi ini dapat ditemukan di sini .

Akurasi model

Karena bobot dikuantisasi setelah pelatihan, mungkin terdapat kehilangan akurasi, terutama untuk jaringan yang lebih kecil. Model terkuantisasi penuh yang telah dilatih sebelumnya disediakan untuk jaringan tertentu di TensorFlow Hub . Penting untuk memeriksa keakuratan model terkuantisasi untuk memverifikasi bahwa penurunan akurasi berada dalam batas yang dapat diterima. Terdapat alat untuk mengevaluasi akurasi model TensorFlow Lite .

Alternatifnya, jika penurunan akurasi terlalu tinggi, pertimbangkan untuk menggunakan pelatihan sadar kuantisasi . Namun, hal ini memerlukan modifikasi selama pelatihan model untuk menambahkan node kuantisasi palsu, sedangkan teknik kuantisasi pasca-pelatihan di halaman ini menggunakan model terlatih yang sudah ada.

Representasi untuk tensor terkuantisasi

Kuantisasi 8-bit memperkirakan nilai floating point menggunakan rumus berikut.

\[real\_value = (int8\_value - zero\_point) \times scale\]

Representasi memiliki dua bagian utama:

  • Bobot per sumbu (alias per saluran) atau per tensor diwakili oleh nilai komplemen dua int8 dalam rentang [-127, 127] dengan titik nol sama dengan 0.

  • Aktivasi/input per-tensor diwakili oleh nilai komplemen dua int8 dalam rentang [-128, 127], dengan titik nol dalam rentang [-128, 127].

Untuk tampilan detail skema kuantisasi kami, silakan lihat spesifikasi kuantisasi kami. Vendor perangkat keras yang ingin menyambungkan ke antarmuka delegasi TensorFlow Lite disarankan untuk menerapkan skema kuantisasi yang dijelaskan di sana.