การตรวจสอบข้อผิดพลาดของ Quantization ด้วย Quantization Debugger

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค ดูรุ่น TF Hub

แม้ว่าการหาจำนวนเต็มจำนวนเต็มจะทำให้ขนาดโมเดลและเวลาแฝงที่ได้รับการปรับปรุง แต่แบบจำลองเชิงปริมาณจะไม่ทำงานตามที่คาดไว้เสมอไป โดยปกติคาดว่าคุณภาพของโมเดล (เช่น ความแม่นยำ, mAP, WER) จะต่ำกว่าโมเดลโฟลตดั้งเดิมเล็กน้อย อย่างไรก็ตาม มีหลายกรณีที่คุณภาพของแบบจำลองอาจต่ำกว่าที่คุณคาดไว้หรือสร้างผลลัพธ์ที่ผิดพลาดโดยสิ้นเชิง

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

ดีบักเกอร์เชิงปริมาณ

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

ข้อกำหนดเบื้องต้น

หากคุณมีไปป์ไลน์ในการควอนไทซ์โมเดลแล้ว คุณมีชิ้นส่วนที่จำเป็นทั้งหมดเพื่อรันดีบักเกอร์ควอนไทซ์!

  • แบบจำลองการหาปริมาณ
  • ชุดข้อมูลตัวแทน

นอกจากโมเดลและข้อมูล คุณจะต้องใช้เฟรมเวิร์กการประมวลผลข้อมูล (เช่น แพนด้า, Google ชีต) เพื่อวิเคราะห์ผลลัพธ์ที่ส่งออก

ติดตั้ง

ส่วนนี้เตรียมไลบรารี่ โมเดล MobileNet v3 และชุดข้อมูลทดสอบ 100 อิมเมจ

# Quantization debugger is available from TensorFlow 2.7.0
pip uninstall -y tensorflow
pip install tf-nightly
pip install tensorflow_datasets --upgrade  # imagenet_v2 needs latest checksum
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import tensorflow as tf
import tensorflow_datasets as tfds
import tensorflow_hub as hub

Boilerplates และตัวช่วย

2021-10-30 11:57:45.262002: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/tmp_3ry7zon/assets
INFO:tensorflow:Assets written to: /tmp/tmp_3ry7zon/assets
2021-10-30 11:57:52.134354: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-10-30 11:57:52.134407: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0
test_ds = ds.map(lambda data: (data['image'], data['label'] + 1)).batch(16)
loss, acc = model.evaluate(test_ds)
print(f'Top-5 accuracy (float): {acc * 100:.2f}%')
7/7 [==============================] - 6s 33ms/step - loss: 88.6092 - sparse_top_k_categorical_accuracy: 11.7143
Top-5 accuracy (float): 1171.43%
eval_tflite(quantized_model, ds)
Top-5 accuracy (quantized): 51.00%

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

ขั้นตอนที่ 1. การเตรียมดีบักเกอร์

วิธีที่ง่ายที่สุดที่จะใช้ดีบัก quantization คือการให้ tf.lite.TFLiteConverter ที่คุณได้รับใช้ในการ quantize รูปแบบ

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset(ds)

# my_debug_dataset should have the same format as my_representative_dataset
debugger = tf.lite.experimental.QuantizationDebugger(
    converter=converter, debug_dataset=representative_dataset(ds))
INFO:tensorflow:Assets written to: /tmp/tmpoa_5gejn/assets
INFO:tensorflow:Assets written to: /tmp/tmpoa_5gejn/assets
2021-10-30 11:58:34.006052: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-10-30 11:58:34.006103: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0

ขั้นตอนที่ 2 เรียกใช้ดีบักเกอร์และรับผลลัพธ์

เมื่อคุณเรียก QuantizationDebugger.run() ดีบักจะเข้าสู่ระบบความแตกต่างระหว่างเทนเซอร์ลอยและเทนเซอร์ไทสำหรับสถานที่สหกรณ์เดียวกันและดำเนินการให้มีตัวชี้วัดที่กำหนด

debugger.run()

การประมวลผลตัวชี้วัดที่สามารถเข้าถึงได้ด้วย QuantizationDebugger.layer_statistics หรือสามารถทิ้งไปยังแฟ้มข้อความในรูปแบบ CSV กับ QuantizationDebugger.layer_statistics_dump()

