Eğitim sonrası niceleme

Eğitim sonrası niceleme, model boyutunu küçültebilen, aynı zamanda CPU ve donanım hızlandırıcı gecikmesini iyileştiren ve model doğruluğunda çok az bozulma sağlayan bir dönüştürme tekniğidir. Zaten eğitilmiş bir kayan TensorFlow modelini TensorFlow Lite Converter kullanarak TensorFlow Lite formatına dönüştürdüğünüzde nicemleyebilirsiniz.

Optimizasyon Yöntemleri

Aralarından seçim yapabileceğiniz çeşitli eğitim sonrası niceleme seçenekleri vardır. Seçeneklerin ve sağladıkları faydaların özet tablosu aşağıda verilmiştir:

Teknik Faydalar Donanım
Dinamik aralık kuantizasyonu 4 kat daha küçük, 2 kat-3 kat hızlanma İşlemci
Tam tamsayı nicemleme 4 kat daha küçük, 3 kattan fazla hızlanma CPU, Edge TPU, Mikrodenetleyiciler
Float16 nicemleme 2 kat daha küçük, GPU hızlandırma CPU, GPU

Aşağıdaki karar ağacı, kullanım durumunuz için hangi eğitim sonrası niceleme yönteminin en iyi olduğunu belirlemenize yardımcı olabilir:

eğitim sonrası optimizasyon seçenekleri

Dinamik aralık kuantizasyonu

Dinamik aralık nicelemesi önerilen bir başlangıç ​​noktasıdır çünkü kalibrasyon için temsili bir veri kümesi sağlamanıza gerek kalmadan daha az bellek kullanımı ve daha hızlı hesaplama sağlar. Bu tür niceleme, dönüşüm süresinde yalnızca kayan noktadan tam sayıya kadar olan ağırlıkları statik olarak niceler ve bu da 8 bitlik hassasiyet sağlar:

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

Çıkarım sırasında gecikmeyi daha da azaltmak için, "dinamik aralık" operatörleri, aktivasyonları 8 bitlik aralıklarına göre dinamik olarak nicemler ve 8 bitlik ağırlıklar ve aktivasyonlarla hesaplamalar gerçekleştirir. Bu optimizasyon, tamamen sabit nokta çıkarımlarına yakın gecikmeler sağlar. Bununla birlikte, çıkışlar hala kayan nokta kullanılarak depolanıyor, dolayısıyla dinamik aralık operasyonlarının artan hızı, tam bir sabit nokta hesaplamasından daha az.

Tam tamsayı nicemleme

Tüm model matematiğinin tam sayıyla nicemlendiğinden emin olarak gecikme süresinde daha fazla iyileştirme, en yüksek bellek kullanımında azalma ve yalnızca tamsayılı donanım aygıtları veya hızlandırıcılarla uyumluluk elde edebilirsiniz.

Tam tamsayı nicemleme için, modeldeki tüm kayan nokta tensörlerinin aralığını (minimum, maksimum) kalibre etmeniz veya tahmin etmeniz gerekir. Ağırlıklar ve önyargılar gibi sabit tensörlerin aksine, model girişi, aktivasyonlar (ara katmanların çıktıları) ve model çıkışı gibi değişken tensörler, birkaç çıkarım döngüsü çalıştırmadığımız sürece kalibre edilemez. Sonuç olarak dönüştürücü, bunları kalibre etmek için temsili bir veri kümesine ihtiyaç duyar. Bu veri kümesi, eğitim veya doğrulama verilerinin küçük bir alt kümesi (yaklaşık ~100-500 örnek) olabilir. Aşağıdaki representative_dataset() işlevine bakın.

TensorFlow 2.7 sürümünden, temsili veri kümesini aşağıdaki örnekte olduğu gibi bir imza aracılığıyla belirtebilirsiniz:

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

Verilen TensorFlow modelinde birden fazla imza varsa imza anahtarlarını belirterek birden fazla veri kümesini belirtebilirsiniz:

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,
      },
    )

Bir giriş tensör listesi sağlayarak temsili veri kümesini oluşturabilirsiniz:

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

TensorFlow 2.7 sürümünden bu yana, giriş tensörü listesi tabanlı yaklaşım yerine imza tabanlı yaklaşımın kullanılmasını öneriyoruz çünkü giriş tensör sıralaması kolayca çevrilebilir.

Test amacıyla aşağıdaki gibi sahte bir veri kümesi kullanabilirsiniz:

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

Kayan nokta geri dönüşlü tamsayı (varsayılan kayan nokta giriş/çıkışını kullanarak)

Bir modeli tamamen tamsayı nicemlemek için, ancak tamsayı uygulaması olmadığında kayan nokta operatörlerini kullanmak için (dönüştürmenin sorunsuz bir şekilde gerçekleşmesini sağlamak için), aşağıdaki adımları kullanın:

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

Yalnızca tamsayı

Yalnızca tamsayılı modeller oluşturmak, Mikrodenetleyiciler ve Coral Edge TPU'lar için TensorFlow Lite için yaygın bir kullanım durumudur.

