大模型隱私洩露攻擊技巧分析與復現

蚁景网安实验室發表於2024-09-03

前言

大型語言模型,尤其是像ChatGPT這樣的模型,儘管在自然語言處理領域展現了強大的能力,但也伴隨著隱私洩露的潛在風險。在模型的訓練過程中,可能會接觸到大量的使用者資料,其中包括敏感的個人資訊,進而帶來隱私洩露的可能性。此外,模型在推理時有時會無意中回憶起訓練資料中的敏感資訊,這一點也引發了廣泛的關注。

隱私洩露的風險主要來源於兩個方面:一是資料在傳輸過程中的安全性,二是模型本身的記憶風險。在資料傳輸過程中,如果沒有采取充分的安全措施,攻擊者可能會截獲資料,進而竊取敏感資訊,給使用者和組織帶來安全隱患。此外,在模型的訓練和推理階段,如果使用了個人身份資訊或企業資料等敏感資料,這些資料可能會被模型運營方窺探或收集,存在被濫用的風險。

過去已經發生了多起與此相關的事件,導致許多大公司禁止員工使用ChatGPT。此前的研究表明,當讓大模型反覆生成某些特定詞彙時,它可能會在隨後的輸出中暴露出訓練資料中的敏感內容。

學術研究表明,對模型進行訓練資料提取攻擊是切實可行的。攻擊者可以透過與預訓練模型互動,從而恢復出訓練資料集中包含的個別示例。例如,GPT-2曾被發現能夠記住訓練資料中的一些個人資訊,如姓名、電子郵件地址、電話號碼、傳真號碼和實際地址。這不僅帶來了嚴重的隱私風險,還對語言模型的泛化能力提出了質疑。

大模型隱私洩露攻擊技巧分析與復現

本文要探討的就是可以高效從大模型中提取出用於訓練的隱私資料的技巧與方法,主要來自《Bag of Tricks for Training Data Extraction from Language Models》,這篇論文發在了人工智慧頂級會議ICML 2023上。

背景知識

儘管大模型在各種下游語言任務中展現了令人矚目的效能,但其內在的記憶效應使得訓練資料可能被提取出來。這些訓練資料可能包含敏感資訊,如姓名、電子郵件地址、電話號碼和實體地址,從而引發隱私洩露問題,阻礙了大模型在更廣泛應用中的推進。

之前谷歌舉辦了一個比賽,連結如下

https://github.com/google-research/lm-extraction-benchmark/tree/master

大模型隱私洩露攻擊技巧分析與復現

這是一個針對性資料提取的挑戰賽,目的是測試參賽者是否能從給定的字首中準確預測字尾,從而構成整個序列,使其包含在訓練資料集中。這與無針對性的攻擊不同,無針對性的攻擊是搜尋訓練資料集中出現的任意資料。

針對性提取被認為更有價值和具有挑戰性,因為它可以幫助恢復與特定主題相關的關鍵資訊,而不是任意的資料。此外,評估針對性提取也更容易,只需檢查給定字首的正確字尾是否被預測,而無針對性攻擊需要檢查整個龐大的訓練資料集。

這個比賽使用1.3B引數的GPT-Neo模型,以1-eidetic記憶為目標,即模型能夠記住訓練資料中出現1次的字串。這比無針對性和更高eidetic記憶的設定更具有挑戰性。

比賽的基準測試集包含從The Pile資料集中選取的20,000個示例,這個資料集已被用於訓練許多最新的大型語言模型,包括GPT-Neo。每個示例被分為長度為50的字首和字尾,攻擊的任務是在給定字首的情況下預測正確的字尾。這些示例被設計成相對容易提取的,即存在一個字首長度使得模型可以準確生成字尾。

訓練資料提取

從預訓練的語言模型中提取訓練資料,即所謂的"語言模型資料提取",是一種恢復用於訓練模型的示例的方法。這是一個相對較新的任務,但背後的許多技術和分析方法,如成員資格推斷和利用網路記憶進行攻擊,早就已經被引入。

Carlini等人是最早定義模型知識提取和κ-eidetic記憶概念的人,並提出了有希望的資料提取訓練策略。關於記憶的理論屬性以及在敏感領域應用模型提取(如臨床筆記分析)等,已經成為這個領域後續研究的焦點。

最近的研究也有一些重要發現:

  1. Kandpal等人證明,在語言模型中,資料提取的效果經常歸因於常用網路抓取訓練集中的重複。

  2. Jagielski等人使用非確定性為忘記記憶示例提供了一種解釋。

  3. Carlini等人分析了影響訓練資料記憶的三個主要因素。

  4. Feldman指出,為了達到接近最優的效能,在自然資料分佈下需要記憶標籤。

  5. Lehman等人指出,預訓練的BERT在訓練臨床筆記時存在敏感資料洩露的風險,特別是當資料表現出高水平的重複或"筆記膨脹"時。

總的來說,這個新興領域正在深入探討如何從語言模型中提取訓練資料,以及這種提取帶來的安全和隱私風險。最新的研究成果為進一步理解和應對這些挑戰提供了重要的洞見。

成員推理攻擊

