一隻熊貓、一點雜訊、一隻長臂猿
這是現代機器學習裡最令人不安的畫面之一。拿一張熊貓的照片,一個訓練良好的圖像分類器會以 58% 的信心標註為「熊貓」。再疊加一層淡淡的雜訊——淡到你的眼睛根本看不出任何變化——同一個模型現在卻以 99% 的信心說這是「長臂猿」。在你看來,這張圖依然百分之百是熊貓。這就是對抗樣本:一個被刻意(往往是不可察覺地)修改過的輸入,目的就是讓模型出錯。
在上一篇裡你見過「無聲的失敗」:當輸入來自一個發生了偏移的分布時,模型會栽跟頭。對抗樣本是這個故事裡最壞的情形——它不是分布偏移帶來的意外,而是攻擊者故意製造出來的失敗。它們不是你偶然碰上的隨機故障,而是攻擊者透過搜尋模型最脆弱之處,精確找出來的輸入。這種區別——隨機的壞運氣,與有智慧的對手——正是為什麼對抗穩健性是一個安全問題,而不僅僅是一個品質問題。
攻擊是怎麼造出來的
這個配方在複用你已知的知識時,幾乎帶著一種詩意。訓練模型時,我們用梯度去微調*權重*,讓損失下降。攻擊則把這件事反過來:它凍住權重,用同樣的梯度去微調*輸入*,讓損失上升——把模型推向錯誤答案。換句話說,正是讓學習得以運轉的那套微積分,反向作用到像素上,就把模型給打破了。這就是為什麼:一個你能對它求梯度的模型,也是一個攻擊者能對它下手的模型。
# normal training: change WEIGHTS to lower loss W <- W - lr * d(loss)/d(W) # attack: freeze W, change the INPUT to RAISE loss x_adv <- x + eps * sign( d(loss)/d(x) ) # eps is kept tiny, so x_adv looks identical to x
攻擊也分不同口味。白盒攻擊能看到模型的權重與梯度,因此可以直接精心炮製擾動。黑盒攻擊只能看到模型的輸出——但它依然可能成功,因為對抗樣本常常會*遷移*:為騙過一個模型而造出來的樣本,往往也能騙過另一個在相似資料上訓練的模型。擾動可以是熊貓身上那種不可察覺的雜訊,也可以是物理的、看得見的——幾張精心擺放的貼紙就能讓停車標誌被讀成限速標誌,或者 T 恤上印一個圖案就能讓偵測器看不見這個人。
防禦,以及那場軍備競賽
最強、也最誠實的防禦是對抗訓練:在訓練過程中生成攻擊,並把它們加進資料裡,讓模型在自己最糟糕的樣本上學習。它確實有用,是當今對抗防禦的中流砥柱。但它絕非免費的午餐——訓練成本要高得多,而且一個針對某個攻擊預算加固過的模型,仍可能敗給一個更大的、或形狀不同的攻擊。針對今天的攻擊贏來的穩健性,並不能保證擋得住明天的攻擊。
還有一整片更廉價防禦的「墳場」,曾試圖繞開那份成本——模糊輸入、遮蔽梯度、偵測「奇怪的」像素。其中很多被發表、被讚譽,然後在幾個月內就被那些乾脆見招拆招的攻擊者攻破了。反覆出現的教訓叫*梯度遮蔽*:一個僅僅把梯度藏起來的防禦,紙面上看著很穩健,可一旦碰上用別的辦法估計梯度的攻擊者,就垮了。這個領域學會了對任何沒有經受過「自適應、且了解防禦機制的攻擊者」檢驗的防禦,保持冷酷的懷疑。
把穩健性當作一種性質
退一步,把穩健性看作模型的一種*性質*,區別於準確率,是很值得的。一個測試準確率出眾的模型,可能極其脆弱,因為準確率問的是「它在平均情況下答對了嗎?」,而穩健性問的是「當輸入在某個鄰域內被擾動時,它還能答對嗎?」這是兩個不同的問題,一個模型完全可能在其中一個上拿滿分,而在另一個上不及格。穩健性其實關乎一個預測的*穩定性*,而不只是它在乾淨測試集上的正確性。
模型一開始為什麼會這麼脆弱?一種主流解釋是:它們抓住了那些預測性很強、卻並不穩健的特徵——一些細微的紋理和統計上的怪癖,它們在整個訓練集裡與標籤相關,卻不承載任何真正的含義。這和虛假相關屬於同一類失敗:模型答對了,但答對的理由很脆弱。攻擊者要做的,不過是利用這些脆弱的理由,去精準擾動那些模型依賴、而人類忽略的特徵。
這裡甚至潛伏著一個令人不舒服的取捨:用今天的方法,把模型推向更強的對抗穩健性,往往會降低它在乾淨資料上的普通準確率。穩健性不是免費的,也不是一個一撥就開的開關——它是一種你要專門去設計、去仔細測量,並以算力、有時還以準確率為代價去換取的性質。
為何重要:安全,以及一張更大的網
只要一個模型擋在攻擊者和他們想要的東西之間,對抗樣本就會變成一個真實的攻擊面。垃圾郵件和惡意軟體過濾器,會被餵入專門調過、能溜過去的輸入。人臉辨識和內容審核系統,會被精心炮製的圖案騙過。自動駕駛汽車的感知,可以在物理世界裡被針對。防禦方的活兒比攻擊方更難:攻擊者只需要一個能奏效的輸入,而防禦者必須擋住對手能想出來的*每一個*輸入。這種不對稱,正是為什麼穩健性是一門兩用的安全學科,而不是一個整整齊齊的基準測試。
同樣的思路在語言模型身上又出現了。所謂*越獄*或*提示注入*,就是文本形式的對抗輸入——一段精心構造、要把模型推過其安全護欄的字串——而那種貓捉老鼠的節奏,和圖像研究者們多年來經歷的一模一樣。要在第一步就察覺一個輸入可疑,就把穩健性和分布外偵測聯繫了起來:一個能標記出「這個輸入和我訓練時見過的任何東西都不像」的系統,才有機會去拒絕或上報,而不是自信地犯錯。
- 先建立威脅模型:寫清楚攻擊者是誰、他們能看到什麼(白盒還是黑盒),以及在你的領域裡多大的擾動才算「小」。
- 在別人動手之前,用強大的、自適應的攻擊去打你自己的模型——把它當作紅隊演練,而不是走過場。
- 在關鍵處加固(對抗訓練、輸入校驗),並加上偵測機制,讓異常輸入被標記出來,而不是被默默信任。
- 假定防禦只是局部的:在高風險決策上保留人類參與,並在生產環境中持續監控,因為攻擊者會不斷適應。
這一切都不構成什麼世界末日。對抗脆弱性是一個具體的、已被深入研究的工程問題——它並不意味著模型暗地裡心懷惡意,或者快要掙脫束縛了。更誠實的表述其實更簡單、也更有用:這些系統是強大的模式匹配器,帶著鋒利、可被利用的邊緣,而穩健性就是這樣一門持續的功夫——在對手之前找到那些邊緣,並把那些要緊的磨鈍。把它當作安全工程來對待,用對抗的方式去度量它,並對任何單一防禦所能承諾的東西保持謙遜。