การหาปริมาณหลังการฝึก

การหาปริมาณหลังการฝึกเป็นเทคนิคการแปลงที่สามารถลดขนาดโมเดลได้ในขณะเดียวกันก็ปรับปรุงเวลาแฝงของตัวเร่งความเร็วของ CPU และฮาร์ดแวร์ด้วยความแม่นยำของโมเดลลดลงเล็กน้อย คุณสามารถวัดปริมาณโมเดลลอยตัว TensorFlow ที่ได้รับการฝึกอบรมมาแล้ว เมื่อคุณแปลงเป็นรูปแบบ TensorFlow Lite โดยใช้ TensorFlow Lite Converter

วิธีการเพิ่มประสิทธิภาพ

มีตัวเลือกการวัดปริมาณหลังการฝึกอบรมหลายแบบให้เลือก ตารางสรุปตัวเลือกและประโยชน์ที่ได้รับมีดังนี้

เทคนิค ประโยชน์ ฮาร์ดแวร์
การหาปริมาณช่วงไดนามิก เล็กลง 4 เท่า เพิ่มความเร็ว 2x-3x ซีพียู
การหาจำนวนเต็มจำนวนเต็ม เล็กลง 4 เท่า เพิ่มความเร็ว 3 เท่า CPU, Edge TPU, ไมโครคอนโทรลเลอร์
การหาปริมาณ Float16 เล็กกว่า 2 เท่า เร่งความเร็ว GPU ซีพียู, GPU

โครงสร้างการตัดสินใจต่อไปนี้สามารถช่วยกำหนดวิธีการหาปริมาณภายหลังการฝึกอบรมที่เหมาะสมที่สุดสำหรับกรณีการใช้งานของคุณ:

ตัวเลือกการเพิ่มประสิทธิภาพหลังการฝึก

การหาปริมาณช่วงไดนามิก

รูปแบบที่ง่ายที่สุดของการควอนไทซ์หลังการฝึกแบบสถิตจะควอนไทซ์เฉพาะตุ้มน้ำหนักจากจุดลอยตัวเป็นจำนวนเต็มซึ่งมีความแม่นยำ 8 บิต:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

ในการอนุมาน น้ำหนักจะถูกแปลงจากความแม่นยำ 8 บิตเป็นทศนิยม และคำนวณโดยใช้เคอร์เนลจุดลอยตัว การแปลงนี้ทำเพียงครั้งเดียวและแคชเพื่อลดเวลาในการตอบสนอง

เพื่อปรับปรุงเวลาแฝงให้ดียิ่งขึ้น ตัวดำเนินการ "ช่วงไดนามิก" จะกำหนดปริมาณการเปิดใช้งานแบบไดนามิกตามช่วงเป็น 8 บิต และทำการคำนวณด้วยน้ำหนัก 8 บิตและการเปิดใช้งาน การปรับให้เหมาะสมนี้ให้เวลาแฝงใกล้เคียงกับการอนุมานจุดคงที่อย่างสมบูรณ์ อย่างไรก็ตาม เอาต์พุตจะยังคงถูกจัดเก็บโดยใช้จุดลอยตัว ดังนั้นการเพิ่มความเร็วด้วย ops ช่วงไดนามิกจะน้อยกว่าการคำนวณแบบจุดตายตัวแบบเต็ม

การหาจำนวนเต็มจำนวนเต็ม

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

สำหรับการหาจำนวนเต็มจำนวนเต็ม คุณต้องสอบเทียบหรือประมาณค่าช่วง กล่าวคือ (ต่ำสุด สูงสุด) ของเทนเซอร์จุดทศนิยมทั้งหมดในแบบจำลอง ไม่เหมือนกับเทนเซอร์คงที่ เช่น น้ำหนักและอคติ เทนเซอร์แบบแปรผัน เช่น อินพุตโมเดล การเปิดใช้งาน (เอาต์พุตของเลเยอร์ระดับกลาง) และเอาต์พุตของโมเดลไม่สามารถสอบเทียบได้ เว้นแต่เราจะรันรอบการอนุมานสองสามรอบ ด้วยเหตุนี้ คอนเวอร์เตอร์จึงต้องการชุดข้อมูลที่เป็นตัวแทนในการปรับเทียบ ชุดข้อมูลนี้สามารถเป็นส่วนย่อยขนาดเล็ก (ประมาณ 100-500 ตัวอย่าง) ของข้อมูลการฝึกอบรมหรือการตรวจสอบ อ้างอิงถึงฟังก์ชัน representative_dataset() ด้านล่าง

