詳解:從L1/L2到譜范數(shù)的機(jī)器學(xué)習(xí)應(yīng)用指南)
1. 為什么我們要關(guān)心“范數(shù)”這個(gè)數(shù)學(xué)工具第一次接觸“范數(shù)”這個(gè)詞很多人會(huì)覺(jué)得它離實(shí)際開(kāi)發(fā)很遠(yuǎn)像是數(shù)學(xué)系課本里才會(huì)出現(xiàn)的抽象概念。但如果你做過(guò)機(jī)器學(xué)習(xí)、數(shù)值計(jì)算、信號(hào)處理甚至只是用過(guò)正則化去調(diào)一個(gè)過(guò)擬合的模型那你其實(shí)已經(jīng)在和范數(shù)打交道了。范數(shù)本質(zhì)上就是“衡量一個(gè)東西有多大”的尺子只不過(guò)這把尺子量的不是長(zhǎng)度或重量而是向量和矩陣的“大小”。我在實(shí)際項(xiàng)目里踩過(guò)的最典型的坑就是早期做特征縮放時(shí)隨手用了默認(rèn)的歐氏距離去度量樣本差異結(jié)果在高維稀疏數(shù)據(jù)上效果極差后來(lái)?yè)Q成L1范數(shù)才把問(wèn)題解決。這件事讓我意識(shí)到選錯(cuò)范數(shù)模型的表現(xiàn)可能天差地別而很多人根本沒(méi)意識(shí)到自己正在做“范數(shù)選擇”這件事。這篇文章想做的事情很明確把向量范數(shù)和矩陣范數(shù)這兩塊內(nèi)容講透從定義、幾何直覺(jué)、計(jì)算方式到它們?cè)谡齽t化、數(shù)值穩(wěn)定性、條件數(shù)分析中的實(shí)際用途全部拆開(kāi)講。適合有一定線性代數(shù)基礎(chǔ)、但沒(méi)系統(tǒng)梳理過(guò)范數(shù)的開(kāi)發(fā)者也適合正在做機(jī)器學(xué)習(xí)或數(shù)值計(jì)算、想搞清楚“為什么這里要用L2而不是L1”的從業(yè)者。讀完你至少能做到三件事第一看到任意一個(gè)范數(shù)定義能快速判斷它屬于哪一類(lèi)第二知道在什么場(chǎng)景下該選哪種范數(shù)第三能手算常見(jiàn)的向量范數(shù)和矩陣范數(shù)并理解背后的計(jì)算邏輯。2. 向量范數(shù)從“長(zhǎng)度”到“一把可定制的尺子”2.1 向量范數(shù)的三條公理到底在約束什么向量范數(shù)說(shuō)穿了就是一個(gè)函數(shù)輸入一個(gè)向量輸出一個(gè)非負(fù)實(shí)數(shù)。但這個(gè)函數(shù)不是隨便定義的它必須滿足三條公理這三條公理決定了它能不能被稱(chēng)為“范數(shù)”。第一條是非負(fù)性對(duì)任意向量 x都有 ||x|| ≥ 0且 ||x|| 0 當(dāng)且僅當(dāng) x 是零向量。這條看起來(lái)廢話但它排除了那些“把非零向量映射成0”的奇怪函數(shù)。第二條是齊次性||αx|| |α| · ||x||也就是說(shuō)你把向量放大 α 倍范數(shù)也放大 |α| 倍。第三條是三角不等式||x y|| ≤ ||x|| ||y||這條最直觀兩點(diǎn)之間直線最短繞路不會(huì)更近。我習(xí)慣用一個(gè)生活類(lèi)比來(lái)解釋這三條把范數(shù)想象成“快遞計(jì)費(fèi)規(guī)則”。非負(fù)性是說(shuō)運(yùn)費(fèi)不能是負(fù)數(shù)且只有空包裹才免運(yùn)費(fèi)齊次性是說(shuō)包裹重量翻倍運(yùn)費(fèi)也翻倍三角不等式是說(shuō)把兩個(gè)包裹合并成一個(gè)寄運(yùn)費(fèi)不會(huì)比分開(kāi)寄更貴。這個(gè)類(lèi)比雖然不嚴(yán)謹(jǐn)?shù)軒托率挚焖俳⒅庇X(jué)。注意很多初學(xué)者會(huì)把“范數(shù)”和“距離”混為一談。范數(shù)是度量單個(gè)向量的大小距離是度量?jī)蓚€(gè)向量之間的差異。距離通常定義為 ||x - y||它是基于范數(shù)導(dǎo)出來(lái)的但兩者概念不同。2.2 最常用的三種向量范數(shù)L1、L2、L∞實(shí)際工作中99%的場(chǎng)景只會(huì)用到三種向量范數(shù)我把它們的定義、計(jì)算方式和典型用途整理成一張表方便你隨時(shí)對(duì)照。范數(shù)類(lèi)型定義式通俗叫法典型用途L1范數(shù)Σ|x?|曼哈頓范數(shù)、出租車(chē)范數(shù)稀疏特征選擇、Lasso正則化L2范數(shù)√(Σx?2)歐氏范數(shù)距離度量、Ridge正則化L∞范數(shù)max|x?|最大范數(shù)、切比雪夫范數(shù)最壞情況分析、魯棒優(yōu)化L1范數(shù)就是把所有分量的絕對(duì)值加起來(lái)。它的幾何形狀是一個(gè)菱形二維情況下這也是為什么L1正則化容易產(chǎn)生稀疏解——菱形的尖角正好落在坐標(biāo)軸上最優(yōu)解很容易取到某個(gè)分量為0的點(diǎn)。L2范數(shù)就是我們中學(xué)學(xué)的“向量長(zhǎng)度”先平方和再開(kāi)根號(hào)。它的幾何形狀是圓形沒(méi)有尖角所以L2正則化會(huì)讓參數(shù)整體變小但很少直接變成0。L∞范數(shù)取所有分量絕對(duì)值的最大值。它衡量的是“最突出的那個(gè)分量有多大”在需要控制最壞情況的場(chǎng)景里特別有用。2.3 手算示例三種范數(shù)的實(shí)際計(jì)算過(guò)程光看定義容易飄我們拿一個(gè)具體向量來(lái)算一遍。假設(shè) x [3, -4, 0, 2]。L1范數(shù)|3| |-4| |0| |2| 3 4 0 2 9。L2范數(shù)√(32 (-4)2 02 22) √(9 16 0 4) √29 ≈5.385。L∞范數(shù)max(|3|, |-4|, |0|, |2|) max(3, 4, 0, 2) 4。這三個(gè)結(jié)果告訴我們同一件事的不同側(cè)面L1說(shuō)“總共有9個(gè)單位的量”L2說(shuō)“直線距離約5.4”L∞說(shuō)“最大的單個(gè)分量是4”。你會(huì)發(fā)現(xiàn) L∞ ≤ L2 ≤ L1這不是巧合而是一個(gè)普遍成立的不等式關(guān)系后面講范數(shù)等價(jià)性時(shí)會(huì)詳細(xì)說(shuō)。2.4 p-范數(shù)把三種范數(shù)統(tǒng)一成一個(gè)公式L1、L2、L∞其實(shí)都是p-范數(shù)的特例。p-范數(shù)的定義是||x||_p (Σ|x?|^p)^(1/p)當(dāng) p1 時(shí)就是L1范數(shù)p2 時(shí)就是L2范數(shù)。那L∞怎么來(lái)的當(dāng) p 趨向無(wú)窮大時(shí)最大的那個(gè)分量會(huì)主導(dǎo)整個(gè)求和其他分量的貢獻(xiàn)被相對(duì)稀釋極限情況下就變成了取最大值。這個(gè)推導(dǎo)過(guò)程我建議你親手推一遍能極大加深理解。p-范數(shù)里有個(gè)反直覺(jué)的點(diǎn)p 越小范數(shù)的值越大。比如同一個(gè)向量L1范數(shù)總是大于等于L2范數(shù)L2又大于等于L∞。這背后的原因是p 越小對(duì)大分量的“懲罰”越輕對(duì)小分量的“計(jì)入”越重所以總和更大。實(shí)操心得在特征工程里做歸一化時(shí)如果你不確定選哪個(gè)范數(shù)先用L2做標(biāo)準(zhǔn)化除以L2范數(shù)這是最穩(wěn)妥的默認(rèn)選擇。只有當(dāng)你有明確理由相信特征應(yīng)該稀疏時(shí)才切換到L1。3. 矩陣范數(shù)當(dāng)“大小”變成一個(gè)更復(fù)雜的問(wèn)題3.1 矩陣范數(shù)和向量范數(shù)的本質(zhì)區(qū)別向量范數(shù)好理解因?yàn)橄蛄烤褪且淮當(dāng)?shù)量它的大小很直觀。但矩陣是一個(gè)二維數(shù)組它的“大小”到底指什么是元素的最大值是所有元素的總和還是它作為一個(gè)線性變換的“放大能力”不同的理解方式導(dǎo)出了不同的矩陣范數(shù)。這是很多人第一次學(xué)矩陣范數(shù)時(shí)最困惑的地方。我當(dāng)初也是花了很久才想明白矩陣范數(shù)分兩大類(lèi)一類(lèi)是元素級(jí)范數(shù)直接把矩陣?yán)疆?dāng)成向量來(lái)算另一類(lèi)是誘導(dǎo)范數(shù)也叫算子范數(shù)衡量的是矩陣作為線性變換時(shí)對(duì)向量長(zhǎng)度的最大放大倍數(shù)。這兩類(lèi)范數(shù)的用途完全不同混用會(huì)出大問(wèn)題。3.2 元素級(jí)范數(shù)Frobenius范數(shù)和它的計(jì)算最常用的元素級(jí)矩陣范數(shù)是Frobenius范數(shù)記作 ||A||_F。它的定義非常直接||A||_F √(Σ?Σ? a??2)就是把矩陣所有元素平方求和再開(kāi)根號(hào)本質(zhì)上就是把矩陣?yán)梢粋€(gè)長(zhǎng)向量然后算L2范數(shù)。舉個(gè)例子A [[1, 2], [3, 4]]那么 ||A||_F √(1 4 9 16) √30 ≈ 5.477。Frobenius范數(shù)在機(jī)器學(xué)習(xí)里出現(xiàn)頻率極高比如矩陣分解的損失函數(shù)、神經(jīng)網(wǎng)絡(luò)的權(quán)重衰減很多時(shí)候用的就是它。它的優(yōu)點(diǎn)是計(jì)算簡(jiǎn)單、可導(dǎo)性好缺點(diǎn)是它忽略了矩陣的結(jié)構(gòu)信息——兩個(gè)元素完全相同但排列不同的矩陣Frobenius范數(shù)是一樣的。3.3 誘導(dǎo)范數(shù)矩陣作為“放大器”的度量誘導(dǎo)范數(shù)的定義稍微繞一點(diǎn)。給定一個(gè)向量范數(shù) ||·||矩陣A的誘導(dǎo)范數(shù)定義為||A|| max{ ||Ax|| / ||x|| : x ≠ 0 }翻譯成人話就是在所有非零向量里找出被A放大倍數(shù)最大的那個(gè)這個(gè)最大倍數(shù)就是A的誘導(dǎo)范數(shù)。它衡量的是矩陣作為線性變換的“最大放大能力”。常用的誘導(dǎo)范數(shù)有三種對(duì)應(yīng)向量的L1、L2、L∞范數(shù)誘導(dǎo)范數(shù)計(jì)算方法特點(diǎn)1-范數(shù)列和的最大值最大列絕對(duì)值和2-范數(shù)最大奇異值計(jì)算復(fù)雜但理論重要∞-范數(shù)行和的最大值最大行絕對(duì)值和1-范數(shù)和∞-范數(shù)的計(jì)算有個(gè)好記的口訣1-范數(shù)看列∞-范數(shù)看行。因?yàn)?橫過(guò)來(lái)像列∞豎著像行這個(gè)記憶法有點(diǎn)牽強(qiáng)但確實(shí)好用。2-范數(shù)最特殊它等于矩陣的最大奇異值計(jì)算需要做奇異值分解成本較高但在理論分析中地位最高。3.4 手算示例三種誘導(dǎo)范數(shù)的完整計(jì)算還是用 A [[1, 2], [3, 4]] 來(lái)算。1-范數(shù)先算每列的絕對(duì)值和。第一列 |1| |3| 4第二列 |2| |4| 6。取最大值||A||_1 6?!?范數(shù)先算每行的絕對(duì)值和。第一行 |1| |2| 3第二行 |3| |4| 7。取最大值||A||_∞ 7。2-范數(shù)需要算 A?A 的最大特征值的平方根。A?A [[10, 14], [14, 20]]特征值是 15 ± √221最大特征值約 29.866開(kāi)根號(hào)約5.465。這三個(gè)結(jié)果差異很大說(shuō)明它們度量的確實(shí)是不同的東西。1-范數(shù)關(guān)注“哪一列的總量最大”∞-范數(shù)關(guān)注“哪一行的總量最大”2-范數(shù)關(guān)注“最大的放大倍數(shù)”。注意誘導(dǎo)范數(shù)必須和某個(gè)向量范數(shù)綁定才有意義。說(shuō)“矩陣的2-范數(shù)”時(shí)默認(rèn)是指由向量L2范數(shù)誘導(dǎo)出來(lái)的。如果你用的是其他向量范數(shù)結(jié)果會(huì)不同。4. 范數(shù)等價(jià)性為什么換個(gè)范數(shù)結(jié)果不會(huì)崩4.1 有限維空間里所有范數(shù)都等價(jià)這是范數(shù)理論里最重要的結(jié)論之一在有限維向量空間里任意兩個(gè)范數(shù)都是等價(jià)的。等價(jià)的意思是存在兩個(gè)正常數(shù) c 和 C使得對(duì)任意向量 x都有c·||x||_a ≤ ||x||_b ≤ C·||x||_a這個(gè)結(jié)論的實(shí)際意義是如果你用L1范數(shù)判斷一個(gè)向量“很大”那用L2范數(shù)判斷它也不會(huì)“很小”。它們對(duì)“大小”的判斷在定性上是一致的只是定量上有常數(shù)倍的差異。我當(dāng)初學(xué)到這里時(shí)有個(gè)疑問(wèn)既然都等價(jià)那還分這么多種范數(shù)干嘛后來(lái)才明白等價(jià)是理論保證但常數(shù) c 和 C 可能相差極大。在高維空間里L(fēng)1和L2的比值可以差到 √n 倍n 是維度。當(dāng) n 是幾萬(wàn)維時(shí)這個(gè)差異就完全不能忽略了。4.2 等價(jià)常數(shù)的具體推導(dǎo)以L1和L2為例我們可以推導(dǎo)出它們之間的等價(jià)關(guān)系。一方面||x||_2 ≤ ||x||_1因?yàn)槠椒胶托∮诘扔诤偷钠椒疆?dāng)所有分量非負(fù)時(shí)取等號(hào)。另一方面||x||_1 ≤ √n · ||x||_2這個(gè)用柯西-施瓦茨不等式可以證明。所以 √(1/n) · ||x||_1 ≤ ||x||_2 ≤ ||x||_1等價(jià)常數(shù)是 1 和 √n。這個(gè)推導(dǎo)過(guò)程建議你親手寫(xiě)一遍它不僅能幫你記住結(jié)論還能讓你理解為什么高維數(shù)據(jù)里L(fēng)1和L2的行為差異那么大。4.3 等價(jià)性在數(shù)值計(jì)算中的實(shí)際影響等價(jià)性在理論上是好事但在實(shí)踐中要小心。比如你做梯度下降用L2范數(shù)做梯度裁剪閾值設(shè)為1.0。如果換成L1范數(shù)做裁剪同樣的閾值下實(shí)際裁剪力度會(huì)完全不同因?yàn)長(zhǎng)1范數(shù)通常比L2范數(shù)大。我在一個(gè)項(xiàng)目里就遇到過(guò)這個(gè)問(wèn)題團(tuán)隊(duì)里兩個(gè)人分別用L1和L2做梯度裁剪結(jié)果模型收斂速度差了一倍。排查了半天才發(fā)現(xiàn)是范數(shù)選擇不一致導(dǎo)致的。統(tǒng)一范數(shù)選擇是團(tuán)隊(duì)協(xié)作里容易被忽視但非常重要的規(guī)范。實(shí)操心得在深度學(xué)習(xí)框架里torch.nn.utils.clip_grad_norm_默認(rèn)用的是L2范數(shù)。如果你要換成L1記得同步調(diào)整閾值否則裁剪力度會(huì)失控。5. 范數(shù)在機(jī)器學(xué)習(xí)中的核心應(yīng)用5.1 L1和L2正則化稀疏性與平滑性的取舍正則化是范數(shù)最廣為人知的應(yīng)用。L1正則化Lasso在損失函數(shù)里加上 λ·||w||_1L2正則化Ridge加上 λ·||w||_22。為什么L1產(chǎn)生稀疏解L2不產(chǎn)生幾何解釋是L1的約束區(qū)域是菱形頂點(diǎn)在坐標(biāo)軸上損失函數(shù)的等高線很容易和菱形在頂點(diǎn)處相切導(dǎo)致某些權(quán)重正好為0。L2的約束區(qū)域是圓形沒(méi)有尖角相切點(diǎn)一般不會(huì)正好落在坐標(biāo)軸上。從優(yōu)化角度看L1在0點(diǎn)不可導(dǎo)次梯度包含0所以最優(yōu)解可以停在0點(diǎn)。L2在0點(diǎn)可導(dǎo)且導(dǎo)數(shù)為0但損失函數(shù)的梯度在0點(diǎn)通常不為0所以最優(yōu)解很少正好是0。實(shí)際選擇時(shí)如果你需要特征選擇、想要一個(gè)稀疏模型用L1。如果你只是想讓模型別過(guò)擬合、權(quán)重別太大用L2。兩者也可以結(jié)合就是彈性網(wǎng)絡(luò)Elastic Net同時(shí)加L1和L2。5.2 譜范數(shù)在對(duì)抗樣本和GAN中的應(yīng)用譜范數(shù)就是矩陣的2-范數(shù)等于最大奇異值。它在深度學(xué)習(xí)里有個(gè)重要應(yīng)用譜歸一化。在GAN訓(xùn)練中判別器的 Lipschitz 常數(shù)如果太大訓(xùn)練會(huì)不穩(wěn)定。譜歸一化通過(guò)把每層的權(quán)重矩陣除以它的譜范數(shù)強(qiáng)制讓每層的 Lipschitz 常數(shù)不超過(guò)1從而穩(wěn)定訓(xùn)練。這個(gè)技巧在WGAN-GP等模型里是標(biāo)配。計(jì)算譜范數(shù)需要做奇異值分解成本較高。實(shí)踐中常用冪迭代法近似迭代幾次就能得到不錯(cuò)的估計(jì)。這個(gè)近似方法我在多個(gè)項(xiàng)目里用過(guò)收斂速度很快通常5到10次迭代就夠了。5.3 核范數(shù)在矩陣補(bǔ)全中的角色核范數(shù)是矩陣奇異值之和記作 ||A||_*。它是矩陣秩的凸松弛也就是說(shuō)最小化核范數(shù)近似于最小化矩陣的秩。在推薦系統(tǒng)里用戶-物品評(píng)分矩陣通常是低秩的因?yàn)橛脩羝每梢杂蒙贁?shù)幾個(gè)隱因子解釋。矩陣補(bǔ)全問(wèn)題就是已知部分評(píng)分預(yù)測(cè)缺失評(píng)分。直接最小化秩是NP難的但最小化核范數(shù)是凸優(yōu)化問(wèn)題可以高效求解。這個(gè)應(yīng)用我做過(guò)一個(gè)完整項(xiàng)目用核范數(shù)正則化的矩陣分解做電影推薦效果比單純的Frobenius范數(shù)正則化好不少尤其是在評(píng)分?jǐn)?shù)據(jù)很稀疏的時(shí)候。6. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄6.1 范數(shù)計(jì)算中的典型錯(cuò)誤問(wèn)題現(xiàn)象可能原因排查方法范數(shù)值異常大忘記開(kāi)根號(hào)或用了錯(cuò)誤的p值檢查公式確認(rèn)p值矩陣范數(shù)和預(yù)期不符混淆了元素級(jí)范數(shù)和誘導(dǎo)范數(shù)確認(rèn)用的是Frobenius還是誘導(dǎo)范數(shù)正則化后模型全零L1正則化系數(shù)λ過(guò)大減小λ或改用L2梯度裁剪后不收斂范數(shù)類(lèi)型和閾值不匹配統(tǒng)一范數(shù)類(lèi)型重新調(diào)閾值譜范數(shù)計(jì)算太慢直接做SVD改用冪迭代近似6.2 數(shù)值穩(wěn)定性問(wèn)題計(jì)算L2范數(shù)時(shí)如果向量分量很大平方后可能溢出。穩(wěn)妥的做法是先除以最大分量算完再乘回去。這個(gè)技巧在數(shù)值計(jì)算庫(kù)里有標(biāo)準(zhǔn)實(shí)現(xiàn)但如果你手寫(xiě)代碼很容易忽略。計(jì)算Frobenius范數(shù)時(shí)如果矩陣很大直接平方求和也可能溢出。可以分塊計(jì)算或者用縮放技巧。我在處理大規(guī)模矩陣時(shí)一般會(huì)用numpy.linalg.norm它內(nèi)部做了數(shù)值優(yōu)化比手寫(xiě)循環(huán)穩(wěn)得多。6.3 范數(shù)選擇的決策清單面對(duì)一個(gè)具體問(wèn)題怎么選范數(shù)我整理了一個(gè)簡(jiǎn)單的決策流程如果你需要稀疏解選L1。如果你需要平滑解、防止過(guò)擬合選L2。如果你關(guān)心最壞情況選L∞。如果你處理的是矩陣且關(guān)心整體能量選Frobenius。如果你關(guān)心矩陣作為變換的放大能力選誘導(dǎo)2-范數(shù)譜范數(shù)。如果你要最小化矩陣的秩選核范數(shù)。這個(gè)清單不是絕對(duì)的但能覆蓋大部分場(chǎng)景。遇到特殊情況再具體分析。最后分享一個(gè)小技巧在調(diào)試正則化相關(guān)問(wèn)題時(shí)先把λ設(shè)為0確認(rèn)模型能正常過(guò)擬合再逐步增大λ觀察權(quán)重范數(shù)的變化。這樣能快速定位是正則化的問(wèn)題還是模型本身的問(wèn)題。7. 從理論到代碼范數(shù)計(jì)算的實(shí)操演示7.1 用NumPy計(jì)算各種范數(shù)理論講完了落到代碼上其實(shí)很簡(jiǎn)單。NumPy提供了numpy.linalg.norm函數(shù)通過(guò)ord參數(shù)指定范數(shù)類(lèi)型。import numpy as np x np.array([3, -4, 0, 2]) # 向量L1范數(shù) l1 np.linalg.norm(x, ord1) # 9.0 # 向量L2范數(shù) l2 np.linalg.norm(x, ord2) # 5.385 # 向量L∞范數(shù) linf np.linalg.norm(x, ordnp.inf) # 4.0 A np.array([[1, 2], [3, 4]]) # Frobenius范數(shù) fro np.linalg.norm(A, ordfro) # 5.477 # 誘導(dǎo)1-范數(shù) norm1 np.linalg.norm(A, ord1) # 6.0 # 誘導(dǎo)∞-范數(shù) norm_inf np.linalg.norm(A, ordnp.inf) # 7.0 # 譜范數(shù)誘導(dǎo)2-范數(shù) spec np.linalg.norm(A, ord2) # 5.465這段代碼我建議你親手跑一遍對(duì)照前面的手算結(jié)果確認(rèn)理解無(wú)誤。特別注意ord參數(shù)對(duì)矩陣和向量的行為不同對(duì)向量ord2是L2范數(shù)對(duì)矩陣ord2是譜范數(shù)。7.2 手動(dòng)實(shí)現(xiàn)范數(shù)計(jì)算如果你想深入理解可以自己實(shí)現(xiàn)一遍。下面是L1、L2、L∞的手動(dòng)實(shí)現(xiàn)def l1_norm(x): return sum(abs(xi) for xi in x) def l2_norm(x): return sum(xi**2 for xi in x) ** 0.5 def linf_norm(x): return max(abs(xi) for xi in x)手動(dòng)實(shí)現(xiàn)的好處是你能完全掌控計(jì)算過(guò)程也方便加一些特殊處理比如數(shù)值穩(wěn)定性優(yōu)化。但在生產(chǎn)環(huán)境里還是用庫(kù)函數(shù)更穩(wěn)妥因?yàn)閹?kù)函數(shù)經(jīng)過(guò)了充分測(cè)試和優(yōu)化。7.3 范數(shù)在梯度裁剪中的實(shí)際代碼梯度裁剪是范數(shù)最常見(jiàn)的工程應(yīng)用之一。下面是一個(gè)完整的例子import torch def clip_gradients(model, max_norm1.0, norm_type2): total_norm 0.0 for p in model.parameters(): if p.grad is not None: param_norm p.grad.data.norm(norm_type) total_norm param_norm.item() ** norm_type total_norm total_norm ** (1.0 / norm_type) clip_coef max_norm / (total_norm 1e-6) if clip_coef 1: for p in model.parameters(): if p.grad is not None: p.grad.data.mul_(clip_coef) return total_norm這段代碼的關(guān)鍵點(diǎn)是1e-6這個(gè)極小量防止除以0。另外clip_coef 1的判斷確保只在梯度超過(guò)閾值時(shí)才裁剪不超過(guò)時(shí)不動(dòng)。這個(gè)細(xì)節(jié)很多人會(huì)忽略導(dǎo)致梯度被意外放大。注意PyTorch自帶的clip_grad_norm_已經(jīng)做了這些處理直接用就行。手寫(xiě)版本主要用于理解原理或者需要自定義范數(shù)類(lèi)型時(shí)使用。8. 范數(shù)選擇的經(jīng)驗(yàn)法則與避坑指南8.1 高維稀疏數(shù)據(jù)優(yōu)先考慮L1在處理文本、推薦系統(tǒng)、基因數(shù)據(jù)這類(lèi)高維稀疏數(shù)據(jù)時(shí)L1范數(shù)往往比L2更合適。原因是高維空間里L(fēng)2范數(shù)會(huì)被大量小分量主導(dǎo)而L1范數(shù)對(duì)大分量更敏感能更好地捕捉稀疏結(jié)構(gòu)。我做過(guò)一個(gè)文本分類(lèi)項(xiàng)目特征維度幾萬(wàn)維用L2正則化效果一般換成L1后不僅準(zhǔn)確率提升模型還變得非常稀疏推理速度提升了好幾倍。這個(gè)經(jīng)驗(yàn)在稀疏場(chǎng)景里基本通用。8.2 數(shù)值計(jì)算中優(yōu)先用Frobenius范數(shù)如果你只是想知道矩陣的“整體大小”Frobenius范數(shù)是最安全的選擇。它計(jì)算簡(jiǎn)單、可導(dǎo)性好、數(shù)值穩(wěn)定而且和矩陣的跡有直接關(guān)系||A||_F2 trace(A?A)。這個(gè)關(guān)系在推導(dǎo)梯度時(shí)特別有用。誘導(dǎo)范數(shù)雖然理論意義更強(qiáng)但計(jì)算成本高而且不可導(dǎo)在最大值點(diǎn)處不適合直接放進(jìn)損失函數(shù)里優(yōu)化。所以實(shí)踐中損失函數(shù)里的矩陣范數(shù)基本都是Frobenius。8.3 譜范數(shù)用于穩(wěn)定性分析當(dāng)你需要分析模型的穩(wěn)定性、控制Lipschitz常數(shù)時(shí)譜范數(shù)是不可替代的工具。它直接給出了矩陣對(duì)向量的最大放大倍數(shù)是判斷“梯度會(huì)不會(huì)爆炸”的關(guān)鍵指標(biāo)。在RNN和GAN的訓(xùn)練中監(jiān)控譜范數(shù)的變化能幫你提前發(fā)現(xiàn)訓(xùn)練不穩(wěn)定的苗頭。如果譜范數(shù)持續(xù)增大說(shuō)明梯度可能會(huì)爆炸需要及時(shí)調(diào)整學(xué)習(xí)率或加正則化。8.4 核范數(shù)用于低秩約束當(dāng)你需要矩陣是低秩的但又不想直接優(yōu)化秩因?yàn)榉峭购朔稊?shù)是最佳選擇。它是秩的凸包絡(luò)最小化核范數(shù)等價(jià)于在凸松弛意義下最小化秩。矩陣補(bǔ)全、魯棒PCA、子空間聚類(lèi)這些任務(wù)里核范數(shù)都是核心工具。不過(guò)核范數(shù)的計(jì)算需要SVD大規(guī)模矩陣上成本較高實(shí)踐中常用隨機(jī)化SVD或增量SVD來(lái)加速。9. 范數(shù)背后的幾何直覺(jué)與深層理解9.1 單位球范數(shù)的幾何可視化每個(gè)范數(shù)都對(duì)應(yīng)一個(gè)單位球也就是所有范數(shù)等于1的向量組成的集合。L1的單位球是菱形L2的單位球是圓形L∞的單位球是正方形。p-范數(shù)的單位球介于菱形和正方形之間p越小越像菱形p越大越像正方形。單位球的形狀決定了正則化的行為。菱形有尖角所以L1正則化的解容易落在坐標(biāo)軸上稀疏。圓形光滑所以L2正則化的解均勻收縮。正方形有四個(gè)尖角L∞正則化會(huì)讓權(quán)重趨向于相等。理解單位球的形狀比死記硬背正則化效果要直觀得多。我建議你在紙上畫(huà)一畫(huà)不同p值的單位球畫(huà)完就再也不會(huì)忘了。9.2 對(duì)偶范數(shù)另一個(gè)視角每個(gè)范數(shù)都有一個(gè)對(duì)偶范數(shù)定義為||y||_* max{ y?x : ||x|| ≤ 1 }對(duì)偶范數(shù)在優(yōu)化理論里非常重要尤其是在推導(dǎo)對(duì)偶問(wèn)題和分析次梯度時(shí)。L1的對(duì)偶是L∞L2的對(duì)偶是L2自對(duì)偶L∞的對(duì)偶是L1。這個(gè)對(duì)偶關(guān)系解釋了一個(gè)現(xiàn)象L1正則化產(chǎn)生稀疏解等價(jià)于在對(duì)偶空間里用L∞約束。L∞約束的是最大值所以只有少數(shù)分量能達(dá)到約束邊界其余分量為0這就是稀疏性的來(lái)源。9.3 范數(shù)和內(nèi)積的關(guān)系范數(shù)和內(nèi)積有深刻聯(lián)系。L2范數(shù)可以由內(nèi)積導(dǎo)出||x||_2 √(x?x)。但L1和L∞范數(shù)不能由任何內(nèi)積導(dǎo)出它們不滿足平行四邊形法則。這個(gè)區(qū)別很重要由內(nèi)積導(dǎo)出的范數(shù)對(duì)應(yīng)希爾伯特空間有正交性、投影定理等良好性質(zhì)。不能由內(nèi)積導(dǎo)出的范數(shù)對(duì)應(yīng)巴拿赫空間性質(zhì)差一些但在特定場(chǎng)景下更有用。理解這一點(diǎn)你就能明白為什么L2范數(shù)在理論分析里地位特殊——它背后的希爾伯特空間結(jié)構(gòu)太豐富了很多漂亮的結(jié)果都依賴它。10. 寫(xiě)在最后我踩過(guò)的那些范數(shù)坑回過(guò)頭看我在范數(shù)上踩的坑主要集中在兩個(gè)地方一是混淆了元素級(jí)范數(shù)和誘導(dǎo)范數(shù)二是在高維場(chǎng)景下沒(méi)意識(shí)到L1和L2的巨大差異。第一個(gè)坑的教訓(xùn)是看到“矩陣范數(shù)”這個(gè)詞先問(wèn)清楚是Frobenius還是誘導(dǎo)范數(shù)。這兩個(gè)東西的計(jì)算方式和用途完全不同混用會(huì)導(dǎo)致完全錯(cuò)誤的結(jié)果。我現(xiàn)在寫(xiě)代碼時(shí)如果用到矩陣范數(shù)一定會(huì)在注釋里寫(xiě)清楚是哪種。第二個(gè)坑的教訓(xùn)是高維數(shù)據(jù)里范數(shù)的選擇不是“隨便選一個(gè)都差不多”而是可能帶來(lái)數(shù)量級(jí)的差異。L1和L2在高維下的比值可以到 √nn是維度。幾萬(wàn)維的數(shù)據(jù)里這個(gè)差異足以改變整個(gè)模型的行為。最后一個(gè)實(shí)用建議如果你不確定該用哪個(gè)范數(shù)先做個(gè)小實(shí)驗(yàn)把幾個(gè)候選范數(shù)都試一遍看哪個(gè)在驗(yàn)證集上表現(xiàn)最好。理論分析能幫你縮小范圍但最終還是要靠實(shí)驗(yàn)說(shuō)話。范數(shù)選擇沒(méi)有銀彈只有適合當(dāng)前問(wèn)題的選擇。