مواصفات قياس الكمي في LiteRT 8 بت

يوضح المستند التالي مواصفات الإصدار 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

المراجع

arXiv:1712.05877