จากเวอร์ชัน TensorFlow 2.7 คุณสามารถระบุชุดข้อมูลที่เป็นตัวแทนผ่าน ลายเซ็น ได้ดังตัวอย่างต่อไปนี้:

def representative_dataset():
  for data in dataset:
    yield {
      "image": data.image,
      "bias": data.bias,
    }

หากมีลายเซ็นมากกว่าหนึ่งรายการในโมเดล TensorFlow ที่กำหนด คุณสามารถระบุชุดข้อมูลหลายชุดโดยระบุคีย์ลายเซ็น:

def representative_dataset():
  # Feed data set for the "encode" signature.
  for data in encode_signature_dataset:
    yield (
      "encode", {
        "image": data.image,
        "bias": data.bias,
      }
    )

  # Feed data set for the "decode" signature.
  for data in decode_signature_dataset:
    yield (
      "decode", {
        "image": data.image,
        "hint": data.hint,
      },
    )

คุณสามารถสร้างชุดข้อมูลตัวแทนได้โดยการจัดเตรียมรายการเทนเซอร์อินพุต:

def representative_dataset():
  for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100):
    yield [tf.dtypes.cast(data, tf.float32)]

ตั้งแต่เวอร์ชัน TensorFlow 2.7 เราขอแนะนำให้ใช้วิธีการแบบอิงลายเซ็นแทนวิธีการอิงตามรายการเทนเซอร์อินพุต เนื่องจากการจัดลำดับเทนเซอร์อินพุตสามารถพลิกได้อย่างง่ายดาย

สำหรับการทดสอบ คุณสามารถใช้ชุดข้อมูลจำลองได้ดังนี้:

def representative_dataset():
    for _ in range(100):
      data = np.random.rand(1, 244, 244, 3)
      yield [data.astype(np.float32)]
 

จำนวนเต็มพร้อม float fallback (โดยใช้อินพุต/เอาต์พุต float เริ่มต้น)

ในการหาจำนวนเต็มของโมเดล แต่ใช้ตัวดำเนินการ float เมื่อพวกมันไม่มีการนำจำนวนเต็มไปใช้งาน (เพื่อให้แน่ใจว่าการแปลงจะเกิดขึ้นอย่างราบรื่น) ให้ทำตามขั้นตอนต่อไปนี้:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
tflite_quant_model = converter.convert()

จำนวนเต็มเท่านั้น

การสร้างโมเดลจำนวนเต็มเท่านั้นเป็นกรณีการใช้งานทั่วไปสำหรับ TensorFlow Lite สำหรับไมโครคอนโทรลเลอร์ และ Coral Edge TPU

นอกจากนี้ เพื่อให้แน่ใจว่าเข้ากันได้กับอุปกรณ์ที่เป็นจำนวนเต็มเท่านั้น (เช่น ไมโครคอนโทรลเลอร์ 8 บิต) และตัวเร่งความเร็ว (เช่น Coral Edge TPU) คุณสามารถบังคับใช้การควอนไทซ์จำนวนเต็มแบบเต็มสำหรับ ops ทั้งหมดรวมถึงอินพุตและเอาต์พุต โดยใช้ขั้นตอนต่อไปนี้:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8
tflite_quant_model = converter.convert()

การหาปริมาณ Float16

คุณสามารถลดขนาดของแบบจำลองจุดลอยตัวได้โดยการหาปริมาณน้ำหนักเป็น float16 ซึ่งเป็นมาตรฐาน IEEE สำหรับตัวเลขทศนิยม 16 บิต ในการเปิดใช้งานการหาปริมาณน้ำหนัก float16 ให้ใช้ขั้นตอนต่อไปนี้:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

ข้อดีของการควอนไทซ์ float16 มีดังนี้:

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

ข้อเสียของการหาปริมาณ float16 มีดังนี้:

  • มันไม่ได้ลดเวลาแฝงมากเท่ากับการหาปริมาณของคณิตศาสตร์จุดคงที่
  • โดยค่าเริ่มต้น โมเดลเชิงปริมาณ float16 จะ "ดีควอไทซ์" ค่าน้ำหนักเป็น float32 เมื่อรันบน CPU (โปรดทราบว่าตัวแทน GPU จะไม่ทำการดีควอนท์ไลซ์นี้ เนื่องจากสามารถทำงานกับข้อมูล float16 ได้)

จำนวนเต็มเท่านั้น: การเปิดใช้งานแบบ 16 บิตด้วยน้ำหนัก 8 บิต (ทดลอง)

