<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一個(gè)「菜鳥」轉(zhuǎn)行AI的成長心得!

          共 10699字,需瀏覽 22分鐘

           ·

          2021-07-09 18:21

          ↑ 點(diǎn)擊藍(lán)字 關(guān)注極市平臺(tái)

          作者丨太子長琴
          來源丨Datawhale
          編輯丨極市平臺(tái)

          極市導(dǎo)讀

           

          本文是一個(gè)轉(zhuǎn)行四年的「菜鳥」的成長心得,圍繞真實(shí)工作場景中,AI算法工程師是如何從頭到尾完成一個(gè)產(chǎn)品需求的。 >>加入極市CV技術(shù)交流群,走在計(jì)算機(jī)視覺的最前沿

          本文是一個(gè)轉(zhuǎn)行四年的「菜鳥」的成長心得,圍繞真實(shí)工作場景中,AI算法工程師是如何從頭到尾完成一個(gè)產(chǎn)品需求的。

          這幾年基本能碰的都折騰過了,另一方面也走了非常多的彎路。終于感覺到自己有了質(zhì)的突破。有點(diǎn)像煉氣期滿筑基,奮斗之路剛剛開始,是有此文。

          00 背景

          我們先假定已經(jīng)接到一個(gè)明確的需求,假定它是一個(gè)比較簡單的分類任務(wù),數(shù)據(jù)和標(biāo)注都有,而且樣本分布也沒有極度不均衡。

          面對(duì)這種情況,以前的我一般都會(huì)毫不猶豫地拿出最新的、最有效果的模型往上懟:效果好就直接用,效果不好再說;如果性能不好,就考慮使用壓縮、蒸餾等瘦身方法。這種搞法不能說一定有問題,但我覺得至少考慮問題不夠全面,也不夠細(xì)致。

          接下來,我們就以此為例討論完成一個(gè)產(chǎn)品需求的全流程。

          01 數(shù)據(jù)準(zhǔn)備

          在需求清晰的前提下,第一步要做的是拿到數(shù)據(jù)和標(biāo)注。有些標(biāo)注是可以通過日志或埋點(diǎn)記錄直接獲取到的,而有些則需要組織人工進(jìn)行標(biāo)注。如果是組織人工標(biāo)注,主要需要注意兩個(gè)方面問題:第一,要讓標(biāo)注人員充分理解 Label 的含義,不能有模棱兩可的情況出現(xiàn);第二,明白標(biāo)注一定會(huì)有錯(cuò)誤。對(duì)于錯(cuò)誤的標(biāo)注,可以先跑模型然后預(yù)測數(shù)據(jù)集,將標(biāo)錯(cuò)的樣本按置信度排序后,重新標(biāo)注。這樣重復(fù)幾個(gè)來回,錯(cuò)誤的標(biāo)注就會(huì)越來越少。

          拿到數(shù)據(jù)后第一件事就是確定數(shù)據(jù)的分布,如果是均勻的那還好,如果是極度不均衡的那就要準(zhǔn)備采樣方案。有些任務(wù)可能需要在已標(biāo)注數(shù)據(jù)的基礎(chǔ)上重新構(gòu)造數(shù)據(jù)集,這種情況需要準(zhǔn)備構(gòu)造方案。比如句子對(duì)模型,我們實(shí)際拿到的標(biāo)注數(shù)據(jù)可能是句子加某個(gè) Label,同一個(gè) Label 的表示句子相似,不同 Label 表示不相似。

          這一步不同的任務(wù)或不同的公司可能都不相同,比如有些公司可能沒有埋點(diǎn),甚至日志記錄都不完整。還有些公司可能沒有標(biāo)注工具,只能使用 Excel 這種傳統(tǒng)的方法。作為一名工程師,如果遇到類似的情況就應(yīng)該開始考慮如何去構(gòu)建這些基本組件和服務(wù)。

          02 數(shù)據(jù)分析

          數(shù)據(jù)構(gòu)造完成后首先要做的是熟悉任務(wù)的數(shù)據(jù)。因?yàn)橛袝r(shí)候數(shù)據(jù)并不是我們想象中的樣子,比如用戶的 query、或者 ASR 之后的文本、或者來自于網(wǎng)頁的內(nèi)容,不同的數(shù)據(jù)有不同的特色。

          用戶的 query 可能會(huì)有錯(cuò)誤,這些錯(cuò)誤可能往往是音近或形近導(dǎo)致的,也有可能有拼音輸入;ASR 之后的文本可能有很多無效的口氣詞,當(dāng)然錯(cuò)誤是免不了的,可能更多的是發(fā)音不準(zhǔn)導(dǎo)致的錯(cuò)誤;而網(wǎng)頁的文本則一般比較規(guī)范,不像 ASR 那么口語化,其中的錯(cuò)誤往往也是句法、語義層面的。不同的數(shù)據(jù)會(huì)影響后續(xù)的處理以及模型的選擇,所以熟悉當(dāng)前任務(wù)的數(shù)據(jù)是第一步要做的。

          接下來要分析數(shù)據(jù)與 Label 之間的關(guān)聯(lián)性。以分類任務(wù)為例,數(shù)據(jù)樣本和每個(gè) Label 之間的關(guān)聯(lián)體現(xiàn)在什么層級(jí)?是一些字詞就能區(qū)分,還是需要字詞的順序?還是需要理解整句語義?是不是需要先進(jìn)行糾錯(cuò),不糾錯(cuò)會(huì)不會(huì)對(duì)結(jié)果產(chǎn)生影響?

          只有清楚了這些才有可能選擇適合該任務(wù)的模型,訓(xùn)練完之后也能夠?qū)︻A(yù)期做出檢驗(yàn)。比如假設(shè)只要單純地使用字詞就可以區(qū)分 Label,那 TextCNN 也許就完全足夠了;如果句子本身可能有一些無效詞,那 TextCNN 的效果也許比 Bert 還好。這也很容易理解,因?yàn)?Bert 的預(yù)訓(xùn)練是建立在正常文本上的,而且是從整體考慮的,對(duì)非正常文本這有時(shí)候反而會(huì)失效。

          所以,熟悉數(shù)據(jù)、熟悉任務(wù)是非常關(guān)鍵的一步。那實(shí)際中有什么好的方法嗎?這個(gè)除了經(jīng)驗(yàn)外,基本也只能自己去看數(shù)據(jù)了,而且即便是有經(jīng)驗(yàn)也最好再熟悉一次,比如不同的 ASR 產(chǎn)品也許犯錯(cuò)的種類不一樣呢。實(shí)際過程中可以對(duì)樣本按類別進(jìn)行均勻采樣,然后去觀察數(shù)據(jù)。

          03 測試方案

          很多人以為分析完數(shù)據(jù)就可以直接開干了,當(dāng)然這也沒問題,但我更覺得在開始之前應(yīng)該先想清楚測試方案。至少應(yīng)該包括以下內(nèi)容:

          1. 正常的精準(zhǔn)、召回、AUC。根據(jù)關(guān)注精準(zhǔn)還是召回,如何權(quán)衡。是否有任務(wù)需要特別關(guān)注的指標(biāo)?比如推薦要評(píng)估多樣性、覆蓋率等。

          2. 如何測試模型的有效性?即如何評(píng)估模型真正學(xué)到了期望學(xué)到的東西。這對(duì)于之后的改進(jìn)有非常重要的意義。

          3. 如何測試模型的性能?能否滿足目標(biāo),比如多少并發(fā)下的平均響應(yīng)時(shí)間。

          4. 如何做回歸測試?主要針對(duì)系統(tǒng)不同組件更新對(duì)其他部分和整體的影響。

          5. 如何做線上 A/B 測試?主要測試組件更新后線上是否真的有效。

          第一個(gè)屬于常識(shí),也是最基本的測試方法,我們需要注意的是,多種方法(比如規(guī)則+模型)配合使用時(shí),如何確定閾值以實(shí)現(xiàn)整個(gè)系統(tǒng)效果最優(yōu)。這里需要重點(diǎn)關(guān)注的是盡量讓不同的方法互補(bǔ),交叉最少。

          第二個(gè)其實(shí)是從系統(tǒng)使用的角度考慮的。比如句子對(duì)相似度模型,我們?cè)趯?shí)際使用時(shí)往往并不是直接給一個(gè)句子對(duì),然后判斷它們是不是相似。往往會(huì)有其他一些應(yīng)用場景,比如在 QA 時(shí)用來查詢最相似的 Answer。這種情況我們應(yīng)該測試的是召回方面的效果。

          第三個(gè)是需要特別強(qiáng)調(diào)的。有時(shí)候我們會(huì)上來就用一個(gè)當(dāng)前效果最好的模型(我以前就經(jīng)常),但很少思考為什么這個(gè)模型可以。這個(gè)模型的哪個(gè)結(jié)構(gòu)或配置起了作用?為什么會(huì)起作用?是不是和我們預(yù)期(分析數(shù)據(jù)階段)的相符?無論我們使用什么模型,都應(yīng)該深入探究起內(nèi)部機(jī)理,比如 TextCNN,我們可以把 MaxPooling 的位置給標(biāo)記出來,不同的 Kernel 該位置的分布是什么樣的,這些位置能否代表整句話輸出對(duì)應(yīng)的 Label。只有明確了這些機(jī)理,做到了心中有數(shù),才有可能根據(jù)不同的任務(wù)和數(shù)據(jù)調(diào)整模型的結(jié)構(gòu)。

          后面幾個(gè)基本都到系統(tǒng)級(jí)別了,涉及到與當(dāng)次任務(wù)組件相關(guān)的其他模塊。性能是保證線上服務(wù)穩(wěn)定的基本,在設(shè)計(jì)模型之前就應(yīng)該予以考慮,這里的考慮不止是性能的目標(biāo),還應(yīng)該充分考慮公司能提供的資源。如果最終服務(wù)沒有 GPU 服務(wù)器,那 GPU 并發(fā)的推理就不予考慮;如果要部署到邊緣設(shè)備,那還要考慮支持哪些算子,是否需要單獨(dú)開發(fā);如果是微服務(wù)方式,則需要考慮服務(wù)間通信、緩存等因素??傊?,最好能在構(gòu)建模型之前就對(duì)最終的使用方式有一定的了解,這樣也便于構(gòu)建和使用最適合的模型。

          大部分情況下,我們面臨的都是一個(gè)系統(tǒng),模型負(fù)責(zé)的任務(wù)可能只是其中的一個(gè)個(gè)組件。很自然地,當(dāng)某個(gè)組件發(fā)生變化時(shí),很有可能會(huì)對(duì)依賴它的其他組件產(chǎn)生影響。比如召回和精排,如果召回模塊出了問題,后面的精排模塊再怎么樣結(jié)果都可能是有問題的。所以,我們?cè)谏暇€新的版本或使用新的模型時(shí),一定要考慮到它可能對(duì)系統(tǒng)整體造成的影響。具體就是在模型發(fā)布在測試環(huán)境后要跑回歸測試,確定模塊之間銜接符合預(yù)期。

          A/B 測試是從產(chǎn)品整體的角度進(jìn)行評(píng)估,一般情況下我們都會(huì)讓新發(fā)布的版本和之前的版本分別在不同的分組上運(yùn)行一段時(shí)間,然后評(píng)估最終效果是否提升。需要特別注意分組最好能夠保證在各個(gè)維度上的隨機(jī)性。

          科學(xué)界有句名言:“沒有測量就沒有科學(xué)”,放在軟件開發(fā)領(lǐng)域依然適用,且無比正確。因?yàn)闊o論我們做什么任務(wù)、用什么模型,最終都是要作為產(chǎn)品的一部分給客戶使用的。作為一名工程師,我們理應(yīng)時(shí)刻站在整個(gè)系統(tǒng)的角度考慮問題。

          04 模型算法

          這部分內(nèi)容應(yīng)該是算法工程師最核心的工作了,尤其是對(duì)于專門從事算法研究的同學(xué)。拋開研究不談,從工業(yè)的角度來看,如果前面數(shù)據(jù)階段已經(jīng)搞得很清楚了,這一部分的工作反倒會(huì)容易很多。因?yàn)槲覀儸F(xiàn)在幾乎所有的模型,尤其是有監(jiān)督訓(xùn)練的模型,本質(zhì)上都只是在 “記憶” 訓(xùn)練數(shù)據(jù),只不過記憶的是特征。不同的模型歸根結(jié)底只是記憶特征的方式不同罷了。這也就是為什么會(huì)有 “數(shù)據(jù)決定上界,模型只是不斷逼近這個(gè)上界” 的說法。

          另外,根據(jù)實(shí)際經(jīng)驗(yàn),模型訓(xùn)練這一過程所花費(fèi)的時(shí)間往往并不多,可能還不到 25%,但絕對(duì)不到 50%。而且大多數(shù)時(shí)候都是把模型跑起來然后就去干其他的了,也不用一直盯著它看。尤其是前面都搞清楚后,這里只需要等模型跑完看下結(jié)果,驗(yàn)證一下是否符合我們的預(yù)期即可。

          當(dāng)然,關(guān)于模型訓(xùn)練我們依然要考慮一些因素:

          資源。最直觀的是機(jī)器資源,有條件的可能使用 TPU,沒條件的可能只能用普通的 CPU,或者要去租賃 GPU。資源的不同除了訓(xùn)練模型的代碼不同外,其實(shí)更重要的是訓(xùn)練策略的不同。比如有幾乎無限制的資源時(shí),我們可能會(huì)多跑幾組模型,多試幾組參數(shù),甚至?xí)匦骂A(yù)訓(xùn)練大模型,自己做蒸餾壓縮。當(dāng)然除了機(jī)器資源,還有人力配備、時(shí)間節(jié)點(diǎn)等等都要予以考慮。

          多模型。當(dāng)面對(duì)一個(gè)任務(wù),尤其是復(fù)雜任務(wù)時(shí),我們經(jīng)常會(huì)有不止一個(gè)想法(模型結(jié)構(gòu))需要驗(yàn)證,自然需要跑多組模型看效果。即便不是這樣,最好也能嘗試多個(gè)側(cè)重點(diǎn)不一樣的模型,這樣更容易驗(yàn)證自己的想法。比如,我們可以同時(shí)跑 CNN 和 LSTM+CNN 判斷時(shí)間順序到底有沒有起作用。

          預(yù)處理。這塊內(nèi)容和任務(wù)強(qiáng)相關(guān),但總的來說中文任務(wù)一般包括以下幾個(gè)方面:

          • 字級(jí)別還是詞級(jí)別的 Token。字相比詞沒有那么稀疏,詞表也比較小,缺點(diǎn)是損失了部分語義。因?yàn)橹形牡幕緲?gòu)成單位是詞,尤其是涉及到實(shí)體,拆開單獨(dú)看可能完全是另一種意思。而詞相比字,除了詞表很大外,還會(huì)有未登錄詞的問題,另外,還需要單獨(dú)做分詞任務(wù)。具體使用字還是詞要看任務(wù)確定。

          • 數(shù)據(jù)清洗。主要是去掉一些無關(guān)的文本,比如超鏈接、圖片、特殊符號(hào)等等。

          • 數(shù)據(jù)歸一。這個(gè)主要是處理具體的、特定的文本。比如句子級(jí)別的任務(wù)中,實(shí)體(包括人名、地名、時(shí)間、方位等)可能并沒有太多意義;部分任務(wù)中具體的數(shù)字可能需要規(guī)范到不同的范圍。3. 調(diào)參。俗稱煉丹,主要是對(duì)同一個(gè)模型使用不同的超參數(shù),比如 Embedding 維度,TextCNN 的 Kernel Size、Filter Size,Bert 的層數(shù),各種 hidden size、激活函數(shù)等等。除此之外,還應(yīng)該包括部分組件的調(diào)整,比如增加歸一化、使用 Dropout等等。使用不同參數(shù)前依然應(yīng)該遵守分析數(shù)據(jù)的方法,假定參數(shù)調(diào)整了結(jié)果會(huì)咋樣,然后通過實(shí)際結(jié)果去驗(yàn)證我們的假設(shè)。

          05 模型部署

          這里主要指將一個(gè)或多個(gè)深度學(xué)習(xí)模型部署為微服務(wù)的情況。這是我個(gè)人比較喜歡的方式,主要有以下好處:

          • 部署使用分離。所有的推理都通過 RPC 或 RestFul 接口實(shí)現(xiàn),與模型部署無關(guān),甚至與模型本身也無關(guān),服務(wù)模塊只關(guān)心輸入和輸出。這樣當(dāng)我們需要更新模型時(shí),只需將新模型放到對(duì)應(yīng)位置即可,代碼層面不用做任何改動(dòng)。
          • 合理利用資源。所有的模型可以統(tǒng)一部署到一個(gè)服務(wù)下,共享同一個(gè)服務(wù)器資源。因?yàn)槟P鸵话闶怯?GPU 服務(wù)器,而普通的服務(wù)一般是用 CPU 服務(wù)器,這樣的部署方式能夠更合理地利用資源。
          • 統(tǒng)一管理監(jiān)控。因?yàn)樗械哪P瓦壿嬌隙荚谝黄穑詿o論日常的管理還是數(shù)據(jù)的監(jiān)控,實(shí)施起來都比較方便。

          在部署時(shí),推薦使用容器化部署方案,使用 k8s 或類似的集群框架對(duì)服務(wù)進(jìn)行管控。這不是我們要趕潮流,主要是考慮到以下幾個(gè)優(yōu)點(diǎn):

          • 部署方便。完全不用考慮不同環(huán)境可能造成的沖突,所有的服務(wù)相互隔離。部署時(shí)通過 YAML 配置服務(wù),實(shí)現(xiàn)一鍵全自動(dòng)部署。
          • 便于擴(kuò)展。水平擴(kuò)展可以直接添加實(shí)例,垂直擴(kuò)展修改資源限制,所有配置均可通過配置文件完成,完全實(shí)現(xiàn)資源配置化。而集群資源不夠時(shí),直接添加節(jié)點(diǎn)主機(jī)即可。
          • 便于管控。通過 Istio 等組件非常容易實(shí)現(xiàn)流量和服務(wù)管控。比如可以很容易地配置實(shí)現(xiàn)灰度發(fā)布,進(jìn)行線上 A/B 測試,而且這些功能都是和業(yè)務(wù)解耦的。
          • 節(jié)約資源。因?yàn)榧旱姆?wù)其實(shí)是共享節(jié)點(diǎn)資源的,所以高峰時(shí)期服務(wù)會(huì)自動(dòng)多占用資源(當(dāng)然不會(huì)超過配置的限制),低谷時(shí)期就自動(dòng)釋放資源。這樣其實(shí)最大限度地利用了可利用的資源,節(jié)約了成本。
          • 管理方便。從管理機(jī)器變成管理服務(wù),只要配置好相應(yīng)的服務(wù),機(jī)器只是無狀態(tài)的節(jié)點(diǎn),多一個(gè)少一個(gè)掛一個(gè)重啟一個(gè)對(duì)服務(wù)沒有影響。而且集群還支持非常細(xì)粒度的權(quán)限控制,使用權(quán)限可以按需下發(fā)到部門或個(gè)人。

          當(dāng)然,使用這種方案本身是有一定學(xué)習(xí)曲線的,不可能一下子掌握。另外,也要根據(jù)公司的實(shí)際情況,分清楚使用場合。

          06 工程開發(fā)

          工程開發(fā)是一個(gè)工程師最核心的能力,我們常說算法工程師他首先得是個(gè)工程師,就意味著算法工程師必須要具備不錯(cuò)的工程能力。這塊其實(shí)是編碼能力,說起來很大,這里也主要談一下自己對(duì)工程開發(fā)的一些淺顯認(rèn)識(shí)。

          寫好測試

          注意我并沒有說 “測試驅(qū)動(dòng)”,因?yàn)檫@個(gè)往往說的人多但能做到或做好的少;而且這個(gè)并不是規(guī)范,更不是銀彈。不過測試的重要性毋庸置疑(我也不大會(huì)相信會(huì)有工程師在寫完工程后再補(bǔ)上測試代碼)。所以,即便不是測試驅(qū)動(dòng),也強(qiáng)烈建議在開發(fā)的同時(shí)完成測試代碼,甚至可以在功能完成后把測試代碼寫好。這其實(shí)是對(duì)自己代碼的一種自測,是代碼清晰、系統(tǒng)穩(wěn)定的基本保證,好處至少包括:

          • 代碼更魯棒。主要體現(xiàn)在邊界和非法輸入測試環(huán)節(jié),它會(huì)強(qiáng)迫我們?nèi)タ紤]各種可能錯(cuò)誤的輸入。

          • 代碼更清晰。比如有個(gè)函數(shù)同時(shí)做了幾件事,在寫測試的時(shí)候就會(huì)發(fā)現(xiàn)很不好寫,因?yàn)閹准驴赡芑ハ嘤杏绊憣?dǎo)致輸出不同的結(jié)果,這就能逼迫你重構(gòu)代碼。

          • 代碼更系統(tǒng)。主要是指多個(gè)函數(shù)(或組件)組合或管道完成一項(xiàng)功能時(shí),結(jié)果不符合預(yù)期的情況。此時(shí)如果某個(gè)函數(shù)(或組件)有完整的測試,那我們就很清楚地知道該函數(shù)(組件)一定沒問題,問題肯定出在它之前或之后。

          • 出錯(cuò)更容易排查。只要發(fā)現(xiàn) Bug,很容易就知道問題出在哪里,因?yàn)閳?bào)錯(cuò)信息一般能提示到具體的方法或函數(shù),根據(jù)報(bào)錯(cuò)信息結(jié)合已知的測試范圍很容易就確定到底是什么原因?qū)е碌腻e(cuò)誤。

          只要寫一次,就會(huì)一直有效。不考慮重構(gòu)的話,測試簡直就是一勞永逸的事,無論代碼怎么改,只要功能和輸入輸出不變,測試就一直有效。還有比這更美好的事嗎?

          至于怎么寫,總的建議是每個(gè)函數(shù)都應(yīng)該有測試,且至少應(yīng)該包括:正常功能測試、邊界測試、非法輸入測試,底線是核心代碼必須要有測試。另外,測試也是要隨著代碼的演進(jìn)不斷重構(gòu)和優(yōu)化的,很多時(shí)候甚至是 Bug 讓我們的測試更加完善。

          寫好注釋

          首先需要澄清的是,這里并不是指 “代碼即注釋”,“代碼即注釋” 應(yīng)該是作為工程師群體的基本共識(shí),不需要再多做討論。這里主要是要解釋為什么這樣做,或者記錄設(shè)計(jì)思路。以我的實(shí)際經(jīng)驗(yàn)看,如果沒有注釋,對(duì)于稍微復(fù)雜的設(shè)計(jì)或思路,過幾個(gè)月再看基本上是看不懂了,或者要想很久。所以說,注釋首先是給自己看的,可以想象,自己寫的代碼過一陣子都看不明白,那又怎么能期望別人(尤其是接你活兒的人)能看懂呢。至于形式我覺得反倒是其次,但如果能按規(guī)范注釋,當(dāng)代碼完成時(shí)我們可以順便得到一份自文檔,這對(duì)于愛偷懶的人絕對(duì)是福音。

          寫好文檔

          這恐怕是絕大部分程序員最不愛干的事,不過還是需要澄清一下,這里指的是 “設(shè)計(jì)文檔”,而不是接口或使用文檔,后者我一般會(huì)傾向于使用自文檔。設(shè)計(jì)文檔至少應(yīng)該編寫兩次,第一次是在項(xiàng)目或任務(wù)開始前,第二次是在結(jié)束后。它主要記錄項(xiàng)目的目的、整體的構(gòu)思、所使用的的技術(shù)、架構(gòu)等,它是戰(zhàn)略層面的指導(dǎo)方針,編寫該文檔的過程其實(shí)是理清自己思路的過程。如果發(fā)現(xiàn)自己無法完成該文檔的編寫,那很有可能是有些地方根本沒想清楚,或者目標(biāo)或需求很不明確。

          模塊化

          與此相類似的還有組件化、微服務(wù)化,不過模塊化是針對(duì)代碼功能層面的。模塊化有不少優(yōu)點(diǎn),比如:系統(tǒng)整體結(jié)構(gòu)清晰,功能結(jié)構(gòu)一目了然;模塊之間相互解耦,便于開發(fā)和維護(hù);模塊可復(fù)用程度高,減少代碼重復(fù)。感覺就像 “代碼即注釋” 一樣,程序員天然就會(huì)在不知不覺地模塊化。

          DRY

          對(duì)這條原則的基本感悟是:如果代碼重復(fù)第二次,就應(yīng)該考慮將其變?yōu)楠?dú)立功能的函數(shù);如果重復(fù)第三次,涉及到的所有代碼應(yīng)該已經(jīng)很好地被重構(gòu)了。其實(shí)我在這里更加想表達(dá)的是,如果有能更省事的方法,就盡量嘗試去用,比如泛型編程、宏、模板。

          分層和抽象

          這應(yīng)該算是一種基本的設(shè)計(jì)方法,其實(shí)我們?cè)谲浖_發(fā)中會(huì)經(jīng)常使用,比如分詞可能是一個(gè)底層服務(wù),情感分類模型可能就是上一層的服務(wù),對(duì)話機(jī)器人可能是更高一層的服務(wù)。不同層的抽象程度不同,底層服務(wù)相比高層服務(wù)往往更加抽象,因?yàn)樗鼈兛赡鼙欢鄠€(gè)不同的上層調(diào)用。這樣設(shè)計(jì)的主要目的還是清晰、隔離、解耦、重用,服務(wù)彼此獨(dú)立且又相互依賴,通過組合形成完整的系統(tǒng)。

          07 運(yùn)維監(jiān)控

          這塊內(nèi)容其實(shí)往往比預(yù)想重要,打個(gè)形象點(diǎn)的比喻,運(yùn)維就是我們的感官,系統(tǒng)現(xiàn)在的 “狀態(tài)” 如何全靠它來展示。這里的狀態(tài)主要可以分為兩個(gè)方面:

          數(shù)據(jù)流轉(zhuǎn)和服務(wù)負(fù)載。數(shù)據(jù)流轉(zhuǎn)是指流程中各個(gè)節(jié)點(diǎn)的輸入和輸出情況,節(jié)點(diǎn)可能是某一個(gè)服務(wù),也可能是一個(gè)組件,甚至是一個(gè)模型,關(guān)注的是流轉(zhuǎn)的內(nèi)容是否正常。服務(wù)負(fù)載是指流程中各個(gè)節(jié)點(diǎn)的流量情況,關(guān)注的是流量的大小。這塊內(nèi)容之前涉及的很少,只是簡單地用過一下 Istio,暫時(shí)也沒有太多的感受。先記錄幾個(gè)自己的直觀認(rèn)知。

          • 配置化。主要針對(duì)運(yùn)維,理想狀態(tài)下每個(gè)模塊都有對(duì)應(yīng)的配置文件,整個(gè)系統(tǒng)的組織就是對(duì)配置文件的組織。這在 k8s 里面是自然的,我們可以通過配置文件很方便地指定環(huán)境變量、資源配置、服務(wù)策略等,然后可以用命令行工具一鍵(或自動(dòng))啟動(dòng)或更新。與此相反的是人工手動(dòng)操作或代碼里寫死,要盡量避免類似的行為,如果需要通過外部變量影響模塊內(nèi)部行為或模式,最好將這些變量映射到外部配置文件。
          • 系統(tǒng)化。主要針對(duì)監(jiān)控,當(dāng)我們?cè)O(shè)計(jì)監(jiān)控系統(tǒng)時(shí),不僅要考慮關(guān)注的節(jié)點(diǎn),還要考慮這些節(jié)點(diǎn)狀態(tài)信息如何傳輸、存儲(chǔ)、讀取、展示,以及數(shù)據(jù)的流動(dòng)是否會(huì)影響系統(tǒng)性能等多個(gè)方面。可以做個(gè)很簡單的實(shí)驗(yàn),一個(gè)簡單的循環(huán)操作,每個(gè)循環(huán)打印結(jié)果和不打印結(jié)果性能會(huì)相差數(shù)十倍,如果要寫信息,性能相差可能會(huì)更大。一個(gè)反面的例子就是無腦打印日志,不僅充斥著大量亂七八糟的無效信息,還嚴(yán)重影響性能。

          08 更新迭代

          軟件工程不同于傳統(tǒng)的工程項(xiàng)目,它在實(shí)施完成后依然需要頻繁地改動(dòng),這也是軟件工程更加復(fù)雜的一個(gè)方面。這里除了代碼層面的可擴(kuò)展性,還包括版本管理和熱更新,此處重點(diǎn)說說后兩個(gè)。

          版本管理

          我們平常一般會(huì)碰到兩種不良的方式:第一種,將一大堆功能堆到一個(gè)版本下面;第二種,有一個(gè)改動(dòng)就生成一個(gè)版本。這一般是粗放式發(fā)展下的結(jié)果,正常情況下,版本管理應(yīng)該至少考慮以下幾個(gè)方面:

          • 需求推動(dòng)。需求往往來自于三個(gè)方面:業(yè)務(wù)方、運(yùn)營方和技術(shù)規(guī)劃。無論哪種需求,我們一般都會(huì)放在需求池中,然后根據(jù)優(yōu)先級(jí)規(guī)劃不同的版本。版本的迭代可以按周、雙周或月,不過個(gè)人不太推薦太長的迭代周期。一來容易懈怠,二來可能有新的重要需求不斷出現(xiàn),三來回退麻煩。比較推薦雙周一版本,時(shí)間分配上,一周用來開發(fā),一周用來規(guī)劃、測試。

          • 語義化版本。這個(gè)本應(yīng)該是軟件開發(fā)的常識(shí),其主要思想是將軟件的變動(dòng)記錄為 主版本號(hào).次版本號(hào).修訂號(hào) 的形式,主版本號(hào)主要是針對(duì)不兼容的改動(dòng);次版本號(hào)是針對(duì)向下兼容的功能新增;修訂號(hào)是針對(duì)向下兼容的功能修正。具體可參考:語義化版本 2.0.0 | Semantic Versioning。這其實(shí)是一種基于約定的方法,作為開發(fā)人員只要一看版本號(hào)就能掌握關(guān)于該版本的基本信息。

          熱更新

          集群環(huán)境下熱更新比較方便,我們這里主要說的是模型的更新。具體又包括以下幾個(gè)方面。

          • 模型全量更新。主要是指模型整體升級(jí),比較推薦 tensorflow/serving: A flexible, high-performance serving system for machine learning models,不僅性能優(yōu)秀,而且可以通過監(jiān)控模型文件的變化自動(dòng)升級(jí)到新的版本。同時(shí),還支持 RPC 和 RestFul 兩種接口,支持版本控制,支持多個(gè)模型,簡直是業(yè)界良心。

          • 模型在線學(xué)習(xí)。主要指模型根據(jù)線上數(shù)據(jù)實(shí)時(shí)或準(zhǔn)實(shí)時(shí)更新模型的情況。這塊目前工作幾乎還未涉及,日后更新。

          • 更新毛刺。主要指模型更新前后線上請(qǐng)求出現(xiàn)的延遲抖動(dòng)現(xiàn)象。一般在規(guī)模很大時(shí)才會(huì)出現(xiàn)。愛奇藝團(tuán)隊(duì)針對(duì) Tensorflow Serving 有過不錯(cuò)的改進(jìn)嘗試,被 Tensorflow 官方公號(hào)發(fā)表。

          以上就是完成一個(gè)產(chǎn)品需求的全流程了。但在實(shí)際工作中,有時(shí)候需求并不是完全清晰的,還可能是偽需求,這部分如果有伙伴感興趣,會(huì)寫一寫AI工程師面對(duì)不確定需求的溝通方法。

          如果覺得有用,就請(qǐng)分享到朋友圈吧!

          △點(diǎn)擊卡片關(guān)注極市平臺(tái),獲取最新CV干貨

          公眾號(hào)后臺(tái)回復(fù)“80”獲取CVPR 2021-Alpha Refine 直播回放及PPT~


          極市干貨
          YOLO教程:一文讀懂YOLO V5 與 YOLO V4大盤點(diǎn)|YOLO 系目標(biāo)檢測算法總覽全面解析YOLO V4網(wǎng)絡(luò)結(jié)構(gòu)
          實(shí)操教程:PyTorch vs LibTorch:網(wǎng)絡(luò)推理速度誰更快?只用兩行代碼,我讓Transformer推理加速了50倍PyTorch AutoGrad C++層實(shí)現(xiàn)
          算法技巧(trick):深度學(xué)習(xí)訓(xùn)練tricks總結(jié)(有實(shí)驗(yàn)支撐)深度強(qiáng)化學(xué)習(xí)調(diào)參Tricks合集長尾識(shí)別中的Tricks匯總(AAAI2021
          最新CV競賽:2021 高通人工智能應(yīng)用創(chuàng)新大賽CVPR 2021 | Short-video Face Parsing Challenge3D人體目標(biāo)檢測與行為分析競賽開賽,獎(jiǎng)池7萬+,數(shù)據(jù)集達(dá)16671張!


          CV技術(shù)社群邀請(qǐng)函 #

          △長按添加極市小助手
          添加極市小助手微信(ID : cvmart2)

          備注:姓名-學(xué)校/公司-研究方向-城市(如:小極-北大-目標(biāo)檢測-深圳)


          即可申請(qǐng)加入極市目標(biāo)檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學(xué)影像/3D/SLAM/自動(dòng)駕駛/超分辨率/姿態(tài)估計(jì)/ReID/GAN/圖像增強(qiáng)/OCR/視頻理解等技術(shù)交流群


          每月大咖直播分享、真實(shí)項(xiàng)目需求對(duì)接、求職內(nèi)推、算法競賽、干貨資訊匯總、與 10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動(dòng)交流~



          覺得有用麻煩給個(gè)在看啦~  
          瀏覽 55
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久四虎影院 | 蜜桃精品噜噜噜成人AV | 操操日操 | 男女日逼免费视频 | 国产激情综合在线 |