RESULTS_FILE = '/tmp/debugger_results.csv'
with open(RESULTS_FILE, 'w') as f:
  debugger.layer_statistics_dump(f)
head /tmp/debugger_results.csv

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

ด้วยแพนด้าหรือไลบรารีประมวลผลข้อมูลอื่นๆ เราสามารถตรวจสอบเมตริกข้อผิดพลาดต่อเลเยอร์โดยละเอียดได้

layer_stats = pd.read_csv(RESULTS_FILE)
layer_stats.head()

ขั้นตอนที่ 3 การวิเคราะห์ข้อมูล

มีหลายวิธีในการวิเคราะห์ผลลัพธ์ ขั้นแรก ให้เพิ่มเมตริกที่มีประโยชน์ซึ่งได้มาจากเอาต์พุตของดีบักเกอร์ ( scale หมายถึงปัจจัย quantization ขนาดสำหรับแต่ละเมตริกซ์.)

  • ช่วง ( 256 / scale )
  • RMSE / ขนาด ( sqrt(mean_squared_error) / scale )

RMSE / scale อยู่ใกล้กับ 1 / sqrt(12) (~ 0.289) เมื่อการกระจายไทมีลักษณะคล้ายกับการกระจายลอยเดิมแสดงให้เห็นเป็นแบบอย่างที่ดี quantized ยิ่งค่ามากเท่าไร ก็มีโอกาสมากขึ้นที่ชั้นจะไม่ได้วัดปริมาณได้ดี

layer_stats['range'] = 255.0 * layer_stats['scale']
layer_stats['rmse/scale'] = layer_stats.apply(
    lambda row: np.sqrt(row['mean_squared_error']) / row['scale'], axis=1)
layer_stats[['op_name', 'range', 'rmse/scale']].head()
plt.figure(figsize=(15, 5))
ax1 = plt.subplot(121)
ax1.bar(np.arange(len(layer_stats)), layer_stats['range'])
ax1.set_ylabel('range')
ax2 = plt.subplot(122)
ax2.bar(np.arange(len(layer_stats)), layer_stats['rmse/scale'])
ax2.set_ylabel('rmse/scale')
plt.show()

png

มีหลายชั้นที่มีช่วงกว้างและชั้นบางอย่างที่มีความสูง RMSE/scale ค่า มาดูเลเยอร์ที่มีเมตริกข้อผิดพลาดสูงกัน

layer_stats[layer_stats['rmse/scale'] > 0.7][[
    'op_name', 'range', 'rmse/scale', 'tensor_name'
]]

ด้วยเลเยอร์เหล่านี้ คุณสามารถลองใช้การหาปริมาณแบบเลือก เพื่อดูว่าการไม่วัดปริมาณเลเยอร์เหล่านั้นช่วยปรับปรุงคุณภาพของโมเดลหรือไม่

suspected_layers = list(
    layer_stats[layer_stats['rmse/scale'] > 0.7]['tensor_name'])

นอกจากนี้ การข้ามการหาปริมาณสำหรับสองสามเลเยอร์แรกยังช่วยปรับปรุงคุณภาพของแบบจำลองเชิงปริมาณอีกด้วย

suspected_layers.extend(list(layer_stats[:5]['tensor_name']))

การหาปริมาณการคัดเลือก

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

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

ตัวเลือก Quantization ดีบักของยอมรับ denylisted_nodes และ denylisted_ops ตัวเลือกสำหรับการกระโดดข้าม quantization สำหรับชั้นที่เฉพาะเจาะจงหรือกรณีของปฏิบัติการที่เฉพาะเจาะจง ใช้ suspected_layers เราเตรียมไว้จากขั้นตอนก่อนหน้านี้เราสามารถใช้ quantization ดีบักที่จะได้รับการคัดเลือกรูปแบบไท

debug_options = tf.lite.experimental.QuantizationDebugOptions(
    denylisted_nodes=suspected_layers)
debugger = tf.lite.experimental.QuantizationDebugger(
    converter=converter,
    debug_dataset=representative_dataset(ds),
    debug_options=debug_options)