นี่คือแผนการหาปริมาณการทดลอง คล้ายกับรูปแบบ "จำนวนเต็มเท่านั้น" แต่การเปิดใช้งานจะถูกกำหนดปริมาณตามช่วงของพวกมันถึง 16 บิต น้ำหนักจะถูกหาปริมาณเป็นจำนวนเต็ม 8 บิต และปริมาณอคติเป็นจำนวนเต็ม 64 บิต นี่เรียกว่าการหาปริมาณ 16x8 เพิ่มเติม

ข้อได้เปรียบหลักของการหาปริมาณนี้คือสามารถปรับปรุงความแม่นยำได้อย่างมาก แต่เพิ่มขนาดโมเดลเพียงเล็กน้อยเท่านั้น

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

หากโอเปอเรเตอร์บางตัวในโมเดลไม่รองรับการควอนไทซ์ขนาด 16x8 โมเดลจะยังคงสามารถควอนไทซ์ได้ แต่ตัวดำเนินการที่ไม่รองรับจะถูกเก็บไว้ในทศนิยม ควรเพิ่มตัวเลือกต่อไปนี้ใน target_spec เพื่ออนุญาต

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

ตัวอย่างของกรณีการใช้งานที่มีการปรับปรุงความแม่นยำโดยรูปแบบการควอนตัมนี้: * ความละเอียดสูงสุด * การประมวลผลสัญญาณเสียง เช่น การตัดเสียงรบกวนและการสร้างลำแสง * การลดสัญญาณรบกวนของภาพ * การสร้าง HDR ใหม่จากภาพเดียว

ข้อเสียของการหาปริมาณนี้คือ:

  • การอนุมานในปัจจุบันช้ากว่าจำนวนเต็ม 8 บิตอย่างเห็นได้ชัดเนื่องจากขาดการนำเคอร์เนลที่ปรับให้เหมาะสมมาใช้
  • ขณะนี้ยังไม่สามารถทำงานร่วมกับผู้ได้รับมอบหมาย TFLite ที่เร่งฮาร์ดแวร์ที่มีอยู่ได้

คุณสามารถดูบทช่วยสอนสำหรับโหมดการหาปริมาณได้ ที่นี่

ความแม่นยำของแบบจำลอง

เนื่องจากตุ้มน้ำหนักเป็นการวัดปริมาณหลังการฝึก จึงอาจมีการสูญเสียความแม่นยำ โดยเฉพาะอย่างยิ่งสำหรับเครือข่ายขนาดเล็ก โมเดลเชิงปริมาณที่ได้รับการฝึกอบรมล่วงหน้าทั้งหมดมีให้สำหรับเครือข่ายเฉพาะบน TensorFlow Hub สิ่งสำคัญคือต้องตรวจสอบความถูกต้องของแบบจำลองเชิงปริมาณเพื่อตรวจสอบว่าความแม่นยำที่ลดลงนั้นอยู่ในขอบเขตที่ยอมรับได้ มีเครื่องมือในการประเมินความถูกต้องของ แบบจำลอง TensorFlow Lite

อีกทางหนึ่ง หากความแม่นยำลดลงสูงเกินไป ให้พิจารณาใช้ การฝึกอบรมการรู้เท่าทันการควอนตั ม อย่างไรก็ตาม การทำเช่นนี้จำเป็นต้องมีการปรับเปลี่ยนระหว่างการฝึกโมเดลเพื่อเพิ่มโหนด quantization ปลอม ในขณะที่เทคนิคการหา quantization หลังการฝึกในหน้านี้ใช้โมเดลที่ฝึกอบรมล่วงหน้าที่มีอยู่

การแทนค่าเทนเซอร์เชิงปริมาณ

การหาปริมาณ 8 บิตจะประมาณค่าจุดลอยตัวโดยใช้สูตรต่อไปนี้

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

การเป็นตัวแทนมีสองส่วนหลัก:

  • น้ำหนักต่อแกน (aka per-channel) หรือน้ำหนักต่อเทนเซอร์ที่แสดงโดยค่าเสริมของ int8 two ในช่วง [-127, 127] โดยมีจุดศูนย์เท่ากับ 0

  • การเปิดใช้งาน/อินพุตต่อเทนเซอร์แสดงโดยค่าเสริมของ int8 two ในช่วง [-128, 127] โดยมีจุดศูนย์อยู่ในช่วง [-128, 127]

สำหรับมุมมองโดยละเอียดของแผนการหาปริมาณของเรา โปรดดู ข้อกำหนด การหาปริมาณของเรา ผู้จำหน่ายฮาร์ดแวร์ที่ต้องการเชื่อมต่อกับอินเทอร์เฟซผู้รับมอบสิทธิ์ของ TensorFlow Lite ขอแนะนำให้ใช้รูปแบบการจัดปริมาณที่อธิบายไว้ที่นั่น