成員資格推斷攻擊(MIA)是一種與訓練資料提取密切相關的對抗性任務,目標是在只能對模型進行黑盒訪問的情況下,確定給定記錄是否在模型的訓練資料集中。MIA已被證明在各種機器學習任務中都是有效的,包括分類和生成模型。

MIA使用的方法主要分為兩類:

  1. 基於分類器的方法:這涉及訓練一個二元分類器來識別成員和非成員之間的複雜模式關係,影子訓練是一種常用的技術。

  2. 基於度量的方法:這透過首先計算模型預測向量上的度量(如歐幾里得距離或餘弦相似度)來進行成員資格推斷。

這兩類方法都有各自的優缺點,研究人員正在不斷探索新的MIA攻擊方法,以更有效地從機器學習模型中推斷訓練資料。這突出了訓練資料隱私保護在模型部署和應用中的重要性。對MIA技術的深入理解,有助於設計更加安全和隱私保護的機器學習模型訓練和部署策略,這對於廣泛應用尤其是在敏感領域的應用至關重要。

其他基於記憶的攻擊

大型預訓練模型由於容易記住訓練資料中的資訊,因此面臨著各種潛在的安全和隱私風險。除了訓練資料提取攻擊和成員資格推斷攻擊之外,還有其他基於模型記憶的攻擊針對這類模型。

其中,模型提取攻擊關注於複製給定的黑盒模型的功能效能。在這類攻擊中,對手試圖構建一個具有與原始黑盒模型相似預測效能的第二個模型,從而可以在不獲取原始模型的情況下複製其功能。針對模型提取攻擊的保護措施,集中在如何限制模型的功能複製。

另一類攻擊是屬性推斷攻擊,其目標是從模型中提取特定的個人屬性資訊,如地點、職業和興趣等。這些屬性資訊可能是模型生產者無意中共享的訓練資料屬性,例如生成資料的環境或屬於特定類別的資料比例。

與訓練資料提取攻擊不同,屬性/屬性推斷攻擊不需要事先知道要提取的具體屬性。而訓練資料提取攻擊需要生成與訓練資料完全一致的資訊,這更加困難和危險。

總之,這些基於模型記憶的各類攻擊,都突顯了大型預訓練模型在隱私保護方面的重大挑戰。如何有效應對這些攻擊,成為當前機器學習安全研究的一個重要焦點。

【----幫助網安學習,以下所有學習資料免費領!加vx:dctintin,備註 “部落格園” 獲取!】

 ① 網安學習成長路徑思維導圖
 ② 60+網安經典常用工具包
 ③ 100+SRC漏洞分析報告
 ④ 150+網安攻防實戰技術電子書
 ⑤ 最權威CISSP 認證考試指南+題庫
 ⑥ 超1800頁CTF實戰技巧手冊
 ⑦ 最新網安大廠面試題合集(含答案)
 ⑧ APP客戶端安全檢測指南(安卓+IOS)

威脅模型

資料集是從 Pile 訓練資料集中抽取的 20,000 個樣本子集。每個樣本由一個 50-token 的字首和一個 50-token 的字尾組成。

攻擊者的目標是給定字首時,儘可能準確地預測字尾。

這個資料集中,所有 100-token 長的句子在訓練集中只出現一次。

採用了 HuggingFace Transformers 上實現的 GPT-Neo 1.3B 模型作為語言模型。這是一個基於 GPT-3 架構複製品,針對 Pile 資料集進行過訓練的模型。

GPT-Neo 是一個自迴歸語言模型 fθ,透過鏈式規則生成一系列token。

這個場景中,攻擊者希望利用語言模型對訓練資料的記憶,來儘可能準確地預測給定字首的字尾。由於資料集中每個句子在訓練集中只出現一次,這就給攻擊者提供了一個機會,試圖從模型中提取這些罕見句子的資訊。

大模型隱私洩露攻擊技巧分析與復現

在句子層面,給定一個字首p,我們表示在字首p上有條件生成某個字尾s的機率為fθ(s|p)。

我們專注於針對性提取 κ-eidetic 記憶資料的威脅模型,我們選擇 κ=1。根據 Carlini定義的模型知識提取,我們假設語言模型透過最可能的標準生成字尾 s。然後我們可以將針對性提取的正式定義寫為:

給定一個包含在訓練資料中的字首 p 和一個預訓練的語言模型 fθ。針對性提取是透過下式來生成字尾

大模型隱私洩露攻擊技巧分析與復現

至於 κ-eidetic 記憶資料,我們遵循 Carlini的定義,即句子 [p, s] 在訓練資料中出現不超過 κ 個示例。在實踐中,生成句子的長度通常使用截斷和連線技術固定在訓練資料集上。如果生成的句子短於指定長度,使用填充 token 將其增加到所需長度。

流程

第一階段 - 字尾生成:

  1. 利用自迴歸語言模型 fθ 計算詞彙表中每個 token 的生成機率分佈。

  2. 從這個機率分佈中取樣生成下一個 token,採用 top-k 策略限制取樣範圍,將 k 設為10。

  3. 不斷重複這個取樣過程,根據字首生成一組可能的字尾。

第二階段 - 字尾排名:

  1. 使用成員資格推斷攻擊,根據每個生成字尾的困惑度進行排序。

  2. 只保留那些機率較高(困惑度較低)的字尾。

