大家好,我是賀老師,嵌入式 AI工程師,《嵌入式AI:讓單片機學會思考》主理人,專注AI在MCU上的落地實踐。
TinyML 項目里最常見的問題是:設計好模型之后,在電腦或云端驗證的時候,準確率在90%以上,但是一旦將模型部署到 STM32 后,就差了很多。本文講解一下應該從哪些步驟排查問題?

排查準確率問題,不要從“模型是不是太小”開始。第一步應該確認:同一條原始數(shù)據(jù),經(jīng)過 Python 訓練腳本和 STM32 固件處理之后,進入模型的輸入數(shù)組是否一致。
只要模型輸入不一致,模型輸出不同就是正常結(jié)果。這個時候繼續(xù)調(diào)學習率、換激活函數(shù)、加層數(shù),解決不了問題。
很多 TinyML 項目在訓練階段使用的是整理好的 CSV、錄音文件、圖片文件。到了 STM32 上,輸入變成了傳感器實時采集的數(shù)據(jù)。看起來都是“加速度”“聲音”“圖像”,實際上差別可能很大。
處理辦法:把 STM32 板子采集到的原始數(shù)據(jù)導出來,重新放回 Python 評估腳本里跑一遍。如果 Python 對板上采集數(shù)據(jù)也識別不好,問題主要在數(shù)據(jù)分布;如果 Python 能識別好,STM32 識別不好,問題更可能在預處理、量化或運行時。
TinyML 的模型很小,小模型對輸入處理更敏感。訓練腳本里少寫一行歸一化,STM32 端多做一次截斷,結(jié)果都可能明顯偏掉。
下面這些細節(jié)要逐項核對,不要靠印象。
排查預處理最有效的方法:
1. 選一條固定原始樣本 raw_sample
2. Python 端輸出:
raw_sample -> preprocess_py -> model_input_py
3. STM32 端輸出:
raw_sample -> preprocess_mcu -> model_input_mcu
4. 對比 model_input_py 和 model_input_mcu
5. 差異超過預期,先修預處理,不要改模型不要只對比最終分類結(jié)果。最終分類結(jié)果只是鏈路末端的現(xiàn)象。真正有價值的是中間數(shù)組:原始采樣、濾波結(jié)果、特征數(shù)組、量化輸入、模型輸出 logits。中間數(shù)組一對比,問題通常會露出來。
STM32 上常用 int8 模型。int8 的好處是模型更小、推理更快、內(nèi)存壓力更低。但是數(shù)值范圍被壓縮,量化參數(shù)和代表性數(shù)據(jù)集會直接影響結(jié)果。
所以,我們在做量化之后,需要做下面的幾個對比
量化時代表性數(shù)據(jù)集要覆蓋:
1. 每個類別的典型樣本
2. 邊界樣本和容易混淆的樣本
3. 不同傳感器位置、距離、光照、負載、噪聲
4. 現(xiàn)場可能出現(xiàn)但訓練時容易忽略的數(shù)據(jù)
5. 不要只拿最干凈的樣本做 representative_dataset如果量化后精度下降明顯,先不要急著放棄 int8。更常見的處理方式是補代表性數(shù)據(jù)集、調(diào)整輸入歸一化、減少異常激活范圍,或者把最敏感的模型結(jié)構(gòu)換成更適合量化的結(jié)構(gòu)。
很多人驗證 STM32 推理,只看串口打印出來的分類標簽。例如打印“shake”或“normal”,然后憑感覺判斷準不準。這個驗證粒度太粗,不足以定位問題。
板上驗證至少要記錄下面這些內(nèi)容。
推薦串口日志格式:
[RAW] min=-0.83 max=1.12 mean=0.04
[FEAT] 12 9 -3 18 21 20 7 -2 ...
[IN] scale=0.0156 zp=-3 first=-8 -6 -3 4 9 ...
[OUT] normal=12 shake=91 idle=4
[TIME] preprocess=2.1ms inference=7.8ms post=0.3ms
[RESULT] shake confidence=0.85 stable_count=3STM32Cube.AI 的驗證功能可以把生成后的 C 模型和原始模型進行對比,驗證可以在電腦端做,也可以在連接的 STM32 板子上做。這個能力很適合排查“模型轉(zhuǎn)換后結(jié)果是否變化”。但業(yè)務最終仍要使用真實傳感器數(shù)據(jù)驗證。
模型輸出不是業(yè)務結(jié)論。很多項目模型本身輸出還可以,但后處理寫得太簡單,最終效果就會變差。
比如動作識別中,單幀結(jié)果偶爾抖動很正常。如果每一幀都立即切換狀態(tài),用戶看到的就是一會兒 normal、一會兒 shake、一會兒 unknown。聲音檢測中,如果只要一幀超過閾值就報警,誤報會明顯增加。異常檢測中,如果閾值固定不變,環(huán)境變化后可能長期誤報。
簡單的連續(xù)幀投票思路:
if (score[target] > threshold) {
hit_count++;
} else {
hit_count = 0;
}
if (hit_count >= 3) {
final_state = TARGET_DETECTED;
}后處理不要寫成“玄學調(diào)參”。閾值、連續(xù)幀數(shù)量、冷卻時間都應該來自測試數(shù)據(jù),而不是現(xiàn)場臨時拍腦袋。
在 PC 上推理時,數(shù)據(jù)通常是直接調(diào)用已經(jīng)采集好的真實的數(shù)據(jù)或者是使用腳本產(chǎn)生的自動模擬的數(shù)據(jù),這些數(shù)據(jù)都是比較理想的測試驗證數(shù)據(jù)。
到了 STM32 上,除了進行模型推理,還有其他的任務在運行,如果實時系統(tǒng)處理的不好,模型拿到的輸入可能是被污染了的。下面羅列出來一些常見的系統(tǒng)問題:
點擊閱讀原文,獲得更多精彩內(nèi)容