ข้อมูลจำเพาะของการแปลงรหัส 8 บิต LiteRT

เอกสารต่อไปนี้สรุปข้อกําหนดสําหรับโหมด 8 บิตของ LiteRT รูปแบบการวัดปริมาณอินเทอร์เน็ต กระบวนการนี้มีไว้เพื่อช่วยนักพัฒนาฮาร์ดแวร์ในการ การรองรับฮาร์ดแวร์สำหรับการอนุมานด้วยโมเดล LiteRT ที่เล็กลง

สรุปข้อกำหนด

เราให้ข้อกำหนดเฉพาะ และรับประกันได้เพียงบางอย่างเกี่ยวกับ หากเป็นไปตามข้อกำหนด เรายังเข้าใจในฮาร์ดแวร์อื่นๆ มีการตั้งค่าและข้อจำกัดที่อาจทำให้เกิดความแตกต่างเล็กน้อยเมื่อ การนำข้อกำหนดไปใช้ซึ่งส่งผลให้เกิดการใช้งานที่ไม่เป็นไปตามข้อกำหนด ขณะที่กรณีส่วนใหญ่ยอมรับได้ (และเราจะจัดหาชุด การทดสอบที่เราทราบอย่างดีที่สุดรวมถึงความคลาดเคลื่อนต่อการดำเนินการที่เรา รวบรวมจากหลากหลายโมเดล) ลักษณะของแมชชีนเลิร์นนิง (และการเรียนรู้เชิงลึก ในกรณีที่พบบ่อยที่สุด) ทำให้ไม่สามารถรับประกันยาก

การแปลงค่าเป็น 8 บิตจะประมาณค่าจำนวนทศนิยมโดยใช้ข้อมูลต่อไปนี้ สูตร

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

ต่อแกน (หรือที่เรียกว่าต่อแชแนลใน Conv ops) หรือน้ำหนักต่อ tensor จะแสดงด้วย ค่าเติมเต็ม 2 ของ int8 ในช่วง [-127, 127] ที่มีจุดเท่ากับ 0 เป็น 0 การเปิดใช้งาน/อินพุตต่อ tensor แสดงด้วยการเติมเต็ม 2 แบบของ int8 ค่าในช่วง [-128, 127] ซึ่งมีจุดเป็น 0 ในช่วง [-128, 127]

มีข้อยกเว้นสำหรับการดำเนินการบางอย่างตามที่ระบุไว้ด้านล่าง

จำนวนเต็มที่มีลายเซ็นเทียบกับจำนวนเต็มที่ไม่ได้ลงนาม

การวัดปริมาณ LiteRT จะให้ความสำคัญกับเครื่องมือและเคอร์เนลสำหรับ การแปลงค่า int8 สำหรับ 8 บิต เพื่อความสะดวกของแบบสมมาตร การวัดปริมาณจะแสดงด้วยจุด 0 ที่มีค่าเท่ากับ 0 นอกจากนี้ ยังมี แบ็กเอนด์มีการเพิ่มประสิทธิภาพเพิ่มเติมสำหรับการสะสม int8xint8

ต่อแกนเทียบกับต่อ tensor

การวัดปริมาณต่อ Tensor หมายความว่าจะมี 1 สเกลและ/หรือ 0 จุดต่อ ทั้งหมด การวัดปริมาณต่อแกนหมายความว่าจะมี 1 สเกลและ/หรือ zero_point ต่อส่วนแบ่งใน quantized_dimension มิติข้อมูลที่เล็กลง ระบุมิติของรูปร่างของ Tensor ที่มาตราส่วนและจุดเป็น 0 ที่สอดคล้องกับ ตัวอย่างเช่น tensor t ที่มี dims=[4, 3, 2, 1] พร้อมด้วย พารามิเตอร์การวัดขนาด: scale=[1.0, 2.0, 3.0], zero_point=[1, 2, 3], quantization_dimension=1 จะถูกแปลงในมิติข้อมูลที่ 2 ของ 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

สมมาตรกับอสมมาตร

การเปิดใช้งานมีความไม่สมมาตรกัน โดยอาจมีจุดเป็น 0 ที่ใดก็ได้ภายในแท็ก ลงนาม int8 ช่วง [-128, 127] การเปิดใช้งานหลายครั้งนั้นมีลักษณะไม่สมมาตรและ การได้คะแนนเต็ม 0% เป็นวิธีที่ค่อนข้างไม่แพง ไบนารีของความแม่นยำ เนื่องจากการเปิดใช้งานจะคูณกับค่าคงที่เท่านั้น ทำให้ค่าคงที่ที่จุดศูนย์สามารถปรับให้เหมาะสมได้อย่างมาก

น้ำหนักจะเป็นแบบสมมาตร: บังคับให้มีจุดเป็น 0 เท่ากับ 0 ค่าน้ำหนักคือ คูณด้วยค่าอินพุตและการเปิดใช้งานแบบไดนามิก ซึ่งหมายความว่ามี ต้นทุนรันไทม์ที่หลีกเลี่ยงไม่ได้ในการคูณจุด 0 ของน้ำหนักด้วยฟังก์ชัน มูลค่าการเปิดใช้งาน การกำหนดให้จุดศูนย์เท่ากับ 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 ที่แปลงค่าแล้ว

เราอธิบายข้อกำหนดเกี่ยวกับปริมาณสำหรับเคอร์เนล tflite ของ int8 ดังต่อไปนี้

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