這樣的兩階段流程,首先利用語言模型生成可能的字尾候選,然後透過成員資格推斷攻擊對這些候選進行評估和篩選,從而儘可能還原出訓練資料中罕見的完整句子。

這個訓練資料提取攻擊的關鍵在於,利用語言模型對訓練資料的"記憶"來生成接近訓練樣本的內容,再結合成員資格推斷技術進一步挖掘出高機率的真實訓練樣本。

大模型隱私洩露攻擊技巧分析與復現

其中 N 是生成句子中的 token 數量。

改進策略

為了改進字尾生成,我們可以來看看真實和生成token的logits分佈。如下圖所示,這兩種分佈之間存在顯著差異。

大模型隱私洩露攻擊技巧分析與復現

為了解決這個問題,我們可以採用一系列技術進行改進

取樣策略

在自然語言處理的條件生成任務中,最常見的目標是最大化解碼,即給定字首,找到具有最高機率的字尾序列。這種"最大似然"策略同樣適用於訓練資料提取攻擊場景,因為模型會試圖最大化生成的內容與真實訓練資料的相似性。

然而,從模型中直接找到理論上的全域性最優解(argmax序列)是一個不切實際的目標。原因在於,語言模型通常是auto-regressive的,每個token的生成都依賴於前面生成的內容,因此搜尋全域性最優解的計算複雜度會隨序列長度呈指數級上升,實際上是不可行的。

因此,常見的做法是採用束搜尋(Beam Search)作為一種近似解決方案。束搜尋會在每一步保留若干個得分最高的部分解,而不是簡單地選擇機率最高的單一路徑。這種方式可以有效降低計算複雜度,但同時也存在一些問題:

  1. 束搜尋可能會缺乏生成輸出的多樣性,因為它總是傾向於選擇得分最高的少數幾個路徑。

  2. 儘管增大束寬度可以提高效能,但當束寬超過一定程度時,效能增益會迅速下降,同時也會帶來更高的記憶體開銷。

為了克服束搜尋的侷限性,我們可以採用隨機取樣的方法,引入更多的多樣性。常見的取樣策略包括:

  1. Top-k 取樣:只從機率最高的k個token中進行取樣,k是一個超引數。這種方法可以控制生成輸出的多樣性,但過大的k可能會降低輸出的質量和準確性。

  2. Nucleus 取樣(Nucleus Sampling):從機率總和達到設定閾值的token集合中進行取樣,可以自適應地調整取樣空間的大小。

  3. 典型取樣(Typical Sampling):從完整的機率分佈中取樣,偏向取樣接近平均機率的token,可以在保持輸出質量的同時引入更多的多樣性。

總的來說,條件生成任務中的解碼策略需要在生成質量、多樣性和計算複雜度之間進行權衡。束搜尋作為一種近似解決方案,能夠有效控制計算成本,但缺乏生成多樣性。而隨機取樣方法則可以引入更多的多樣性,但需要在取樣策略上進行細緻的調整。這些技術在訓練資料提取攻擊中都有重要的應用價值。

大模型隱私洩露攻擊技巧分析與復現

Nucleus取樣的核心思想是從總機率達到一定閾值η的token集合中進行取樣,而不是簡單地從機率最高的k個token中取樣。

在故事生成任務中,研究表明較低的η值(如0.6左右)更有利於生成更為多樣化和創造性的內容。這說明在生成任務中,保留一定程度的低機率token是有益的,可以引入更多的多樣性。但在訓練資料提取攻擊這樣的任務中,較大的η值(約0.6)效果更好,相比基線提升了31%的提取精度。這表明對於資料提取這類任務,我們需要更加關注生成內容與訓練資料的相似性,而不是過度強調多樣性。

如下圖示進一步說明了這一點,即η值過大或過小都會導致效能下降。存在一個最優的η值區間,需要根據具體任務進行調整。

大模型隱私洩露攻擊技巧分析與復現

Typical-ϕ是一種用於自然語言生成任務的取樣策略。它的核心思想是選擇與預期輸出內容相似的token,從而保證在典型解碼中能夠考慮到原始分佈的機率質量。這種策略可以提高生成句子的一致性,同時減少一些容易出現的退化重複等問題。Typical-ϕ 策略在數學上等價於一個帶有熵率約束的子集最佳化問題。這種策略在一定程度上可以控制生成文字的多樣性和流暢性,平衡了文字質量和創造性。

Typical-ϕ 策略在不同任務中表現可能會有所不同。例如,在抽象摘要和故事生成任務中,Typical-ϕ 策略展現出一定的非單調趨勢,即隨著ϕ值的變化,生成文字的質量並非線性提升。這說明Typical-ϕ需要根據具體任務進行合適的引數調整,以達到最佳的生成效果。

大模型隱私洩露攻擊技巧分析與復現

機率分佈調整

溫度控制(Temperature)

  • 這是一種直接調整機率分佈的策略,透過引入溫度引數T來重新歸一化語言模型的輸出機率分佈。較高的溫度T > 1會降低模型預測的確信度,但可以增加生成文字的多樣性。研究發現,在生成過程中逐漸降低溫度是有益的,可以在多樣性和生成效率之間達到平衡。但過高的溫度也可能導致生成的文字偏離真實分佈,降低效率。因此需要合理調節溫度引數。

