เอกสารต่อไปนี้จะสรุปข้อกำหนดสำหรับรูปแบบการจัดลำดับแบบ 8 บิตของ TensorFlow Lite มีจุดมุ่งหมายเพื่อช่วยนักพัฒนาฮาร์ดแวร์ในการให้การสนับสนุนฮาร์ดแวร์สำหรับการอนุมานด้วยโมเดล TensorFlow Lite เชิงปริมาณ
สรุปข้อมูลจำเพาะ
เรากำลังจัดเตรียมข้อกำหนด และเราสามารถให้การรับประกันเกี่ยวกับพฤติกรรมบางอย่างได้ก็ต่อเมื่อปฏิบัติตามข้อกำหนดเท่านั้น เรายังเข้าใจดีว่าฮาร์ดแวร์ที่แตกต่างกันอาจมีการกำหนดลักษณะและข้อจำกัดที่อาจทำให้เกิดการเบี่ยงเบนเล็กน้อยเมื่อใช้งานข้อมูลจำเพาะที่ส่งผลให้มีการใช้งานที่ไม่แน่นอนบิต ในขณะที่นั่นอาจเป็นที่ยอมรับได้ในกรณีส่วนใหญ่ (และเราจะจัดเตรียมชุดการทดสอบที่ความรู้ที่ดีที่สุดของเรารวมถึงความคลาดเคลื่อนต่อการทำงานที่เรารวบรวมจากแบบจำลองต่างๆ) ธรรมชาติของการเรียนรู้ด้วยเครื่อง (และการเรียนรู้เชิงลึกโดยทั่วไป กรณี) ทำให้ไม่สามารถให้การค้ำประกันใด ๆ ได้
การหาปริมาณ 8 บิตจะประมาณค่าจุดลอยตัวโดยใช้สูตรต่อไปนี้
\[real\_value = (int8\_value - zero\_point) \times scale\]
ต่อแกน (aka ต่อช่องทางในการปฏิบัติการ Conv) หรือต่อเมตริกซ์น้ำหนักโดยมีตัวแทน int8
สองของค่าสมบูรณ์ในช่วง [-127, 127]
กับจุดศูนย์เท่ากับ 0. การเปิดใช้งานต่อเมตริกซ์ / ปัจจัยการผลิตโดยมีตัวแทน int8
สองของค่าสมบูรณ์ในช่วง [-128, 127]
มีจุดศูนย์ในช่วง [-128, 127]
มีข้อยกเว้นอื่นๆ สำหรับการดำเนินการเฉพาะที่ระบุไว้ด้านล่าง
จำนวนเต็มลงนาม vs จำนวนเต็มไม่ได้ลงนาม
TensorFlow Lite quantization จะจัดลำดับความสำคัญการขับรถเป็นหลักและเมล็ดสำหรับ int8
quantization สำหรับ 8 บิต นี่คือเพื่อความสะดวกของควอนสมมาตรถูกแทนด้วยจุดศูนย์เท่ากับ 0 แบ็กเอนด์จำนวนมากนอกจากนี้ยังมีการเพิ่มประสิทธิภาพเพิ่มเติมสำหรับ int8xint8
สะสม
ต่อแกนเทียบกับต่อเทนเซอร์
การหาปริมาณต่อเทนเซอร์หมายความว่าจะมีหนึ่งมาตราส่วนและ/หรือจุดศูนย์ต่อเมตริกซ์ทั้งหมด ต่อแกน quantization หมายถึงว่าจะมีหนึ่งขนาดและ / หรือ zero_point
ต่อชิ้นใน quantized_dimension
มิติข้อมูลเชิงปริมาณระบุขนาดของรูปร่างของเทนเซอร์ที่มาตราส่วนและจุดศูนย์สอดคล้องกัน ยกตัวอย่างเช่นเมตริกซ์ t
กับ dims=[4, 3, 2, 1]
กับ params quantization: scale=[1.0, 2.0, 3.0]
, zero_point=[1, 2, 3]
, quantization_dimension=1
จะได้รับการ quantized ข้าม มิติที่สองของ 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
ของน้ำหนักของ convolutions แต่ในทางทฤษฎีมันสามารถเป็นมิติที่สอดคล้องกับแต่ละจุดผลิตภัณฑ์ในการดำเนินเคอร์เนลที่ช่วยให้เมล็ด quantization มากขึ้นโดยไม่ผลกระทบต่อประสิทธิภาพการทำงาน มีการปรับปรุงความแม่นยำอย่างมาก
TFLite มีการรองรับแบบทีละแกนสำหรับการดำเนินการที่มีจำนวนเพิ่มขึ้นเรื่อยๆ ในช่วงเวลาของเอกสารนี้ มีการสนับสนุนสำหรับ Conv2d และ DepthwiseConv2d
สมมาตรกับอสมมาตร
การเปิดใช้งานมีความไม่สมมาตร: พวกเขาสามารถมีได้ทุกจุดศูนย์ของพวกเขาภายในลงนาม int8
ช่วง [-128, 127]
การเปิดใช้งานจำนวนมากมีลักษณะไม่สมมาตรและจุดศูนย์เป็นวิธีที่ไม่แพงนักในการรับบิตไบนารีที่มีความแม่นยำเป็นพิเศษ เนื่องจากการเปิดใช้งานจะถูกคูณด้วยน้ำหนักคงที่เท่านั้น ค่าจุดศูนย์คงที่สามารถปรับให้เหมาะสมได้ค่อนข้างมาก
น้ำหนักมีความสมมาตร: บังคับให้มีจุดศูนย์เท่ากับ 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
ด้านล่างนี้เราจะอธิบายข้อกำหนดด้านปริมาณสำหรับเมล็ด 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