時美顏)
翻抽屜翻出一疊舊資料最上面是一份打印版筆試題——?dú)g聚時代2018校招圖像算法工程師深度學(xué)習(xí)A卷。當(dāng)年在宿舍做這份卷子時的尷尬勁兒還記得清清楚楚傳統(tǒng)圖像處理學(xué)了深度學(xué)習(xí)也看過不少網(wǎng)絡(luò)結(jié)構(gòu)圖可真要手推卷積尺寸、手寫銳化原理、現(xiàn)場設(shè)計(jì)一套美顏方案的時候還是露怯了。后來在算法崗上做了幾年從直播美顏到短視頻特效再到現(xiàn)在折騰大模型圖像生成回看這份卷子才發(fā)現(xiàn)當(dāng)年覺得“變態(tài)”的考點(diǎn)沒有一道是白問的幾乎每一題都能在真實(shí)業(yè)務(wù)里找到影子。這份卷子對準(zhǔn)備圖像算法方向筆試面試的同學(xué)來說是一份很好的自測樣本。它不會考那種背一遍就能答的“什么是CNN”而是把卷積計(jì)算、圖像處理基礎(chǔ)、網(wǎng)絡(luò)設(shè)計(jì)、工程化方案串在一起考察你能不能從一張輸入圖像出發(fā)把整條算法鏈路想明白。這篇不打算貼“標(biāo)準(zhǔn)答案”那東西網(wǎng)上到處都是也不一定對。我更想把這份A卷背后真正想考察的能力項(xiàng)拆開講清楚以過來人的身份說說每類題該怎么答、為什么這么答再把當(dāng)年踩過的坑和后來工作中的印證補(bǔ)上。1. 直播業(yè)務(wù)決定了這份考卷的出題方向準(zhǔn)備筆試的第一步很多人會忽略先搞清楚這家公司到底做什么業(yè)務(wù)。歡聚時代2018年的基本盤是直播和短視頻旗下產(chǎn)品線里圖像算法團(tuán)隊(duì)的核心KPI就是讓攝像頭里的人好看、讓視頻內(nèi)容有可玩性。這個背景直接決定了考卷不會去考遙感圖像、醫(yī)學(xué)影像分割這種偏門方向考點(diǎn)高度集中在人像美化、實(shí)時視頻處理上。1.1 給應(yīng)屆生的第一課先看公司做什么再猜它考什么大部分應(yīng)屆生復(fù)習(xí)算法筆試是“按目錄復(fù)習(xí)”從機(jī)器學(xué)習(xí)到深度學(xué)習(xí)從目標(biāo)檢測到圖像分割每個知識點(diǎn)都淺嘗輒止。這種無差別復(fù)習(xí)效率很低因?yàn)椴煌瑯I(yè)務(wù)線的圖像算法筆試差別很大做自動駕駛的公司會考BEV感知和3D目標(biāo)檢測做電商的公司會考商品識別和圖像檢索而做直播的公司考的就是人臉、美顏、特效這一套。當(dāng)年我拿到A卷先掃了一遍題目發(fā)現(xiàn)幾乎每道題都能和直播產(chǎn)品掛上鉤。卷積計(jì)算題后面跟著“視頻幀處理”的應(yīng)用背景圖像銳化題明顯在暗示美顏里的細(xì)節(jié)增強(qiáng)最后的開放方案題干脆直接讓你設(shè)計(jì)一套實(shí)時美顏系統(tǒng)。這不是巧合而是出題人從業(yè)務(wù)需求出發(fā)反向設(shè)計(jì)考卷。所以復(fù)習(xí)前建議做一件事打開目標(biāo)公司的官網(wǎng)和產(chǎn)品列出它的圖像算法應(yīng)用場景。歡聚時代這種直播公司核心訴求就兩個實(shí)時、自然。實(shí)時意味著端上算力有限所以筆試考拉普拉斯這種輕量級算子而不是讓你堆幾十層的分割網(wǎng)絡(luò)自然意味著美顏不能糊成一張假臉?biāo)詴谝獗_?、?xì)節(jié)、時序一致性。理解了這兩條再看整張卷子出題邏輯一下就清晰了。1.2 從崗位JD反推出來的三個核心考察維度把A卷的題目歸歸類會落在三個維度上。這三個維度在當(dāng)時的崗位JD里也有對應(yīng)表述面試官其實(shí)早就把考察范圍寫在招人要求里了。第一個維度是深度學(xué)習(xí)基礎(chǔ)。包括卷積、池化、激活函數(shù)、反向傳播、損失函數(shù)、優(yōu)化器以及經(jīng)典網(wǎng)絡(luò)結(jié)構(gòu)。這是所有算法工程師的底子不管做什么方向都躲不開。對應(yīng)到卷面上是計(jì)算題和簡答題比如給你一個卷積層參數(shù)讓你算輸出尺寸和參數(shù)量或者問ResNet為什么能解決網(wǎng)絡(luò)退化問題。第二個維度是傳統(tǒng)圖像處理。直播美顏在2018年仍然是傳統(tǒng)算法為主、深度學(xué)習(xí)為輔的狀態(tài)所以拉普拉斯銳化、直方圖均衡化、邊緣檢測、濾波這類經(jīng)典知識點(diǎn)是必考的。這個維度很多自學(xué)深度學(xué)習(xí)的同學(xué)容易忽略覺得有了CNN就不需要懂傳統(tǒng)圖像處理了。這是典型的誤解實(shí)際上直到今天引導(dǎo)濾波、雙邊濾波這些傳統(tǒng)算子仍然大量用在美顏算法里CNN只是替換了其中一部分模塊。第三個維度是工程化方案設(shè)計(jì)。卷子最后的大題通常是開放性的給你一個業(yè)務(wù)場景讓你做個方案。這類題沒有標(biāo)準(zhǔn)答案考的是你有沒有全局視野懂不懂分解需求、懂不懂權(quán)衡精度和性能、懂不懂怎么把算法落地到真實(shí)產(chǎn)品里。當(dāng)年很多人栽在這道題上不是不會算法而是只盯著“用什么模型”完全沒有考慮“幀率能不能達(dá)標(biāo)”“用戶在美顏強(qiáng)度30%時希望看到什么效果”這類問題。這三個維度就是整張A卷的骨架。2. 深度學(xué)習(xí)基礎(chǔ)題卷積計(jì)算與感受野是必考硬傷A卷的深度學(xué)習(xí)基礎(chǔ)部分風(fēng)格相當(dāng)務(wù)實(shí)。不會讓你背“CNN由卷積層、池化層、全連接層組成”這種話而是直接甩一道計(jì)算題過來考察你能不能準(zhǔn)確算出一個卷積層的前向傳播。這類題看著簡單實(shí)際上手算的時候特別容易翻車因?yàn)榧?xì)節(jié)太多了。2.1 一道典型的計(jì)算題輸出尺寸、參數(shù)量、感受野卷子里有一道很典型的題大概意思是輸入一張224×224×3的圖像接一個3×3卷積padding1stride2卷積核數(shù)量為64求輸出feature map的尺寸和這一層的參數(shù)量。先算尺寸。卷積輸出的公式是H_out floor((H_in 2×padding - kernel_size) / stride) 1代入得floor((224 2 - 3) / 2) 1 floor(223 / 2) 1 111 1 112。所以輸出是112×112×64。這里有兩個坑容易被忽略。第一個坑是padding的語義padding1到底是在單邊補(bǔ)一行還是上下左右各補(bǔ)一行實(shí)踐中默認(rèn)是兩邊都補(bǔ)即上下左右各補(bǔ)一圈所以224變成226再減3得223。第二個坑是stride除法要向下取整卷積沒有“四舍五入”的說法。這些細(xì)節(jié)面試官一眼就能看出你是真懂還是背過公式。再說參數(shù)量。一個3×3卷積核輸入通道3輸出通道64對應(yīng)的參數(shù)是3×3×3×64 1728。注意這里還沒有加bias如果每題都帶偏置項(xiàng)要加上64變成1792。很多人在計(jì)算題里漏掉bias這屬于低級失誤但真的非常常見。感受野也是這個板塊的??汀R粋€比較經(jīng)典的問法為什么很多網(wǎng)絡(luò)用兩層3×3卷積代替一層5×5卷積答案有兩個層面。數(shù)學(xué)上兩層3×3疊加感受野正好等于5×5三層3×3等于7×7參數(shù)上兩層3×3的參數(shù)量是2×3×318一層5×5是25參數(shù)更少且非線性更強(qiáng)。這個點(diǎn)背下來不難但理解了以后對設(shè)計(jì)網(wǎng)絡(luò)結(jié)構(gòu)很有幫助。2.2 反向傳播和梯度問題的考察方式反向傳播在筆試?yán)锿ǔS袃煞N考法。第一種是給一個簡單的兩層全連接網(wǎng)絡(luò)要求手寫梯度表達(dá)式。這種題必須踏踏實(shí)實(shí)把鏈?zhǔn)椒▌t展開用具體的數(shù)值代進(jìn)去算不要只寫一個loss對w的偏導(dǎo)公式因?yàn)殚喚硎前床襟E給分的你跳過中間推導(dǎo)就算結(jié)果對也拿不到滿分。第二種是概念題問為什么sigmoid在深層網(wǎng)絡(luò)里會導(dǎo)致梯度消失ReLU為什么能緩解。原因是sigmoid函數(shù)在兩端飽和導(dǎo)數(shù)的最大值只有0.25。鏈?zhǔn)椒▌t在反向傳播時是不斷連乘的每乘一個小于1的數(shù)梯度就縮一圈網(wǎng)絡(luò)越深梯度越小淺層的參數(shù)幾乎得不到有效更新。而ReLU在正區(qū)間導(dǎo)數(shù)恒為1梯度不會在激活函數(shù)這一步衰減。不過ReLU也有自己的問題。負(fù)數(shù)區(qū)域梯度直接歸零如果一個神經(jīng)元的輸入長期落在負(fù)區(qū)間它就再也學(xué)不動了這叫Dead ReLU。所以筆試如果追問“ReLU有什么不足”要能答出Dead ReLU并順勢引出LeakyReLU、PReLU這些變體。另外BatchNorm在2018年的卷子里出現(xiàn)頻率已經(jīng)很高了它通過對每層激活值做歸一化讓輸入分布相對穩(wěn)定既緩解梯度問題又能允許你用更大的學(xué)習(xí)率訓(xùn)練這個機(jī)制要能講清楚。2.3 損失函數(shù)與優(yōu)化器的選擇邏輯損失函數(shù)的選擇筆試題通常以“你在這個場景里用什么損失函數(shù)為什么”的形式出現(xiàn)。圖像分類默認(rèn)softmax 交叉熵。這里值得記住一個推導(dǎo)結(jié)論交叉熵?fù)p失對softmax輸入logits的梯度形式很簡潔等于預(yù)測概率減去真實(shí)one-hot標(biāo)簽即 y_hat - y_true。寫代碼的時候很多深度學(xué)習(xí)框架里CrossEntropyLoss已經(jīng)內(nèi)置了softmax直接用即可但筆試題偶爾會要求你解釋這一步別到時候露怯?;貧w任務(wù)用L2損失但L2對離群點(diǎn)異常敏感一個臟標(biāo)注就能把模型拉偏。所以工程里常改用Smooth L1它在誤差較小時保持L2的平滑誤差較大時退化成L1對離群點(diǎn)更魯棒。問到這個的時候如果能順口說出“目標(biāo)檢測邊框回歸里Smooth L1是標(biāo)配”很加分。優(yōu)化器這塊當(dāng)時幾乎必問“Adam和SGD有什么區(qū)別你選哪個”。常規(guī)答法是Adam自適應(yīng)學(xué)習(xí)率、收斂快、適合調(diào)參初期SGDMomentum雖然收斂慢但配合合適的學(xué)習(xí)率往往能收斂到更好的極值點(diǎn)泛化性更優(yōu)。面試官想聽到的不只是“Adam快”而是你對“什么時候該用誰”的判斷。我的經(jīng)驗(yàn)是小數(shù)據(jù)集、快速驗(yàn)證用Adam正式訓(xùn)練大模型、追求精度時換成SGDMomentum配warmup和cosine decay學(xué)習(xí)率。這個技能不是筆試能考出來的但提前準(zhǔn)備好面試環(huán)節(jié)很加分。3. 圖像算法題從拉普拉斯銳化到直方圖均衡化A卷的第二大板塊是傳統(tǒng)圖像處理這部分和直播業(yè)務(wù)結(jié)合得很緊。拉普拉斯銳化、直方圖均衡化、邊緣檢測都是圖像增強(qiáng)里的基礎(chǔ)操作放到直播間里直接對應(yīng)清晰度提升、光影調(diào)節(jié)、人像輪廓增強(qiáng)這些功能。題目不難但考察得非常細(xì)。3.1 拉普拉斯算子為什么能銳化圖像拉普拉斯算子是一個二階微分算子。圖像里邊緣區(qū)域的像素變化劇烈一階導(dǎo)在邊緣處取得極值二階導(dǎo)在邊緣兩側(cè)會出現(xiàn)“零交叉”——從正變負(fù)或從負(fù)變正。把二階導(dǎo)的信息疊加回原圖就能讓邊緣兩側(cè)的對比更強(qiáng)視覺上就是變清晰了這就是銳化的原理。離散情況下拉普拉斯模板一般有兩種。四鄰域模板 0 1 0 1 -4 1 0 1 0八鄰域模板 1 1 1 1 -8 1 1 1 1用四鄰域模板時銳化公式是g(x, y) f(x, y) - ?2f也就是原圖減去拉普拉斯結(jié)果。但這里有個特別容易踩的符號坑如果你用的模板中心是正數(shù)比如0 -1 0 / -1 4 -1 / 0 -1 0公式就要改成原圖加上拉普拉斯結(jié)果。好多人背公式時沒注意模板符號寫出來的代碼效果完全不對。Python實(shí)現(xiàn)很直接import cv2 import numpy as np img cv2.imread(input.jpg, cv2.IMREAD_GRAYSCALE).astype(np.float32) # 四鄰域拉普拉斯核中心為負(fù) kernel np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]]) lap cv2.filter2D(img, -1, kernel) sharp cv2.subtract(img, lap) # 原圖減拉普拉斯 sharp np.clip(sharp, 0, 255).astype(np.uint8)注意filter2D的輸出可能包含負(fù)值所以后面要用clip裁剪到0~255或者用cv2.subtract來截?cái)喾駝t顯示出來會是黑一塊白一塊的噪點(diǎn)圖。筆試如果考到拉普拉斯往往會追加一問“它有什么缺點(diǎn)”。答案是二階導(dǎo)對噪聲非常敏感一張有輕微噪點(diǎn)的圖銳化后噪點(diǎn)會被明顯放大。所以在美顏場景里拉普拉斯很少單獨(dú)用而是配合保邊濾波一起使用或者用高反差保留即原圖減去低頻圖來提取細(xì)節(jié)層再按強(qiáng)度疊加回去。這個思路在直播美顏的磨皮和細(xì)節(jié)增強(qiáng)里很常見。3.2 直方圖均衡化公式、步驟與實(shí)現(xiàn)直方圖均衡化的目標(biāo)是把灰度分布從集中在某個區(qū)間擴(kuò)展到整個灰度范圍提升對比度。直播場景里光線不好的時候人像發(fā)灰均衡化能讓畫面干凈通透一些是很多實(shí)時視頻前處理鏈路里的常駐模塊。標(biāo)準(zhǔn)步驟分四步。第一步統(tǒng)計(jì)每個灰度級的像素?cái)?shù)得到直方圖。第二步把直方圖除以總像素?cái)?shù)得到概率密度PDF。第三步從低灰度到高灰度逐級累加得到累積分布CDF。第四步用CDF乘以255再取整得到映射表然后把原圖像素值逐一代入映射。代碼核心邏輯如下def hist_equalize(img): h, w img.shape total h * w # 統(tǒng)計(jì)直方圖 hist np.bincount(img.ravel(), minlength256).astype(np.float32) # 計(jì)算概率密度和累積分布 pdf hist / total cdf np.cumsum(pdf) # 映射表 map_table np.round(cdf * 255).astype(np.uint8) # 查表映射 return map_table[img]這里有一個不容易注意到的細(xì)節(jié)如果直方圖里0和255兩個端點(diǎn)有大量像素均衡化后灰度會被拉伸得特別夸張反而導(dǎo)致圖像發(fā)白發(fā)灰甚至出現(xiàn)偽輪廓。工程上很少用全局均衡化更多用CLAHE也就是限制對比度自適應(yīng)直方圖均衡化。它先把圖像分成若干小塊分別做均衡化再對局部直方圖的高度做裁剪把超出閾值的部分重新分配能有效抑制噪聲放大和過度增強(qiáng)。筆試問到“直方圖均衡化有什么不足怎么改進(jìn)”把CLAHE的機(jī)制說清楚是個不錯的加分點(diǎn)。3.3 邊緣檢測和CNN卷積核的關(guān)系邊緣檢測在直播和短視頻里是很多后續(xù)處理的基礎(chǔ)。Sobel算子是經(jīng)典的一階梯度算子用兩個3×3卷積核分別計(jì)算水平方向和垂直方向的梯度再合成為梯度幅值。Canny則是更完整的邊緣檢測流程先高斯模糊降噪再算梯度幅值和方向然后做非極大值抑制把邊緣細(xì)化成單像素寬最后用雙閾值滯后連接來消除斷裂。這一節(jié)里面試官最喜歡的追問是“那你覺得傳統(tǒng)邊緣檢測算子和CNN里學(xué)到的卷積核有什么關(guān)系”這個問題我當(dāng)年沒答好后來研究模型可視化了才徹底想明白。CNN第一層卷積核可視化之后你會發(fā)現(xiàn)它們很多都在學(xué)習(xí)邊緣、紋理、顏色塊和Sobel、Gabor這些手工設(shè)計(jì)的濾波器長得非常像。區(qū)別在于CNN的卷積核是數(shù)據(jù)驅(qū)動學(xué)出來的能做到“針對任務(wù)定制”而不只是通用的邊緣提取。這個理解在直播人像分割、高清人像增強(qiáng)任務(wù)里很關(guān)鍵當(dāng)你需要的是“人臉邊緣”而不是“所有物體邊緣”時CNN自上而下的語義信息比單純的梯度計(jì)算有效得多。4. 經(jīng)典網(wǎng)絡(luò)結(jié)構(gòu)題手推VGG參數(shù)量講清ResNet動機(jī)2018年校招筆試網(wǎng)絡(luò)結(jié)構(gòu)題基本是必然出現(xiàn)的板塊。A卷在這一塊不僅考“你認(rèn)不認(rèn)識這些網(wǎng)絡(luò)”更考“你能不能動手算參數(shù)、講清設(shè)計(jì)動機(jī)”。過了這么幾年模型結(jié)構(gòu)迭代了很多但LeNet到ResNet這條演進(jìn)線里的思想仍然是面試官考察網(wǎng)絡(luò)理解能力的試金石。4.1 從LeNet到ResNet的演進(jìn)邏輯LeNet5是1998年的網(wǎng)絡(luò)手寫數(shù)字識別5層結(jié)構(gòu)奠定了“卷積池化全連接”的基本范式。AlexNet在2012年拿到ImageNet冠軍帶來了三個核心改進(jìn)ReLU加速收斂、Dropout緩解過擬合、GPU并行訓(xùn)練讓模型能做得更大。VGG的貢獻(xiàn)是把大卷積核替換成小卷積核堆疊網(wǎng)絡(luò)更深結(jié)構(gòu)更規(guī)整。GoogLeNet用Inception模塊在同一個stage里用不同尺度的卷積并行提取特征同時用1×1卷積做維度升降來控制計(jì)算量。ResNet則在2015年引入了殘差連接徹底解決了深層網(wǎng)絡(luò)訓(xùn)練困難的問題。如果考試讓你“簡述卷積神經(jīng)網(wǎng)絡(luò)的發(fā)展”不要把這些點(diǎn)孤立羅列而要挨個說清“它解決了什么問題、代價(jià)是什么”。比如VGG用3×3堆疊好處是參數(shù)少、非線性強(qiáng)代價(jià)是計(jì)算量仍然很大256層的VGG根本訓(xùn)練不動。正是這些代價(jià)推動GoogLeNet和ResNet的出現(xiàn)。4.2 手算VGG16參數(shù)量算一遍就忘不掉VGG16在筆試?yán)锍霈F(xiàn)頻率極高因?yàn)樗Y(jié)構(gòu)規(guī)整、參數(shù)好算非常適合拿來考察網(wǎng)絡(luò)基本功。VGG16包含13個卷積層和3個全連接層。帶bias參數(shù)的計(jì)算方式每次卷積都會加上輸出通道數(shù)個偏置但為了方便記憶和手算通常先忽略bias最后再統(tǒng)一說明。各層參數(shù)大致如下層卷積核輸入通道輸出通道參數(shù)量conv1_13×33641728conv1_23×3646436864conv2_13×36412873728conv2_23×3128128147456conv3_13×3128256294912conv3_23×3256256589824conv3_33×3256256589824conv4_13×32565121179648conv4_23×35125122359296conv4_33×35125122359296conv5_13×35125122359296conv5_23×35125122359296conv5_33×35125122359296卷積層累加大約是1471萬參數(shù)真正的大頭在后面的全連接層。輸入224×224經(jīng)過5次空間分辨率減半到最后一個卷積層輸出是7×7×512拉平得到25088維所以fc1的參數(shù)量是25088×4096 ≈ 1.028億fc2是4096×4096 ≈ 1678萬fc3是4096×1000 ≈ 410萬。三項(xiàng)加起來超過1.2億VGG16總參數(shù)量約1.38億其中全連接層占了80%以上。這也解釋了為什么后來很多網(wǎng)絡(luò)把全連接層換成全局平均池化參數(shù)瞬間砍掉一大截精度損失卻很小。準(zhǔn)備筆試時一定要親手算一遍這個表算完對VGG的參數(shù)分布會有非常直觀的感受面試官問“VGG哪部分參數(shù)最多”這種細(xì)節(jié)題也不會卡殼。4.3 “設(shè)計(jì)一個分類網(wǎng)絡(luò)”這類題的答題框架A卷簡答題里有一類開放題讓你針對一個給定任務(wù)設(shè)計(jì)網(wǎng)絡(luò)結(jié)構(gòu)比如“為100類圖像分類設(shè)計(jì)一個CNN”。這種題沒有標(biāo)準(zhǔn)答案但答題邏輯是有章法的。我后來在面試別人時發(fā)現(xiàn)能拿高分的候選人都有一個共同點(diǎn)回答有框架不是東一句西一句。我的建議是按下述結(jié)構(gòu)答。第一步明確任務(wù)約束輸入尺寸多大、類別數(shù)多少、計(jì)算設(shè)備是什么、目標(biāo)幀率多少。這些參數(shù)直接決定了網(wǎng)絡(luò)規(guī)模的上限。第二步提出基礎(chǔ)方案先用預(yù)訓(xùn)練的ResNet50做遷移學(xué)習(xí)這是絕大多數(shù)實(shí)際項(xiàng)目的默認(rèn)起點(diǎn)成本低、效果好。第三步如果要求不依賴預(yù)訓(xùn)練或者要端上部署再設(shè)計(jì)輕量結(jié)構(gòu)一個stem卷積加4個stage每個stage堆疊兩個殘差塊通道數(shù)翻倍、分辨率減半最后全局平均池化接全連接層。第四步講訓(xùn)練配置數(shù)據(jù)增強(qiáng)、BatchNorm、學(xué)習(xí)率warmup、Dropout。第五步給出評估指標(biāo)和備選方案。這套框架答下來無論面試官出什么變體你都能從“約束—選型—設(shè)計(jì)—訓(xùn)練—評估”的完整鏈路去應(yīng)對而不是卡在“選什么網(wǎng)絡(luò)”這一步。5. 開放性方案題兩小時內(nèi)設(shè)計(jì)一個實(shí)時美顏系統(tǒng)A卷最后一道大題我記得印象非常深大意是“某直播平臺需要對視頻流做實(shí)時美顏處理包括磨皮、美白、瘦臉請?jiān)O(shè)計(jì)一套算法方案并說明處理流程和關(guān)鍵技術(shù)選型。”這類題是整張卷子的壓軸也是最容易拉開差距的地方。很多人在前面選擇題、計(jì)算題上答得不錯到了這道題就把“美顏”理解成“用一個深度學(xué)習(xí)模型輸入原圖輸出美化圖”然后就沒有然后了。這種回答在真實(shí)工程里根本落不了地。5.1 讀懂題目里的性能約束端上實(shí)時意味著什么開放性方案題的第一步不是上來就寫模塊而是先解讀約束條件。這道題最關(guān)鍵的詞是“實(shí)時視頻流”。直播場景下美顏算法跑在用戶的手機(jī)端視頻流每秒30幀意味著單幀處理的時間預(yù)算只有約33毫秒。而這33毫秒還要留給采集、編碼、網(wǎng)絡(luò)傳輸真正分給美顏算法的可能只有10到20毫秒。這個約束會推翻很多“看起來很美”的方案。比如直接用GAN做端到端人像美化2018年的技術(shù)水平根本跑不到實(shí)時幀率用一個上百層的分割網(wǎng)絡(luò)做人像分割再美化推理耗時也超標(biāo)。所以真正合理的方案必須走輕量化路線人臉檢測用輕量級網(wǎng)絡(luò)磨皮美白用傳統(tǒng)圖像算子瘦臉大眼用基于關(guān)鍵點(diǎn)的局部變形而不是盲目堆深度學(xué)習(xí)。答這類題能夠主動說出“單幀要在20ms內(nèi)完成所以必須考慮計(jì)算量”這句話比列一堆先進(jìn)模型的名字要強(qiáng)得多因?yàn)樗f明你真的做過工程而不只是看過論文。5.2 模塊拆解人臉檢測、關(guān)鍵點(diǎn)、分割與美化一個可落地的實(shí)時美顏系統(tǒng)通常拆成四個模塊。人臉檢測負(fù)責(zé)找到畫面里的人臉區(qū)域。2018年MTCNN是主流選擇它用一個小網(wǎng)絡(luò)級聯(lián)在CPU上也能跑得動現(xiàn)在工程上更多人用RetinaFace或者SCRFD這類輕量級檢測器精度更高。人臉關(guān)鍵點(diǎn)定位負(fù)責(zé)輸出眉毛、眼睛、鼻子、嘴巴、臉部輪廓的位置瘦臉、大眼這類形變操作全靠這些關(guān)鍵點(diǎn)。磨皮美白之前最好先做皮膚分割或人臉解析生成一張只包含皮膚區(qū)域的mask這樣磨皮不會把眼睛、頭發(fā)、眉毛一起糊掉。最后才是美化算子本身磨皮用雙邊濾波或引導(dǎo)濾波美白用亮度曲線調(diào)整和顏色校正瘦臉大眼用圖像局部仿射變形每一步處理完后通過mask做透明度混合。這個鏈路可以整理成一張表模塊典型算法輸出說明人臉檢測MTCNN / RetinaFace人臉包圍盒鎖定處理區(qū)域關(guān)鍵點(diǎn)定位68點(diǎn) / 106點(diǎn) / 240點(diǎn)面部關(guān)鍵點(diǎn)坐標(biāo)支撐瘦臉、大眼皮膚分割BiSeNet / 傳統(tǒng)顏色空間皮膚mask限定磨皮美白區(qū)域磨皮雙邊濾波 / 引導(dǎo)濾波平滑后的人臉區(qū)域保邊避免糊臉美白亮度曲線 / 色彩調(diào)整更白的膚色與磨皮疊加局部變形基于關(guān)鍵點(diǎn)的網(wǎng)格仿射瘦臉/大眼效果強(qiáng)度由用戶控制答模塊拆解的時候還要講清楚“時序一致性”的問題。視頻是連續(xù)的人臉關(guān)鍵點(diǎn)檢測每一幀都會有輕微抖動如果拿原始坐標(biāo)直接做瘦臉畫面里臉型會閃來閃去。所以關(guān)鍵點(diǎn)坐標(biāo)必須做時序平滑最簡單的做法是對坐標(biāo)序列做指數(shù)滑動平均更高級一點(diǎn)用卡爾曼濾波。這個細(xì)節(jié)當(dāng)年很多人答不出來但恰恰是直播美顏里最影響用戶體驗(yàn)的問題之一。5.3 面試官追問時的加分回答筆試只是第一關(guān)后面的面試還會圍繞方案題追問。有幾個追問方向當(dāng)年我都被問過提前整理一下很有價(jià)值。追問一“為什么不用GAN做美顏”你的回答要說明GAN生成結(jié)果不可控實(shí)時性差訓(xùn)練不穩(wěn)定在端上算力嚴(yán)重受限的條件下很難滿足30幀要求。事實(shí)上直播美顏的核心思路是“保守”用戶要的是自然好看不是風(fēng)格化大變臉。后來很多輕量級生成模型出來之后端側(cè)確實(shí)也能跑一些生成式美化效果了但工程上仍然傾向于用可解釋、可調(diào)節(jié)的傳統(tǒng)算子。追問二“低端手機(jī)上跑不動怎么辦”這是性能優(yōu)化問題。可以從三方面回答第一是模型輕量化用模型剪枝、通道剪枝把推理量降下去第二是量化FP32模型轉(zhuǎn)成FP16、INT8推理在端上能帶來幾倍的加速內(nèi)存占用也大幅下降。FP16、INT8這些模型壓縮技術(shù)現(xiàn)在已經(jīng)是部署標(biāo)配第三是工程優(yōu)化比如多線程并行、算子融合、GPU/NPU加速等。追問三“美顏強(qiáng)度如何讓用戶調(diào)節(jié)”這就要在方案里加上“美化后圖像和原圖做透明度混合”的步驟用戶拖動滑塊時改變alpha系數(shù)。這個點(diǎn)很細(xì)但能體現(xiàn)產(chǎn)品思維面試官會覺得你不只懂技術(shù)還理解需求。6. 復(fù)盤建議筆試不是終點(diǎn)是工程能力的起點(diǎn)前面把考點(diǎn)拆得差不多了最后聊點(diǎn)實(shí)干層面的東西。筆試這件事結(jié)果當(dāng)然重要但備考的過程本身就是一次系統(tǒng)性的能力梳理。大多數(shù)人算法基礎(chǔ)不差短板在于對知識的理解浮于表面會背概念不會算題會調(diào)框架不會手推。A卷這種考察風(fēng)格恰恰是在逼你把基礎(chǔ)打扎實(shí)。6.1 做題順序與時間分配我當(dāng)年拿到A卷先快速掃了一圈然后把計(jì)算題和基礎(chǔ)簡答題做掉把開放方案題留在最后。這個順序總體是對的但有一個教訓(xùn)不要在計(jì)算題上戀戰(zhàn)。卷子里有一道多層的感受野題我第一次計(jì)算時因?yàn)樵凇暗谝粚觭tride要不要計(jì)入感受野公式”上糾結(jié)太久結(jié)果方案題的時間被壓縮了答得倉促。后來才發(fā)現(xiàn)方案題占的分值比重更大而且更容易拿分。合理的節(jié)奏大致是前10分鐘通讀全卷標(biāo)記題目難度然后先做會做的計(jì)算題和簡答題每道題控制時間不會的果斷跳過留足30分鐘給方案題最后10分鐘檢查計(jì)算題的公式、單位、符號。這個時間分配不是萬能的但可以避免“難題寫不完、簡單題沒空做”的尷尬。6.2 不會的題怎么辦筆試遇到完全不會的題最忌諱的是留白。哪怕不會寫完整答案也要把你想到的相關(guān)知識點(diǎn)、已有條件、可能的解決思路寫上去。比如不會寫拉普拉斯銳化的完整代碼就把卷積模板和公式寫出來說明它的作用不會設(shè)計(jì)完整的實(shí)時美顏系統(tǒng)就把人臉檢測關(guān)鍵點(diǎn)美化的鏈路畫出來再講講每個模塊負(fù)責(zé)什么。閱卷老師在這個過程中能看到你的分析能力而候選人之間拉開差距的往往不是知識量而是“遇到陌生問題時如何組織思路”。6.3 現(xiàn)在回看哪些考點(diǎn)已經(jīng)過時哪些依然是核心2018年到今天圖像算法領(lǐng)域變化很大。原題里很多內(nèi)容已經(jīng)不再是主流技術(shù)路徑MTCNN換成了更輕量的檢測器傳統(tǒng)美顏算子正在被生成式模型覆蓋CNN之外有了Transformer、擴(kuò)散模型這些新架構(gòu)。但你看這份A卷考察的能力——卷積計(jì)算、網(wǎng)絡(luò)設(shè)計(jì)、圖像處理基礎(chǔ)、工程取舍——沒有一樣過時。無論模型怎么換你依然需要理解感受野、理解參數(shù)量、理解數(shù)據(jù)分布、理解性能瓶頸。現(xiàn)在再準(zhǔn)備校招除了把基本功補(bǔ)扎實(shí)建議把模型部署這條線也補(bǔ)上。FP16、BF16、INT8這些數(shù)值格式的差異和選型邏輯在真實(shí)項(xiàng)目里非常重要。舉個小例子同一個模型在FP32下顯存占用是4字節(jié)FP16是2字節(jié)后者能讓一個原來跑不動的batch size變得可行推理速度也更快。這類細(xì)節(jié)在2018年校招里極少出現(xiàn)但現(xiàn)在已經(jīng)成了算法工程師的基本功?;乜催@份卷子對我來說最大的意義不是拿到offer而是它讓我在入職之前就把圖像算法的“地面功夫”練了一遍。如果你正在準(zhǔn)備類似的筆試我的建議是拿一份過去的真題關(guān)掉搜索引擎給自己完整的兩小時老老實(shí)實(shí)做一遍。做不出來很正常但做完之后對照解析把每一道錯題背后的知識點(diǎn)補(bǔ)上這一輪下來效果比看十篇面試經(jīng)驗(yàn)都實(shí)在。卷子會過時但底層能力不會。