重複懲罰(Repetition Penalty)

  • 這是一種基於條件語言模型的策略,透過修改每個token的生成機率來抑制重複token的出現。具體做法是,重複token的logit在進入softmax層之前被除以一個值r。當r > 1時會懲罰重複,r < 1則會鼓勵重複。研究發現,重複懲罰對訓練資料提取任務通常有負面影響,因為它可能會抑制一些有用的重複資訊。因此在使用重複懲罰時,需要根據具體任務和資料特點來合理設定引數r,在抑制不必要重複和保留有意義重複之間尋求平衡。

總的來說,溫度控制和重複懲罰是兩種常見的直接調整機率分佈的策略,可以在一定程度上提高自然語言生成的質量和多樣性。但它們也存在一些侷限性,需要根據實際應用場景進行合理的引數調整和組合使用,以達到最佳的生成效果。

大模型隱私洩露攻擊技巧分析與復現

為了有效的向量化,通常在訓練語言模型時將多個句子打包成固定長度的序列。例如,句子"Yu的電話號碼是12345"可能在訓練集中被截斷,或與另一個句子拼接成字首,如"Yu的地址在XXX。Yu的電話號碼是12345"。訓練集中的這些字首序列並不總是完整的句子。為了更好地模擬這種訓練設定,我們可以調整上下文視窗大小和位置偏移。

動態上下文視窗

訓練視窗的長度可能與提取視窗的長度不同。因此,提出調整上下文視窗的大小,即之前生成的token的數量,如下所示。

大模型隱私洩露攻擊技巧分析與復現

此外,鼓勵不同上下文視窗大小的結果在確定下一個生成的token時進行協作:

其中 hW 表示整合方法,W 表示整合超引數,包括不同上下文視窗大小的數量 m 和每個視窗大小 w_i。我們在程式碼中使用 m = 4 和 w_i ∈ {n, n - 1, n - 2, n - 3}。

動態位置偏移

位置嵌入被新增到像 GPT-Neo 這樣的模型中的 token 特徵中。在訓練過程中,這是按句子批次新增的,導致相同的句子在不同的訓練批次和生成過程中具有不同偏移的位置嵌入。

為了改進對記憶字尾的提取,可以透過評估不同偏移位置並選擇 "最佳" 的一個來恢復訓練期間使用的位置。具體來說,對於給定的字首 p,評估不同的偏移位置 C = c_i,其中 c_i 是一系列連續自然數的列表,c_i = {c_i1, ...},使得 |c_i| = |p|,並計算相應的困惑度值。然後選擇具有最低困惑度值的位置作為生成字尾的位置。

透過評估不同的位置偏移來選擇最佳的位置嵌入,來提高模型對記憶字尾的提取能力。這種方法可以很好地補充原有的位置嵌入方法,增強模型的效能。

大模型隱私洩露攻擊技巧分析與復現

其中 ψ(·) 表示位置編碼層,φ(·) 表示特徵對映函式,𝜙^ϕ^ 表示包含位置編碼的特徵對映函式,P 計算字首的困惑度。

前瞻(Look-Ahead)

有時候在生成過程中只有一個或兩個token被錯誤生成或者放置在不適當的位置。為了解決這個問題,可以使用一種技術,它涉及向前看ν步,並使用後續token的機率來通知當前token的生成。前瞻的目標是使用後驗分佈來幫助計算當前token的生成機率。後驗被計算為:

大模型隱私洩露攻擊技巧分析與復現

設 Track(xstart, xend | xcond) 表示從 xstart 開始到 xend 結束,在 xcond 條件下的軌跡的機率乘積。那麼我們可以寫ν步後驗為:

大模型隱私洩露攻擊技巧分析與復現

其中 Track 被計算為:

大模型隱私洩露攻擊技巧分析與復現

超引數最佳化

以上提到的技巧涉及到各種超引數,簡單地使用最佳引數通常是次優的。

手動搜尋最佳超引數,也稱為 "babysitting",可能非常耗時。

所以其實可以使用多功能的架構自動調整方法,結合了高效的搜尋和剪枝策略,根據先進的框架來確定最佳化的超引數。作為搜尋演算法,比如可以確定搜尋目標為 MP(精確度),搜尋的引數包括 top-k、nucleus-η、typical-ϕ、溫度 T 和重複懲罰 r。

字尾排名改進

在生成多個字尾之後,會進行一個排名過程,使用困惑度 P 作為度量來消除那些不太可能的字尾。然而,下圖的統計分析揭示了真實句子並不總是具有最低困惑度值

大模型隱私洩露攻擊技巧分析與復現

句子級標準

文字的熵,由 Zlib 壓縮演算法用位數來確定,是序列資訊內容的量化指標。使用由 GPT-Neo 模型計算的給定句子的困惑度與相同句子的 Zlib 熵的比率作為成員推斷的度量。此外還可以分析困惑度和 Zlib 熵的乘積的潛在效用,因為當模型對其預測有高度信心時,這兩種度量都趨於減少。實驗表明這兩種度量在成員推斷任務的整體效能上只產生了邊際改進。

詞級別標準

