Terima kasih telah mendengarkan Google I/O. Lihat semua sesi sesuai permintaan Tonton sesuai permintaan

Kuantisasi pasca-pelatihan

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

Metode Optimasi

Ada beberapa opsi kuantisasi pasca-pelatihan untuk dipilih. Berikut adalah tabel ringkasan dari pilihan dan manfaat yang mereka berikan:

Teknik Manfaat Perangkat keras
Kuantisasi rentang dinamis 4x lebih kecil, kecepatan 2x-3x CPU
Kuantisasi bilangan bulat penuh 4x lebih kecil, 3x+ percepatan CPU, TPU Tepi, 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 bilangan bulat 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 mengkuantisasi aktivasi berdasarkan jangkauannya hingga 8-bit dan melakukan komputasi dengan bobot dan aktivasi 8-bit. Pengoptimalan ini memberikan latensi yang mendekati inferensi titik tetap sepenuhnya. Namun, output masih disimpan menggunakan floating point sehingga peningkatan kecepatan ops rentang dinamis kurang dari perhitungan 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 hanya bilangan bulat dengan memastikan semua matematika model terkuantisasi bilangan bulat.

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

Dari versi TensorFlow 2.7, Anda dapat menentukan perwakilan dataset 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 tertentu, Anda dapat menentukan beberapa kumpulan 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 set data representatif dengan memberikan daftar tensor input:

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 versi TensorFlow 2.7, kami merekomendasikan penggunaan pendekatan berbasis tanda tangan daripada pendekatan berbasis daftar tensor input karena pengurutan tensor input dapat dengan mudah dibalik.

Untuk tujuan pengujian, Anda dapat menggunakan dataset 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 sepenuhnya mengkuantisasi bilangan bulat model, tetapi gunakan operator float ketika mereka tidak memiliki implementasi bilangan bulat (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()

Bilangan bulat saja

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

Selain itu, untuk memastikan kompatibilitas dengan perangkat khusus bilangan bulat (seperti mikrokontroler 8-bit) dan akselerator (seperti TPU Coral Edge), Anda dapat menerapkan kuantisasi bilangan bulat 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 bobot ke 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 dari kuantisasi float16 adalah sebagai berikut:

  • Ini mengurangi ukuran model hingga setengahnya (karena semua bobot menjadi setengah dari ukuran aslinya).
  • Ini menyebabkan kerugian minimal dalam akurasi.
  • Ini mendukung beberapa delegasi (misalnya delegasi GPU) yang dapat beroperasi langsung pada data float16, menghasilkan eksekusi yang lebih cepat daripada perhitungan 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 "bilangan bulat saja", tetapi aktivasi dikuantisasi berdasarkan jangkauannya hingga 16-bit, bobot dikuantisasi dalam bilangan bulat 8-bit dan bias dikuantisasi menjadi bilangan bulat 64-bit. Ini disebut sebagai kuantisasi 16x8 lebih lanjut.

Keuntungan utama dari kuantisasi ini adalah dapat meningkatkan akurasi secara signifikan, tetapi 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, tetapi operator yang tidak didukung tetap berada di float. Opsi berikut harus ditambahkan ke target_spec untuk memungkinkan 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 di mana peningkatan akurasi disediakan oleh skema kuantisasi ini meliputi:

  • resolusi super,
  • pemrosesan sinyal audio seperti noise cancelling dan beamforming,
  • de-noise gambar,
  • Rekonstruksi HDR dari satu gambar.

Kerugian dari kuantisasi ini adalah:

  • Saat ini inferensi terasa lebih lambat daripada integer penuh 8-bit karena kurangnya implementasi kernel yang dioptimalkan.
  • Saat ini tidak kompatibel dengan delegasi TFLite akselerasi perangkat keras yang ada.

Tutorial untuk mode kuantisasi ini dapat ditemukan di sini .

Akurasi model

Karena bobot dikuantisasi setelah pelatihan, mungkin ada kehilangan akurasi, khususnya untuk jaringan yang lebih kecil. Model terkuantisasi penuh pra-pelatihan disediakan untuk jaringan tertentu di TensorFlow Hub . Penting untuk memeriksa keakuratan model terkuantisasi untuk memverifikasi bahwa setiap penurunan akurasi berada dalam batas yang dapat diterima. Ada alat untuk mengevaluasi akurasi model TensorFlow Lite .

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

Representasi untuk tensor terkuantisasi

Kuantisasi 8-bit mendekati 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 pelengkap int8 dua 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 mendetail tentang skema kuantisasi kami, silakan lihat spesifikasi kuantisasi kami. Vendor perangkat keras yang ingin terhubung ke antarmuka delegasi TensorFlow Lite didorong untuk mengimplementasikan skema kuantisasi yang dijelaskan di sana.