Activation 是一個「一個數字進、一個數字出」的函數。訓練時真正重要的不只是它的形狀 f(x),還有它的斜率 f′(x):反向傳播每經過一層,就要乘上這一層的斜率。斜率接近 0 的地方,梯度在這裡就停了。下面把十種 activation 和它們的斜率畫在同一張圖上,把「輸入的範圍」拉到 ±10,看 sigmoid 和 tanh 的兩端發生什麼事。
講義列的四個性質:
另外一個實務上一直存在的條件是計算便宜:每一層、每一個 token、每一個像素都要算一次,exp 或 erf 的成本會被放大成千上萬倍。這是 SEC.04 最後講 mobile 的原因。
三種角色(講義的整理):(1)表達能力:讓模型表示非線性函數與複雜決策邊界。(2)資訊選擇:決定哪些 feature 通過、抑制、放大或歸零。(3)訓練與部署:影響 gradient、sparsity、quantization、outlier 與硬體成本。所有的演進都在平衡這三件事。
演進:
ReLU 的負半軸斜率是 0。一個神經元算 z = w·x + b,如果所有輸入算出來的 z 都落在負半軸,它的輸出就全部是 0,傳回來的梯度也全部是 0。梯度是 0,權重就不會被更新;權重不更新,z 就永遠留在負半軸。它不是「暫時沒反應」,是永遠停工。下面這個神經元在學一條目標折線,你可以讓它好好訓練,也可以給它一記大梯度,看它怎麼死。
稀疏表示:講義說,用以 0 為中心的均勻初始化時,大約 50% 的 hidden unit 輸出是 0,加上 regularization 會更多。講義的貓耳偵測器例子:convolution 對「貓耳」反應 3.2、「毛髮邊緣」0.5、「平坦背景」−1.8;過 ReLU 後變成 3.2、0.5、0。負反應被當成「這個特徵不存在」。
ReLU 的注意事項(講義):只用在 hidden layer,輸出層分類用 softmax、回歸用線性。0 斜率會擋住梯度,但只要梯度能沿著某些路徑傳回去就不是大問題。輸出沒有上界可能數值不穩,L1 regularization 有幫助;ReLU6 把上界設在 6,方便 INT8 量化。試過用平滑的 Softplus 取代,結果 ReLU 比較好。
| 名字 | 負半軸 | 解決什麼 | 代價 |
|---|---|---|---|
| ReLU | 0 | 最簡單、最稀疏、硬體成本最低;正半軸不飽和 | 會死 |
| ReLU6 | 0,正半軸上限 6 | 限制 activation 範圍,INT8 量化比較好設 scale | 大訊號被截掉 |
| Leaky ReLU | αx,α 固定(如 0.01) | 負半軸還有梯度,避免完全無梯度 | 不再有 exact zero |
| PReLU | αx,α 是學出來的 | 讓負斜率可學習 | 多一個參數,可能 overfit |
| ELU / SELU | α(eˣ − 1),平滑地飽和到 −α | 輸出平均更接近 0,改善分佈 | 要算 exp;負區域仍會飽和;有 normalization 和 residual 後優勢被取代 |
| MaxOut | 不是固定函數 | 取 K 條直線的最大值,可近似任意凸的 activation,涵蓋 ReLU 與 Leaky ReLU;不飽和、不會死 | 參數變成 K 倍 |
MaxOut 的寫法就是 max(XW + b, axis=1):先算 K 組線性輸出,再取最大。ReLU 是 K = 2、其中一組固定為 0 的特例。
修補的兩個方向(講義):保留 ReLU 優勢的一派(ReLU、ReLU6、ReLU²);修補 ReLU 缺陷的一派(Leaky、PReLU、ELU / SELU)。ReLU² 在 SEC.04 會回來。
SEC.01 看到 sigmoid 的斜率最大只有 0.25。一層看起來還好,問題在深:chain rule 說,傳到第一層的梯度,是每一層斜率一路乘起來。0.25 乘 10 次是百萬分之一。反過來,如果每層放大超過 1,乘 30 次會變成天文數字。下面把「每層的斜率 × 權重大小」連乘,用對數刻度畫出來。
MNIST 的例子(講義引用):用 sigmoid 的全連接網路,2 層 96.48%、3 層 96.9%、4 層 96.57%、5 層 96.53%。加深沒有變好,反而退步。原因是靠近輸入的那幾層幾乎沒在學:同一個網路裡,越前面的層梯度越小。講義的結論是:深網路的梯度是不穩定的。
為什麼是 1/4:σ′(x) = σ(x)(1 − σ(x))。σ 在 0 到 1 之間,兩個加起來是 1 的數相乘,最大是 0.5 × 0.5 = 0.25,出現在 x = 0。一旦 x 偏離 0,σ′ 更小;在飽和的兩端趨近 0。
Tanh:最大斜率是 1,又以 0 為中心,所以講義說 tanh 永遠比 sigmoid 好;但它兩端一樣飽和,還是會梯度消失。
和初始化的關係:權重太小,訊號一層層縮到 0;權重太大,tanh 和 sigmoid 被推進飽和區。Xavier 初始化讓每層輸出的變異數維持一樣(Var(W) = 1/n);ReLU 會把一半的輸出變 0,所以 He 初始化再多乘 2。
Exploding gradient:倍率大於 1 時,梯度一路放大,一步更新就把權重推到很遠,loss 變成 NaN。講義也提醒 ReLU 的輸出沒有上界,可能造成數值不穩,L1 regularization 有幫助。
講義的比喻:ReLU 是開關,SiLU 是調光器。它不只問「要不要通過」,而是問「通過多少」。GELU 和 SiLU 讓強正值幾乎完整通過、小負值保留一點、強負值慢慢壓下去。現代 LLM 再往前一步:通過多少不由自己決定,而是由另一條路徑算出來的 gate 決定。這就是 SwiGLU。下面比較兩個神經元:一個是 ReLU(x₁ + x₂),一個是 Swish(x₂) × x₁。
GELU(Gaussian Error Linear Unit):GELU(x) = x · Φ(x),Φ 是標準常態分佈的累積分佈函數。講義的解讀:把輸入乘上「它比其他輸入大的機率」;也可以看成 ReLU 的平滑版加上依輸入決定的 dropout。講義的例子:x = −0.5(微弱負面訊號)時 ReLU 給 0、梯度 0;GELU 給約 −0.154、梯度約 0.13,訊號還在,還能更新權重。x = −10(極端噪音)時兩者都接近 0。精確版要算 erf,實務常用近似式 0.5x(1 + tanh[√(2/π)(x + 0.044715x³)]) 或 x·σ(1.702x)。
為什麼 BERT 用 GELU:token representation 的每一個維度不一定能用「正 = 有用、負 = 沒用」解釋,GELU 讓弱負訊號仍可參與表示;它和 LayerNorm、residual connection、large-batch training 搭配良好。講義的另一個例子是 “not bad”:硬切負訊號可能丟掉語意反轉的關鍵。缺點:沒有 exact sparsity,硬體比 ReLU 複雜,activation 仍可能出現 outlier。
SiLU / Swish:f(x) = x · σ(βx),β = 1 時叫 SiLU。是用自動搜尋找出來的 activation,在比較深的模型上常比 ReLU 好,常見於 EfficientNet 這類 modern CNN。平滑、非單調、正半軸近似線性。限制:需要 sigmoid,沒有 exact sparsity,量化或 ASIC 上比 ReLU 複雜,單純替換不保證每個架構都變好。
Mish:x · tanh(softplus(x)),延續 Swish 的平滑 self-gating。講義備註引用的論文數字:最終準確度比 Swish 高 0.494%、比 ReLU 高 1.671%。曲線幾乎處處平滑,輸出地貌比較平滑、比較好最佳化。限制:softplus 和 tanh 成本高,改善依資料集與架構而異,在大模型上微小的 accuracy 增益可能抵不過運算成本。
GLU → SwiGLU:原始 GLU 是 σ(xW) ⊙ (xV),SwiGLU 把 σ 換成 Swish:SwiGLU(x) = (xW + b) ⊙ SiLU(xV + c)。LLM 的 FFN 變成三個矩陣:內容路徑 value = xWᵥ、閘門路徑 gate = SiLU(xW_g)、逐元素相乘後再乘輸出投影 W_o。講義的比較:
| 特性 | SiLU FFN | SwiGLU FFN |
|---|---|---|
| 公式 | x · σ(x),套在一條 projection 上 | (xW + b) ⊙ SiLU(xV + c) |
| 矩陣 | 2 個(升維、降維) | 3 個(第一層變 2 個) |
| 計算 | 較低 | 參數與計算量約多 50%,通常把 hidden 維度縮小來平衡 |
| 代表模型 | GPT-2、早期視覺模型 | LLaMA 3、Gemma、DeepSeek-V3 |
數學直覺:標準 FFN 每個 hidden unit 是 φ(aᵀx),一個 projection 套一條曲線;gated FFN 是 φ(gᵀx) · (vᵀx),兩個 projection 相乘,近似加入二階的 feature interaction。好處是更強的條件式表達;代價是更大的動態範圍;系統上的問題是量化與 kernel 成本。
ReLU² 與 sparse LLM:為什麼 ReLU 又回來:ReLU²(x) = max(0, x)²。負值仍是 0,保留 exact sparsity;大正值平方放大,重要特徵更突出。講義的想像:一個有 10,000 個 neuron 的 FFN,7,000 個輸出 0、3,000 個啟動;如果 kernel 和記憶體排程能利用這些 0,就可能少讀權重、少算 GEMM。真正的挑戰是:零值比例不等於實際加速,還需要 structured sparsity、低 mask overhead、batch-friendly kernel。
Mobile 與量化:部署端最好的數學函數不一定最快。ReLU6 = min(max(0, x), 6) 限制 activation 範圍,INT8 的 scale 比較好配;Hard-Swish = x · ReLU6(x + 3) / 6 把 Swish 裡的 sigmoid 換成分段直線(講義說「分段線性近似」),對 mobile CPU / NPU 比較友善(PROBE A 可以選來看);GELU / SiLU 也可以用查表(LUT)、分段線性(PWL)或多項式近似 exp / erf。手機上每個 token、每個像素都要算一次 activation,這些成本會被大量放大。
怎麼選:不要問「哪個最好」,要問「用在哪裡」(講義的整理):
| 場景 | 常見選擇 | 理由 |
|---|---|---|
| CNN | ReLU / SiLU | ReLU 快且稀疏;SiLU 常提高 accuracy |
| Mobile CNN | ReLU6 / Hard-Swish | 控制範圍,降低 latency 與量化難度 |
| Transformer / ViT | GELU | 平滑、保留弱負訊號、kernel 成熟 |
| LLM FFN | SwiGLU | 依輸入決定的 gating,現代 LLM 主流 |
| Sparse LLM | ReLU / ReLU² | 製造 exact zero,利於條件式計算 |
| RNN / gate | Sigmoid / Tanh | 有界的 gate 與有界的 state 仍然必要 |
| Implicit representation | Sine / periodic | 直接表示高頻訊號與波動場 |
講義列的其他常見錯誤:只拿相同 hidden 維度的 GELU FFN 和 SwiGLU FFN 比較並不公平,SwiGLU 多一條 projection,要對齊參數量、training FLOPs 或實際時間;SELU 的 self-normalizing 依賴初始化、結構、dropout 形式和統計假設,不能隨意取代 ReLU;Sigmoid 和 Tanh 沒有被淘汰,只是不再適合當所有深層 hidden layer 的通用函數,它們仍是 gate、機率輸出、有界 state 與連續控制的核心工具。
講義最後整理的實務選擇與常見錯誤,挑四條最容易講錯的。