對高置信度的獎勵。記憶資料的高置信度存在是被稱為 "記憶效應"的現象的明確特徵之一。我們對高置信度的 token 進行獎勵。如果句子包含置信度高的 token,那麼生成的 token 的可能性高於某個閾值,並且生成的 token 與其他 token 之間的差異也高於某個閾值,我們會將其排名提高。具體來說,對於生成字尾中的 token 𝑥𝑛x**n,如果其機率高於閾值 0.9,那麼我們會從字尾 𝑠𝑖s**i 的分數中減去一個給定的數值 0.1(原始分數 𝑠𝑖s**i 是其困惑度)。

鼓勵驚訝模式。根據最近的研究,人類文字生成經常表現出一種模式,即高困惑度的 token 被間歇性地包含,而不是一直選擇低困惑度的 token。為了解決這個問題,透過只基於大多數 token 計算生成提示的困惑度來鼓勵驚訝 token(高困惑度 token)的存在:

大模型隱私洩露攻擊技巧分析與復現

其中 µ 和 σ 分別表示一批中 𝑝(𝑥𝑛∣𝑥[0:𝑛−1])p(x**n∣x[0:n−1]) 的均值和標準差。使用這種方法,生成中包含的驚訝 token 不會在整體句子困惑度上產生負面影響,從而在成員推斷期間增加了它們被選擇的可能性。

實戰

分析關鍵的函式

如下函式透過批處理方式高效地生成文字,並計算每個生成文字的損失,以評估模型在生成任務中的表現。這樣可以幫助分析和改進生成文字的質量和模型的泛化能力。

大模型隱私洩露攻擊技巧分析與復現

該函式的主要目的是從給定的提示中生成文字,並計算生成文字的機率(或損失)。

輸入引數

  • prompts: 一個包含提示的numpy陣列。

  • batch_size: 每次處理的提示數量,預設值為32。

主要步驟

  1. 初始化:

    • 初始化空列表用於儲存生成的文字和相應的損失。

    • 確定生成文字的總長度,這包括字首和字尾的長度。

  2. 批次處理:

    • 將提示按批次進行處理,批次大小由 batch_size 決定。

    • 將每個批次的提示堆疊成一個批次,並轉換為PyTorch張量。

  3. 生成文字:

    • 使用模型生成文字。生成過程中:

      • 將輸入提示移至GPU。

      • 設定生成文字的最大長度。

      • 進行隨機取樣(do_sample=True),並只考慮機率最高的10個標記(top_k=10)。

      • 處理生成過程中可能出現的填充標記。

  4. 計算機率:

    • 將生成的文字再次輸入模型,計算每個標記的機率。

    • 提取模型輸出的logits,重新整形為二維張量。

    • 使用交叉熵計算每個標記的損失。

    • 將損失重新整形,並提取字尾部分的損失。

    • 計算每個生成序列的平均損失,作為生成文字的機率。

  5. 儲存結果:

    • 將生成的文字和損失轉換為numpy陣列,並分別儲存在列表中。

  6. 返回結果:

    • 返回生成的文字和相應的損失,以numpy陣列的形式返回。

如下函式組合在一起用於評估和比較語言模型的生成質量。write_array函式儲存生成結果,hamming函式計算生成文字與真實文字之間的漢明距離,gt_position函式計算真實答案的損失,compare_loss函式比較生成文字與真實文字的損失,plot_hist函式則用於視覺化損失分佈。透過這些步驟,可以全面評估模型在生成任務中的表現和準確性。

大模型隱私洩露攻擊技巧分析與復現

1. write_array

  • 功能: 將numpy陣列儲存到檔案中,檔名包含一個唯一識別符號。

  • 輸入: 檔案路徑(包含格式化標記)、陣列、唯一識別符號(整數或字串)。

  • 實現: 使用給定的格式化標記生成檔名,然後將陣列儲存到該檔案中。

2. hamming

  • 功能: 計算生成序列與真實序列之間的漢明距離。

  • 輸入: 真實序列和生成的序列。

  • 實現:

    • 如果生成的序列是二維的,逐行計算每行的漢明距離。

    • 否則,計算生成序列第一行與真實序列的漢明距離。

    • 返回平均漢明距離和漢明距離的形狀。

3. gt_position

  • 功能: 計算真實答案序列的損失。

  • 輸入: 真實答案序列列表和批次大小(預設為50)。

  • 實現:

    • 將答案分批處理。

    • 計算每個標記的logits。

    • 使用交叉熵計算每個標記的損失。

    • 提取字尾部分的損失,並計算平均損失。

    • 返回每個序列的損失列表。

4. compare_loss

  • 功能: 比較真實序列和生成序列的損失。

  • 輸入: 真實序列的損失和生成序列的損失。

  • 實現:

    • 將兩組損失拼接在一起。

    • 對每個序列的損失進行排序。

    • 獲取排序後的索引。

    • 返回排序後的損失,排序索引和排名第一的索引。

5. plot_hist

  • 功能: 繪製損失的直方圖。

  • 輸入: 損失陣列。

  • 實現: 該函式目前為空,未實現繪圖邏輯。

如下函式組合在一起用於處理和評估語言模型的生成任務。load_prompts函式載入提示資料,is_memorization函式評估生成模型是否記住了訓練資料,error_100函式計算在發生100次錯誤之前的匹配次數,precision_multiprompts函式計算多提示生成序列的精確度,prepare_data函式則準備實驗所需的資料和目錄結構。這些步驟幫助全面評估和改進模型的生成質量和泛化能力。

