搜尋課程與筆記

搜尋筆記

輸入主題、關鍵字或單元編號,例如 Flow Matching、U4。

    按 Esc 關閉 · ⌘ / Ctrl K 開啟搜尋

    L4.3 19 分鐘閱讀 2026年10月

    L4.3 一張圖裡同時有紋理、物件和整個場景,一個固定大小的核怎麼辦?

    一個核只看得到一個尺度

    上一篇的卷積只看一小塊,照片卻同時有細節與整體。看地圖時也一樣:縮小能看出整條路,放大才看清街口。模型能不能同時保留這兩種資訊?

    真實的資料不是這樣。一張照片裡同時有紋理(幾個像素的週期性)、物件(幾十個像素)、和整個場景的構圖(整張圖)。而「這是貓還是狗」這個判斷可能需要同時用到毛的質感和耳朵的形狀,兩者差了兩個數量級的尺度。

    一個 K×KK\times K 核看的是邊長 KK 的區域。先考慮最直接的做法:stride 1、無 dilation 地疊 dd 層。理論上輸出可能受哪一塊輸入影響?這是接受域(receptive field),邊長為

    RF=1+d (K−1).\mathrm{RF}=1+d\,(K-1).

    K=5K=5 時:

      depth   1   RF =    5
      depth   2   RF =    9
      depth   4   RF =   17
      depth   8   RF =   33
      depth  16   RF =   65
      depth  32   RF =  129

    接受域隨深度線性成長。 要看到相隔 128128 個位置的兩件事,要疊 3232 層——而且那 3232 層每一層都在原始解析度上跑,每一層都是全尺寸的計算。

    一個 5×55\times5 的核要看到相隔 128128 個位置,得疊 3232 層;
    只要每兩層把解析度砍半,1010 層就能看到 249249——
    那被砍掉的東西去哪裡了?

    課堂提問Q1

    降取樣(把解析度砍半)讓接受域便宜了非常多。先算清楚便宜多少,再問代價:被丟掉的具體是什麼資訊?而它回得來嗎?

    先想一想,再展開看整理後的答案

    先算便宜多少。 降取樣之後,同樣一個 K×KK\times K 的核在原始座標上覆蓋的範圍加倍了。所以接受域的成長從「每層加 K−1K-1」變成「每層加 (K−1)×(K-1)\times 目前的 stride」,而 stride 每降一次就乘二。實測(每兩層降一次):

      depth   1   RF =    5   (stride 1)
      depth   2   RF =    9   (stride 2)
      depth   4   RF =   25   (stride 4)
      depth   6   RF =   57   (stride 8)
      depth   8   RF =  121   (stride 16)
      depth  10   RF =  249   (stride 32)

    這張表假設每第二個 5×55\times5 卷積使用 stride 2。一般可逐層算 rℓ=rℓ−1+(Kℓ−1)jℓ−1r_\ell=r_{\ell-1}+(K_\ell-1)j_{\ell-1}、jℓ=sℓjℓ−1j_\ell=s_\ell j_{\ell-1}:rr 是原始座標中的接受域,jj 是輸出相鄰位置在原圖的間距。通道數固定時,較小特徵圖可省計算;若通道同時增加,總成本還要另外算。

    代價是什麼。 降取樣把相鄰的幾個值合成一個。一個在兩三個取樣點的尺度上變化的東西——一條細線、一個邊界的確切位置、一段高頻紋理——在合併之後就不見了。

    而且它回不來。 升取樣(把一個值複製成兩個、或內插)只能造出「在這個尺度上平滑」的東西,它沒有任何資訊可以用來重建那些細節。這不是實作不夠好,是資訊已經被刪掉了。

    所以問題變成:這個代價要不要付?

    • 如果輸出是低維的(一個類別、一個分數),那細節本來就要被丟掉,降取樣只是提早做了這件事。這就是分類網路的形狀:一路降到底。
    • 如果輸出和輸入一樣大而且需要細節(分割的邊界、去噪後的影像、生成的圖),那丟掉就是致命的——你要輸出的正是那些被刪掉的東西。

    一個自然的嘗試是:讓高解析度細節另有一條路,不必全部經過瓶頸。編碼側取得大範圍資訊,解碼側逐步升回解析度,同時接入編碼側對應層的特徵;這就是 U-Net 的長 skip connection。它是常用設計,不是唯一可行架構。

    降取樣毀掉的到底是什麼

    上面說「高頻回不來」是定性的。把它量出來。

    做法很單純:拿一個純頻率的訊號(長度 6464 的餘弦),做一次 2×2\times 平均池化再用最近鄰升回原長度,然後問兩件事——同一個頻率剩下多少振幅,以及整條訊號還差多遠。

        f   週期(取樣點)   保留下來的同頻振幅   整體重建誤差
        1        64.0             0.9976            0.0491
        2        32.0             0.9904            0.0980
        4        16.0             0.9619            0.1951
        8         8.0             0.8536            0.3827
       12         5.3             0.6913            0.5556
       16         4.0             0.7071            0.7071
       24         2.7             0.1464            0.9239
       31         2.1             0.0024            0.9988
       32         2.0             0.0000            1.0000

    最後一列是乾淨的零。 週期剛好是兩個取樣點的成分(+1,−1,+1,−1,…+1,-1,+1,-1,\dots)在 2×2\times 平均之後每一組都變成 00——完全消失,不是變小。

    這張表量的是指定 sinusoid 經過這個平均濾波與降取樣之後的變化。不同頻率受影響不同,但不能把它改說成所有五、六像素以下的特徵都會損失一半;訊號形狀、相位與採樣方式也重要。

    而右邊那一欄說得更直接:週期 88 個取樣點的訊號,降一次再升回來,整體誤差已經是 38%38\%。降兩次就是在對已經模糊的東西再模糊一次。

    平均池化可能讓不同輸入變成同一個輸出;只靠這個輸出,不能唯一還原原本細節。升取樣可以猜細節,但不是找回已保留的證據。

    這張表只測一種池化、升取樣與正弦訊號,不能推出通用的 s/5s/5 門檻。實際設計要檢查細節是否在通道、skip 或其他表示中保留;降低空間解析度不必然刪掉所有資訊,例如把像素重排到通道可以是可逆的。

    注意表裡有一列不是單調的,而那是混疊

    仔細看會發現 f=16f=16(週期 44)的保留振幅是 0.70710.7071,比 f=12f=12(週期 5.35.3)的 0.69130.6913 還高。這不是量測誤差。

    降取樣會讓部分不同頻率在新格點上難以區分,這叫混疊;升取樣又可能產生影像頻率。還要分清傅立葉振幅與投影到原餘弦的係數,並注意相位與奈奎斯特頻率的特殊情況。f=20f=20 比 f=12f=12 高,不能把它稱為原本不存在的低頻。這張表不適合直接推出普遍的頻率衰減門檻。

    右邊那一欄(整體重建誤差 0.55560.5556 對 0.70710.7071)就沒有這個非單調——因為它把「搬到別處去」也算成誤差。

    實務上的後果是:降取樣之前通常要先低通濾波(先模糊再取樣),否則高頻會偽裝成低頻混進來。這也是為什麼在生成模型裡,單純用 stride-2 的升降取樣容易產生棋盤狀的假紋理,而加上平滑就好很多。

    接受域買到什麼,降取樣付掉什麼

    圖說: 降取樣擴大原始座標中的接受域;平均池化可能丟失細節,因此高解析度資訊需要另外保留。

    那條橫跨的線

    Q1 已經把 skip connection 的動機推出來了:如果輸出需要細節,細節就不能經過瓶頸。

    但要把這件事和另一個常被混在一起的東西分開。深度學習裡有兩種「skip」,它們解決的是完全不同的問題:

    • U-Net 的 skip(長跳接):從編碼側第 kk 層接到解碼側對應的第 kk 層,通常是串接(concatenate)。它解決的是資訊被降取樣刪掉的問題,跨越的是整個瓶頸。
    • 殘差連接(短跳接):hl+1=hl+F(hl)h_{l+1}=h_l+F(h_l),跨越一兩層,通常是相加。它解決的是深度本身讓網路難以訓練的問題。

    兩者都叫 skip,但一個是為了資訊、一個是為了梯度。下一節處理第二個。

    深度本身的代價

    把網路疊深有一個獨立於接受域的問題:它會變得訓練不起來。這件事在 同一張地圖從不同地方出發:損失曲面與初始化 已經用 gain 掃過一次;這裡換一個角度,直接量深度。

    設定:一個 144→32→32→⋯→1144\to32\to32\to\cdots\to1 的 tanh 堆疊,深度從 88 到 6464,三種接法——無殘差(h←tanh⁡(hW+b)h\leftarrow\tanh(hW+b))、殘差(h←h+tanh⁡(hW+b)h\leftarrow h+\tanh(hW+b))、殘差後接 LayerNorm。Adam η=0.003\eta=0.003、1200 步、三個 seed 取中位數。

    先看初始化時每一層輸出的大小(深度 3232):

                  L1       L4       L8       L16      L32
      無殘差     0.2418   0.2265   0.1695   0.1513   0.0928
      殘差       0.2418   0.5845   1.2501   2.5496   4.3765
      殘差+LN    0.2418   1.0000   1.0000   1.0000   1.0000

    表中的量級不同,但不能只靠這張表唯一辨認原因。Ba、Kiros 與 Hinton [3] 的 LayerNorm,先對指定特徵維度計算平均 μ(h)\mu(h) 與變異數 s2(h)s^2(h):

    LN⁡(h)=γ⊙h−μ(h)s2(h)+ε+β.\operatorname{LN}(h)=\gamma\odot\frac{h-\mu(h)}{\sqrt{s^2(h)+\varepsilon}}+\beta.

    只有在忽略 ε\varepsilon、未使用可學 affine 縮放等特定情況,標準化後的變異數才恰好為 1;實務值接近 1 並非所有 LN 輸出都精確等於 1。

    再看梯度能不能傳回去(第一層與最後一個隱藏層的梯度大小比,11 表示兩端一樣強):

      depth   4   無殘差 2.87e-01   殘差 1.41e+01   殘差+LN 2.71e-02
      depth   8   無殘差 7.05e-01   殘差 5.61e+00   殘差+LN 6.59e-02
      depth  16   無殘差 7.60e-02   殘差 1.18e+00   殘差+LN 1.74e-01
      depth  32   無殘差 6.47e-02   殘差 7.64e-01   殘差+LN 1.38e-01
      depth  64   無殘差 7.33e-02   殘差 4.97e-01   殘差+LN 1.29e-01

    在深度 6464 這一列,殘差的前後梯度比更接近 1。它的局部 Jacobian 是 I+∂F/∂hlI+\partial F/\partial h_l,因此多了直接傳遞的分支;但總梯度仍可能受到其他分支抵消或放大。這張表支持這次設定有改善,不保證所有殘差網路都不會梯度消失。

    最後看真的訓練得起來嗎:

      depth   8   無殘差 0.0000   殘差 0.0000   殘差+LayerNorm 0.0000
      depth  16   無殘差 0.0000   殘差 0.0000   殘差+LayerNorm 0.0000
      depth  32   無殘差 0.7399   殘差 0.0000   殘差+LayerNorm 0.0000
      depth  64   無殘差 0.9915   殘差 0.0000   殘差+LayerNorm 0.9096

    深度 3232 那一列就是整個殘差連接存在的理由:同一個容量、同一個資料、同一個最佳化器,沒有殘差的版本停在 0.73990.7399(幾乎等於「輸出常數」的水準),有殘差的版本降到 0.00000.0000。

    殘差不是讓網路變強,是讓已經存在的容量變得訓練得到。

    展開細節為什麼「II 加上一個小修正」是一個好的預設行為

    把一層寫成 hl+1=hl+F(hl)h_{l+1}=h_l+F(h_l)。若特別將殘差分支初始化得很小,它接近恆等映射;但很多小修正相加仍可能累積,不保證疊一百層後整體也很接近恆等。

    這件事有兩個好處。

    一,起點是一個合理的函數。 一個無殘差的深網路在初始化時算出來的東西,和輸入幾乎沒有關係(上表的 0.09280.0928:訊號已經被壓掉大半)。殘差網路的起點是「把輸入原樣送出去」,那至少是一個有意義的函數,而訓練從那裡開始只需要學修正。

    二,加深不會變差。 如果第 L+1L+1 層學到 F≈0F\approx0,那整個網路就退化成 LL 層。所以「更深」在假設空間上包含「更淺」——這在無殘差的堆疊上是不成立的,因為每一層都必須做點什麼。

    代價是上表中間那一行:輸出的大小隨深度成長(0.24→4.380.24\to4.38),因為每一層都在往上加。真實的架構用兩種方式處理它——在殘差分支上乘一個小係數(例如 1/21/\sqrt2 或一個學出來的接近零的初值),或在每一層之後做正規化。下一節是後者。

    刻意違反:正規化不是免費的保險

    前一節的最後一列有一個沒有被解釋的數字:深度 6464,殘差是 0.00000.0000,殘差加 LayerNorm 是 0.90960.9096。

    加了正規化反而訓練不起來。這和「正規化讓深網路更好訓練」這個常見說法是反的,所以需要解釋。

    線索在梯度比那張表:殘差在深度 6464 是 0.4970.497,殘差加 LN 是 0.1290.129——LN 讓梯度比變差了。原因是 LayerNorm 在每一層都把訊號投影到一個固定的尺度上,而那個投影會把梯度裡「改變整體大小」的成分消掉(見下面那個精確的量測)。在這個特定的 toy 上,殘差造成的那個成長本來就沒有失控到需要處理,而 LN 的那點損失就變成純虧。

    但 LayerNorm 也真的在做一件很具體、很有價值的事。 量出來:

      W 乘以   0.01 :  max|LN(XWc) - LN(XW)| = 6.853e-03
      W 乘以   1.00 :  max|LN(XWc) - LN(XW)| = 0.000e+00
      W 乘以 100.00 :  max|LN(XWc) - LN(XW)| = 6.874e-07

    一層的輸出對自己權重的大小完全免疫。 把 WW 放大一百倍,正規化之後的輸出一模一樣(10−710^{-7} 是浮點誤差;c=0.01c=0.01 那個 10−310^{-3} 是 ε=10−5\varepsilon=10^{-5} 造成的,把 ε\varepsilon 調小它也會消失)。

    而這件事對梯度的後果是精確的:

      W 乘以  0.1 :  對 W 的梯度範數 = 178.238   (× c = 17.824)
      W 乘以  1.0 :  對 W 的梯度範數 =  17.824   (× c = 17.824)
      W 乘以 10.0 :  對 W 的梯度範數 =   1.782   (× c = 17.824)

    對孤立的 LN⁡(XW)\operatorname{LN}(XW),忽略 ε\varepsilon 且 c>0c>0 時,正向輸出對 W↦cWW\mapsto cW 不變,相應梯度按 1/c1/c 縮放。但權重範數同時乘 cc,所以固定步長的相對更新量按 1/c21/c^2 改變,不是自動固定。加入 bias、非線性或殘差後,也要重新檢查這個尺度關係。

    正規化買的是「對尺度免疫」,賣的是「梯度裡關於尺度的那一部分」;在尺度本來就沒失控的時候,那是純付出。

    所以這兩件事的關係不是「都加上去比較安全」。 殘差解決梯度路徑,正規化解決尺度漂移。真實的深網路兩個都需要,因為它們在寬度、深度、非線性、學習率都放大之後,殘差造成的成長會真的失控。但在這個 3232 寬、tanh⁡\tanh、小學習率的 toy 上,第二個問題不存在,於是只剩成本。

    這件事在自己的專案上怎麼判斷:量一次每一層輸出的 RMS。如果它隨深度穩定,正規化大概只是在收費;如果它像上表那樣一路爬到幾十幾百,那就是它要解決的問題。

    接受域、頻率、深度:三個設定

    互動 demo:降取樣次數、skip、深度、接法四個設定,對應三個互相獨立的問題。

    一個 U 形要怎麼設計

    把三節的結論合成一組可以照做的決定。

    1. 先算你需要多大的接受域。 這是一個關於任務的問題:判斷要用到的最遠的兩個東西相隔多少個像素?算出來之後,用第一節的兩張表決定「疊深」與「降取樣」怎麼配。
    2. 再算你能降幾次。 用第二節的規則:要保留尺度為 ss 的特徵,總降取樣倍數不要超過 s/5s/5。如果這兩個數字打架(要看得很遠,又要保留很細的東西),那就是需要 U 形的訊號——降下去取得脈絡,用 skip 把細節帶回來。
    3. 決定 skip 接什麼、怎麼接。 串接保留兩邊的完整資訊但讓通道數變多;相加比較省但要求兩邊的語意可以直接疊加。輸出需要精確定位(分割、去噪、生成)時,通常串接比較穩。
    4. 檢查梯度路徑。 toy 的深度門檻不是通用門檻;各層梯度、更新量與訓練表現要一起看。
    5. 比較正規化的具體版本。 pre-norm、post-norm、affine 與步長都會影響結果;單看 RMS 不能確定加不加 LN。

    這一切依賴什麼。 一,資料真的有多尺度結構;如果沒有(例如所有有用的模式都是同一個大小),一個平的堆疊更簡單也更好。二,降取樣的對象要是空間上平滑的;對於本來就沒有「相鄰」概念的輸入,降取樣沒有意義。三,第四、五節的數字是在一個 3232 寬的 tanh⁡\tanh 堆疊上量的——深度的門檻和正規化的必要性都會隨寬度、非線性與學習率而變,所以那兩個結論要在自己的設定上重量一次,而重量的方法就在上面第 4、5 點。

    檢查理解

    想一想

    第二節的表裡,f=32f=32(週期 22 個取樣點)降取樣後的保留振幅是精確的 0.00000.0000。這說明:

    想一想

    一個任務要判斷相隔約 100100 個像素的兩個物件的關係,同時要輸出寬度只有 33 個像素的邊界。最合適的設計方向是:

    想一想

    深度 6464 時,殘差的訓練 MSE 是 0.00000.0000 而殘差加 LayerNorm 是 0.90960.9096。最準確的解讀是:

    想一想

    下列哪一句不對?

    參考文獻

    1. Ronneberger, O., Fischer, P. & Brox, T. U-Net: Convolutional Networks for Biomedical Image Segmentation. MICCAI 2015.(編碼–解碼加長跳接的原始設計,以及它為什麼在需要精確定位的任務上是必要的。)
    2. He, K., Zhang, X., Ren, S. & Sun, J. Deep Residual Learning for Image Recognition. CVPR 2016.(殘差連接、以及「更深不該更差」這個論證。)
    3. Ba, J., Kiros, J. & Hinton, G. Layer Normalization. 2016.(本篇第五節那個尺度免疫性質的出處與推導。)