Ek olarak, yalnızca tam sayı cihazlarıyla (8 bit mikro denetleyiciler gibi) ve hızlandırıcılarla (Coral Edge TPU gibi) uyumluluğu sağlamak için, aşağıdaki adımları kullanarak giriş ve çıkış dahil tüm işlemler için tam tamsayı nicelemeyi zorunlu kılabilirsiniz:

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

Float16 nicemleme

Ağırlıkları, 16 bitlik kayan nokta sayıları için IEEE standardı olan float16'ya nicemleyerek kayan nokta modelinin boyutunu azaltabilirsiniz. Ağırlıkların float16 nicemlemesini etkinleştirmek için aşağıdaki adımları kullanın:

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

Float16 kuantizasyonunun avantajları aşağıdaki gibidir:

  • Model boyutunu yarıya kadar azaltır (çünkü tüm ağırlıklar orijinal boyutlarının yarısı kadar olur).
  • Doğrulukta minimum kayba neden olur.
  • Doğrudan float16 verileri üzerinde çalışabilen bazı delegeleri (örn. GPU temsilcisi) destekler, bu da float32 hesaplamalarına göre daha hızlı yürütme sağlar.

Float16 kuantizasyonunun dezavantajları aşağıdaki gibidir:

  • Gecikmeyi sabit nokta matematiğine niceleme kadar azaltmaz.
  • Varsayılan olarak, bir float16 kuantize edilmiş model, CPU üzerinde çalıştırıldığında ağırlık değerlerini float32'ye "dekuantize edecektir". (GPU temsilcisinin, float16 verileri üzerinde çalışabildiği için bu dekuantizasyonu gerçekleştirmeyeceğini unutmayın.)

Yalnızca tam sayı: 8 bitlik ağırlıklarla 16 bitlik etkinleştirmeler (deneysel)

Bu deneysel bir nicemleme şemasıdır. "Yalnızca tam sayı" şemasına benzer, ancak aktivasyonlar 16 bitlik aralıklarına göre nicelendirilir, ağırlıklar 8 bitlik tamsayı olarak nicelendirilir ve önyargı 64 bitlik tam sayıya nicelendirilir. Buna ayrıca 16x8 kuantizasyon adı verilir.

Bu nicelemenin temel avantajı doğruluğu önemli ölçüde artırabilmesi, ancak model boyutunu yalnızca biraz arttırmasıdır.

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

Modeldeki bazı operatörler için 16x8 niceleme desteklenmiyorsa model yine de nicelenebilir ancak desteklenmeyen operatörler değişken durumda tutulur. Buna izin vermek için target_spec'e aşağıdaki seçenek eklenmelidir.

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

Bu niceleme şeması tarafından sağlanan doğruluk iyileştirmelerinin olduğu kullanım durumlarına örnekler şunları içerir:

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

Bu nicelemenin dezavantajı şudur:

  • Şu anda çıkarım, optimize edilmiş çekirdek uygulamasının olmaması nedeniyle 8 bitlik tam sayıdan belirgin şekilde daha yavaştır.
  • Şu anda mevcut donanım hızlandırmalı TFLite delegeleriyle uyumlu değildir.

Bu niceleme modu için bir öğreticiyi burada bulabilirsiniz.

Model doğruluğu

Ağırlıklar eğitim sonrasında nicelendirildiğinden, özellikle daha küçük ağlarda doğruluk kaybı olabilir. TensorFlow Hub'daki belirli ağlar için önceden eğitilmiş, tamamen nicelenmiş modeller sağlanır. Doğruluktaki herhangi bir bozulmanın kabul edilebilir sınırlar içinde olduğunu doğrulamak için nicelenmiş modelin doğruluğunu kontrol etmek önemlidir. TensorFlow Lite modelinin doğruluğunu değerlendirmek için araçlar vardır.

Alternatif olarak, doğruluk düşüşü çok yüksekse kuantizasyona duyarlı eğitim kullanmayı düşünün. Ancak bunu yapmak, sahte niceleme düğümleri eklemek için model eğitimi sırasında değişiklikler yapılmasını gerektirir; oysa bu sayfadaki eğitim sonrası niceleme teknikleri, önceden eğitilmiş mevcut bir modeli kullanır.

Nicelenmiş tensörlerin gösterimi

8 bitlik nicemleme, aşağıdaki formülü kullanarak kayan nokta değerlerine yaklaşır.

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

Temsil iki ana bölümden oluşur:

  • Sıfır noktası 0'a eşit olan [-127, 127] aralığında int8 ikinin tamamlayıcı değerleri ile temsil edilen eksen başına (diğer adıyla kanal başına) veya tensör başına ağırlıklar.

  • Tensör başına aktivasyonlar/girişler, int8 ikinin [-128, 127] aralığındaki tamamlayıcı değerleri ile temsil edilir ve sıfır noktası [-128, 127] aralığındadır.

Kuantizasyon şemamızın ayrıntılı bir görünümü için lütfen kuantizasyon spesifikasyonumuza bakın. TensorFlow Lite'ın delege arayüzüne bağlanmak isteyen donanım satıcılarının burada açıklanan niceleme şemasını uygulamaları teşvik edilmektedir.