مواصفات تكمية TensorFlow Lite 8 بت

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.

تحدد الوثيقة التالية مواصفات مخطط تكميم 8 بت TensorFlow Lite. يهدف هذا إلى مساعدة مطوري الأجهزة في توفير دعم الأجهزة للاستدلال باستخدام نماذج TensorFlow Lite الكمية.

ملخص المواصفات

نحن نقدم المواصفات ، ولا يمكننا تقديم بعض الضمانات على السلوك إلا إذا تم اتباع المواصفات. نتفهم أيضًا أنه قد يكون للأجهزة المختلفة تفضيلات وقيود قد تسبب انحرافات طفيفة عند تنفيذ المواصفات التي تؤدي إلى عمليات تنفيذ ليست دقيقة البت. في حين أن ذلك قد يكون مقبولاً في معظم الحالات (وسوف نقدم مجموعة من الاختبارات التي تشمل ، على حد علمنا ، التفاوتات لكل عملية التي جمعناها من عدة نماذج) ، وطبيعة التعلم الآلي (والتعلم العميق في أكثرها شيوعًا case) يجعل من المستحيل تقديم أي ضمانات قوية.

تقترب عملية التكميم المكونة من 8 بتات من قيم النقطة العائمة باستخدام الصيغة التالية.

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

في محور (الملقب لكل قناة في التقاط التحويل) أو يتم تمثيل الأوزان لكل موتر من int8 اثنين من القيم مكمل في نطاق [-127, 127] مع صفر نقطة يساوي 0. التنشيط لكل موتر / تتمثل المدخلات من قبل int8 اثنين من القيم مكملا في نطاق [-128, 127] ، مع نقطة الصفر في مجموعة [-128, 127] .

هناك استثناءات أخرى لعمليات معينة موثقة أدناه.

عدد صحيح بعلامة مقابل عدد صحيح بدون إشارة

TensorFlow لايت تكميم سوف الأدوات الأولوية في المقام الأول وحبات ل 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 لديه دعم لكل محور لعدد متزايد من العمليات. في وقت هذا المستند ، يوجد دعم لكل من Conv2d و DepthwiseConv2d.

متماثل مقابل غير متماثل

التنشيط هي غير المتماثلة: يمكن أن يكون في أي مكان نقطة الصفر في غضون موقعة int8 مجموعة [-128, 127] . العديد من عمليات التنشيط غير متماثلة في طبيعتها ونقطة الصفر هي طريقة غير مكلفة نسبيًا للوصول بفعالية إلى جزء ثنائي إضافي من الدقة. نظرًا لأن عمليات التنشيط تتضاعف فقط بأوزان ثابتة ، فيمكن تحسين قيمة نقطة الصفر الثابتة بشكل كبير.

الأوزان متماثلة: يتم إجبارها على أن تكون نقطة الصفر مساوية لـ 0. يتم ضرب قيم الوزن في الإدخال الديناميكي وقيم التنشيط. هذا يعني أن هناك تكلفة وقت تشغيل لا مفر منها لضرب نقطة الصفر للوزن مع قيمة التنشيط. من خلال فرض أن نقطة الصفر هي 0 ، يمكننا تجنب هذه التكلفة.

شرح الرياضيات: هذا يشبه القسم 2.3 في أرخايف: +1712.05877 ، باستثناء فارق أن نسمح القيم على نطاق وأن يكون لكل محور. هذا معمم بسهولة على النحو التالي:

\(A\) هو \(m \times n\) مصفوفة التنشيط الكم.
\(B\) هو \(n \times p\) مصفوفة الأوزان الكم.
النظر في ضرب \(j\)عشر صف من \(A\)، \(a_j\) من قبل \(k\)عشر عمود\(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-tensor
    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