大模型隱私洩露攻擊技巧分析與復現

1. load_prompts

  • 功能: 從指定目錄載入numpy檔案並轉換為64位整數型別的numpy陣列。

  • 輸入:

    • dir_: 檔案所在的目錄路徑。

    • file_name: 檔名。

  • 實現: 透過拼接目錄路徑和檔名構造完整檔案路徑,載入檔案並轉換資料型別。

2. is_memorization

  • 功能: 計算生成的序列與真實序列完全匹配的比例,以確定模型是否記住了訓練資料。

  • 輸入:

    • guesses: 生成的序列。

    • answers: 真實序列。

  • 實現:

    • 對比生成的序列和真實序列是否完全相同,統計完全匹配的次數。

    • 計算匹配次數在所有生成序列中的比例。

3. error_100

  • 功能: 計算在前100個錯誤之前的正確匹配次數。

  • 輸入:

    • guesses_order: 按順序排列的生成序列。

    • order: 序列順序索引。

    • answers: 真實序列。

  • 實現:

    • 遍歷生成序列,統計與真實序列匹配的次數,直到發生100次錯誤為止。

    • 返回在發生100次錯誤之前的總遍歷次數和超出100次錯誤的匹配數。

4. precision_multiprompts

  • 功能: 計算多提示生成序列的精確度。

  • 輸入:

    • generations: 多提示生成的序列。

    • answers: 真實序列。

    • num_perprompt: 每個提示生成的序列數量。

  • 實現:

    • 擷取每個提示生成的前num_perprompt個序列。

    • 檢查每個提示生成的序列是否與真實序列匹配。

    • 計算匹配的提示數量佔總提示數量的比例。

5. prepare_data

  • 功能: 準備資料和目錄結構以進行實驗。

  • 輸入:

    • val_set_num: 驗證集的數量。

  • 實現:

    • 構造實驗目錄和生成結果、損失結果的子目錄。

    • 載入提示資料,並提取驗證集部分的提示資料。

    • 返回構造的目錄路徑和提示資料。

### 如下函式組合在一起用於處理和評估語言模型的生成任務。

  • write_guesses_order函式將生成的序列按順序寫入CSV檔案,便於進一步分析。

  • edit_dist函式計算生成序列和真實序列之間的編輯距離,這是評估生成質量的重要指標。

  • metric_print函式計算並列印各種評估指標,包括精度、多提示精度、前100個錯誤之前的正確匹配數、漢明距離和編輯距離。這些指標幫助全面評估模型在生成任務中的表現和準確性。

大模型隱私洩露攻擊技巧分析與復現

1. write_guesses_order

  • 功能: 將生成的序列按順序寫入CSV檔案。

  • 輸入:

    • generations_per_prompt: 每個提示生成的序列數。

    • order: 序列的順序索引。

    • guesses_order: 生成的序列按順序排列。

  • 實現:

    • 開啟CSV檔案進行寫操作,檔名包含generations_per_prompt

    • 寫入表頭。

    • 遍歷序列索引和生成的序列,將每個序列按指定格式寫入CSV檔案。

2. edit_dist

  • 功能: 計算生成序列和真實序列之間的編輯距離。

  • 輸入:

    • answers: 真實序列。

    • generations_one: 生成的單個序列。

  • 實現:

    • 初始化編輯距離總和為0。

    • 遍歷真實序列和生成序列,計算每對序列的編輯距離並累加。

    • 返回平均編輯距離。

3. metric_print

  • 功能: 計算並列印各種評估指標。

  • 輸入:

    • generations_one: 單個生成序列。

    • all_generations: 所有生成序列。

    • generations_per_prompt: 每個提示生成的序列數。

    • generations_order: 按順序排列的生成序列。

    • order: 序列的順序索引。

    • val_set_num: 驗證集的數量。

  • 實現:

    • 載入真實答案資料。

    • 列印生成序列和真實序列的形狀。

    • 計算生成序列的精度並列印。

    • 計算多提示生成序列的精度並列印。

    • 計算前100個錯誤之前的正確匹配數並列印。

    • 計算生成序列和真實序列的漢明距離並列印。

    • 計算生成序列和真實序列的編輯距離並列印。

    • 返回各種評估指標。

我們首先來看基線的攻擊效果

大模型隱私洩露攻擊技巧分析與復現

我們在前面提到Zlib 壓縮演算法,可以用來衡量文字的熵,即資訊內容的量化指標。在這項研究中,Zlib 用於與語言模型計算的困惑度相結合,作為成員推斷的一個度量標準。具體地,使用 GPT-Neo 模型對給定句子計算的困惑度與相同句子的 Zlib 熵的比值,來評估句子是否可能屬於模型的訓練資料集。但是 Zlib 方法的效果是有限的。儘管 Zlib 熵和困惑度都是衡量模型對句子預測信心的指標,且兩者在模型高度自信時趨於減少,但它們在成員推斷任務的整體效能上只產生了邊際(即很小的)改進。這表明,儘管 Zlib 方法在理論上是一個有趣的嘗試,但在實際應用中可能不是最有效的手段。所以我們可以來看看是否如此