INFO:tensorflow:Assets written to: /tmp/tmpqqc57uli/assets
INFO:tensorflow:Assets written to: /tmp/tmpqqc57uli/assets
2021-10-30 11:59:13.603355: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-10-30 11:59:13.603400: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0
selective_quantized_model = debugger.get_nondebug_quantized_model()
eval_tflite(selective_quantized_model, ds)
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0
Top-5 accuracy (quantized): 64.00%

ความแม่นยำยังคงต่ำกว่าเมื่อเทียบกับรุ่นโฟลตดั้งเดิม แต่เรามีการปรับปรุงที่โดดเด่นจากแบบจำลองเชิงปริมาณทั้งหมดโดยข้ามการหาปริมาณไปประมาณ 10 เลเยอร์จาก 111 เลเยอร์

คุณยังสามารถพยายามไม่ใช้ quantized ops ทั้งหมดในคลาสเดียวกัน ตัวอย่างเช่นในการข้าม quantization สำหรับ Ops เฉลี่ยทุกท่านสามารถส่งผ่าน MEAN การ denylisted_ops

debug_options = tf.lite.experimental.QuantizationDebugOptions(
    denylisted_ops=['MEAN'])
debugger = tf.lite.experimental.QuantizationDebugger(
    converter=converter,
    debug_dataset=representative_dataset(ds),
    debug_options=debug_options)
INFO:tensorflow:Assets written to: /tmp/tmpxltlornb/assets
INFO:tensorflow:Assets written to: /tmp/tmpxltlornb/assets
2021-10-30 11:59:44.677473: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-10-30 11:59:44.677519: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0
selective_quantized_model = debugger.get_nondebug_quantized_model()
eval_tflite(selective_quantized_model, ds)
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0
Top-5 accuracy (quantized): 54.00%

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

การใช้งานขั้นสูง

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

เมตริกที่กำหนดเอง

โดยค่าเริ่มต้น ดีบักเกอร์ quantization จะปล่อยตัววัด 5 ตัวสำหรับความแตกต่างของ float-quant แต่ละตัว: ขนาดเทนเซอร์ ส่วนเบี่ยงเบนมาตรฐาน ค่าเฉลี่ยข้อผิดพลาด ข้อผิดพลาดสัมบูรณ์สูงสุด และข้อผิดพลาดกำลังสองเฉลี่ย คุณสามารถเพิ่มเมตริกที่กำหนดเองได้โดยส่งต่อไปยังตัวเลือกต่างๆ สำหรับแต่ละเมตริก ผลลัพธ์ควรเป็นค่าโฟลตเดียว และเมตริกที่ได้จะเป็นค่าเฉลี่ยของเมตริกจากตัวอย่างทั้งหมด

  • layer_debug_metrics : คำนวณตัวชี้วัดที่อยู่บนพื้นฐานของความแตกต่างของแต่ละสหกรณ์เอาท์พุทจากลอยและเอาท์พุท quantized op
  • layer_direct_compare_metrics : แทนที่จะได้รับ diff เพียงนี้จะคำนวณตัวชี้วัดที่อยู่บนพื้นฐานของลอยดิบและเทนเซอร์ไทและพารามิเตอร์ของควอน (ขนาดจุดศูนย์)
  • model_debug_metrics : ใช้เฉพาะเมื่อ float_model_(path|content) ถูกส่งไปยังดีบัก นอกจากเมตริกระดับ op แล้ว เอาต์พุตของเลเยอร์สุดท้ายจะถูกเปรียบเทียบกับเอาต์พุตอ้างอิงจากโมเดล float ดั้งเดิม
debug_options = tf.lite.experimental.QuantizationDebugOptions(
    layer_debug_metrics={
        'mean_abs_error': (lambda diff: np.mean(np.abs(diff)))
    },
    layer_direct_compare_metrics={
        'correlation':
            lambda f, q, s, zp: (np.corrcoef(f.flatten(),
                                             (q.flatten() - zp) / s)[0, 1])
    },
    model_debug_metrics={
        'argmax_accuracy': (lambda f, q: np.mean(np.argmax(f) == np.argmax(q)))
    })

debugger = tf.lite.experimental.QuantizationDebugger(
    converter=converter,
    debug_dataset=representative_dataset(ds),
    debug_options=debug_options)
