يوضح المستند التالي مواصفات الإصدار 8 بت من LiteRT نظام العد التنازلي. والهدف من ذلك هو مساعدة مطوري الأجهزة في تقديم أجهزة دعم الاستنتاج باستخدام نماذج LiteRT الكمية.
ملخّص المواصفات
نحن نقدم مواصفات، ولا يمكننا تقديم سوى بعض الضمانات على السلوك إذا تم اتباع المواصفات. ندرك أيضًا أنّ الأجهزة المختلفة قد تفضيلات وقيود قد تؤدي إلى انحرافات طفيفة عند تنفيذ المواصفات التي ينتج عنها عمليات تنفيذ غير دقيقة بت. وحيث إن ذلك قد يكون مقبولاً في معظم الحالات (وسنقدم مجموعة من على حد علمنا، تتضمن معايير التسامح مع كل عملية تم جمعها من عدة نماذج)، وطبيعة التعلم الآلي (والتعلم المتعمق) في الحالة الأكثر شيوعًا) يجعل من المستحيل تقديم أي ضمانات راسخة.
يعمل أسلوب التحديد الكمي بتنسيق 8 بت على تقريب قيم النقطة العائمة باستخدام ما يلي: المعادلة.
\[real\_value = (int8\_value - zero\_point) \times scale\]
يتم تمثيل الترجيحات حسب كل محور (تُعرف أيضًا باسم "لكل قناة في عمليات الإحالات الناجحة") أو ترجيحات لكل متوتر
قيم int8
اثنان كتامة في النطاق [-127, 127]
بصفر نقطة
إلى 0. يتم تمثيل عمليات التفعيل/الإدخالات لكل متسابق من خلال المكمّل الثاني لـ int8
.
في النطاق [-128, 127]
، مع نقطة صفرية في النطاق [-128, 127]
.
هناك استثناءات أخرى لعمليات معيّنة موثّقة أدناه.
عدد صحيح موقَّع مقابل عدد صحيح غير موقَّع
سيُعطي قياس LiteRT الأولوية في المقام الأول للأدوات والنواة
تحديد الكمي لـ int8
لنظام 8 بت. هذا لسهولة استخدام البيانات المتماثلة
كمية يتم تمثيلها بنقطة صفرية تساوي 0. بالإضافة إلى ذلك، العديد من
الخلفيات على تحسينات إضافية لتجميع int8xint8
.
حسب المحور مقابل كل متوتر
يعني التحديد الكمي لكل متسابق أنه سيكون هناك مقياس واحد و/أو نقطة صفرية لكل
متوتر كامل. يعني التحديد الكمّي لكل محور أنه سيكون هناك مقياس واحد و/أو
zero_point
لكل شريحة في quantized_dimension
. السمة الكمية
لتحديد بُعد شكل Tensor الذي تستخدمه المقاييس والنقاط الصفرية
يتجاوب مع. على سبيل المثال، تنسور t
، مع dims=[4, 3, 2, 1]
مع
مَعلمات تحديد الكمية: scale=[1.0, 2.0, 3.0]
، zero_point=[1, 2, 3]
،
سيتم قياس quantization_dimension=1
على مستوى السمة الثانية من t
:
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
غالبًا، يكون quantized_dimension
هو output_channel
من أوزان
الالتفاف، ولكن نظريًا يمكن أن يكون البعد الذي يتجاوب مع كل
البيانات النقطية في تطبيق النواة، ما يسمح بمزيد من دقة الكمي
بدون آثار على الأداء. ويؤدي ذلك إلى تحسينات كبيرة على الدقة.
يتوفر في TFLite دعم حسب المحور لعدد متزايد من العمليات. في وقت هذا المستند، يتوفر دعم لـ Convert2d وDepthwiseConvert2d.
المتماثل مقابل غير المتماثل
عمليات التفعيل غير متماثلة: يمكن أن تكون لها نقطة صفرية في أي مكان داخل
تم التوقيع على نطاق int8
[-128, 127]
. العديد من التنشيطات غير متماثلة بطبيعتها
النقطة الصفرية طريقة غير مكلفة نسبيًا للوصول بشكل فعال إلى
وحدة بت الدقة الثنائي. نظرًا لأن عمليات التفعيل يتم ضربها فقط في الثابت
الترجيحات، يمكن تحسين القيمة الثابتة للنقطة الصفرية إلى حد كبير.
الأوزان متماثلة: يجب أن تكون قيمة نقطة صفرية تساوي 0. قيم الوزن هي مضروبة في قيم الإدخال الديناميكي والتفعيل. وهذا يعني أن هناك ضرب النقطة الصفرية للوزن في قيمة التفعيل. ويمكننا تجنُّب هذه التكلفة من خلال فرض تلك النقطة على صفر.
شرح الرياضيات: يشبه ذلك القسم 2.3 في arXiv:1712.05877، باستثناء الفرق أننا نسمح بأن تكون قيم المقياس لكل محور. يتم تعميم ذلك بسهولة، حيث التالي:
$A$ عبارة عن مصفوفة $m\times n$ لعمليات التفعيل الكَمية.
$B$ عبارة عن مصفوفة $n\times p$ للأوزان الكَمية.
ضع في اعتبارك ضرب الصف $j$th من $A$، $a_j$ في العمود $k$th
$B$، $b_k$، كلاهما $n$ قيم الأعداد الصحيحة الكميّة
قيم النقاط الصفرية هي $q_a$ و$z_a$ و $q_b$ و$z_b$ على التوالي.
\[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\]
منلا يمكن تجنب \(\sum_{i=0}^{n} q_{a}^{(i)} q_{b}^{(i)}\) العبارة نظرًا لتنفيذ ناتج الضرب النقطي لقيمة الإدخال وقيمة الوزن.
\(\sum_{i=0}^{n} q_{b}^{(i)} z_a\) و \(\sum_{i=0}^{n} z_a z_b\) العبارتان مكونة من ثوابت تظل كما هي لكل استدعاء، وبالتالي يمكن المحسوبة مسبقًا.
يجب احتساب العبارة \(\sum_{i=0}^{n} q_{a}^{(i)} z_b\) في كل استنتاج. لأن التفعيل يتغير مع كل استنتاج. من خلال فرض الترجيح يمكننا إزالة التكلفة لهذا الحد.
مواصفات عامل التشغيل الكمي في int8
نوضّح في ما يلي متطلبات الكمّي لنواة int8 tflite:
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