首先來看看zlib在實現上的不同

大模型隱私洩露攻擊技巧分析與復現

generate_for_prompts函式用於生成給定提示的輸出序列,並計算每個生成序列的損失

輸入引數

  • prompts: 一個包含提示序列的numpy陣列。

  • batch_size: 每個批次處理的提示數量,預設值為32。

輸出

  • 生成的序列陣列和對應的損失陣列。

步驟

  1. 初始化:

    • generationslosses 用於儲存生成的序列和計算的損失。

    • generation_len 計算生成序列的長度,該長度為字尾和字首的總和。

  2. 批次處理:

    • 將提示序列按批次進行處理。

    • 對每個批次,提取相應的提示序列,並將其轉換為PyTorch張量。

  3. 生成序列:

    • 在禁用梯度計算的上下文中,使用模型生成序列。

    • max_length 設定為生成序列的總長度。

    • do_sample=Truetop_k=10 控制生成策略。

    • pad_token_id=50256 設定填充標記ID,避免警告。

  4. 計算損失:

    • 生成序列後,計算每個生成序列的機率。

    • 將生成的序列作為輸入和標籤傳遞給模型。

    • 提取logits並重新形狀,以適應交叉熵損失計算。

    • 計算每個標記的損失,只考慮字尾部分的損失。

  5. 壓縮長度調整:

    • 使用zlib庫對每個生成的序列進行壓縮,並獲取壓縮後的長度。

    • 調整每個生成序列的損失,使其與壓縮長度成正比。

  6. 結果儲存:

    • 將生成的序列和對應的損失新增到結果列表中。

    • 最後,將結果轉換為至少二維的numpy陣列並返回。

該函式透過以下幾個步驟生成序列並計算損失:

  • 按批次載入提示序列。

  • 使用預訓練模型生成序列。

  • 計算生成序列的損失。

  • 透過壓縮調整損失。

  • 儲存並返回生成的序列和損失。

這種方法既考慮了生成序列的質量(透過損失計算),又透過壓縮長度的調整,間接考慮了序列的複雜性和壓縮率。

執行後效果如下

大模型隱私洩露攻擊技巧分析與復現

之前還提到了動態上下文視窗(Dynamic Context Window)技術。

在語言模型生成文字時,如果生成了一個錯誤的token,可能會因為語言模型的自迴歸特性而導致後續的token也生成錯誤。透過使用動態上下文視窗,可以從不同長度的歷史上下文中獲取資訊,這有助於減少這種錯誤傳播。透過調整上下文視窗的大小,即考慮不同數量的之前生成的token,可以幫助模型更好地理解字首的上下文,從而提高生成字尾的準確性。文中提到的實驗結果顯示,使用動態上下文視窗可以顯著提高資料提取的準確性。動態上下文視窗允許模型在生成每個token時考慮不同長度的上下文,這增加了生成過程的靈活性,使模型能夠根據當前的上下文資訊選擇最合適的token。

有兩種實現動態上下文視窗的方法。第一種是加權平均策略(Weighted Average Strategy),第二種是基於投票機制的策略(Voting Strategy)。兩種方法都旨在結合不同視窗大小生成的機率,以提高生成字尾的準確性。

我們首先來看程式碼上的不同

大模型隱私洩露攻擊技巧分析與復現

1. winlen_logits_output

  • 功能: 計算輸入序列的一部分(從win_leninput_len的片段)的模型輸出logits。

  • 輸入:

    • input_batch: 輸入序列的批次。

    • win_len: 截斷視窗的起始位置。

    • input_len: 截斷視窗的結束位置。

    • answer_batch: 真實答案的批次。

  • 實現:

    • 禁用梯度計算以提高效率。

    • 擷取輸入序列的指定部分並傳遞給模型,計算logits。

    • 初始化一個空列表val,準備儲存一些計算結果(但在此函式中並未實際使用)。

    • 根據訓練標誌決定如何處理logits。

    • 返回最後一層logits和空的val列表。

2. zlib_filter

  • 功能: 預留的過濾函式,目前沒有實現任何功能。

3. vote_for_the_one

  • 功能: 透過投票機制選擇最可能的輸出序列。

  • 輸入:

    • last_logits: 最後一層的logits。

    • k: 用於投票的前k個logits。

    • answers: 真實答案。

    • input_len: 輸入序列的長度。

  • 實現:

    • 初始化投票計數陣列。

    • 獲取logits中每個序列的前k個最高值的索引。

    • 為每個索引分配線性權重。

    • 列印預測結果和原始結果的比較。

    • 返回投票計數最高的索引作為最終預測。

4. logits_add

  • 功能: 透過加權求和的方式整合logits,得到最終的預測。

  • 輸入:

    • last_logits: 多個視窗的logits。

    • weight_win: 每個視窗的權重。

  • 實現:

    • 使用權重加權求和各個視窗的logits。

    • 返回加權求和後的logits中機率最高的索引作為最終預測。

這些函式用於處理和評估生成模型的輸出:

  • winlen_logits_output 提取並計算輸入序列部分片段的logits,幫助理解模型對不同輸入片段的響應。

  • vote_for_the_one 使用投票機制從logits中選擇最可能的輸出,提高預測的準確性。

  • logits_add 透過加權求和不同視窗的logits,進一步最佳化預測結果。

  • zlib_filter 目前未實現,可能預留用於將來對資料進行某種過濾處理。