INFO:tensorflow:Assets written to: /tmp/tmpm7cb9qcd/assets
INFO:tensorflow:Assets written to: /tmp/tmpm7cb9qcd/assets
2021-10-30 12:00:18.502193: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-10-30 12:00:18.502238: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
INFO:tensorflow:Assets written to: /tmp/tmpzkg3ny_8/assets
INFO:tensorflow:Assets written to: /tmp/tmpzkg3ny_8/assets
2021-10-30 12:00:28.401195: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-10-30 12:00:28.401241: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0
debugger.run()
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/numpy/lib/function_base.py:2691: RuntimeWarning: invalid value encountered in true_divide
  c /= stddev[:, None]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/numpy/lib/function_base.py:2692: RuntimeWarning: invalid value encountered in true_divide
  c /= stddev[None, :]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/lite/tools/optimize/debugging/python/debugger.py:382: RuntimeWarning: Mean of empty slice
  metrics[metric_name] = np.nanmean(metrics[metric_name])
CUSTOM_RESULTS_FILE = '/tmp/debugger_results.csv'
with open(CUSTOM_RESULTS_FILE, 'w') as f:
  debugger.layer_statistics_dump(f)

custom_layer_stats = pd.read_csv(CUSTOM_RESULTS_FILE)
custom_layer_stats[['op_name', 'mean_abs_error', 'correlation']].tail()

ผลมาจากการ model_debug_metrics สามารถมองเห็นได้แยกต่างหากจาก debugger.model_statistics

debugger.model_statistics
{'argmax_accuracy': 0.36}

การใช้ (ภายใน) mlir_quantize API เพื่อเข้าถึงคุณสมบัติเชิงลึก

from tensorflow.lite.python import convert

โหมดการตรวจสอบทั้งโมเดล

ลักษณะการทำงานเริ่มต้นสำหรับการสร้างแบบจำลองการดีบักคือการตรวจสอบทีละชั้น ในโหมดนี้ อินพุตสำหรับ float และ quantize op pair มาจากแหล่งเดียวกัน (op quantized ก่อนหน้า) อีกโหมดหนึ่งคือการตรวจสอบทั้งโมเดล โดยที่โมเดลทุ่นและเชิงปริมาณแยกจากกัน โหมดนี้จะเป็นประโยชน์ในการสังเกตว่าข้อผิดพลาดถูกเผยแพร่ลงในแบบจำลองอย่างไร ต้องการเปิดใช้งาน enable_whole_model_verify=True เพื่อ convert.mlir_quantize ขณะที่การสร้างรูปแบบการแก้ปัญหาด้วยตนเอง

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.representative_dataset = representative_dataset(ds)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter._experimental_calibrate_only = True
calibrated_model = converter.convert()
INFO:tensorflow:Assets written to: /tmp/tmp2oa0sp06/assets
INFO:tensorflow:Assets written to: /tmp/tmp2oa0sp06/assets
2021-10-30 12:01:33.233118: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:363] Ignored output_format.
2021-10-30 12:01:33.233171: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:366] Ignored drop_control_dependency.
# Note that enable_numeric_verify and enable_whole_model_verify are set.
quantized_model = convert.mlir_quantize(
    calibrated_model,
    enable_numeric_verify=True,
    enable_whole_model_verify=True)
debugger = tf.lite.experimental.QuantizationDebugger(
    quant_debug_model_content=quantized_model,
    debug_dataset=representative_dataset(ds))
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0

การหาปริมาณจากแบบจำลองที่ได้รับการสอบเทียบแล้ว

คุณโดยตรงสามารถเรียก convert.mlir_quantize ที่จะได้รับรูปแบบไทคัดเลือกจากแบบจำลองการสอบเทียบแล้ว ซึ่งจะเป็นประโยชน์อย่างยิ่งเมื่อคุณต้องการปรับเทียบแบบจำลองเพียงครั้งเดียว และทดลองกับชุดค่าผสมปฏิเสธต่างๆ

selective_quantized_model = convert.mlir_quantize(
    calibrated_model, denylisted_nodes=suspected_layers)
eval_tflite(selective_quantized_model, ds)
fully_quantize: 0, inference_type: 6, input_inference_type: 0, output_inference_type: 0
Top-5 accuracy (quantized): 64.00%