做一個算法工程師最重要的素質是在海量的算法方案中理解,吃透那些真正的干貨,然后不斷在實踐中去驗證,并總結吸收到自己的腦子里。今天分享算法工程師一些關于技術上的經驗總結。
今天是正式工作后的第一年,打算做一件事,以后要持續記錄自己的工作感想和生活狀態。
人這一輩子那么有限,作為一個普通人,也許我窮極一生也不會有什么大的成就可以讓外人為我寫下一個傳記。但是我可以用自己的手記錄下我這一生,吃過的苦,犯過的錯,愛過的人,在和一些網友聊過之后,我發現我是蕓蕓眾生中的一粒沙,那些自以為的經歷其實在陌生的一個環境里也有人同樣地經歷著。
希望我的文字可以激勵那些人,希望我的錯誤可以警惕那些人。
我的具體研究方向是計算機視覺算法工程師,眾所周知,當我們在說起算法工程師的時候,大家一般都會把工程師說成調參俠,而那種天天看論文發論文的又被捧上天。其實不然,我想以我從業一年的角度來說,一個計算機視覺算法工程師需要具備的技能。
算法工程師的工作內容首先是每日三問:業務KPI達標了嗎?badcase解決了嗎?CornerCase優化了嗎?你所有的工作的目的就是去解決這三個問題。
所以日常的工作內容是看看什么Case沒有解決,制定優化目標,迭代,再看,再優化,不斷循環往復。看上去是不是覺得算法工程師這個工作簡單,枯燥,無聊?
其實不然,因為我相信每一份工作都是有它枯燥簡單的地方,大名鼎鼎的李飛飛,吳恩達這些數據科學家難道就沒有做過調參的工作了?凡是不可以偏概全,我眼中的算法工程師要具備的技能點是這樣的。
頂尖的數據科學家肯定是會比一般人更理解數據的價值,以及做一個算法類的項目,需要用到什么樣的數據,使用什么樣的特征,有哪些需要考量的細節,在這個項目中的優化目標所關聯的數據需求是什么。
這一個我就是要打臉那些說算法工程師是調參俠的人了,你以為的調參俠是把一個學習率從0到1e-3挨個嘗試,改改配置就行。
實際上當接到一個新項目的時候,作為一個算法工程師是需要快速調研算法論文,并且制定算法優化方案的。并且很多時候這個子方向你是之前沒有接觸過,比如突然讓你去從一個分類項目中去做一個跟蹤項目,你需要在一周之內去調研業界的跟蹤算法文章并理清楚跟蹤算法的分類成績,優缺點分析,核心思想分析,這一點沒有論文積累是比較難的。
優秀的算法工程師就是要具備這種快速選型并且抓重點,最后還能給出一個合理的算法選型。一般考慮的角度是(可部署性,精度指標,速度怎么樣,有沒有不支持的算子,是否開源等等)。話說在這一點上,沒有人會傻到對一個新項目去復現沒開源的SOTA論文。
這方面算軟實力,偏項目管理。正如我之前說的一個需求從定義,調研,方案制定,數據采集,標注,模型訓練,Inference,SDK的集成。
這一套流程都是要有時間節點的,不僅僅是項目負責人給的節點,算法工程師自身也要給自己定義節點并且高效把控。比如采集的安排要考慮采集方案的合理性,高效性。
標注的時候要定義好標注邊界,在你手里過的數據要要詳細的記錄,不然到時候數據找不到真是個很麻煩的事情。模型訓練的時候從輸入圖片校對,target校對,inference代碼,看著loss慢慢降下去了就可以安心喝個咖啡休息休息,這套流程其實就是一般的軟件開發一樣,不需要擔心完不成的問題,但是要考慮風險,把控進度,注重細節,考驗的是一個算法工程細不細的問題。
算法工程師基本都是Python為主,python作為一種簡單的語言使用起來當然非常方便。(不要用C++的高端來批判使用python的我們了,用C++寫模型的訓練那是憨憨或者是大神(yolo作者)干的事。
python代碼除了基礎的操作,數字,字符串,類,裝飾器等等,其他就是各種工具要用的數量,numpy, pandas, torch, opencv, multiprocess等,具體看你的研究方向了。
在系統架構上,我覺得學習開源代碼,比如PaddlePaddle和MMLab的代碼都是非常好的學習資源。只不過我們所謂的架構是把一個算法項目的前處理,后處理,model_build,backbone,neck,head等等這些組件化的一種架構,但是我認為一些設計模式的思想還是和軟件開發一樣的,大量的工廠模式,觀察者模式的思想在這些算法架構中都有體現。
對于C++這方面,我之前也有執念要不要學CUDA,現在覺得不需要,我所認為的算法工程師的C++功底是要能高效完成邏輯上的處理,以及能夠快速定位和調試遇到的bug,Cmake也要能看得懂,要有把算法模型部署上線的能力,對C++的基礎類型,STL,指針,引用,多態,繼承,命名空間,模板都熟悉。至于一些指令級優化,算子融合啥的,那都是專業的人去做了。
這是個核心技能,一定要秉持著數據>算法>創新的思路去做一個項目,當優先級高的遇到了瓶頸了再去做下一個環節的事情。
數據側就是要不斷去做badcase分析,按場景按類別去分好自己的訓練數據,同樣要對測試集,測試方案,測試指標要不斷改進和優化。算法上則要考慮的是backbone的設計選擇,neck的設計選擇,head中target的設計選擇,數據增強方案(這個比較重要,除了幾何增強,還有像素級增強),更好的Pretrain模型,后處理的邏輯優化,大模型KD優化,類別不均衡的優化,難樣本挖掘優化等。
重點說下后處理,這個環節其實非常重要,很多時候基于邏輯的規則可以提高你模型一大半的性能,代碼一般都簡單,但是需要你去從數據反饋中挖掘這個規則怎么制定。創新性則是你的研究能力。
很多論文其實價值不大,不是在于沒有創新,而是在于這個創新都是為了“新”去做的,并且在那么一兩個公開數據集上達到了比較好的效果就可以發論文來證明這個工作的價值。有時候實驗了發現不好,就改一通網絡,我已經看了很多篇加了deform_conv魔改網絡的方案了。
非常solid的文章當然值得尊重,比如之前看多目標跟蹤的時候看完centertrack的時候,感覺這篇文章真的簡單,溫柔,有力量!不過我其實也不是吃不到葡萄說葡萄酸哈,能發頂會當然是大大的好哈。畢竟程序員往高了走,頂會頂刊,行業影響力是妥妥的硬通貨!但是不過是工程還會做研究,調研論文,復現論文都是必備的技能,這塊其實我覺得也是屬于研究能力的范疇。
很多人都說算法工程師對數學要求高,其實我不太清楚這個要求高具體指啥水平,但是起碼公式推導是肯定要掌握的,不然很多論文也看不懂的,比如最近在看目標跟蹤的文章,我感覺對數學水平還是有一定要求的,不然連傅里葉變換,卡爾曼濾波都整不明白,那真的沒法玩,至于比這更高的數學要求,那就讓那些數學家,研究員搞去吧。我反正是搞不了,爹媽就給我這腦袋,不是金剛鉆我也不攬瓷器活。
由點開始出發,算法一般就是推薦,搜索,NLP,CV,控制規劃這些子方向。我本身是做CV的,所以對CV稍微比較了解一點,在CV里其實方向也非常多,傳統圖像處理,識別,檢測,分割,單目標跟蹤,多目標跟蹤,人臉相關任務(屬性,情緒,識別等等),GAN,顯著性檢測,異常檢測,超分辨率,OCR,圖像復原(去霧,去雨,去陰影,補全圖像...),深度估計,ReID,SLAM,以及通用技術模型量化,剪枝,模型蒸餾,meta learning,遷移學習……。
看到這應該明白為啥CV這么卷了吧,而且有些方向的門檻和技術棧比較高,比如SLAM,一般社招SLAM的話基本都是要有相關經驗的,不然一個只做過分類任務的人去做SLAM估計會很吃力。
我的想法就是要從一個小方向出發,在幾個小方向內挖深,然后對其他大方向也觸類旁通,這樣才能有更好的進步。畢竟方向是不一樣,能力需求還是差不多的。
這一年下來,我感覺自己在技術上收獲還是蠻多的,在這個大項目組里,檢測,分割,分類,識別,關鍵點都有所接觸,同事也非常nice,不同方向的同事平時也樂于分享自己技術棧里的工作和前沿文章。但是有點比較無奈的就是自己在算法創新這一點上還是有所欠缺。希望下一年的時間里,自己可以不斷加強這方面的能力提升。
當然是重中之重,leetcode不僅僅是招聘的篩選標準,也是鍛煉一個人算法思維的重要手段。雖然不得不說hard的題一般都是有一些ACM的技巧性在里面,但是我認為一個成熟的算法工程師,一定是要有秒解easy題,對middle的題也要基本能cover得住。不然用技巧性,題目和業務不搭邊這樣的說法只能是掩蓋自己思維能力不足的借口。這一點自己做得還不夠好,還是要不斷提高。
對,沒錯,我要把這個放到技術篇。因為寫PPT真的是個技術活!!!看了組內老大哥寫的那PPT,技術邏輯條理分明,布局結構美觀大氣,講PPT那個滔滔不絕的樣子真是好萊塢大片一鏡到底,絕了!!!作為一個有語言障礙的人,十分佩服,羨慕這樣的人。
不過我總結了大佬的PPT和演講。做一個好的PPT,尤其是技術類的PPT,第一點就是要對自己的技術棧非常清晰,技術能力是絕對要過關。圖和文字上,就是要以圖代字,不能空洞,也不用浮夸,更不用像學校課件一樣放一些動態特效。
技術人員的PPT只要三個點:邏輯清晰,內容充實,一目了然。
在美觀性上,我下載了論壇和組內會議的優質PPT分析了下,所謂美觀其實只要有個簡約的背景,文字和圖標最好一起用,多放一些柱狀圖,折線圖等說明你的工作,時間線的匯報來個帶箭頭的圖表述下。
PPT這個東西,要積累模板,要理清邏輯,要整理材料,要抓住重點,要自信表達。
希望自己和觀眾老爺們的PPT能力都可以不斷進步,一時菜雞不要緊,永遠不行動才是最可怕的。
做算法這一點確實是和其他行業差異比較大的,算法的技術更迭特別快。
要經常閱讀前沿論文,也許不會直接拿來用,但是技術的優化細節是否有助于現有的項目這個其實還是需要考量一下的。
不要用(不都是用老方法做項目)這樣的說法來diss我,你要是這么想你就用10年的算法一直用,近3年的文章都不看,當有新的有價值的東西出來的時候等你知道了別人早就用上了,而且長時間不看論文。也會慢慢喪失對文獻閱讀和理解的能力,就和一個人長時間不寫代碼了就不會寫代碼一樣。
僅僅根據自己比較了解的識別,檢測,分割方面的一些總結。
比較通用的算法側優化是backbone(resnet resnext resnest efficientNet等大模型,mobilenet hrnet shufflenet等系列小模型),Neck(fpn, bi-fpn,panet等各種FPN層),比較實用的網絡優化(deform_conv,se-net,cbam等attention結構),head優化(主要是target設計的方方面面。
比如檢測anchor-base和anchor-free之間的差異就是在于target和輸出之間加了一個anchor作為橋梁),訓練策略優化(主要集中在正負樣本均衡,損失函數設計,比如過采樣,欠采樣,損失函數比如FocalLoss,triplet_loss,訓練流程上比如OHEM等)。訓練參數優化(CosineLearningRate等LR方面的優化,AutoAugment、Mixup、CutOut等數據增強方面的優化),預訓練模型(基于無監督大數據Moco等, 大分辨率pretrain, 最差也得ImageNet-pretrain了,這塊NLP方面做的比較好,CV這塊我比較看好無監督或者半監督的方法),新方案(ViT,DETR等transformer在CV里的各種應用)。知識蒸餾,大模型蒸餾小模型是每一個公司都會要的技術棧,可看hinto的開山之作,當時后面還有各種多teacher,加權等方案。
最后就是訓練數據的干凈,對不同場景都能cover到,對于訓練參數中的具體數值就跑模型看效果。
以上是我這一年經驗所總結的算法優化方向,重點在于總結方向,具體細節方法太多了就不一一贅述。就這一年的工作經驗看來,很多時候不同的算法方案之間很多時候效果上實際差距其實不大,這一點在我跑ATSS的實驗的時候也更加確定。但是有些東西比如attention_block,transformer,KD等確實是硬通貨。
做一個算法工程師最重要的素質是在海量的算法方案中理解,吃透那些真正的干貨,然后不斷在實踐中去驗證,并總結吸收到自己的腦子里。
后記:以后的時間啊,要做一個說書人,記錄自己的所思所想,講好一個故事,一個屬于我的故事。在這個誰都不認識誰的網絡世界里,輸出我對這個世界的看法,激勵和我曾經一樣墮落的人,照亮和我一樣前進的人,溫暖和我一樣坎坷的人。清除了所有的可能包含個人信息的痕跡,我想以后,在這個世界里,為自己,寫一個故事,一個用一生來記錄的故事。