大模型隱私洩露攻擊技巧分析與復現

這用於生成給定提示的輸出序列,並計算每個生成序列的損失的函式

輸入引數

  • prompts: 包含提示序列的numpy陣列。

  • batch_size: 每個批次處理的提示數量。

  • _SUFFIX_LEN, _PREFIX_LEN: 字尾和字首的長度。

  • _DATASET_DIR.value: 資料集的目錄路徑。

  • _val_set_num.value: 用於載入的驗證集數量。

輸出

  • 生成的序列陣列 (generations) 和對應的損失陣列 (losses)。

主要步驟

  1. 初始化:

    • generationslosses 初始化為空列表。

    • generation_len 計算生成序列的長度,為字尾和字首長度之和。

    • answers 載入驗證集的答案資料。

  2. 迴圈處理提示序列:

    • 根據設定的批次大小,迴圈處理提示序列。

    • 每次迴圈中,提取並準備輸入的提示批次 (prompt_batch) 和對應的答案批次 (answers_batch)。

  3. 生成序列:

    • 使用帶有截斷視窗的方法生成序列,透過呼叫 gene_next_token 函式獲取每次生成的下一個標記。

    • 將生成的標記 (generated_tokens) 拼接在一起形成完整的生成序列。

    • 將生成序列轉換為PyTorch張量,並在禁用梯度計算的上下文中生成模型輸出 (generated_tokens 是最終的生成序列)。

  4. 計算損失:

    • 計算每個生成序列的logits。

    • 使用交叉熵損失函式計算損失。

    • 將損失加入到 losses 列表中。

  5. 返回結果:

    • generationslosses 轉換為至少二維的numpy陣列,並返回。

執行後效果如下

大模型隱私洩露攻擊技巧分析與復現

在上圖可以看到指標有極大的提升(可以看precision,精確度是指正確生成的字尾佔給定字首總數的比例。這是透過比較生成的字尾和實際的訓練資料字尾來計算的。精確度反映了模型生成正確字尾的能力。這個值越高說明效果越好;或者也可以看hamming dist,漢明距離是用來衡量兩個等長字串之間差異的指標,計算為兩個字串對應位置上不同符號的數量。在訓練資料提取的上下文中,漢明距離用來定量評估生成字尾與真實字尾之間的相似度,提供了一個在token級別上對提取方法效能的評估。這個值越小,說明效果越好)

在來看看我們在上文提到的另一個改進策略:一種基於詞級別的排名方法,稱為 "Reward on high confidence"(簡稱 highconf 方法)。這種方法的核心思想是獎勵那些在生成字尾中包含高置信度 token 的候選字尾。具體來說,如果一個生成的字尾中的某個 token 具有高於特定閾值(例如 0.9)的機率,那麼這個字尾在排名時會被賦予更高的分數。這種策略的目的是利用語言模型對其預測的置信度來提高提取任務的效能。

對應的程式碼如下

大模型隱私洩露攻擊技巧分析與復現

這段程式碼的功能是生成給定提示的輸出序列,並計算每個生成序列的損失。

輸入引數

  • prompts: 包含提示序列的numpy陣列。

  • batch_size: 每個批次處理的提示數量。預設為32。

輸出

  • 生成的序列陣列 (generations) 和對應的損失陣列 (losses)。

主要步驟

  1. 初始化:

    • generationslosses 初始化為空列表。

    • generation_len 計算生成序列的長度,為字尾和字首長度之和。

    • 將輸入的 batch_size 設定為32,這個值在後續迴圈中使用。

  2. 迴圈處理提示序列:

    • 根據設定的批次大小,迴圈處理提示序列。

    • 每次迴圈中,提取並準備輸入的提示批次 (prompt_batch),並將其轉換為PyTorch張量 (input_ids)。

  3. 生成序列:

    • 使用帶有截斷的方法生成序列,透過呼叫 _MODEL.generate 函式獲取生成的標記 (generated_tokens)。

    • 在生成的標記上禁用梯度計算,並透過計算模型輸出 (outputs.logits) 獲得每個標記的logits值。

  4. 損失計算:

    • 計算每個標記的損失 (loss_per_token),使用交叉熵損失函式 (torch.nn.functional.cross_entropy)。

    • 對損失進行後處理:

      • 使用標準差過濾異常值,如果損失超出3倍標準差範圍,則設定為1。

      • 根據前兩個最高的logits分數之間的差異和是否大於0.5來調整損失值。

      • 最後,計算每個生成序列的平均損失 (likelihood)。

  5. 結果整理:

    • 將生成的序列 (generated_tokens) 和損失 (likelihood) 新增到 generationslosses 列表中。

  6. 返回結果:

    • generationslosses 轉換為至少二維的numpy陣列,並返回。

執行後如下所示

大模型隱私洩露攻擊技巧分析與復現

在上圖中,也是用我們之前說的方法,看指標,precision,hamming dist等都相比基線方法有了較大提升。也就表明我們在本文中所說的這些策略都是有效的。

更多網安技能的線上實操練習,請點選這裡>>

相關文章