Eğitim sonrası niceleme

Eğitim sonrası niceleme, model boyutunu küçültürken model doğruluğunda çok az düşüşle CPU ve donanım hızlandırıcı gecikmesini iyileştirebilen bir dönüşüm tekniğidir. TensorFlow Lite Converter'ı kullanarak TensorFlow Lite biçimine dönüştürdüğünüzde, önceden eğitilmiş bir kayan TensorFlow modelini sayısal olarak ölçebilirsiniz.

Optimizasyon Yöntemleri

Aralarından seçim yapabileceğiniz çeşitli eğitim sonrası miktar belirleme seçenekleri vardır. Aşağıda, seçeneklerin ve sağladıkları avantajların özet tablosu yer almaktadır:

Teknik Avantajları Nalbur
Dinamik aralık nicelleştirme 4 kat daha küçük, 2-3 kat hızlanma CPU
Tam tamsayı niceleme 4 kat daha küçük, 3 kattan fazla hızlandırma CPU, Edge TPU, Mikrodenetleyiciler
Kayan nokta16 niceliği 2 kat daha küçük, GPU hızlandırması CPU, GPU

Aşağıdaki karar ağacı, kullanım alanınız için en iyi eğitim sonrası miktar belirleme yönteminin hangisi olduğunu belirlemenize yardımcı olabilir:

eğitim sonrası optimizasyon seçenekleri

Nicelendirme Yok

Miktarı belirlemeden TFLite modeline geçmek, önerilen bir başlangıç noktasıdır. Bu işlem, kayan TFLite modeli oluşturur.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
tflite_quant_model = converter.convert()

Orijinal TF model operatörlerinin TFLite ile uyumlu olduğunu doğrulamak için bu işlemi ilk adım olarak yapmanızı öneririz. Ayrıca sonraki eğitim sonrası ölçüm yöntemleri tarafından ortaya çıkan niceleme hatalarını ayıklamak amacıyla da kullanılabilir. Örneğin, nicel bir TFLite modeli beklenmedik sonuçlar üretirken kayan TFLite modeli doğruysa sorunu TFLite operatörlerinin sayısallaştırılmış sürümünün oluşturduğu hatalarla daraltabiliriz.

Dinamik aralık nicelemesi

Dinamik aralık nicelemesi, kalibrasyon için temsili bir veri kümesi sağlamak zorunda kalmadan daha az bellek kullanımı ve daha hızlı hesaplama sağlar. Bu tür niceleme, dönüşüm zamanında yalnızca kayan noktadan tam sayıya ağırlıkları statik olarak ölçer ve 8 bit 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, etkinleştirmeleri 8 bit aralıklarına göre dinamik olarak ölçer, 8 bit ağırlık ve etkinleştirmelerle hesaplamalar gerçekleştirir. Bu optimizasyon, tamamen sabit noktalı çıkarımlara yakın gecikmeler sağlar. Bununla birlikte, çıkışlar kayan nokta kullanılarak depolanmaya devam eder. Bu nedenle, dinamik aralıklı işlemlerin artan hızı, tam sabit noktalı hesaplamadan daha azdır.

Tam tam sayı niceleme

Tüm model hesaplamasının tamsayı olarak ölçüldüğünden emin olarak daha fazla gecikme iyileştirmesi, en yüksek bellek kullanımında azalma ve yalnızca tamsayılı donanım cihazları veya hızlandırıcılarla uyumluluk elde edebilirsiniz.

Tam tamsayı nicelemesi için aralığı kalibre etmeniz veya tahmin etmeniz gerekir: (min., maks.) olarak ayarlanır. Ağırlıklar ve sapmalar gibi sabit tensörlerin aksine, birkaç çıkarım döngüsü çalıştırmadığımız sürece model girişi, etkinleştirmeler (ara katmanların çıkışları) ve model çıkışı gibi değişken tensörler kalibre edilemez. Sonuç olarak, dönüştürücüde bunların kalibre edilmesi için temsili bir veri kümesi gerekir. 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, aşağıdaki örnekteki gibi temsili veri kümesini bir imza üzerinden belirtebilirsiniz:

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

Belirtilen TensorFlow modelinde birden fazla imza varsa imza anahtarlarını belirterek birden çok 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 itibaren, giriş tensörü sıralaması kolayca çevrilebildiğinden giriş tensörü listesi tabanlı yaklaşım yerine imza tabanlı yaklaşımı kullanmanızı öneririz.

Test amacıyla model veri kümesini aşağıdaki gibi kullanabilirsiniz:

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

Kayan yedekli tam sayı (varsayılan kayan giriş/çıkış kullanılarak)

Bir modelin miktarını tam olarak belirlemek ancak tamsayı uygulaması olmayan kayan noktalı operatörleri kullanmak (dönüşümün sorunsuz bir şekilde gerçekleşmesini sağlamak amacıyla) için aşağıdaki adımları uygulayı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 tam sayı

Yalnızca tamsayılara dayalı modeller oluşturmak, Mikrodenetleyiciler için TensorFlow Lite ve Coral Edge TPU'lar için yaygın bir kullanım alanıdır.

