בדיקת שגיאות כימות באמצעות באגים לכמות

הצג באתר TensorFlow.org הפעל בגוגל קולאב צפה במקור ב-GitHub הורד מחברת ראה דגם TF Hub

למרות שקונטיזציה של מספרים שלמים מספקת גודל מודל משופרים והשהייה, המודל המקוונטי לא תמיד יעבוד כמצופה. בדרך כלל זה צפוי שאיכות הדגם (למשל דיוק, mAP, WER) תהיה מעט נמוכה יותר מדגם הצוף המקורי. עם זאת, ישנם מקרים שבהם איכות הדגם יכולה לרדת מתחת לציפיות שלך או לייצר תוצאות שגויות לחלוטין.

כאשר בעיה זו מתרחשת, קשה וכואב לזהות את הגורם השורשי של שגיאת הקוונטיזציה, וקשה עוד יותר לתקן את שגיאת הקוונטיזציה. כדי לסייע בתהליך בדיקת מודל זה, הבאגים קוונטיזציה יכולים לשמש כדי לזהות שכבות בעייתיות, ו קוונטיזציה סלקטיבית יכולה לעזוב אלה שכבות בעייתיות לצוף כך דיוק המודל ניתן לשחזר במחיר של גמלה מופחתת מן קוונטיזציה.

Debugger של קוונטיזציה

Debugger של קוונטיזציה מאפשר לבצע ניתוח מדדי איכות קוונטיזציה במודל הקיים. מאתר הבאגים של קוונטיזציה יכול להפוך תהליכים להפעלת מודל עם מערך נתונים של איתור באגים, ואיסוף מדדי איכות קוונטיזציה עבור כל טנסור.

דרישות מוקדמות

אם כבר יש לך צינור לכימות מודל, יש לך את כל החלקים הדרושים כדי להפעיל את ניפוי הבאגים של קוונטיזציה!

  • מודל לכימות
  • מערך נתונים מייצג

בנוסף למודל ולנתונים, תצטרך להשתמש במסגרת עיבוד נתונים (למשל פנדות, Google Sheets) כדי לנתח את התוצאות המיוצאות.

להכין

חלק זה מכין ספריות, דגם 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

דוודים ועוזרים

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. הכנת באגים

הדרך הקלה ביותר לשימוש הבאגים קוונטיזציה היא לספק tf.lite.TFLiteConverter כי השתמשת לקוואנטיזציה המודל.

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() , הבאגים ירשמו הבדלים בין tensors לצוף tensors הבדיד עבור אותו מיקום op, ולעבד אותם עם מדדים נתון.

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 אומר הגורם מידה קוונטיזציה לכל מותח.)

  • טווח ( 256 / scale )
  • RMSE / סולם ( sqrt(mean_squared_error) / scale )

RMSE / scale קרוב 1 / sqrt(12) (~ 0.289) כאשר בדיד ההפצה היא דומה להתפלגות לצוף המקורי, מה שמעיד על מודל בדיד טוב. ככל שהערך גדול יותר, סביר יותר שהשכבה לא תכומת היטב.

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), קוונטיזציה סלקטיבית תגרום לפיצול של המודל ותגרום להשהיית מסקנות איטית יותר הנגרמת בעיקר על ידי עלות העברת נתונים בין המעבד לאותם מאיצים. . כדי למנוע זאת, תוכל לשקול הצגת קוונטיזציה הכשרה מודעת לשמור את כול ההשכבות שלמות תוך שמירה על דיוק המודל.

קוונטיזציה של האופציה הבאגים מקבלת denylisted_nodes ו denylisted_ops אפשרויות מדלגים קוונטיזציה עבור שכבות מסוימות, או כל המופעים של חיילים מיחידות ספציפיים. שימוש suspected_layers שהכנו מהשלב הקודם, אנו יכולים להשתמש הבאגים קוונטיזציה לקבל מודל בדיד סלקטיבי.

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 שכבות.

אתה יכול גם לנסות לא לכמת את כל האופציות באותה מחלקה. לדוגמה, כדי לדלג קוונטיזציה לכל 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. בשלב הבא נסקור טכניקות מתקדמות לשיפור דיוק המודל עוד יותר.

שימושים מתקדמים

בעזרת התכונות הבאות, תוכל להתאים אישית יותר את צינור ניפוי הבאגים שלך.

מדדים מותאמים אישית

כברירת מחדל, מאתר הבאגים לכיוונט פולט חמישה מדדים עבור כל הבדל כמות צפה: גודל טנזור, סטיית תקן, שגיאה ממוצעת, שגיאה מוחלטת מקסימלית ושגיאה בריבוע ממוצעת. אתה יכול להוסיף עוד מדדים מותאמים אישית על ידי העברתם לאפשרויות. עבור כל מדד, התוצאה צריכה להיות ערך צף בודד והמדד שיתקבל יהיה ממוצע של מדדים מכל הדוגמאות.

  • layer_debug_metrics : לחשב מדד המבוסס על הבדל עבור כול יציאות אופ מ לצוף ותפוקות אופ בדידות.
  • layer_direct_compare_metrics : ולא מקבל הבדל רק, זה יהיה לחשב מדד המבוסס על לצוף הגלם tensors קוואנטיים, ופרמטרים קוונטיזציה שלה (בסולם, אפס נקודות)
  • model_debug_metrics : להשתמש רק כאשר float_model_(path|content) מועבר הבאגים. בנוסף למדדים ברמת ההפעלה, פלט השכבה הסופית מושווה לפלט הייחוס מהמודל הצף המקורי.
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

מצב אימות שלם של הדגם

התנהגות ברירת המחדל ליצירת מודל ניפוי באגים היא אימות לפי שכבה. במצב זה, הקלט עבור צמד פעולות צוף ו-quantize הוא מאותו מקור (אופ קוונטי קודם). מצב נוסף הוא אימות דגם שלם, שבו מופרדים בין המודלים לצוף ולכמת. מצב זה יהיה שימושי כדי לראות כיצד השגיאה מופצת לאורך המודל. כדי לאפשר, 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%