![]() |
![]() |
![]() |
![]() |
![]() |
雖然完整整數量化可改善模型大小和延遲時間,但量化模型不一定能如預期般運作。通常預期模型品質 (例如準確度、mAP、WER) 會略低於原始浮點模型。但是,在某些情況下,模型品質可能會低於您的預期或產生完全錯誤的結果。
當發生此問題時,找出量化錯誤的根本原因既棘手又痛苦,而修正量化錯誤更是困難。為了協助此模型檢查流程,量化偵錯工具可用於識別有問題的層,而選擇性量化可以讓這些有問題的層保持浮點數,以便在犧牲量化優勢的情況下恢復模型準確度。
量化偵錯工具
量化偵錯工具可以對現有模型執行量化品質指標分析。量化偵錯工具可以自動化使用偵錯資料集執行模型,以及收集每個張量的量化品質指標的流程。
先決條件
如果您已經有量化模型的管線,您就擁有執行量化偵錯工具的所有必要元件!
- 要量化的模型
- 代表性資料集
除了模型和資料之外,您還需要使用資料處理架構 (例如 pandas、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
樣板程式碼和輔助程式
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}%')
eval_tflite(quantized_model, ds)
我們可以發現,原始模型在我們的小型資料集上的前 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))
步驟 2. 執行偵錯工具並取得結果
當您呼叫 QuantizationDebugger.run()
時,偵錯工具會記錄相同運算位置的浮點張量和量化張量之間的差異,並使用給定的指標處理這些差異。
debugger.run()
處理後的指標可以使用 QuantizationDebugger.layer_statistics
存取,或者可以使用 QuantizationDebugger.layer_statistics_dump()
以 CSV 格式傾印到文字檔。
RESULTS_FILE = '/tmp/debugger_results.csv'
with open(RESULTS_FILE, 'w') as f:
debugger.layer_statistics_dump(f)
head /tmp/debugger_results.csv
在傾印中的每一列,運算名稱和索引會先出現,然後是量化參數和錯誤指標 (包括使用者定義的錯誤指標,如果有的話)。產生的 CSV 檔案可用於挑選具有大量化錯誤指標的有問題層。
透過 pandas 或其他資料處理程式庫,我們可以檢查詳細的每層錯誤指標。
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) 上執行量化模型,則選擇性量化會導致模型分散,並導致較慢的推論延遲時間,這主要是由 CPU 和這些加速器之間的資料傳輸成本引起的。為了防止這種情況,您可以考慮執行量化感知訓練,以將所有層保持在整數中,同時保持模型準確度。
量化偵錯工具的選項接受 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)
selective_quantized_model = debugger.get_nondebug_quantized_model()
eval_tflite(selective_quantized_model, ds)
與原始浮點模型相比,準確度仍然較低,但是透過略過 111 層中的約 10 層的量化,我們從整體量化模型中獲得了顯著的改進。
您也可以嘗試不要量化相同類別中的所有運算。例如,若要略過所有平均運算的量化,您可以將 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)
selective_quantized_model = debugger.get_nondebug_quantized_model()
eval_tflite(selective_quantized_model, ds)
透過這些技術,我們能夠提高量化 MobileNet V3 模型的準確度。接下來,我們將探索進階技術,以進一步提高模型準確度。
進階用法
透過以下功能,您可以進一步自訂偵錯管線。
自訂指標
預設情況下,量化偵錯工具會針對每個浮點數-量化差異發出五個指標:張量大小、標準差、平均誤差、最大絕對誤差和均方誤差。您可以透過將更多自訂指標傳遞至選項來新增它們。對於每個指標,結果應該是單一浮點值,而產生的指標將是所有範例指標的平均值。
layer_debug_metrics
:根據浮點數和量化運算輸出的每個運算輸出的差異計算指標。layer_direct_compare_metrics
:與僅取得差異不同,這將根據原始浮點數和量化張量及其量化參數 (比例、零點) 計算指標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)
debugger.run()
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
使用 (內部) mlir_quantize API 存取深入功能
from tensorflow.lite.python import convert
完整模型驗證模式
偵錯模型產生的預設行為是每層驗證。在此模式下,浮點數和量化運算對的輸入來自相同的來源 (先前的量化運算)。另一種模式是完整模型驗證,其中浮點數和量化模型是分開的。此模式可用於觀察錯誤如何在模型中向下傳播。若要啟用,請將 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()
# 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))
從已校正模型進行選擇性量化
您可以直接呼叫 convert.mlir_quantize
,以從已校正模型取得選擇性量化模型。當您想要校正模型一次,並試驗各種拒絕清單組合時,這特別有用。
selective_quantized_model = convert.mlir_quantize(
calibrated_model, denylisted_nodes=suspected_layers)
eval_tflite(selective_quantized_model, ds)