Aşağıdaki dokümanda, LiteRT'in 8 bit sürümü için spesifikasyonlar nicelikleme şemasıdır. Burada amaç, donanım geliştiricilerinin nicel LiteRT modelleriyle çıkarım için donanım desteği.
Spesifikasyon özeti
Bir spesifikasyon sağlıyoruz ve bunun için yalnızca bazı garantiler verebiliyoruz. bir davranış sergileyeceğinden emin olun. Ayrıca farklı donanımların küçük sapmalara neden olabilecek tercihlere ve kısıtlamalara uygulanmasına yol açan teknikler de vardır. Çoğu durumda bu kabul edilebilir bir uygulamadır (ve size yardımcı olacak ve bu testler, uyguladığımız işlem başına toleransları çeşitli modellerden toplanan verileri içeren, makine öğreniminin (ve derin öğrenme) ) somut garantiler verilmesini imkansız hale getirir.
8 bitlik niceleme, aşağıdakini kullanarak kayan nokta değerlerini tahmin eder: formülünü kullanabilirsiniz.
\[real\_value = (int8\_value - zero\_point) \times scale\]
Eksen başına (Dönş. işlemlerinde kanal başına) veya tensör başına ağırlıklar
int8
[-127, 127]
aralığındaki ikinin tamamlayıcı değerleri (sıfır noktasına eşit)
0 olarak ayarladı. Tensör başına etkinleştirme/girişler, int8
ikinin tamamlayıcısı ile gösterilir.
[-128, 127]
aralığında sıfır noktasına sahip, [-128, 127]
aralığında bir değer.
Belirli işlemler için, aşağıda belgelenen başka istisnalar da vardır.
İmzalı tam sayı ile imzasız tam sayı karşılaştırması
LiteRT nicelemesi, öncelikli olarak araç ve çekirdeklere
8 bit için int8
nicelemesi. Bu, simetrik kullanım kolaylığı
0'a eşit sıfır noktasıyla temsil edilen nicelemedir. Ayrıca birçok
arka uçlarda int8xint8
toplama için ek optimizasyonlar var.
Eksen başına ve tensör başına
Tensör başına miktar verme, her seferinde bir ölçek ve/veya sıfır nokta olacağı anlamına gelir.
düşünebilirsiniz. Eksen başına nicelik, tek bir ölçek ve/veya
quantized_dimension
içindeki dilim başına zero_point
. Ölçülen boyut
Ölçeklendirildiği Tensor şeklinin boyutunu belirtir ve
anlamına gelir. Örneğin, t
tensörü ve dims=[4, 3, 2, 1]
içeren
niceleme parametreleri: scale=[1.0, 2.0, 3.0]
, zero_point=[1, 2, 3]
,
quantization_dimension=1
, t
öğesinin ikinci boyutunda ölçülecektir:
t[:, 0, :, :] will have scale[0]=1.0, zero_point[0]=1
t[:, 1, :, :] will have scale[1]=2.0, zero_point[1]=2
t[:, 2, :, :] will have scale[2]=3.0, zero_point[2]=3
Genellikle quantized_dimension
, ağırlıkların output_channel
kadarıdır
ancak teoride her bir döngüye karşılık gelen
çekirdek uygulamasında nokta çarpımı, daha fazla miktar belirleme ayrıntı düzeyi
performansı etkilemeyecek. Bu yaklaşımda doğrulukta büyük artışlar söz konusudur.
TFLite, artan işlem sayısı için eksen başına destek sunar. Şu tarihte: bu dokümanda Conv2d ve DepthwardConv2d için destek devam etmektedir.
Simetrik ve asimetrik
Etkinleştirmeler asimetriktir:
imzalı int8
aralığı [-128, 127]
. Birçok asimetrik doğası gereği asimetriktir
sıfır noktasının, ek bir maliyete neden olmak için etkili bir şekilde
ikili hassasiyetten oluşur. Etkinleştirmeler sadece sabit sayılarla çarpıldığı için
sabit sıfır noktalı değer oldukça yüksek oranda optimize edilebilir.
Ağırlıklar simetriktir: sıfır noktası 0'a eşit olmaya zorlanır. Ağırlık değerleri: ve aktivasyon değerleriyle çarpılır. Bunun anlamı şudur: ağırlığın sıfır noktasını etkinleştirme değeri. Sıfır noktasının 0 olmasını zorunlu kılarak bu maliyeti önleyebiliriz.
Matematik açıklaması: Bu, Bölüm 2.3'e benzerdir arXiv:1712.05877 (fark hariç) her eksen için ayrı ayrı ayarlanmasına izin veririz. Bu, açıklamanın şöyle olur:
$A$, nicel etkinleştirmelere ait $m \times n$ tutarında bir matristir.
.
$B$, nicel ağırlıklara ilişkin $n \times p$ matristir.
.
$A$için $j$. satırı, $a_j$ ile $k$. sütunu arasında
$B$, $b_k$, her ikisi de $n$ uzunluğunda. Ölçülen tam sayı değerleri ve
sıfır puan değerleri sırasıyla $q_a$, $z_a$ ve $q_b$ ve $z_b$ şeklindedir.
\[a_j \cdot b_k = \sum_{i=0}^{n} a_{j}^{(i)} b_{k}^{(i)} = \sum_{i=0}^{n} (q_{a}^{(i)} - z_a) (q_{b}^{(i)} - z_b) = \sum_{i=0}^{n} q_{a}^{(i)} q_{b}^{(i)} - \sum_{i=0}^{n} q_{a}^{(i)} z_b - \sum_{i=0}^{n} q_{b}^{(i)} z_a + \sum_{i=0}^{n} z_a z_b\]
ile başarısız oluyorElbette \(\sum_{i=0}^{n} q_{a}^{(i)} q_{b}^{(i)}\) terim kaçınılmazdır, çünkü giriş değerinin ve ağırlık değerinin nokta çarpımını uygulayabilirsiniz.
\(\sum_{i=0}^{n} q_{b}^{(i)} z_a\) ve \(\sum_{i=0}^{n} z_a z_b\) terimler çıkarım çağrısı başına aynı kalan sabit değerlerden oluşur ve bu nedenle, olması gerekir.
\(\sum_{i=0}^{n} q_{a}^{(i)} z_b\) teriminin her çıkarımda hesaplanması gerekir çünkü etkinleştirme işlemi her çıkarımı değiştiriyor. Belirlenecek ağırlıkları zorunlu kılarak simetrik olduğundan bu terimin maliyetini kaldırabiliriz.
int8 ölçülebilir operatör özellikleri
Aşağıda, int8 tflite çekirdeklerimiz için miktar belirleme gereksinimlerini açıklanmaktadır:
ADD
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
AVERAGE_POOL_2D
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
CONCATENATION
Input ...:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
CONV_2D
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1 (Weight):
data_type : int8
range : [-127, 127]
granularity: per-axis (dim = 0)
restriction: zero_point = 0
Input 2 (Bias):
data_type : int32
range : [int32_min, int32_max]
granularity: per-axis
restriction: (scale, zero_point) = (input0_scale * input1_scale[...], 0)
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
DEPTHWISE_CONV_2D
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1 (Weight):
data_type : int8
range : [-127, 127]
granularity: per-axis (dim = 3)
restriction: zero_point = 0
Input 2 (Bias):
data_type : int32
range : [int32_min, int32_max]
granularity: per-axis
restriction: (scale, zero_point) = (input0_scale * input1_scale[...], 0)
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
FULLY_CONNECTED
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1 (Weight):
data_type : int8
range : [-127, 127]
granularity: per-axis (dim = 0)
restriction: zero_point = 0
Input 2 (Bias):
data_type : int32
range : [int32_min, int32_max]
granularity: per-tensor
restriction: (scale, zero_point) = (input0_scale * input1_scale[...], 0)
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
L2_NORMALIZATION
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: (scale, zero_point) = (1.0 / 128.0, 0)
LOGISTIC
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: (scale, zero_point) = (1.0 / 256.0, -128)
MAX_POOL_2D
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
MUL
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
RESHAPE
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
RESIZE_BILINEAR
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
SOFTMAX
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: (scale, zero_point) = (1.0 / 256.0, -128)
SPACE_TO_DEPTH
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
TANH
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: (scale, zero_point) = (1.0 / 128.0, 0)
PAD
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
GATHER
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
BATCH_TO_SPACE_ND
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
SPACE_TO_BATCH_ND
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
TRANSPOSE
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
MEAN
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
SUB
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
SUM
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
SQUEEZE
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
LOG_SOFTMAX
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: (scale, zero_point) = (16.0 / 256.0, 127)
MAXIMUM
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
ARG_MAX
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
MINIMUM
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
LESS
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
PADV2
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
GREATER
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
GREATER_EQUAL
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
LESS_EQUAL
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
SLICE
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
restriction: Input and outputs must all have same scale/zero_point
EQUAL
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
NOT_EQUAL
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Input 1:
data_type : int8
range : [-128, 127]
granularity: per-tensor
SHAPE
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
QUANTIZE (Requantization)
Input 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor
Output 0:
data_type : int8
range : [-128, 127]
granularity: per-tensor