練到穩(wěn)定上線的完整路徑)
去年年初我的主要工作還是“訓(xùn)練模型”——調(diào)參、刷指標(biāo)、在Jupyter Notebook里反復(fù)驗(yàn)證想法。直到有幾個(gè)項(xiàng)目陸續(xù)在“上線”這個(gè)環(huán)節(jié)卡住甚至直接爛尾我才意識(shí)到自己一直是半個(gè)AI工程師真正缺的是從模型到系統(tǒng)的那一公里。后來(lái)我花了大半年時(shí)間把一套AI服務(wù)從零搭到穩(wěn)定運(yùn)行把數(shù)據(jù)、訓(xùn)練、部署、監(jiān)控全部串起來(lái)踩了無(wú)數(shù)個(gè)坑之后算是摸清了“ai-engineering from scratch”這條路該怎么走。這篇文章不聊花哨的算法只講從零開(kāi)始工程化落地時(shí)真實(shí)會(huì)遇到的問(wèn)題和我最終采用的解法希望讓正準(zhǔn)備轉(zhuǎn)向AI工程方向或者第一次負(fù)責(zé)整個(gè)AI服務(wù)的人少走點(diǎn)彎路。1. 從調(diào)參俠到AI工程師這個(gè)轉(zhuǎn)變卡在了哪里1.1 模型訓(xùn)練只是AI工程的一個(gè)環(huán)節(jié)很多人剛開(kāi)始接觸AI項(xiàng)目時(shí)容易把“AI工程”等同于“訓(xùn)練一個(gè)高精度模型”。我過(guò)去就是這樣。模型在離線測(cè)試集上跑出不錯(cuò)的準(zhǔn)確率就以為任務(wù)完成了。但實(shí)際上模型訓(xùn)練在整個(gè)AI工程鏈條里占的比例遠(yuǎn)沒(méi)有想象中那么大。數(shù)據(jù)獲取與清洗、特征工程、實(shí)驗(yàn)管理、模型部署、服務(wù)編排、監(jiān)控反饋、持續(xù)迭代這些環(huán)節(jié)加起來(lái)的工作量和復(fù)雜度通常比訓(xùn)練本身多出好幾倍。我經(jīng)歷的一個(gè)真實(shí)案例非常典型團(tuán)隊(duì)花了三周時(shí)間把模型精度從85%調(diào)到了92%但上線時(shí)發(fā)現(xiàn)接口響應(yīng)需要600毫秒業(yè)務(wù)方接受不了。于是我們開(kāi)始折騰推理優(yōu)化——嘗試量化、裁剪、改用更輕量的模型結(jié)構(gòu)最后才把延遲壓到120毫秒以下。整個(gè)過(guò)程又花了快兩周而且期間還因?yàn)镃PU和GPU的推理結(jié)果存在微小差異排查了半天。如果一開(kāi)始就把“端到端響應(yīng)延遲”納入工程目標(biāo)而不是只盯著準(zhǔn)確率這些時(shí)間完全可以壓縮一半。這里就引出一個(gè)關(guān)鍵認(rèn)知AI工程的目標(biāo)不是“做出最聰明的模型”而是“讓模型在真實(shí)環(huán)境中穩(wěn)定、高效、可維護(hù)地創(chuàng)造價(jià)值”。從零搭建一個(gè)AI項(xiàng)目最先要考慮的不是選多先進(jìn)的網(wǎng)絡(luò)結(jié)構(gòu)而是你要解決什么業(yè)務(wù)問(wèn)題數(shù)據(jù)能不能支撐以及模型上線后如何衡量它是否真的有效。1.2 我親眼見(jiàn)過(guò)多少項(xiàng)目死在工程化這一關(guān)我知道的不少AI項(xiàng)目在Paper或Demo階段很漂亮一到生產(chǎn)環(huán)境就露餡。最常見(jiàn)的死法有這么幾種離線評(píng)估和線上效果差異太大模型看似很好實(shí)際業(yè)務(wù)指標(biāo)沒(méi)有變化。模型迭代沒(méi)有記錄版本混亂出問(wèn)題后根本不知道線上跑的是哪個(gè)模型、用的哪份數(shù)據(jù)。服務(wù)接口只能單機(jī)跑沒(méi)有負(fù)載均衡、沒(méi)有容錯(cuò)一個(gè)推理進(jìn)程崩潰整套服務(wù)就掛了。訓(xùn)練數(shù)據(jù)和線上數(shù)據(jù)的分布悄悄發(fā)生偏移但沒(méi)有任何監(jiān)控提示模型性能逐漸劣化卻沒(méi)人發(fā)現(xiàn)。我自己就經(jīng)歷過(guò)線上模型效果突然變差查了兩天才發(fā)現(xiàn)是上游特征日志格式改版導(dǎo)致特征拼接產(chǎn)生了大量空值。如果沒(méi)有一套數(shù)據(jù)質(zhì)量監(jiān)控和特征校驗(yàn)機(jī)制這種問(wèn)題會(huì)反復(fù)出現(xiàn)。所以做AI工程與其說(shuō)是挑戰(zhàn)算法深度不如說(shuō)是挑戰(zhàn)系統(tǒng)化思維——你要把模型當(dāng)作一個(gè)常年運(yùn)行的軟件組件來(lái)看待而不是一次性的成果。2. 從零搭建的第一套技術(shù)棧選型邏輯與替代方案2.1 數(shù)據(jù)管線的選擇腳本、編排器還是特征平臺(tái)剛開(kāi)始做項(xiàng)目時(shí)數(shù)據(jù)預(yù)處理經(jīng)??繋讉€(gè)Python腳本串起來(lái)每天手動(dòng)跑一次。數(shù)據(jù)量不大、字段穩(wěn)定的時(shí)候沒(méi)問(wèn)題但只要上游數(shù)據(jù)結(jié)構(gòu)一變、或者需要按天/按小時(shí)定時(shí)生成訓(xùn)練集這套腳本很快就變成“僵尸代碼”——沒(méi)人敢改跑掛了也沒(méi)法快速定位。后來(lái)我引入了Airflow來(lái)做數(shù)據(jù)任務(wù)編排。當(dāng)時(shí)考慮過(guò)其他方案比如Prefect、Dagster但團(tuán)隊(duì)對(duì)Airflow更熟悉文檔也多就先用它。其實(shí)選什么不是關(guān)鍵關(guān)鍵是你要有一個(gè)能被調(diào)度、能重試、能記錄日志的數(shù)據(jù)管線框架。Airflow里每個(gè)任務(wù)節(jié)點(diǎn)盡量做到冪等——同一份輸入重復(fù)執(zhí)行得到相同結(jié)果這樣就不會(huì)因?yàn)槟炒问≈嘏芏a(chǎn)生重復(fù)數(shù)據(jù)。另一個(gè)容易被忽略的點(diǎn)是特征管理。一開(kāi)始我只是把特征工程代碼放在訓(xùn)練腳本里后來(lái)訓(xùn)練和推理都需要用到同一套特征邏輯開(kāi)始出現(xiàn)“訓(xùn)練代碼里特征邏輯一份在線服務(wù)里又復(fù)制一份”的窘境。特征定義一旦不統(tǒng)一訓(xùn)練和服務(wù)的效果就會(huì)出現(xiàn)系統(tǒng)性偏差。當(dāng)時(shí)我考慮特征平臺(tái)比如Feast但后來(lái)評(píng)估后覺(jué)得項(xiàng)目規(guī)模還沒(méi)到那個(gè)程度最終采用的方式是把所有特征工程邏輯抽成一個(gè)獨(dú)立的Python包訓(xùn)練和推理共用同一份代碼用同一個(gè)版本號(hào)構(gòu)建。這樣做成本低效果立竿見(jiàn)影。table:需求場(chǎng)景推薦工具注意點(diǎn)定時(shí)批量數(shù)據(jù)處理Airflow / Prefect任務(wù)必須冪等日志留存特征邏輯統(tǒng)一獨(dú)立特征代碼包訓(xùn)練與推理必須共用同一份實(shí)現(xiàn)超大數(shù)據(jù)量處理Spark / Ray先評(píng)估數(shù)據(jù)量別過(guò)早引入分布式實(shí)時(shí)特征需求Flink / Redis考慮延遲與一致性盡量后置2.2 實(shí)驗(yàn)跟蹤與模型注冊(cè)為什么必須做但總是被拖到最后一刻如果只做過(guò)兩三個(gè)模型實(shí)驗(yàn)靠腦子記確實(shí)夠用。但模型到了二十個(gè)以上參數(shù)、驗(yàn)證集指標(biāo)、數(shù)據(jù)集版本混在一起光靠文件名命名就會(huì)徹底失控。我記得有一段時(shí)間自己特別自信覺(jué)得每個(gè)實(shí)驗(yàn)都寫(xiě)了備忘結(jié)果一周后再看自己都分不清“model_v3_final”和“model_v3_final2”到底差在哪。后來(lái)我老老實(shí)實(shí)接入了MLflow。用它管理實(shí)驗(yàn)記錄、自動(dòng)記錄參數(shù)和指標(biāo)并把每次實(shí)驗(yàn)對(duì)應(yīng)的代碼版本、數(shù)據(jù)版本一并存下來(lái)。MLflow還有一個(gè)Model Registry功能可以把模型標(biāo)記為Staging或Production配合部署流程使用。說(shuō)實(shí)話這一套體系并不復(fù)雜難的是讓大家養(yǎng)成“每次訓(xùn)練都記錄完整實(shí)驗(yàn)信息”的習(xí)慣。我們當(dāng)時(shí)的做法是寫(xiě)了一個(gè)統(tǒng)一的訓(xùn)練腳本入口所有參數(shù)都通過(guò)配置文件傳入訓(xùn)練結(jié)束后自動(dòng)寫(xiě)入MLflow避免人工記錄造成的遺漏。從零開(kāi)始的項(xiàng)目我建議盡早引入實(shí)驗(yàn)跟蹤哪怕團(tuán)隊(duì)只有一個(gè)人。因?yàn)橐坏╉?xiàng)目進(jìn)入迭代期任何一次“我隨手改了一下”的記錄缺失都可能在后面變成幾小時(shí)的排查成本。2.3 部署與推理優(yōu)化從Flask到專(zhuān)用推理服務(wù)的遷移有很多教程喜歡拿Flask包一個(gè)模型接口當(dāng)示例但生產(chǎn)環(huán)境和那種Demo差距很大。首次嘗試時(shí)我也用FastAPI部署了一個(gè)簡(jiǎn)單模型接口單機(jī)能跑延遲也能接受??珊竺嫘枰С峙空?qǐng)求、版本切換、以及多個(gè)模型組合調(diào)用時(shí)Flask方案變得非常難維護(hù)。后來(lái)遷移到了KServe ONNX Runtime這套組合。模型先導(dǎo)出成ONNX格式再放到KServe上自動(dòng)拉起彈性服務(wù)。這樣做有幾個(gè)好處第一模型版本切換通過(guò)配置管理不用改代碼第二KServe內(nèi)置了監(jiān)控和日志采集第三支持自動(dòng)擴(kuò)縮容可以應(yīng)對(duì)突發(fā)的流量。對(duì)于小團(tuán)隊(duì)來(lái)說(shuō)用Triton Inference Server也是一個(gè)很穩(wěn)的選擇它支持多模型并發(fā)和動(dòng)態(tài)batch能顯著提升GPU利用率。我的一個(gè)經(jīng)驗(yàn)是在開(kāi)始寫(xiě)服務(wù)代碼之前先明確你的性能指標(biāo)——P99延遲、吞吐量、并發(fā)數(shù)——然后用壓力測(cè)試工具跑一輪再?zèng)Q定要不要上專(zhuān)門(mén)的推理服務(wù)。很多團(tuán)隊(duì)一上來(lái)就上Kubernetes和KServe結(jié)果流量沒(méi)多少運(yùn)維成本倒是先上去了。3. 一個(gè)從零起步項(xiàng)目的完整落地記錄3.1 需求拆解別急著定模型先定義評(píng)估指標(biāo)我接手過(guò)的一個(gè)具體項(xiàng)目是“客服對(duì)話意圖分類(lèi)”。業(yè)務(wù)方最開(kāi)始只給了一個(gè)模糊需求“識(shí)別用戶是不是想退款”。如果直接按這個(gè)需求去訓(xùn)練一個(gè)二分類(lèi)模型你會(huì)發(fā)現(xiàn)很多邊緣情況用戶說(shuō)“錢(qián)能不能退”是退款意圖說(shuō)“我想找人工客服”算不算說(shuō)“昨天買(mǎi)的東西不喜歡”是不是要引導(dǎo)退款這類(lèi)模糊場(chǎng)景如果不在需求階段理清楚模型上線后就會(huì)不斷出現(xiàn)“誤判”。所以我采取的方法是把需求拆成一個(gè)可執(zhí)行的問(wèn)題定義業(yè)務(wù)目標(biāo)智能識(shí)別退款意圖提升退款流程自助化比例。模型輸出一段對(duì)話中用戶是否表達(dá)退款意愿以及對(duì)應(yīng)的置信度。成功指標(biāo)線上AUC和業(yè)務(wù)上的“人工介入率”下降幅度??山邮艿难舆t單次分類(lèi)響應(yīng)小于200毫秒。在這個(gè)過(guò)程中最重要的是定義“評(píng)估指標(biāo)”和“業(yè)務(wù)指標(biāo)”的差異。離線評(píng)估可以看精確率、召回率、F1但線上必須看業(yè)務(wù)指標(biāo)比如退款請(qǐng)求被準(zhǔn)確觸達(dá)的比例、人工客服轉(zhuǎn)接率。只有把這些指標(biāo)對(duì)齊了模型迭代才有方向。我們?cè)陧?xiàng)目管理文檔里專(zhuān)門(mén)列了一頁(yè)“指標(biāo)定義表”每改一版模型都必須同步更新這個(gè)表避免后面爛賬。3.2 數(shù)據(jù)清洗最常見(jiàn)的臟數(shù)據(jù)比想象中更隱蔽很多人以為“數(shù)據(jù)清洗”就是把空值填一下、去重一下。真實(shí)項(xiàng)目里更隱蔽的問(wèn)題是數(shù)據(jù)分布不一致和標(biāo)簽噪聲。在我這個(gè)客服項(xiàng)目里一開(kāi)始收集了半年客服對(duì)話日志按關(guān)鍵詞和人工標(biāo)注組合的方式生成標(biāo)簽。但后來(lái)發(fā)現(xiàn)一個(gè)問(wèn)題日志里包含大量系統(tǒng)自動(dòng)回復(fù)并不是真實(shí)客服回復(fù)而且用戶消息和客服消息混合在一個(gè)字段里需要拆分。更麻煩的是有些對(duì)話里用戶先說(shuō)了退款后面又說(shuō)“算了不退了”按整段對(duì)話打標(biāo)簽就很糾結(jié)。我采用的清洗流程是這樣的第一步按會(huì)話ID拆分消息區(qū)分用戶消息和客服消息。第二步根據(jù)退款相關(guān)關(guān)鍵詞退款、退貨、錢(qián)、取消訂單等做粗篩。第三步人工標(biāo)注一萬(wàn)條樣本建立標(biāo)注規(guī)范明確邊界情況。第四步用簡(jiǎn)單規(guī)則模型去自動(dòng)標(biāo)注其余樣本再抽檢一致性。這套流程做下來(lái)訓(xùn)練集質(zhì)量明顯提升模型AUC提升了約4%。數(shù)據(jù)清洗不是花哨的技術(shù)活但決定了一個(gè)模型的上限。你后面模型調(diào)得再好數(shù)據(jù)是臟的一切都白搭。3.3 訓(xùn)練迭代用實(shí)驗(yàn)記錄表取代拍腦袋訓(xùn)練過(guò)程中最容易犯的錯(cuò)是“調(diào)參沒(méi)記日志憑感覺(jué)說(shuō)哪個(gè)版本更好”。在我用了MLflow之后形成了一套固定的迭代流程每次實(shí)驗(yàn)前明確要驗(yàn)證的假設(shè)比如“加入會(huì)話歷史信息能否提升分類(lèi)準(zhǔn)確率”。通過(guò)config文件設(shè)置所有超參數(shù)訓(xùn)練腳本讀入config并自動(dòng)記錄到MLflow。訓(xùn)練結(jié)束時(shí)自動(dòng)記錄測(cè)試集指標(biāo)和生成混淆矩陣。每天下班前花十分鐘查看當(dāng)天所有實(shí)驗(yàn)的記錄比較不同版本差異。這樣做了以后團(tuán)隊(duì)討論模型方案時(shí)不再靠說(shuō)“我覺(jué)得”而是直接說(shuō)“你看實(shí)驗(yàn)ID 32的召回比29高但精確率明顯下降這可能是數(shù)據(jù)標(biāo)簽噪聲導(dǎo)致的”。用數(shù)據(jù)說(shuō)話效率高很多。我還遇到過(guò)一個(gè)特別容易踩的坑訓(xùn)練的時(shí)候隨便設(shè)了隨機(jī)種子結(jié)果兩次訓(xùn)練同樣的配置結(jié)果差異很大讓人誤以為是某個(gè)參數(shù)起作用了。后來(lái)所有實(shí)驗(yàn)固定隨機(jī)種子使用seed 42并且記錄到MLflow。雖然這樣不能完全消除隨機(jī)性但至少每個(gè)對(duì)照實(shí)驗(yàn)差異可控。另外對(duì)于訓(xùn)練腳本里的“數(shù)據(jù)加載”部分我建議把數(shù)據(jù)集版本作為輸入的一部分而不是在腳本里寫(xiě)死路徑。這樣才能準(zhǔn)確知道每個(gè)模型用的哪份數(shù)據(jù)。DVC在這方面很有用可以像管理代碼一樣管理數(shù)據(jù)文件版本。我在小項(xiàng)目里沒(méi)有一開(kāi)始用DVC后來(lái)數(shù)據(jù)文件被誤覆蓋過(guò)一次損失了半天時(shí)間才老老實(shí)實(shí)補(bǔ)上版本管理。3.4 上線與監(jiān)控當(dāng)線上的分鐘級(jí)延遲故障找上門(mén)項(xiàng)目上線第一天就出事了。早上九點(diǎn)多流量開(kāi)始上來(lái)接口P99延遲從150毫秒飆升到4秒部分請(qǐng)求直接超時(shí)。當(dāng)時(shí)的臨時(shí)對(duì)策是重啟服務(wù)并擴(kuò)容但問(wèn)題沒(méi)有根治。后來(lái)經(jīng)過(guò)排查定位在兩個(gè)地方特征計(jì)算里有一段對(duì)嵌套JSON的解析每次請(qǐng)求都會(huì)重新計(jì)算一次沒(méi)有做緩存。模型推理用的是動(dòng)態(tài)batch但batch策略設(shè)置不合理在低并發(fā)下反而增加延遲。修復(fù)方案是把特征計(jì)算結(jié)果緩存到Redis里同時(shí)把推理服務(wù)改成FIXED_BATCH模式并調(diào)整最大batch等待時(shí)間。很快P99延遲恢復(fù)到120毫秒左右。這個(gè)經(jīng)歷讓我深刻明白上線前的壓力測(cè)試不能只看平均QPS必須單獨(dú)觀察P99和P99.9延遲并且要模擬真實(shí)并發(fā)模式。監(jiān)控體系的搭建也從這次故障之后提上了日程。我使用了Prometheus Grafana重點(diǎn)監(jiān)控以下指標(biāo)每秒請(qǐng)求數(shù)RPS響應(yīng)延遲的分布P50/P99/P99.9模型推理錯(cuò)誤的計(jì)數(shù)和占比GPU利用率和顯存占用緩存命中率數(shù)據(jù)質(zhì)量指標(biāo)比如推理輸入中空值比例模型效果本身也需要監(jiān)控。比如意圖分類(lèi)模型的置信度分布、各分類(lèi)的調(diào)用量占比如果某些分類(lèi)的占比突然變化往往說(shuō)明線上數(shù)據(jù)分布發(fā)生了變化。還有更直接的辦法定期采樣線上預(yù)測(cè)結(jié)果做人工標(biāo)注評(píng)估對(duì)比離線測(cè)試集的表現(xiàn)。這樣一旦發(fā)生數(shù)據(jù)漂移你能盡早發(fā)現(xiàn)。4. 工程化避坑清單每個(gè)坑我都踩過(guò)不止一次4.1 數(shù)據(jù)版本控制代碼回滾了模型和數(shù)據(jù)呢代碼有Git管著但數(shù)據(jù)和模型文件往往散落在服務(wù)器上。某次訓(xùn)練用到了一份手動(dòng)修正過(guò)的CSV文件放在服務(wù)器的/tmp目錄里后來(lái)機(jī)器重啟文件沒(méi)了那個(gè)實(shí)驗(yàn)變成不可復(fù)現(xiàn)。更慘的是模型上線后發(fā)現(xiàn)效果差想回退到之前更好的一個(gè)版本卻因?yàn)楫?dāng)時(shí)沒(méi)有把模型文件和對(duì)應(yīng)的數(shù)據(jù)版本一起登記折騰了很久才找到正確的模型文件?,F(xiàn)在的做法是每個(gè)實(shí)驗(yàn)所依賴(lài)的所有數(shù)據(jù)文件都登記在DVC倉(cāng)庫(kù)中模型文件上傳到模型倉(cāng)庫(kù)比如MLflow的artifact store并記錄其對(duì)應(yīng)的數(shù)據(jù)版本、代碼Git Commit ID和配置信息。這樣任何模型都可以從零復(fù)現(xiàn)。雖然前期需要多花一點(diǎn)時(shí)間維護(hù)但長(zhǎng)期看絕對(duì)值得。4.2 GPU利用率明明很高為什么推理還是很慢訓(xùn)練階段大家容易覺(jué)得“GPU利用率高速度快”到了推理階段就發(fā)現(xiàn)不一定。我的一個(gè)模型在GPU推理時(shí)單次請(qǐng)求延遲反而比CPU還高。后來(lái)用Nsight分析才發(fā)現(xiàn)瓶頸在數(shù)據(jù)預(yù)處理。每個(gè)請(qǐng)求進(jìn)來(lái)后都需要做文本分詞、向量化這些操作在CPU上執(zhí)行而且沒(méi)有和GPU推理并行——GPU大部分時(shí)間在等CPU算完。這個(gè)問(wèn)題在在線推理場(chǎng)景里非常常見(jiàn)。解決思路是把預(yù)處理操作做成異步模式讓GPU推理和CPU預(yù)處理重疊?;蛘呤褂孟馮riton這樣的推理服務(wù)器它會(huì)自動(dòng)調(diào)度模型執(zhí)行的并發(fā)繞過(guò)Python的GIL鎖效率提升非常明顯。另外如果輸入數(shù)據(jù)不是固定shape盡量避免每次動(dòng)態(tài)padding最好把數(shù)據(jù)整理成固定長(zhǎng)度或使用動(dòng)態(tài)shape優(yōu)化。這些細(xì)節(jié)看起來(lái)不起眼但對(duì)在線端到端延遲的影響常常是倍數(shù)級(jí)的。4.3 監(jiān)控體系別只盯著Loss業(yè)務(wù)指標(biāo)才是終點(diǎn)上線初期我的監(jiān)控面板全是模型相關(guān)的訓(xùn)練loss曲線、驗(yàn)證集AUC、線上輸出分布。后來(lái)發(fā)現(xiàn)業(yè)務(wù)方根本不關(guān)心AUC他們關(guān)心的是“退款意圖被識(shí)別出來(lái)后有多少用戶真的走了自助退款流程”。如果模型輸出都正常但業(yè)務(wù)轉(zhuǎn)化沒(méi)上來(lái)那說(shuō)明整個(gè)系統(tǒng)鏈路里一定還有其他問(wèn)題——比如業(yè)務(wù)邏輯判斷條件寫(xiě)錯(cuò)、前端沒(méi)有正確觸發(fā)退款引導(dǎo)。所以現(xiàn)在的項(xiàng)目里我至少會(huì)設(shè)置三層監(jiān)控基礎(chǔ)設(shè)施層服務(wù)存活、CPU/內(nèi)存/GPU、網(wǎng)絡(luò)延遲。模型層面請(qǐng)求量、預(yù)測(cè)分布、特征數(shù)據(jù)質(zhì)量、模型結(jié)構(gòu)版本。業(yè)務(wù)層面用戶響應(yīng)率、轉(zhuǎn)化率、兜底人工介入率。第三層往往需要和業(yè)務(wù)系統(tǒng)聯(lián)動(dòng)但這個(gè)閉環(huán)恰恰是AI工程真正產(chǎn)生價(jià)值的地方。如果只盯模型指標(biāo)你只能保證“模型在工作”不能保證“業(yè)務(wù)在變好”。5. 如果讓我從零再來(lái)一遍給新人的優(yōu)先級(jí)建議如果現(xiàn)在有人讓我?guī)匦伦咭槐閺牧汩_(kāi)始做AI工程的路我會(huì)建議他按照這個(gè)順序打基礎(chǔ)第一先把數(shù)據(jù)管線和實(shí)驗(yàn)管理做扎實(shí)。這是AI工程的地基數(shù)據(jù)不可復(fù)用、實(shí)驗(yàn)不可復(fù)現(xiàn)后面所有優(yōu)化都是空中樓閣。第二一定要理解“離線評(píng)估”和“線上評(píng)估”的差異。多花時(shí)間設(shè)計(jì)好線上業(yè)務(wù)指標(biāo)和監(jiān)控方案比多調(diào)一個(gè)點(diǎn)的AUC重要得多。第三部署方面不要迷信用Kubernetes來(lái)彰顯“技術(shù)含量”。先用單機(jī)服務(wù)把推理邏輯跑通加上緩存、限流、優(yōu)雅啟動(dòng)和退出這些最基本的東西就已經(jīng)完成80%的工作了。第四學(xué)會(huì)做性能剖析。模型慢不要盲目換更大的GPU先用profile工具看瓶頸在數(shù)據(jù)加載、預(yù)處理、網(wǎng)絡(luò)傳輸還是推理本身。我自己就遇到過(guò)瓶頸壓根不在模型上的情況。最后保持系統(tǒng)思維。AI工程不是一個(gè)純算法問(wèn)題而是一個(gè)融合了數(shù)據(jù)工程、模型開(kāi)發(fā)、系統(tǒng)架構(gòu)、DevOps的交叉領(lǐng)域。遇到問(wèn)題時(shí)先想清楚這個(gè)問(wèn)題的邊界在哪是數(shù)據(jù)問(wèn)題、代碼問(wèn)題還是架構(gòu)問(wèn)題再動(dòng)手修?;仡櫸易约旱某砷L(zhǎng)過(guò)程最大的轉(zhuǎn)折點(diǎn)不是學(xué)會(huì)了一個(gè)新框架而是把視角從“怎么把模型訓(xùn)練好”變成了“怎么讓整個(gè)系統(tǒng)跑起來(lái)”包括數(shù)據(jù)的保質(zhì)保量、實(shí)驗(yàn)的規(guī)范管理、服務(wù)的穩(wěn)定迭代、效果的持續(xù)評(píng)估。這當(dāng)中沒(méi)有太多玄學(xué)真正稀缺的是愿意補(bǔ)全工程短板的態(tài)度。尤其是當(dāng)項(xiàng)目規(guī)模變大、參與的人變多之后規(guī)范化帶來(lái)的價(jià)值會(huì)指數(shù)級(jí)上升。這套從零搭建的經(jīng)驗(yàn)對(duì)我來(lái)說(shuō)最重要的收獲就是AI工程化的核心競(jìng)爭(zhēng)力在于讓復(fù)雜的事情變得可重復(fù)、可觀測(cè)、可演進(jìn)。如果你也正準(zhǔn)備從零開(kāi)始自己的AI工程實(shí)踐不妨把這條原則也刻在腦子里。