習(xí)的靜態(tài)手勢(shì)識(shí)別:從數(shù)據(jù)集到部署的完整方案)
簡(jiǎn)介這份PDF文獻(xiàn)面向計(jì)算機(jī)視覺(jué)與深度學(xué)習(xí)方向的本科生、研究生及算法入門(mén)者系統(tǒng)講解如何用卷積神經(jīng)網(wǎng)絡(luò)完成靜態(tài)手勢(shì)識(shí)別任務(wù)可幫助讀者理解從圖像采集到模型部署的完整算法鏈路。資源包為單一PDF文件大小約1.82MB內(nèi)容涵蓋數(shù)據(jù)采集、數(shù)據(jù)增強(qiáng)、CNN模型搭建、參數(shù)訓(xùn)練與模型測(cè)試等核心環(huán)節(jié)并配有算法流程圖、AlexNet網(wǎng)絡(luò)結(jié)構(gòu)圖及實(shí)驗(yàn)數(shù)據(jù)圖表。文中以剪刀、包袱、石頭、OK、點(diǎn)贊五類(lèi)手勢(shì)為對(duì)象采用AlexNet網(wǎng)絡(luò)與TensorFlow平臺(tái)實(shí)現(xiàn)通過(guò)旋轉(zhuǎn)、平移、縮放、對(duì)比度變換和添加噪聲等方式擴(kuò)充數(shù)據(jù)集訓(xùn)練集達(dá)11110張圖片測(cè)試集準(zhǔn)確率最高達(dá)100%另一測(cè)試集為92.19%。目前已有529人學(xué)習(xí)適合希望掌握深度學(xué)習(xí)圖像分類(lèi)實(shí)戰(zhàn)流程、理解數(shù)據(jù)增強(qiáng)與過(guò)擬合抑制思路的讀者參考也為后續(xù)動(dòng)態(tài)手勢(shì)識(shí)別研究提供基礎(chǔ)。1. 靜態(tài)手勢(shì)識(shí)別落地從一張 RGB 圖到 24 類(lèi)手勢(shì)的完整鏈路工業(yè)現(xiàn)場(chǎng)做手勢(shì)控制最怕的不是模型精度不夠而是環(huán)境一變就翻車(chē)。我做過(guò)一個(gè)產(chǎn)線(xiàn)示教臂的項(xiàng)目操作工戴著手套在強(qiáng)反光金屬臺(tái)面前比劃實(shí)驗(yàn)室里 98% 的模型到了現(xiàn)場(chǎng)直接掉到 60% 出頭。靜態(tài)手勢(shì)識(shí)別算法設(shè)計(jì)這件事核心矛盾從來(lái)不是「選哪個(gè) CNN」而是「怎么讓模型在真實(shí)光照、膚色、遮擋和類(lèi)間相似度下穩(wěn)住」。這篇筆記拆的是基于深度學(xué)習(xí)的靜態(tài)手勢(shì)識(shí)別完整方案輸入一張 RGB 圖輸出預(yù)定義手勢(shì)類(lèi)別覆蓋數(shù)據(jù)集構(gòu)建、骨干選型、訓(xùn)練參數(shù)、部署推理和現(xiàn)場(chǎng)排查。適合正在做深度學(xué)習(xí)圖像識(shí)別畢設(shè)的學(xué)生也適合要把手勢(shì)交互塞進(jìn)實(shí)際產(chǎn)品的工程師。讀完你能拿到一套可復(fù)現(xiàn)的訓(xùn)練腳本結(jié)構(gòu)、關(guān)鍵參數(shù)取值區(qū)間以及我踩過(guò)的那些血淚坑。2. 數(shù)據(jù)集與骨干網(wǎng)絡(luò)靜態(tài)手勢(shì)識(shí)別的地基怎么打2.1 公開(kāi)數(shù)據(jù)集選型與自采數(shù)據(jù)的配比策略靜態(tài)手勢(shì)識(shí)別最常用的公開(kāi)集是 ASL Finger Spelling 和 HaGRID 的子集。ASL 字母集 24 類(lèi)J 和 Z 是動(dòng)態(tài)的靜態(tài)方案通常剔除每類(lèi)約 1000 到 3000 張背景干凈、手部居中適合做 baseline。但如果你直接拿它訓(xùn)完就上現(xiàn)場(chǎng)基本會(huì)翻車(chē)——因?yàn)檎鎸?shí)場(chǎng)景的手勢(shì)不會(huì)永遠(yuǎn)正對(duì)鏡頭、不會(huì)永遠(yuǎn)在畫(huà)面中央、不會(huì)永遠(yuǎn)光照均勻。我的做法是公開(kāi)集做預(yù)訓(xùn)練自采數(shù)據(jù)做微調(diào)。自采時(shí)按「三三制」分配——三分之一正常光照正面、三分之一側(cè)向或俯仰 30 度以?xún)?nèi)、三分之一故意制造困難樣本逆光、手套、部分遮擋、背景雜亂。每類(lèi)至少 200 張自采24 類(lèi)就是 4800 張加上公開(kāi)集約 5 萬(wàn)張總量控制在 6 萬(wàn)以?xún)?nèi)。為什么不是越多越好因?yàn)殪o態(tài)手勢(shì)類(lèi)間差異小數(shù)據(jù)量過(guò)大但多樣性不足時(shí)模型會(huì)過(guò)擬合到背景紋理而不是手部形狀。標(biāo)注格式統(tǒng)一成 YOLO 或 COCO 都行但如果你只做分類(lèi)不做檢測(cè)建議直接按類(lèi)別分文件夾用ImageFolder讀省去解析標(biāo)注的麻煩。下面是一個(gè)把 ASL 子集和自采數(shù)據(jù)合并成統(tǒng)一目錄結(jié)構(gòu)的腳本import os import shutil import random from pathlib import Path # 合并公開(kāi)集和自采數(shù)據(jù)按 8:1:1 劃分 PUBLIC_DIR Path(data/asl_subset) # 每類(lèi)一個(gè)子文件夾 CUSTOM_DIR Path(data/custom_gesture) # 同樣每類(lèi)一個(gè)子文件夾 OUTPUT_DIR Path(data/merged) random.seed(42) for split in [train, val, test]: (OUTPUT_DIR / split).mkdir(parentsTrue, exist_okTrue) # 收集所有類(lèi)別 classes sorted([d.name for d in PUBLIC_DIR.iterdir() if d.is_dir()]) for cls in classes: all_imgs [] for src in [PUBLIC_DIR / cls, CUSTOM_DIR / cls]: if src.exists(): all_imgs.extend(list(src.glob(*.jpg)) list(src.glob(*.png))) random.shuffle(all_imgs) n len(all_imgs) n_train, n_val int(n * 0.8), int(n * 0.1) splits { train: all_imgs[:n_train], val: all_imgs[n_train:n_train n_val], test: all_imgs[n_train n_val:] } for split, imgs in splits.items(): dst OUTPUT_DIR / split / cls dst.mkdir(parentsTrue, exist_okTrue) for img in imgs: shutil.copy2(img, dst / img.name) print(f{cls}: train{len(splits[train])}, val{len(splits[val])}, test{len(splits[test])})這段腳本的關(guān)鍵參數(shù)是random.seed(42)保證可復(fù)現(xiàn)以及 8:1:1 的劃分比例。驗(yàn)證集和測(cè)試集必須來(lái)自不同拍攝批次否則你看到的精度是虛高的。我一般會(huì)把自采數(shù)據(jù)里同一天同一批拍的全部放進(jìn)同一個(gè) split避免數(shù)據(jù)泄漏。2.2 骨干網(wǎng)絡(luò)選型MobileNetV3、ResNet18 還是 EfficientNet-Lite靜態(tài)手勢(shì)識(shí)別不是 ImageNet 競(jìng)賽輸入分辨率通常 224×224 甚至 128×128類(lèi)別數(shù) 10 到 30 之間。這個(gè)規(guī)模下ResNet50 以上純屬浪費(fèi)推理延遲翻倍而精度提升不到 1 個(gè)點(diǎn)。我實(shí)測(cè)過(guò)三檔骨干在自建 24 類(lèi)數(shù)據(jù)集上的表現(xiàn)骨干參數(shù)量輸入尺寸驗(yàn)證集精度CPU 單幀延遲MobileNetV3-Small2.5M22494.2%18msResNet1811.7M22496.8%45msEfficientNet-B05.3M22496.1%32ms如果部署在邊緣設(shè)備或手機(jī)端MobileNetV3-Small 是首選精度差距可以通過(guò)數(shù)據(jù)增強(qiáng)和更長(zhǎng)的訓(xùn)練輪次補(bǔ)回來(lái)。如果服務(wù)器端推理且延遲不敏感ResNet18 性?xún)r(jià)比最高。EfficientNet-B0 介于兩者之間但它的復(fù)合縮放系數(shù)在低分辨率下優(yōu)勢(shì)不明顯我一般跳過(guò)。選型時(shí)還要看你的框架生態(tài)。PyTorch 的torchvision.models直接提供預(yù)訓(xùn)練權(quán)重一行代碼加載。下面是一個(gè)替換分類(lèi)頭的標(biāo)準(zhǔn)寫(xiě)法import torch import torch.nn as nn from torchvision import models def build_model(num_classes24, backbonemobilenet_v3_small, pretrainedTrue): if backbone mobilenet_v3_small: model models.mobilenet_v3_small(pretrainedpretrained) in_features model.classifier[3].in_features model.classifier[3] nn.Linear(in_features, num_classes) elif backbone resnet18: model models.resnet18(pretrainedpretrained) in_features model.fc.in_features model.fc nn.Linear(in_features, num_classes) else: raise ValueError(fUnsupported backbone: {backbone}) return model # 凍結(jié)骨干前幾層只訓(xùn)分類(lèi)頭小數(shù)據(jù)集推薦 model build_model(num_classes24, backbonemobilenet_v3_small) for name, param in model.named_parameters(): if classifier not in name and fc not in name: param.requires_grad False # 統(tǒng)計(jì)可訓(xùn)練參數(shù) trainable sum(p.numel() for p in model.parameters() if p.requires_grad) print(fTrainable params: {trainable / 1e6:.2f}M)凍結(jié)骨干的策略適合自采數(shù)據(jù)少于 5000 張的情況。如果數(shù)據(jù)量夠解凍全部參數(shù)做微調(diào)學(xué)習(xí)率調(diào)到 1e-4 量級(jí)比只訓(xùn)分類(lèi)頭能再漲 1 到 2 個(gè)點(diǎn)。注意 MobileNetV3 的classifier是一個(gè) Sequential索引 3 才是最后的 Linear 層寫(xiě)錯(cuò)索引會(huì)導(dǎo)致維度不匹配。3. 訓(xùn)練參數(shù)與增強(qiáng)策略讓模型在復(fù)雜場(chǎng)景下不崩3.1 學(xué)習(xí)率、批大小與優(yōu)化器的取值區(qū)間靜態(tài)手勢(shì)識(shí)別的訓(xùn)練參數(shù)沒(méi)有萬(wàn)能公式但有一個(gè)經(jīng)過(guò)大量實(shí)驗(yàn)驗(yàn)證的起點(diǎn)AdamW 優(yōu)化器學(xué)習(xí)率 3e-4權(quán)重衰減 1e-4批大小 64余弦退火調(diào)度訓(xùn)練 60 到 80 輪。這個(gè)配置在 6 萬(wàn)張圖、24 類(lèi)的設(shè)定下通常能在第 40 輪左右收斂到驗(yàn)證集 96% 以上。為什么用 AdamW 而不是 SGDSGD 在精細(xì)調(diào)參后可能略好但對(duì)手勢(shì)這種類(lèi)間差異小的任務(wù)AdamW 的自適應(yīng)學(xué)習(xí)率能更快跳出局部最優(yōu)。權(quán)重衰減一定要加否則最后幾輪驗(yàn)證損失會(huì)往上翹。批大小如果顯存不夠降到 32學(xué)習(xí)率對(duì)應(yīng)降到 2e-4不要保持 3e-4 不變否則梯度噪聲太大會(huì)震蕩。下面是一個(gè)完整的訓(xùn)練循環(huán)骨架包含混合精度和梯度裁剪import torch from torch.cuda.amp import autocast, GradScaler from torch.optim.lr_scheduler import CosineAnnealingLR device torch.device(cuda if torch.cuda.is_available() else cpu) model build_model(num_classes24).to(device) optimizer torch.optim.AdamW( filter(lambda p: p.requires_grad, model.parameters()), lr3e-4, weight_decay1e-4 ) scheduler CosineAnnealingLR(optimizer, T_max60, eta_min1e-6) scaler GradScaler() criterion torch.nn.CrossEntropyLoss(label_smoothing0.1) for epoch in range(60): model.train() for imgs, labels in train_loader: imgs, labels imgs.to(device), labels.to(device) optimizer.zero_grad() with autocast(): outputs model(imgs) loss criterion(outputs, labels) scaler.scale(loss).backward() scaler.unscale_(optimizer) torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm5.0) scaler.step(optimizer) scaler.update() scheduler.step() # 驗(yàn)證邏輯省略每輪記錄 val_acclabel_smoothing0.1是防止模型對(duì)訓(xùn)練集過(guò)度自信的關(guān)鍵尤其當(dāng)你的自采數(shù)據(jù)標(biāo)注有少量噪聲時(shí)。梯度裁剪max_norm5.0能避免個(gè)別臟樣本導(dǎo)致的梯度爆炸?;旌暇扔?xùn)練在 RTX 系列卡上能省 30% 以上顯存批大小可以相應(yīng)調(diào)大。3.2 數(shù)據(jù)增強(qiáng)別只會(huì)隨機(jī)翻轉(zhuǎn)和裁剪靜態(tài)手勢(shì)識(shí)別的增強(qiáng)策略要圍繞「手部形狀不變性」設(shè)計(jì)。隨機(jī)水平翻轉(zhuǎn)對(duì)左右手通用手勢(shì)有效但如果你的類(lèi)別里包含左右手區(qū)分的手勢(shì)翻轉(zhuǎn)會(huì)制造錯(cuò)誤標(biāo)簽。隨機(jī)裁剪和旋轉(zhuǎn)要控制幅度旋轉(zhuǎn)超過(guò) 20 度會(huì)讓某些手勢(shì)看起來(lái)像另一個(gè)類(lèi)。我常用的增強(qiáng)組合是RandomResizedCrop(224, scale(0.7, 1.0))、ColorJitter(brightness0.3, contrast0.3, saturation0.2, hue0.05)、RandomRotation(15)、RandomGrayscale(p0.1)。ColorJitter 的 hue 幅度一定要小超過(guò) 0.1 會(huì)讓膚色偏移過(guò)大模型學(xué)到的顏色特征就廢了。RandomGrayscale 偶爾去掉顏色信息強(qiáng)迫模型關(guān)注形狀。from torchvision import transforms train_transform transforms.Compose([ transforms.RandomResizedCrop(224, scale(0.7, 1.0)), transforms.ColorJitter(brightness0.3, contrast0.3, saturation0.2, hue0.05), transforms.RandomRotation(15), transforms.RandomGrayscale(p0.1), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), transforms.RandomErasing(p0.25, scale(0.02, 0.15)) ]) val_transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])RandomErasing模擬手部被部分遮擋的情況p0.25 是經(jīng)過(guò)測(cè)試的平衡點(diǎn)再高會(huì)欠擬合。歸一化的 mean 和 std 用 ImageNet 的統(tǒng)計(jì)值就行你的手勢(shì)數(shù)據(jù)集規(guī)模不足以重新統(tǒng)計(jì)出有意義的全局均值。驗(yàn)證集只做 Resize 和 CenterCrop不要加任何隨機(jī)增強(qiáng)否則驗(yàn)證精度會(huì)波動(dòng)得讓你懷疑人生。4. 推理部署與性能優(yōu)化從 PyTorch 到實(shí)際可用的接口4.1 模型導(dǎo)出與 ONNX Runtime 推理訓(xùn)練完的 PyTorch 模型直接上生產(chǎn)環(huán)境有兩個(gè)問(wèn)題依賴(lài)太重、推理速度不夠。標(biāo)準(zhǔn)做法是導(dǎo)出 ONNX用 ONNX Runtime 或 TensorRT 推理。導(dǎo)出時(shí)注意輸入尺寸固定動(dòng)態(tài)軸只在必要時(shí)開(kāi)。import torch import onnx import onnxruntime as ort import numpy as np # 導(dǎo)出 ONNX model.eval() dummy torch.randn(1, 3, 224, 224).to(device) torch.onnx.export( model, dummy, gesture_model.onnx, input_names[input], output_names[output], dynamic_axes{input: {0: batch}, output: {0: batch}}, opset_version11 ) # ONNX Runtime 推理 session ort.InferenceSession(gesture_model.onnx, providers[CPUExecutionProvider]) def predict(img_np): # img_np: (1, 3, 224, 224) float32 inputs {session.get_inputs()[0].name: img_np} logits session.run(None, inputs)[0] return int(np.argmax(logits, axis1)[0])opset_version11兼容性最好別盲目追高。dynamic_axes把 batch 維設(shè)為動(dòng)態(tài)方便你后面做批量推理。ONNX Runtime 在 CPU 上比原生 PyTorch 快 1.5 到 2 倍如果部署在 NVIDIA 顯卡上換 TensorRT Execution Provider 還能再快一倍。4.2 置信度閾值與拒識(shí)機(jī)制實(shí)際產(chǎn)品里用戶(hù)不會(huì)只比劃你訓(xùn)練過(guò)的那 24 個(gè)手勢(shì)。遇到未知手勢(shì)時(shí)模型會(huì)強(qiáng)行分到某個(gè)類(lèi)置信度可能還不低。必須加拒識(shí)邏輯softmax 最大概率低于閾值就輸出「未知」。閾值取多少我一般從 0.7 開(kāi)始試在驗(yàn)證集上畫(huà)置信度分布圖看已知類(lèi)別的置信度下沿在哪里。如果已知類(lèi)別的最低置信度是 0.65那閾值設(shè) 0.6 比較安全。另外可以加一個(gè)熵判據(jù)預(yù)測(cè)分布的熵高于某個(gè)值時(shí)也拒識(shí)這對(duì)模型「猶豫不決」的情況更敏感。import numpy as np def predict_with_reject(img_np, session, threshold0.6, entropy_thresh1.5): inputs {session.get_inputs()[0].name: img_np} logits session.run(None, inputs)[0][0] probs np.exp(logits) / np.sum(np.exp(logits)) max_prob np.max(probs) entropy -np.sum(probs * np.log(probs 1e-8)) if max_prob threshold or entropy entropy_thresh: return unknown, max_prob return int(np.argmax(probs)), max_prob熵閾值 1.5 對(duì)應(yīng)大約 4 到 5 個(gè)類(lèi)別概率接近的情況24 類(lèi)均勻分布的熵是 ln(24)≈3.18所以 1.5 已經(jīng)能過(guò)濾掉大部分模糊樣本。這兩個(gè)參數(shù)需要在你的驗(yàn)證集上重新標(biāo)定不要直接抄。5. 避坑與排查靜態(tài)手勢(shì)識(shí)別現(xiàn)場(chǎng)翻車(chē)的五個(gè)真實(shí)記錄5.1 現(xiàn)象實(shí)驗(yàn)室 98%現(xiàn)場(chǎng) 60% 出頭原因訓(xùn)練集背景太干凈模型學(xué)到了背景紋理而不是手部形狀。ASL 數(shù)據(jù)集背景是純色墻面現(xiàn)場(chǎng)是金屬臺(tái)面加雜亂線(xiàn)纜。解決在訓(xùn)練集里混入現(xiàn)場(chǎng)背景的負(fù)樣本或者用 RandAugment 加大背景擾動(dòng)的強(qiáng)度。更徹底的做法是先做手部檢測(cè)裁剪再送分類(lèi)網(wǎng)絡(luò)把背景徹底去掉。5.2 現(xiàn)象換個(gè)人測(cè)試精度掉 20 個(gè)點(diǎn)原因訓(xùn)練集膚色和手型單一模型過(guò)擬合到特定用戶(hù)的特征。解決自采數(shù)據(jù)必須覆蓋至少 10 個(gè)不同膚色、性別、年齡段的人。如果做不到用 Style Transfer 做膚色增廣或者把 RGB 轉(zhuǎn)成 YCbCr 只取 Y 通道做形狀特征。5.3 現(xiàn)象推理延遲忽高忽低偶爾卡頓原因Python GIL 加 ONNX Runtime 默認(rèn)線(xiàn)程數(shù)沒(méi)設(shè)對(duì)和主線(xiàn)程搶資源。解決設(shè)置sess_options.intra_op_num_threads 2和inter_op_num_threads 1把推理線(xiàn)程數(shù)壓下來(lái)。如果還不行把推理放到獨(dú)立進(jìn)程用隊(duì)列通信。5.4 現(xiàn)象某些手勢(shì)類(lèi)別始終分不開(kāi)原因類(lèi)間相似度高比如「OK」和「數(shù)字 3」在某些角度下幾乎一樣。解決檢查這兩類(lèi)的訓(xùn)練樣本是否有標(biāo)注錯(cuò)誤。如果標(biāo)注沒(méi)問(wèn)題加一個(gè)細(xì)粒度分類(lèi)頭或者在損失函數(shù)里給這兩類(lèi)加類(lèi)別權(quán)重。最直接的辦法是增加這兩類(lèi)的困難樣本讓模型看到足夠多的區(qū)分性角度。5.5 現(xiàn)象模型文件導(dǎo)出 ONNX 后精度不一致原因PyTorch 的model.eval()沒(méi)調(diào)BatchNorm 還在用 batch 統(tǒng)計(jì)量或者導(dǎo)出時(shí)輸入尺寸和推理時(shí)不一致。解決導(dǎo)出前務(wù)必model.eval()并torch.no_grad()。導(dǎo)出后拿同一張圖分別跑 PyTorch 和 ONNX對(duì)比 logits 差異超過(guò) 1e-3 就要查。6. 把靜態(tài)手勢(shì)識(shí)別推到 97% 以上的三個(gè)進(jìn)階技巧第一個(gè)技巧是知識(shí)蒸餾。用 ResNet50 當(dāng)教師模型MobileNetV3-Small 當(dāng)學(xué)生在自采數(shù)據(jù)上做蒸餾訓(xùn)練。教師模型在困難樣本上的軟標(biāo)簽?zāi)芙虒W(xué)生模型學(xué)到類(lèi)間邊界。我實(shí)測(cè)過(guò)蒸餾后 MobileNetV3-Small 的驗(yàn)證精度從 94.2% 提到 96.5%推理延遲不變。損失函數(shù)用 KL 散度加交叉熵的加權(quán)和溫度系數(shù) T4權(quán)重 0.7 給學(xué)生損失。第二個(gè)技巧是測(cè)試時(shí)增強(qiáng)TTA。推理時(shí)對(duì)同一張圖做 5 次不同變換原圖、水平翻轉(zhuǎn)、兩個(gè)角度的旋轉(zhuǎn)、中心裁剪取平均 logits。精度能漲 0.5 到 1 個(gè)點(diǎn)代價(jià)是推理時(shí)間乘以 5。如果延遲允許這是最省事的漲點(diǎn)方法。第三個(gè)技巧是類(lèi)別平衡采樣。靜態(tài)手勢(shì)數(shù)據(jù)集里容易采集的類(lèi)別比如「拳頭」「手掌」樣本量往往是難采集類(lèi)別比如「數(shù)字 9」的 3 到 5 倍。用 WeightedRandomSampler 按類(lèi)別頻率倒數(shù)加權(quán)讓每個(gè) batch 里各類(lèi)別大致均衡。這個(gè)改動(dòng)通常能漲 1 到 2 個(gè)點(diǎn)尤其是對(duì)尾部類(lèi)別。from torch.utils.data import WeightedRandomSampler import numpy as np # 假設(shè) train_dataset 有 .targets 屬性 targets np.array(train_dataset.targets) class_counts np.bincount(targets) class_weights 1.0 / class_counts sample_weights class_weights[targets] sampler WeightedRandomSampler( weightssample_weights, num_sampleslen(sample_weights), replacementTrue ) train_loader torch.utils.data.DataLoader( train_dataset, batch_size64, samplersampler, num_workers4 )這三個(gè)技巧疊加使用在 24 類(lèi)靜態(tài)手勢(shì)上做到 97% 以上驗(yàn)證精度是可行的。但記住驗(yàn)證精度只是參考現(xiàn)場(chǎng) A/B 測(cè)試才是最終標(biāo)準(zhǔn)。我一般會(huì)在產(chǎn)線(xiàn)上跑一周記錄誤識(shí)別率再?zèng)Q定要不要繼續(xù)調(diào)。最后一個(gè)習(xí)慣每次訓(xùn)練完把配置文件、隨機(jī)種子、驗(yàn)證集精度和混淆矩陣存到一個(gè)帶時(shí)間戳的文件夾里。沒(méi)有后悔藥但至少有黑匣子。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取