習(xí)全鏈路實踐:從數(shù)據(jù)上傳到在線推理部署指南)
我花了大概兩周時間把華為云ModelArts的完整鏈路跑了一遍從上傳數(shù)據(jù)集、跑訓(xùn)練作業(yè)到把模型注冊上線最后部署成一個能接收圖片請求的在線推理服務(wù)。這篇學(xué)習(xí)筆記把中間踩過的坑和關(guān)鍵路徑都記了下來目標是讓后來的人少走彎路也當(dāng)給自己留一份復(fù)現(xiàn)手冊。在真正動手之前我一直有個疑問訓(xùn)練代碼不是本地也能跑嗎為什么還要上云把整個流程走完我的答案是——如果模型一次訓(xùn)練要幾個小時中途還伴隨著環(huán)境依賴、數(shù)據(jù)管理和部署上線云端平臺帶來的收益就會非常明顯。ModelArts剛好是那種把訓(xùn)練、管理、部署揉成一站式平臺的產(chǎn)品很適合個人學(xué)習(xí)和中小團隊做實驗驗證。如果你也是剛接觸建議先別急著寫代碼把下面的準備步驟跟一遍后面會省掉很多“找不到文件”的煩惱。1. 先把思路理清楚為什么選擇云端訓(xùn)練ModelArts能省掉哪些事1.1 本地訓(xùn)練的真實困境我自己在本地跑過一段時間的模型訓(xùn)練最開始用的是普通筆記本電腦。數(shù)據(jù)集幾個G就足夠讓磁盤報警訓(xùn)練一個不算大的分類網(wǎng)絡(luò)CPU要跑幾個小時GPU根本談不上。后來好不容易找到一張舊的獨立顯卡又折騰驅(qū)動、CUDA版本、深度學(xué)習(xí)框架版本好不容易把環(huán)境裝好發(fā)現(xiàn)顯卡顯存只有4G稍微大一點的batch size直接OOM。這種體驗在個人開發(fā)者里太常見了。做模型訓(xùn)練的人很大一部分時間不是花在模型設(shè)計上而是花在環(huán)境配置、硬件升級這些和算法無關(guān)的事情上。云端平臺解決的正是這部分問題。ModelArts本身不取代你的算法設(shè)計能力它提供一個開箱即用的計算環(huán)境你提交訓(xùn)練代碼平臺負責(zé)拉鏡像、分配資源、跑任務(wù)、收集日志。對個人來說最大的變化是“訓(xùn)練”這件事從“折騰設(shè)備和環(huán)境”變成了“提交任務(wù)和看結(jié)果”。1.2 ModelArts在整條鏈路里的位置ModelArts并不是只有一個訓(xùn)練功能。它覆蓋了從數(shù)據(jù)準備到模型上線的四個環(huán)節(jié)數(shù)據(jù)層面可以創(chuàng)建數(shù)據(jù)集、做標注、直接管理OBS對象存儲里的訓(xùn)練數(shù)據(jù)開發(fā)層面提供代碼開發(fā)環(huán)境也支持使用預(yù)置算法直接訓(xùn)練訓(xùn)練層面可以提交訓(xùn)練作業(yè)支持PyTorch、TensorFlow、MindSpore等主流框架部署層面模型注冊之后可以發(fā)布成在線服務(wù)、批量任務(wù)或者邊緣推理。我這次重點跑的是其中一條路線自定義訓(xùn)練腳本 → 訓(xùn)練作業(yè) → 模型注冊 → 在線部署。這四個環(huán)節(jié)也是絕大多數(shù)深度學(xué)習(xí)應(yīng)用落地的核心路徑。1.3 使用云平臺前需要接受的三件事第一數(shù)據(jù)不能假設(shè)在本地磁盤旁。訓(xùn)練代碼在云端執(zhí)行數(shù)據(jù)源一般放在對象存儲OBS里代碼需要先把它拉取到本地的臨時目錄或者邊讀邊流式加載。這和平時“直接指向本地路徑”的思路不一樣。第二任務(wù)不是交互式的。訓(xùn)練作業(yè)提交后基本是黑盒執(zhí)行你通過日志觀察進度。如果腳本里寫死了本地交互輸入訓(xùn)練一定會卡住或者失敗。第三計費與資源池綁定。不用的時候要把服務(wù)刪除、作業(yè)停止否則會一直產(chǎn)生費用。這不是說平臺貴而是說你要換一種使用習(xí)慣按需開、用完關(guān)。接受這三點之后整個ModelArts的操作邏輯就順了。2. 環(huán)境準備清單賬號、OBS桶、委托權(quán)限一個都不能少2.1 賬號開通與區(qū)域選擇使用ModelArts的第一步是開通服務(wù)。整個過程不復(fù)雜但有幾點值得注意賬戶要完成實名認證否則部分資源完全拿不到初次使用會要求選擇區(qū)域數(shù)據(jù)存儲在哪個區(qū)域的OBS訓(xùn)練作業(yè)當(dāng)前也建議用同一區(qū)域跨區(qū)域訪問會帶來額外延遲和流量費用如果只是學(xué)習(xí)選擇距離自己較近且資源充足的區(qū)域即可后面可以在設(shè)置里調(diào)整。區(qū)域這個問題我第一次沒當(dāng)回事選了離自己最近的區(qū)域結(jié)果訓(xùn)練作業(yè)依賴的某個公共鏡像在那個區(qū)域沒有同步只能換區(qū)重來。后來我學(xué)聰明了先查一下想用的算法框架或者鏡像在哪個區(qū)域可用再決定最終落點。2.2 創(chuàng)建OBS桶與目錄規(guī)劃OBS桶可以理解成一個云端的大硬盤對象存儲不需要關(guān)心文件系統(tǒng)的掛載和分區(qū)上傳之后就有一個全局唯一的訪問路徑。我創(chuàng)建桶時的要點桶名全局唯一建議用項目名加后綴比如xxx-modelarts-demo存儲類別選“標準存儲”就夠訓(xùn)練場景用不到低頻存儲桶策略保持“私有讀寫”默認設(shè)置訓(xùn)練作業(yè)通過委托方式訪問不要圖省事設(shè)成公開讀。目錄結(jié)構(gòu)建議提前規(guī)劃好。我用的結(jié)構(gòu)比較簡單my-modelarts-demo/ ├── data/ │ ├── train/ │ └── valid/ ├── output/ └── code/data放原始訓(xùn)練數(shù)據(jù)output放訓(xùn)練輸出code放訓(xùn)練腳本壓縮包。這樣訓(xùn)練作業(yè)的輸入路徑、輸出路徑、代碼路徑一目了然。2.3 數(shù)據(jù)上傳的三種方法上傳數(shù)據(jù)很容易被忽略但真正做起來坑也不少。我試過三種方式第一種控制臺直接上傳。適合小文件幾十個文件以內(nèi)沒問題。超過幾百個文件的目錄控制臺上傳體驗就非常差了。第二種obsutil命令行工具。這是我最常用的方式支持批量上傳、斷點續(xù)傳、并發(fā)控制。命令大致長這樣./obsutil cp ./data/ s3://my-modelarts-demo/data/ -r -f-r表示遞歸-f表示強制覆蓋。大文件傳一半斷了重新執(zhí)行一遍obsutil會跳過已經(jīng)傳完的部分這對多文件數(shù)據(jù)集來說非常實用。第三種通過SDK寫腳本上傳。適合定期更新數(shù)據(jù)的場景比如每周自動把新的訓(xùn)練數(shù)據(jù)同步上去。個人學(xué)習(xí)階段用不太到但值得知道有這條路。2.4 委托權(quán)限最容易忽略的隱藏卡點我把OBS桶和數(shù)據(jù)都準備好之后第一次提交訓(xùn)練作業(yè)就報錯了錯誤信息大概是“訪問OBS被拒絕”。查了半天問題出在賬號沒有給ModelArts授權(quán)訪問OBS。這是很典型的新手問題。ModelArts執(zhí)行訓(xùn)練作業(yè)時需要臨時以某個身份訪問你的OBS桶這個身份就是委托。你需要在管理控制臺的權(quán)限配置里創(chuàng)建一個委托并授權(quán)給ModelArts。創(chuàng)建委托時選“自動獲取”即可平臺會自動關(guān)聯(lián)OBS相關(guān)權(quán)限。這個配置只需要做一次后面所有訓(xùn)練作業(yè)都會使用這個身份去讀寫數(shù)據(jù)。提示如果換了新賬號、新區(qū)域或者換了項目務(wù)必重新檢查委托是否已配置。很多報錯的第一排查項不是代碼而是權(quán)限。3. 訓(xùn)練任務(wù)實操從零寫一個可跑通的PyTorch腳本3.1 從自動學(xué)習(xí)開始還是直接寫自定義腳本ModelArts提供了好幾條訓(xùn)練路線不同熟練度的人選擇不一樣。自動學(xué)習(xí)是最低門檻的入口不需要寫代碼只需要上傳若干張圖片平臺會自動完成訓(xùn)練和部署。它的本質(zhì)是遷移學(xué)習(xí)加自動調(diào)參對小規(guī)模分類任務(wù)很有效。我最初用一組不足兩百張的圖片試過準確率已經(jīng)能到9成以上非常適合驗證業(yè)務(wù)想法。但自動學(xué)習(xí)適合快速驗證不適合深度定制模型結(jié)構(gòu)、損失函數(shù)和評估指標。如果后續(xù)要調(diào)網(wǎng)絡(luò)結(jié)構(gòu)、加數(shù)據(jù)增強、設(shè)計復(fù)雜的訓(xùn)練邏輯還得走自定義訓(xùn)練腳本這條路。這次學(xué)習(xí)筆記里我重點記錄自定義訓(xùn)練腳本的過程因為這條路線的可控性最強理解之后也能遷移到其他云平臺。3.2 訓(xùn)練腳本與云端路徑的交互方式在ModelArts上寫訓(xùn)練腳本最核心的一點是理解輸入輸出參數(shù)。訓(xùn)練作業(yè)提交時可以給腳本傳入一系列參數(shù)。最常用的兩個是--data_url訓(xùn)練數(shù)據(jù)的OBS路徑--train_url訓(xùn)練輸出的OBS路徑。訓(xùn)練作業(yè)啟動后代碼所在的目錄是預(yù)置工作目錄數(shù)據(jù)并不在這個目錄里它還在OBS上。如果腳本直接找相對路徑文件必掛無疑。正確做法是先把OBS上的數(shù)據(jù)拷貝到本地緩存目錄訓(xùn)練完成后再把模型文件拷貝回OBS輸出路徑。因為對象存儲上的IO性能遠低于本地盤拷貝到本地再訓(xùn)練速度會明顯更快。這段代碼是我使用的下載和訓(xùn)練骨架的一部分import argparse import os import torch import torchvision import torch.nn as nn import moxing as mox def parse_args(): parser argparse.ArgumentParser() parser.add_argument(--data_url, typestr, requiredTrue) parser.add_argument(--train_url, typestr, requiredTrue) parser.add_argument(--epochs, typeint, default5) parser.add_argument(--batch_size, typeint, default32) return parser.parse_args() def main(): args parse_args() local_data_path /cache/data os.makedirs(local_data_path, exist_okTrue) # OBS數(shù)據(jù)拷貝到本地緩存 mox.file.copy_parallel(args.data_url, local_data_path) dataset torchvision.datasets.ImageFolder( rootlocal_data_path, transformtorchvision.transforms.Compose([ torchvision.transforms.Resize((224, 224)), torchvision.transforms.ToTensor() ]) ) loader torch.utils.data.DataLoader( dataset, batch_sizeargs.batch_size, shuffleTrue ) model torchvision.models.resnet18(pretrainedTrue) model.fc nn.Linear(model.fc.in_features, 2) criterion nn.CrossEntropyLoss() optimizer torch.optim.SGD(model.parameters(), lr0.001, momentum0.9) # 訓(xùn)練循環(huán)略去 local_output_path /cache/output os.makedirs(local_output_path, exist_okTrue) torch.save(model.state_dict(), os.path.join(local_output_path, model.pth)) # 模型拷貝回OBS mox.file.copy_parallel(local_output_path, args.train_url) if __name__ __main__: main()這段代碼里moxing是平臺內(nèi)置的OBS訪問庫在ModelArts的訓(xùn)練環(huán)境里可以直接使用。它的copy_parallel方法可以把整個目錄遞歸拷貝非常方便。3.3 本地使用OBS路徑時的三個常見坑第一路徑協(xié)議別寫錯。有些文檔用s3://有些用obs://模型服務(wù)配置界面里常顯示s3://桶名/路徑。本質(zhì)上它們指向同一個對象存儲但腳本內(nèi)路徑必須和運行時環(huán)境支持的方式匹配。我的經(jīng)驗是在訓(xùn)練作業(yè)中盡量用s3://桶名/路徑這種格式因為在ModelArts內(nèi)部它兼容性更好。第二路徑末尾的斜杠也會影響行為。copy_parallel把s3://bucket/data當(dāng)作目錄拷貝和s3://bucket/data/在某些版本里可能表現(xiàn)不同。要么都帶要么都不帶保持統(tǒng)一。第三目錄不要寫進相對路徑。很多代碼寫習(xí)慣了默認把輸出模型放在當(dāng)前目錄。訓(xùn)練作業(yè)結(jié)束前平臺會保留當(dāng)前環(huán)境的臨時文件但不會幫你把任意路徑的文件同步到OBS。只要模型沒有上傳到train_url指定路徑后面注冊模型時就找不到任何內(nèi)容。3.4 創(chuàng)建訓(xùn)練作業(yè)時的配置項解讀腳本準備好之后在ModelArts控制臺創(chuàng)建訓(xùn)練作業(yè)。關(guān)鍵配置項有這些算法來源選擇“自定義”方式上傳剛才準備好的腳本和對應(yīng)的框架環(huán)境。也可以選擇預(yù)置算法鏡像省去配置依賴的麻煩代碼目錄填寫代碼在OBS上的目錄啟動文件填寫要執(zhí)行的Python腳本文件名數(shù)據(jù)來源選擇“OBS”填入訓(xùn)練數(shù)據(jù)路徑訓(xùn)練輸出選擇“OBS”填入輸出路徑資源池測試階段可以用CPU正式訓(xùn)練用GPU。經(jīng)驗是先用一小批數(shù)據(jù)在CPU上把代碼跑通再換GPU跑全量避免一個明顯的代碼錯誤燒掉大把時間超參數(shù)可以直接在控制臺填入--epochs、--batch_size也可以寫進腳本默認值。創(chuàng)建時還有一個“重啟策略”建議選“從不”。訓(xùn)練失敗時不會自動重跑方便你自己看到原始報錯。調(diào)通之后再改成“總是”可以節(jié)省人工盯任務(wù)的時間。訓(xùn)練作業(yè)一旦創(chuàng)建就會進入排隊、啟動、運行的狀態(tài)此時可以在詳情頁看到實時日志。如果日志遲遲沒有輸出先看看是不是排隊等待資源。如果顯示“啟動失敗”多半是鏡像拉取或者腳本路徑配置錯誤日志信息會把根本原因點出來。4. 訓(xùn)練過程監(jiān)控與模型注冊日志、曲線和版本管理4.1 實時日志的正確看法訓(xùn)練作業(yè)啟動后最關(guān)心的就是日志。ModelArts控制臺提供日志預(yù)覽和下載兩種方式。預(yù)覽適合看少量輸出下載則適合拿日志做二次分析。日志的輸出位置來自兩個方向一是訓(xùn)練腳本本身的標準輸出也就是print語句的內(nèi)容二是框架、系統(tǒng)在運行時產(chǎn)生的輸出。腳本里print的信息都會在日志里出現(xiàn)所以建議在關(guān)鍵節(jié)點多打印每個epoch結(jié)束后的loss和accuracy每完成一定步數(shù)后的當(dāng)前進度模型保存時打印保存路徑。我踩過的坑是腳本跑了一小時日志一直沒有更新我以為是卡住了。后來發(fā)現(xiàn)是打印內(nèi)容太多日志頁面刷新滯后刷新了幾次之后內(nèi)容一次性全部出現(xiàn)了。如果訓(xùn)練卡住更可靠的判斷指標是CPU/GPU利用率資源池監(jiān)控面板里利用率長時間為0才是真正出問題。4.2 訓(xùn)練指標曲線的生成邏輯ModelArts在訓(xùn)練作業(yè)詳情頁會展示算法指標曲線比如損失曲線、準確率曲線。但這些曲線不是平臺自發(fā)生成的它需要訓(xùn)練腳本在輸出日志時使用特定的格式平臺才能解析。不同版本的控制臺識別方式不完全一樣。如果你的腳本只是普通print(loss0.123),頁面通常不會生成曲線。這時候不要以為平臺壞了更直接的辦法是自己在腳本里把指標寫入一個日志文件訓(xùn)練結(jié)束后從輸出目錄拿回來再畫圖。我自己更常做的做法是每個epoch結(jié)束后把epoch、loss、acc打印成一行訓(xùn)練結(jié)束之后用腳本把打印出來的數(shù)據(jù)抄下來本地快速畫圖。雖然麻煩一點但完全不依賴平臺解析。4.3 訓(xùn)練輸出與模型文件命名訓(xùn)練結(jié)束后輸出目錄里就是所有拷貝回OBS的文件。這里有一個特別需要注意的點模型文件的命名最好固定、且容易識別。ModelArts在模型注冊時經(jīng)常需要你指定模型文件名。如果腳本保存的是best_model.pth注冊時把文件名填對就行。但如果一個訓(xùn)練作業(yè)里同時保存了多個文件比如checkpoint_1.pth、checkpoint_2.pth注冊時就要特別小心別選錯版本。我習(xí)慣把最終用于部署的模型固定命名為model.pth中間檢查點單獨放在一個子目錄。這樣可以減少后續(xù)操作中的歧義。4.4 模型注冊與版本管理模型注冊簡單理解就是把訓(xùn)練產(chǎn)物以及配套的推理配置打包成一個“可用的模型”。它是訓(xùn)練環(huán)節(jié)和部署環(huán)節(jié)之間的橋梁。在ModelArts控制臺進入“模型管理”創(chuàng)建模型時可以選擇“從訓(xùn)練作業(yè)導(dǎo)入”選中剛才的訓(xùn)練作業(yè)平臺會自動讀取輸出目錄里的模型文件也可以選擇“從模板導(dǎo)入”按固定目錄結(jié)構(gòu)把模型文件和推理代碼傳到一個OBS路徑。比較關(guān)鍵的是“模型版本”這個概念。同一個模型名稱下可以管理多個版本每次重新訓(xùn)練生成新版本。比如model.pth基于V1數(shù)據(jù)訓(xùn)練后來又基于擴充后的V2數(shù)據(jù)訓(xùn)練兩個版本都會保留。部署時可以顯式指定版本號。這樣做的價值在于上線穩(wěn)定版本后后續(xù)新版本可以在測試環(huán)境中驗證驗證通過再切換流量不必每次改動都重構(gòu)整個部署。5. 部署在線推理服務(wù)配置、推理代碼與接口測試5.1 三種部署形態(tài)怎么選ModelArts部署過程支持三種方式在線服務(wù)是最常用的形態(tài)。模型部署后會提供一個固定API地址客戶端隨時發(fā)起請求適合實時推理場景比如在線識圖、實時風(fēng)控。批量服務(wù)則是一次性處理一批數(shù)據(jù)。數(shù)據(jù)準備好之后提交任務(wù)平臺跑完再把結(jié)果存到OBS適合離線批量計算比如周末把某個月存量圖片全部跑一遍。邊緣服務(wù)則是把模型下發(fā)到靠近數(shù)據(jù)源的設(shè)備端適合需要低延遲、弱網(wǎng)、離線場景。我這次用的是在線服務(wù)也是學(xué)習(xí)階段最直觀的方式。5.2 在線服務(wù)的關(guān)鍵配置創(chuàng)建在線服務(wù)時核心是這幾項選擇模型及版本通常直接選剛才注冊好的模型即可資源規(guī)格如果是用CPU推理選擇合適的內(nèi)存規(guī)格就行如果模型比較大、推理時延要求高可考慮GPU規(guī)格。個人試驗階段先用CPU規(guī)格把流程跑順再根據(jù)實際耗時決定要不要升級。實例數(shù)先從1開始。ModelArts支持自動擴縮容但自動擴縮容的對數(shù)策略對個人學(xué)習(xí)階段來說不是必需品。手動控制不但省錢還能讓你更清楚資源利用情況。環(huán)境變量有些模型需要環(huán)境變量控制推理行為比如編碼格式、超時時間。按需配置不需要就不填。5.3 推理腳本里要做的事部署在線服務(wù)時ModelArts會加載模型并執(zhí)行推理腳本。推理腳本不能只是“加載一下模型”它需要完成三個步驟預(yù)處理把網(wǎng)絡(luò)請求里的原始數(shù)據(jù)轉(zhuǎn)換成模型可接受的張量格式。最常見的圖片請求客戶端傳過來的可能是base64字符串你要先解碼成圖像再縮放、歸一化。推理調(diào)用模型forward或者predict方法得到原始輸出。后處理把Tensor輸出轉(zhuǎn)換成Python原生類型。這里是我踩得最慘的一個坑我直接返回了一個Tensor對象部署后調(diào)用服務(wù)報錯報錯信息無法序列化。處理方式很簡單用.item()或者int()把Tensor轉(zhuǎn)成數(shù)字再包裝成dict。推理腳本的長相大致是這樣import base64 import torch from PIL import Image from torchvision import transforms from model_service.model_service import ModelService class MyService(ModelService): def __init__(self, model_name, model_path): super().__init__(model_name, model_path) self.model torch.load(model_path, map_locationcpu) self.model.eval() self.transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), ]) def preprocess(self, data): image_base64 data.get(image_base64) if image_base64 is None: raise ValueError(缺少image_base64字段) image_bytes base64.b64decode(image_base64) image Image.open(image_bytes).convert(RGB) image self.transform(image).unsqueeze(0) return image def inference(self, data): with torch.no_grad(): outputs self.model(data) return torch.softmax(outputs, dim1) def postprocess(self, data): probabilities, indices torch.max(data, dim1) label_idx int(indices[0].item()) confidence float(probabilities[0].item()) return { label_idx: label_idx, confidence: confidence }這里特別要說明一點具體推理類的繼承方式不同版本會略有差別但整體思路是通用的。如果遇到平臺的模板和示例代碼優(yōu)先讀它自帶的模板確認類名和方法名。5.4 接口聯(lián)調(diào)與業(yè)務(wù)封裝服務(wù)部署完成后控制臺會分配一個API地址同時提供“調(diào)試”功能。最方便的做法是先在調(diào)試頁面上傳一張圖片看返回是否正常。如果調(diào)試正常再去外部調(diào)用接口。調(diào)用方式我建議用curl或者Postman先確認接口本身沒問題再寫業(yè)務(wù)代碼對接。一個簡單的curl示例如下curl -X POST https://your-api-endpoint/predict \ -H Content-Type: application/json \ -d {image_base64: 這里放圖片的base64編碼}有些服務(wù)會配置安全認證比如Bearer Token、AK/SK簽名。我在學(xué)習(xí)階段先把安全配置關(guān)閉用最簡單的接口調(diào)試通。正式部署時再開啟鑒權(quán)。返回結(jié)果應(yīng)該是一段JSON類似{ label_idx: 1, confidence: 0.91 }拿到這個結(jié)果后再做業(yè)務(wù)集成比如調(diào)用方根據(jù)label_idx展示不同的信息或者進一步分析置信度是否達到業(yè)務(wù)閾值。6. 排障現(xiàn)場高頻報錯與實際問題處理技巧6.1 我遇到的高頻報錯匯總這一部分直接整理成表格方便對應(yīng)查找。報錯關(guān)鍵詞實際原因排查方法NoSuchKeyOBS路徑下的文件不存在先確認上傳目錄結(jié)構(gòu)尤其注意大小寫和路徑前綴AccessDenied委托權(quán)限未配置或授權(quán)不足檢查委托是否已關(guān)聯(lián)ModelArts桶策略是否放行CUDA out of memoryGPU顯存不足降低batch size或換更大顯存的資源規(guī)格FileNotFoundError代碼里引用了本地不存在路徑確認已經(jīng)執(zhí)行數(shù)據(jù)拷貝到/cache不要假設(shè)數(shù)據(jù)就在當(dāng)前目錄model.pth not found訓(xùn)練輸出文件沒拷貝到OBS確認訓(xùn)練結(jié)束前調(diào)用了copy_parallel或類似上傳邏輯JSON序列化失敗推理返回值包含Tensor、ndarray在postprocess階段全部轉(zhuǎn)成Python原生類型服務(wù)一直顯示異常推理進程崩潰或端口未啟動查看服務(wù)日志確認模型加載成功與否確認推理腳本沒有語法錯誤其中“NoSuchKey”是我發(fā)生的最高頻的錯誤。原因幾乎都是數(shù)據(jù)上傳目錄和訓(xùn)練作業(yè)里填的路徑不完全一致比如多了個前導(dǎo)子目錄。最好辦法是用obsutil在本地執(zhí)行一次ls把桶里的實際路徑列出來和訓(xùn)練作業(yè)配置里填的路徑對一遍。6.2 資源與成本控制經(jīng)驗談大多數(shù)人剛開始用云平臺最容易忽視成本。我自己的幾條經(jīng)驗是訓(xùn)練作業(yè)一定要先小數(shù)據(jù)集調(diào)試。用幾十張圖片把整個流程跑通確認模型能正常訓(xùn)練和保存再換全量數(shù)據(jù)。一個完整的訓(xùn)練任務(wù)持續(xù)幾小時和幾分鐘費用完全不同。在線服務(wù)不調(diào)試時記得刪除。在線服務(wù)是持續(xù)計費的就算沒有請求也會占用資源。個人學(xué)習(xí)階段我在調(diào)試完成后直接刪除服務(wù)需要演示時再重新創(chuàng)建。這個操作很快不必一直保留。合理使用“自動停止”功能。訓(xùn)練作業(yè)和Notebook都支持配置自動停止時間。一旦訓(xùn)練意外卡住至少不會白白扣費。不需要的時候把作業(yè)或服務(wù)實例停掉。6.3 把學(xué)習(xí)筆記轉(zhuǎn)化為可復(fù)用的模版整個流程跑通之后我做的最后一件事是把腳本、命令、目錄結(jié)構(gòu)整理成一個模板存到了自己的代碼倉庫里。下一次遇到新任務(wù)只需要復(fù)制模板改一下數(shù)據(jù)集和模型定義就能快速跑通。這個習(xí)慣對我來說價值很大。因為云端任務(wù)流程非常標準化模板化之后換任務(wù)只是在填充幾個變量不需要從零思考數(shù)據(jù)怎么上傳、路徑怎么填、模型怎么注冊。如果你也是剛?cè)腴T我建議你也做一件類似的事把這份筆記里的目錄結(jié)構(gòu)、訓(xùn)練腳本骨架、推理腳本骨架存下來作為自己的“ModelArts起手式”。6.4 一些最后的排障心得云端訓(xùn)練的報錯和本地最大的不同在于你無法直接看到機器上的完整狀態(tài)。所以排查時不要靠猜一定要先打開日志把第一處異??疵靼?。很多問題都是前面的一個小錯誤引發(fā)后面連鎖報錯比如路徑前綴寫錯導(dǎo)致數(shù)據(jù)沒加載然后dataloader報空數(shù)據(jù)集最后一臉茫然。如果遇到實在查不出的問題有一個很笨但有效的方法寫一個最小測試腳本先不訓(xùn)練只打印“讀取數(shù)據(jù)成功”和“當(dāng)前環(huán)境溫度、目錄結(jié)構(gòu)”提交一遍訓(xùn)練作業(yè)。如果最小腳本能跑通說明環(huán)境沒問題再把完整腳本放上去對比差異。這個方法看起來浪費時間實際能省很多時間。因為環(huán)境、路徑、權(quán)限的問題最小腳本一分鐘就能暴露而不完整的模型訓(xùn)練腳本可能要跑十分鐘才報錯。我個人在實際使用中還有一個體會云平臺的功能很多但自己真正需要的只是其中一條主鏈路。剛開始不要被控制臺里五花八門的菜單帶偏方向?qū)W臄?shù)據(jù)到部署的一條路走通把這里面的原理搞清楚其他功能可以邊用邊學(xué)。做完一次完整的模型訓(xùn)練與部署后再回頭讀ModelArts的文檔你會發(fā)現(xiàn)自己能看懂的東西一下多了很多。那些之前覺得陌生的概念比如委托、資源池、模型注冊全都對應(yīng)到了自己做過的某一步操作。這個“從操作反推概念”的過程是學(xué)習(xí)云計算平臺最省力的方式。