การวัดปริมาณหลังการฝึกอบรม

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

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

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

เทคนิค ประโยชน์ ฮาร์ดแวร์
ช่วงไดนามิก การวัดขนาด เล็กลง 4 เท่า เร่งความเร็วได้ 2-3 เท่า CPU
จำนวนเต็มแบบเต็ม การวัดขนาด เล็กลง 4 เท่า เร่งความเร็วได้มากกว่า 3 เท่า CPU, Edge TPU ไมโครคอนโทรลเลอร์
การวัดปริมาณ Float16 เล็กลง 2 เท่า, GPU การเร่งความเร็ว CPU, GPU

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

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

ไม่มีการกำหนดปริมาณ

ขอแนะนำให้แปลงเป็นโมเดล TFLite โดยไม่ใช้การวัดปริมาณ คะแนน การดำเนินการนี้จะสร้างโมเดล TFLite แบบลอย

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
tflite_quant_model = converter.convert()

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

การวัดช่วงไดนามิก

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

การแปลงค่าจำนวนเต็มแบบเต็ม

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

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

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

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

หากมีลายเซ็นมากกว่า 1 รายการในโมเดล 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,
      },
    )

คุณสร้างชุดข้อมูลตัวแทนได้โดยการระบุรายการ Tensor อินพุต ดังนี้

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 เวอร์ชัน 2.7 เป็นต้นไป เราขอแนะนำให้ใช้แนวทางแบบอิงตามลายเซ็น วิธีการที่อิงตามรายการ Tensor อินพุต เนื่องจากการจัดลำดับ Tensor อินพุตสามารถ พลิกได้ง่าย

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

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

จำนวนเต็มที่มีการสำรองแบบลอย (โดยใช้อินพุต/เอาต์พุตแบบลอยที่เป็นค่าเริ่มต้น)

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

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()

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

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

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

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

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

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()

ข้อดีของการวัดปริมาณด้วย Float 16 มีดังนี้

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

ข้อเสียของการวัดปริมาณ Float 16 มีดังนี้

  • ซึ่งไม่ได้ลดเวลาในการตอบสนองมากเท่ากับการแปลงปริมาณเป็นการคำนวณจุดคงที่
  • โดยค่าเริ่มต้น โมเดล Floatized 16 จะ "แยกปริมาณ" ค่าน้ำหนัก เป็น Float32 เมื่อเรียกใช้บน CPU (โปรดทราบว่าตัวแทนของ GPU จะไม่ทำงาน การลดปริมาณนี้ เนื่องจากสามารถทํางานกับข้อมูล Float 16 ได้)

จำนวนเต็มเท่านั้น: การเปิดใช้งาน 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 ที่เร่งการแสดงผลด้วยฮาร์ดแวร์ที่มีอยู่ ผู้แทน

ดูบทแนะนำสำหรับโหมดการวัดปริมาณนี้ได้ ที่นี่

ความถูกต้องของโมเดล

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

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

การนำเสนอสำหรับ Tensor ที่เล็กลง

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

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

การนำเสนอประกอบด้วย 2 ส่วนหลักๆ ดังนี้

  • น้ำหนักต่อแกน (หรือที่เรียกว่าต่อแชแนล) หรือน้ำหนักต่อ tensor แสดงด้วยค่า int8 2 เติมเต็มค่าในช่วง [-127, 127] ที่มีจุดศูนย์เท่ากับ 0

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

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