Ayrıca, yalnızca tamsayılı cihazlar (8 bit mikrodenetleyiciler gibi) ve hızlandırıcılar (Coral Edge TPU gibi) ile uyumluluğu sağlamak için aşağıdaki adımları uygulayarak giriş ve çıkış dahil tüm işlemlerde tam sayı niceliğini 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()

Kayan nokta16 niceliği

16 bit kayan nokta sayıları için IEEE standardı olan kayan nokta 16 standardına göre ağırlıkları ölçerek kayan nokta modelinin boyutunu azaltabilirsiniz. Ağırlıkların bolluk16 niceliğini etkinleştirmek için aşağıdaki adımları uygulayı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()

bolluk16 nicelemesinin avantajları şunlardır:

  • Model boyutunu yarıya kadar küçültür (çünkü tüm ağırlıklar orijinal boyutlarının yarısına kadar gelir).
  • Doğrulukta minimum kayıp yaşanır.
  • Doğrudan float16 verileri üzerinde çalışabilen ve böylece float32 hesaplamalarına göre daha hızlı yürütme imkanı sunan bazı yetki verilmiş kullanıcıları (ör. GPU yetki verilmiş kullanıcı) destekler.

bolluk16 niceliğinin dezavantajları şunlardır:

  • Gecikmeyi sabit noktalı matematiğin nicelemesi kadar azaltmaz.
  • Varsayılan olarak, float16 nicelenmiş model, CPU'da çalıştırıldığında ağırlık değerlerini float32'ye "çıkarar". (Bu, float16 verilerinde çalışabileceği için GPU yetkilendirmesinin bu ayırma işlemini gerçekleştirmeyeceğini unutmayın.)

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

Bu, deneysel bir miktar belirleme şemasıdır. "Yalnızca tam sayı" şemasına benzer ancak etkinleştirme işlemleri 16 bit aralıklarına göre, ağırlıklar 8 bitlik tam sayılarla ve sapma ise 64 bitlik tam sayı olarak ölçülür. Buna, 16x8 ölçüm olarak da bilinir.

Bu niceleştirmenin temel avantajı, doğruluğu önemli ölçüde artırabilmesi ancak model boyutunu yalnızca küçük bir oranda artırabilmesidir.

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 miktarlandırma desteklenmiyorsa model yine de ölçülebilir ancak desteklenmeyen operatörler kayan noktalı değerde 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 ölçme şemasının doğruluğunda iyileşme sağladığı kullanım alanlarına örnekler:

  • super-resolution,
  • gürültü giderme ve ışınlama gibi ses sinyali işleme,
  • resimdeki parazit giderme,
  • Tek bir görüntüden HDR yeniden oluşturma.

Bu hesaplamanın dezavantajı ise şudur:

  • Optimize edilmiş çekirdek uygulamasının olmaması nedeniyle çıkarım şu anda 8 bitlik tam tamsayıya göre belirgin bir şekilde daha yavaştır.
  • Şu anda mevcut donanım hızlandırmalı TFLite yetkilileriyle uyumlu değildir.

Bu miktar belirleme moduyla ilgili bir eğiticiye buradan ulaşabilirsiniz.

Model doğruluğu

Ağırlıklar eğitim sonrası ölçüldüğünden özellikle küçük ağlarda doğruluk kaybı olabilir. Önceden eğitilmiş tamamen miktarlandırılmış modeller Kaggle Modelleri üzerindeki belirli ağlar için sağlanır. Doğruluktaki herhangi bir azalmanın kabul edilebilir sınırlar dahilinde olduğunu doğrulamak için nicelleştirilmiş modelin doğruluğunu kontrol etmek önemlidir. TensorFlow Lite modelinin doğruluğunu değerlendirecek araçlar vardır.

Alternatif olarak, doğruluk düşüşü çok yüksekse miktara duyarlı eğitim kullanmayı düşünebilirsiniz. Ancak bunu yapmak, model eğitimi sırasında sahte miktarlandırma düğümleri eklemek için değişiklikler gerektirir. Bu sayfadaki eğitim sonrası miktar belirleme teknikleri ise önceden eğitilmiş mevcut bir modeli kullanır.

Nicel tensörlerin temsili

8 bitlik niceleme, aşağıdaki formülü kullanarak kayan nokta değerlerini tahmin eder.

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

Temsilin iki ana bölümü vardır:

  • Eksen başına (kanal başına olarak da bilinir) veya sıfır noktası 0'a eşit olan [-127, 127] aralığındaki int8 iki'nin tamamlayıcı değerleriyle temsil edilen tensör başına ağırlıklar.

  • [-128, 127] aralığındaki [-128, 127] aralığında sıfır noktası olmak üzere, int8 ikinci'nin tamamlayıcı değerleriyle temsil edilen tensör başına etkinleştirmeler/girişler.

Nicelendirme şemamızın ayrıntılı bir görünümü için lütfen nicelleştirme spesifikasyonumuzu inceleyin. TensorFlow Lite'ın yetki verilen arayüzüne bağlanmak isteyen donanım tedarikçilerinin, burada açıklanan nicelikleştirme şemasını uygulamaları önerilir.