הצג באתר 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
דוודים ועוזרים
MODEL_URI = 'https://tfhub.dev/google/imagenet/mobilenet_v3_small_100_224/classification/5'
def process_image(data):
data['image'] = tf.image.resize(data['image'], (224, 224)) / 255.0
return data
# Representative dataset
def representative_dataset(dataset):
def _data_gen():
for data in dataset.batch(1):
yield [data['image']]
return _data_gen
def eval_tflite(tflite_model, dataset):
"""Evaluates tensorflow lite classification model with the given dataset."""
interpreter = tf.lite.Interpreter(model_content=tflite_model)
interpreter.allocate_tensors()
input_idx = interpreter.get_input_details()[0]['index']
output_idx = interpreter.get_output_details()[0]['index']
results = []
for data in representative_dataset(dataset)():
interpreter.set_tensor(input_idx, data[0])
interpreter.invoke()
results.append(interpreter.get_tensor(output_idx).flatten())
results = np.array(results)
gt_labels = np.array(list(dataset.map(lambda data: data['label'] + 1)))
accuracy = (
np.sum(np.argsort(results, axis=1)[:, -5:] == gt_labels.reshape(-1, 1)) /
gt_labels.size)
print(f'Top-5 accuracy (quantized): {accuracy * 100:.2f}%')
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(224, 224, 3), batch_size=1),
hub.KerasLayer(MODEL_URI)
])
model.compile(
loss='sparse_categorical_crossentropy',
metrics='sparse_top_k_categorical_accuracy')
model.build([1, 224, 224, 3])
# Prepare dataset with 100 examples
ds = tfds.load('imagenet_v2', split='test[:1%]')
ds = ds.map(process_image)
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.representative_dataset = representative_dataset(ds)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
quantized_model = converter.convert()
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()
ישנם רבדים רבים עם טווחים רחבים, וכמה שכבות שיש הגבוהה 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%