PPO 小註解

Proximal Policy Optimization 是一個 fine-tune Model 的方式, 另一個主流方式是 DPO (Direct Preference Optimization). 這邊主要是整理課程影片中 PPO 的公式 (只用大約 2 分鐘超高速閃過…), 以便有空時可以查詢.

[基本架構]

有一個 LLM model, 和可調整的參數: θ, query: X, response: Y, 所有輸出入組合 rollout 表示為 (X, Y).

因為我們要微調這個 model, 所以要給一個獎勵函數 (reward function): r(X,Y), 用來調整模型 πθ (X,Y).

獎勵是對所有輸出的 Y 取期望值

EY~πθ (X,Y) [r(X,Y)], 其中 Y~πθ (X,Y), 表示 Y 在 πθ (X,Y) 的輸出組合.

也對每個 query X 計算

EX~D[EY~πθ (X,Y) [r(X,Y)]] ——————— (1)

其中 X~D, D 表示 X 的散度 (Divergence), 依此類推.

我們找出一個得到最多獎勵的那組參數, 就算是 fine-tune 完成.

π* (X,Y) = arg maxπ {EX~D[EY~πθ (X,Y) [r(X,Y)]]}, {} 裡面就是上面那包.

[Reference model]

做得好不好, 我們要有一個 reference model 來當評審.

πref (X,Y)

Model 的輸出愈接近 reference model 就表示學得愈好.

[懲罰值]

KL 是 Kullback-Leibler 兩個人名的縮寫. KL penality coefficient 是它們衡量懲罰的函數. 基於 reference model πref (X,Y) 下, 對 πθ (X,Y) 產生的懲罰 DKL 表示為

DKLθ (X,Y) || πref (X,Y)]

[綜合期望值和懲罰值]

π* (X,Y) = arg maxπ {EX~D[EY~πθ (X,Y) [r(X,Y)]] – β * 懲罰值} =>

π* (X,Y) = arg maxπ {EX~D[EY~πθ (X,Y) [r(X,Y)]] – β DKLθ (X,Y) || πref (X,Y)]}


為了要知道往哪個方向調整, 我們要找 θ 的梯度.

[只看 reward function]

這是 reward function 在特定 model 參數 θ 的期望值

E[rY ] = EY~πθ (X,Y) [r(X,Y)]

將它表示為解析函數 [1], 期望值等於所有 Y 可能的值乘上它的機率的和

E[rY ] = ∑Y r(X,Y)πθ (Y|X) —— (2)

最優化的參數 θ⌃ 就是所有 θ 中 reward 最好的. (我打不出 hat theta, 所以把帽子放右邊)

θ⌃ = arg maxθ [E[rY ]] = arg maxθ [∑Y r(X,Y)πθ (Y|X)]

對式子 (2) 取 θ 的梯度,

θ E[rY ] = ∑Y r(X,Y)θ πθ (Y|X)] ——– (3)

按照微積分的 chain rule [3]

θ log (πθ (Y|X)) = θπθ (Y|X) / πθ (Y|X) =>

θπθ (Y|X) = θ log (πθ (Y|X)) * πθ (Y|X) —– (4)

把這個變長的 (4) 帶回去 (3),

θ E[rY ] = ∑Y r(X,Y)θ πθ (Y|X)] =>

θ E[rY ] = ∑Y r(X,Y)θ log (πθ (Y|X)) * πθ (Y|X) =>

θ E[rY ] = EY~πθ (Y|X) r(X,Y)θ log (πθ (Y|X))

再把 X 考慮進去, 就得到

Ex~D [θ E[rY ] ] = θ Ex~D [ E[rY ] ]

意思是說, 當 β = 0, 忽略掉懲罰的話, 對式子 (1) 取梯度, 等效只對 reward function 取梯度. 反之亦然.

這有什麼意義呢? 我請 AI 幫我解釋. 我試了幾次都沒有它講得好.

θ E[rY ] = EY~πθ (Y|X) r(X,Y)θ log (πθ (Y|X)) 這個結果是 策略梯度定理(Policy Gradient Theorem)[2] 的核心公式。其意義在於:

  • 將梯度轉換為期望形式:原始梯度需遍歷所有可能的輸出 θY(計算量巨大),但此公式表明:梯度可通過從策略 πθ   中採樣 Y 來近似計算。
  • 避開解析計算:無需知道所有 Y 的機率分佈,只需對採樣的 Y 計算  r(X,Y)θ log (πθ (Y|X)) 的平均值。

它與 Monte Carlo Method 的相似處在於: 透過採樣直接估計期望值,無需精確計算所有可能的 Y.

蒙特卡羅方法收斂速度為 O(1/√N​), N 夠大就好. 而窮舉法不可行.

最後再筆記一下懲罰項.

Kullback-Leibler 方法其實是要避免訓練後新的參數和舊的參數偏差太遠. 以至於學會新的東西就忘了舊的 – 災難性遺忘 (Catastrophic Forgetting), 和 reward 無關. 因此討論原理時可以忽略它.

但它對於穩定系統非常重要, 其主要角色是作為正則化項 (Regularizer), 將策略更新限制在信賴域 (Trust Region) 內. 在PPO算法中,KL 散度還會動態調整更新步長. 當 DKL​ 超過閾值時自動縮小學習率,此設計本質上將 “避免遺忘" 和 “促進學習" 綁定為同一過程。

[REF]

  1. 解析函數 – 維基百科,自由的百科全書
  2. https://en.wikipedia.org/wiki/Policy_gradient_method
  3. Slide 1

GGUF 小註解

拜台幣升值 10% 左右之賜, 我在 Q2 的投資差點要 GG. 我期望不高, 只要月底能跟 Q1 對齊, 也算是有 10% 看不見的成長了. 在這混亂的國際局勢下, 我來筆記一下 GGUF. 它不是 “GG, U Failed" 的縮寫! 而是全名 GPT-Generated Unified Format, 一個為了 LLM 推理而設計出的檔案格式.

一般我們去 Huggingface 下載一個模型, 它會可能是 .bin 檔, safetensor 檔, 或是 ONNX 檔. 以 safetensor 而言, 裡面放的是模型未量化過的模型權重. 至於 model 的架構 (graph 長相), 會另外寫在 config.json 裡面. 雖然這個檔案名稱也通用於很多其他的地方, 這裡特別是指用來描述模型的 config.json.

例如 Gemma-2-2B 的 config.json [1] :

{
  "architectures": [
    "Gemma2ForCausalLM"
  ],
  "attention_bias": false,
  "attention_dropout": 0.0,
  "attn_logit_softcapping": 50.0,
  "bos_token_id": 2,
  "cache_implementation": "hybrid",
  "eos_token_id": 1,
  "final_logit_softcapping": 30.0,
  "head_dim": 256,
  "hidden_act": "gelu_pytorch_tanh",
  "hidden_activation": "gelu_pytorch_tanh",
  "hidden_size": 2304,
  "initializer_range": 0.02,
  "intermediate_size": 9216,
  "max_position_embeddings": 8192,
  "model_type": "gemma2",
  "num_attention_heads": 8,
  "num_hidden_layers": 26,
  "num_key_value_heads": 4,
  "pad_token_id": 0,
  "query_pre_attn_scalar": 256,
  "rms_norm_eps": 1e-06,
  "rope_theta": 10000.0,
  "sliding_window": 4096,
  "torch_dtype": "float32",
  "transformers_version": "4.42.4",
  "use_cache": true,
  "vocab_size": 256000
}

使用 GGUF 就不用單獨的 config.json 了, 但是生成 GGUF 的時候還是需要. 所以從Huggingface 下載 GGUF 時看到 config.json 也不用太驚訝. 總之, GGUF 檔案裡面除了放模型的權重, 還放了超參數和詞彙表. 所謂超參數就是模型訓練中需要手動設定、無法透過模型訓練的參數 – 這些就是從 config.json 抄過來的.

至於詞彙表 (Vacabulary) 裡面就是放所有 toekn 的字典. 它有一點大, 但不會太大. 假設u有個模型認得 128K 個 token (大約是 GPT-4 的用量), 每個 token 長度 4 bytes, 算起來才 5.1MB, 比起模型權重動輒就是幾 GB, 真的也不差多哪一點.

GGUF 把這些都打包起來, 使用時就不用東市買駿馬,西市買鞍韉,南市買轡頭,北市買長鞭. 假設要量化參數, 下個指令轉出新的 .gguf 檔就好. 包括混合精度也能做到. 更不會改了參數檔, 結果 config.json 沒改到. 我們常常會遇到這個 bug.

雖然 GGUF 把相關資料都包在一起, 但它執行起來並不像個肥宅, 甚至它更省記憶體. 如果我們使用 safetensor, 因為那一整包都是權重, 我們無法知道哪一個 byte 是屬於哪一層的參數, 所以通常整包都得放進記憶體. 像是 Llama 3 70B 量化過也需要用 30GB 記憶體.

反觀 GGUF 自己就有完整的訊息, 它可以把檔案中的模型 memory mapping 到 virtual memory 裡面, run 到哪個 chunk, CPU 或 GPU 直接看 index 載入哪部分的參數即可, 號稱可以作到 zero copy. 以前述 Llama 3 70B 模型為例, 可能只需要 500MB~2GB 的記憶體就夠了. 據說在一台 16GB 的筆電上也能運行.

另外, safetensor 檔案裡面只放權重, 還大剌剌地以 safe 為名. GGUF 包了更多東西進去, 那還能保證安全嗎? 答案也是肯定的. 它對格式和 API 都有所規範, 並內建 SHA-256 校驗, 所以不至於輕易地被駭客埋 code 進去, 並且被當作 Python 執行. 至於 pickle (.pt) 或是 .bin 檔案則是有這方面風險.

最後談 GGUF 的缺點. 首先是它只支援 LLM, 不像 ONNX 適用於所有深度學習 (Yolo 等等)、safetensor 更適用於儲存所有 tensor. 其次是背後沒有大人認養, 所以 toolchain 比較不足. 最後的主要缺點是 – 它對 CPU 優化較好, 同一個 model 用 ONNX 表示的話, 在 GPU 上會跑得更快.

最後叫 Monica 生成一個簡單的 GGUF 檔案範本, 這樣比較好理解.

[檔案頭 Metadata]
general.name = "MiniModel-v1"
general.description = "示範用微型語言模型"
general.file_type = 1 (FP32)
general.architecture = "Transformer"
general.quantization_version = 2

[tensors]
1. token_embedding.weight
   - shape: [5, 3]  # 5個token,每個token向量大小為3
   - data: [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], ...]

2. layer.0.attention.wq.weight
   - shape: [3, 2]  # 3維輸入 → 2維輸出
   - data: [[0.7, 0.8], [0.9, 1.0], [1.1, 1.2]]

3. layer.0.ffn.w1.weight
   - shape: [2, 4]
   - data: [[...], ...]

實際上 head -c 1000 granite-7b-lab-Q4_K_M.gguf | xxd -c 32, 可以看到檔案前面有幾個文字可讀, 後面 tensor 就都是 binary. 如果仔細看下圖, 會看到裡面還看到 ggml 的字樣, 那是 GGUF 的前代格式. 主要是差在舊版沒有 chunked index 結構, 不方便快速抓出某一層參數, 以及沒有 SHA 保護機制.

[REF]

  1. https://blog.csdn.net/shizheng_Li/article/details/144866526

IC 設計公司營收排名 2024

去年的統計更新了. 幾個重點整理如下:

  1. 聯發科持續成長, 大者恆大.
  2. 瑞昱又再次超車聯詠, 螃蟹公司證明它上次搶到第二名不是偶然.
  3. 老牌公司信驊, 矽統, 世紀民生繳出倍數的成長. 世紀民生成長高達 659.47%.
  4. 業績成長或衰退雙位數的比個位數的還多. 表示競爭激勵, 不進則退.
  5. 因為幣別的關係, 譜瑞-KY 去年就放錯位置, 深感抱歉! 現在往前追溯修正.
  6. 美金最近還在漲, 以下官方如果沒有特別引用匯率, 我就用 32.5:1 來計算.
排名公司股號2024 (K NTD)成長率 (%)
1聯發科2454530,585,88622.41
2瑞昱2379113,393,69819.14
3聯詠3034102,787,751-6.92
群聯 [*]829958,935,51322.2
4世芯-KY366151,976,78265.45
5奇景光電HIMX40,300,00042.43
新唐 [*]491931,923,290-9.69
擎亞 [*]809628,157,01625.47
6慧榮SIMO26,325,0000.2748
旺宏 [*]233725,883,475-6.3
7創意344325,044,192 -4.56
8瑞鼎359224,376,80232.87
9天鈺496119,224,74618.12
10達發科技652619,122,10440.86
11矽力-KY641518,450,37519.6
12矽創801617,826,5056.6
13譜瑞496616,246,76617.99
14威盛238815,910,68625.81
15敦泰354514,538,9877.15
16晶豪科300613,485,16813.47
17義隆245812,695,8625.29
18智原303511,064,852-7.53
19原相32278,362,27343.08
20致新80818,252,6644.32
21祥碩52698,081,07126.24
22聯陽30146,632,5785.67
23信驊52746,459,666106.35
24凌陽24016,434,08624.01
25茂達61386,089,50412.43
26昇佳電子67324,940,6838.76
27神盾64624,790,32824.47
28愛普65314,176,356-0.94
29宜特 [*]32894,345,52614
30力智67193,697,96321.75
31立積49683,679,34823.28
32力旺35293,605,96818.22
33鈺創53513,473,21730.48
34創惟61043,178,69026.36
35偉詮24363,094,6197.25
36富鼎82612,918,3812.36
37大中64352,716,0852.24
38晶焱64112,744,6844.06
39松翰54712,744,4665.15
40盛群62022,501,630-3.64
41尼克森33.172,468,2610.15
42凌通49522,461,89513.61
43安國80542,192,58810.17
44沛亨62911,824,248-26.39
45凌陽創新52361,817,92710.17
46研通62291,796,99663.24
47聚積35271,792,664-3.43
48威鋒電子67561,700,310-16.45
49杰力52991,691,956-2.38
50揚智30411,628,22413.08
51系微62311,614,58820.27
52晶宏31411,507,390-18.65
53M3166431,480,903-8.15
54通嘉35881,453,90627.36
55晶心科65331,381,50730.6
56九齊64941,345,3000.92
57點序64851,261,971-25.09
58普誠6129 1,150,966-30.64
59倚強32191,137,860-1.67
60宏觀65681,065,4916.97
61海德威3268972,915-7.38
62類比科3438963,3709.51
63禾瑞亞3556955,594-16.39
64亞信3169852,618-3.94
65虹冠3257816,028-24.01
66矽統2363 738,560294.56
67迅杰6243716,549-18.14
68九暘8040644,041-10.3
69世紀民生5314643,931659.47
70驊訊6237448,7417.45
71金麗科3228424,69640.73
72旺玖6233417,22515.73
73笙泉3122364,666-1.78
74笙科5272 331,795-0.52
75鑫創3259239,109-13.25
76佑華微8024224,068-6.29
77通泰5487194,27720.6
78聯傑3094165,860-31.62
79凱鈺5468120,5681.52
80點晶328881,779-16.62
81合邦610354,87513.98
82太欣530213,91213.46

比特幣出金記

話說很多年前, 我就趕時髦挖比特幣. 後來聽說挖礦的成本 (電費)高於比特幣的價值, 所以就停挖了. 又過了幾年, 聽說雖然比特幣挖不動, 但挖以太幣換比特幣還有賺頭, 所以我又挖了第二次!

當然除了買貴鬆鬆的顯卡, 老婆抱怨經過我房間門口都特別熱 (電費換成喜歡的形式) 之外, 整個電腦都變得不穩. 不但遊戲玩不成, 部落格後台也頻頻當機, 最後只得停工.

最近看到比特幣漲了不少. 於是又開啟 RTX 4090 挖了一下下. 結果本來很穩的電腦, 那個不便宜的 ECC DDR 就這樣燒壞了. 於是我退出江湖, 設法將比特幣出金. 雖然這幾天真的很冷, 挖礦等於開暖氣還賺錢, 還滿懷念的, 哈!

川普當選好像對比特幣有益, 這東西長期應該也是看漲. 不過我只求賺回買顯卡的錢就好了, 所以我算是一面倒地 (又龜速地) 站在賣方. 不幸地, 今年年初起手式就錯了, 我傻傻地從礦場轉帳到自己冷錢包, 這一個動作就被扣了些手續費 0.0001 BTC.

接下來我以為可以找個人交易了, 卻發現場外交易沒那麼簡單. 接著我就做了第二件蠢事, 我把冷錢包的錢轉到幣安, 想說幣安這麼大, 應該很容易賣掉吧! 結果幣安要換美金、甚至換日幣都比較容易, 要找個台幣的賣家根本困難重重. 只好再研究一下那裡好賣? Google 後我找到 Max 交易所.

Max 的認證有點嚴, 我的審查資格搞了好幾天, 比特幣都漲起來了. But, 從幣安轉到 Max, 我又被收一次手續費 0.0000071 BTC. 在心疼手續費之餘, Max 一通過我的身分驗證, 我就市價怒賣比特幣!

成交本身滿快的, 分成兩單被人接走. 然而我想把台幣再轉帳到我的帳戶, 又再被扣了 15 元 NTD 手續費. 在幣安設定帳號時, 它會轉進 1 元新台幣驗證帳戶可用性, 所以算起來我少虧一元. 合計搬家四次後, 手續費總共是 0.0001071 BTC (約 340 新台幣) 和 14 塊新台幣, 合計高達 354 元左右! 股市跌 354 萬都還會漲回來, 這手續費可是一去不回. 總之, 今年總算入袋為安了.

另外, 促使我加速出場的一則新聞是 Google 量子電腦 Willow 的進展. 這個新聞確實讓比特幣跌了一下下 [1]. 其實研究團隊最大的進展在於找到糾錯量子位元 (Error-corrected qubits) 的 pattern, 讓位元數增加時, 糾錯能力可以隨之上升, 把錯誤率壓下來. 因此開啟了更多量子位元的可能.

這讓我好奇究竟量子電腦能否顛覆虛擬貨幣? 稍微研究後發現其實是可以的, 但目前量子電腦都要針對特定用途 (算法) 做設計, 把演算法轉換成疊加態, 才能達到快速計算. 它還不像是個人電腦那樣能夠泛用, 打幾個字就可以寫程式. 所以投資人要評估把剩下的比特幣全部挖完能賺多少, 才知道值不值得為它設計個量子挖礦機? 還是花同樣的力氣去攻略別的標的更划算?

換個角度想, 要是一秒鐘能挖完所有的虛擬貨幣, 那比特幣存在的價值 (公信力) 會剩多少就還不好說? 假設比特幣因此被認為沒有價值, 駭客還不如去破解更保值的東西. 所以這不是送分題. 如果是委內瑞拉要拚一次性挖完比特幣那就還算合理, 因為這本來就是它的法幣 [3], 它說有價值就有價值了, 還不怕別人跟它哄抬挖礦成本.

[REF]

  1. Google Willow量子晶片!即將邁入量子電腦時代!?Google解決什麼關鍵性的問題?
  2. 未來趨勢!一次了解量子電腦將如何掀起運算革命!量子科技原理全解析!
  3. https://0xzx.com/zh-tw/2024090603314843272.html

關於 LLM 的自我審查

先前用過 ChatGPT 3 的人應該都記得這些 Model 動不動就說自己不知道, 不能說, … 但變個花樣問, 不能說的又全說了!

那麼 LLM 怎麼做到自我審查呢? 基本的做法是 RLHF (Reinforcement Learning from Human Feedback) [1], 也就是靠人類的意見來約束 LLM. 但我們不知道 LLM 會被問什麼問題, 總不能一筆一筆叫網路警察來核准吧! 所以我們先根據真人的反饋, 來建立一個獎勵模型 (reward model), 以後就叫 reward model 來代替人工.

當大量的問題, 都有被人類標記為優選的答案, 他們就是一個標準答案 reward model. 它其實也是一個 LLM, 但我們先忘記這件事. 下面講到 LLM 都是指那未經自我審查 / fine tune 的 LLM.

顯然地, 我們拿 LLM 的標準問題 prompt 以及輸出 completion對, 去和 reward model 的標準 prompt + completion 比較, 計算兩者 logits 層 (未經 softmax 之類 activation function 的原始輸出) 的差異, 就知道這個 LLM 回答得像不像人? 然後把 LLM 的 logits 往人類標記的方向調整 [註 A], 就會讓 LLM 的答案愈來愈像人的回答.

我們也可以叫 reward model 標記 LLM 的輸出是否有害? 例如做個 remodel model 專門學 LLM 的輸出是否拉高仇恨值? LLM 答題主要依據 helpful, honest, 和 harmless 三原則. 身為一個機器人, 誠實是基本的. 不能出現言語傷害 (harmless 原則), 也不能因為怕講錯話而淨說沒用的廢話 (helpful 原則) [註 B].

本圖取材自 https://primo.ai/index.php?title=Reinforcement_Learning_(RL)from_Human_Feedback(RLHF

上面的論述略過了好幾段段情節, 在此補充:

[註 A] Reward model 怎麼微調 LLM 參數. 目前常用的一個演算法是 PPO (proximal policy optimization). 我們將它理解為可以調整參數, 但一次不要調太多, 免得把辛苦 train 了半天的 model 調壞. 因此就算要調整, 也是利用 PEFT (Parameter-Efficient Fine-Tuning) 的做法, 包括有名的 Lora.

[註 B] 為避免 Reward model 把 LLM 帶偏, 變成只求不出錯就好, 我們同樣限制調整過的參數和原本的參數 (reference model or frozen model) 不能差太多. 可用的演算法包括 Kullback-Leibler (KL) divergence, 它可以用 softmax 的輸出來比較像不像, 所以根本不用管輸出的 token 是啥以減少計算量. 它可以跟 reward model 共存.

最後, 不免有人會問, 如果一定要有 Human 才能幫 LLM 做思想審查, 是不是太不 AI 了. 沒錯! 其實 Human 也可以換成 AI. 但我們不會叫小學生去教小學生, 我們先叫 LLM 產生一堆負面教材, 然後 train LLM 避免生成這些仇恨、色情、暴力的言論即可. 於是乎, 當我們問 LLM, 不可以上那些色情網站時, 這些剛好都是 RLAIF (Reinforcement Learning from AI Feedback) 的紅隊演練考題, 因此他們侃侃而談, 不知道中計! 當然, 這已經是過去式了~~

[REF]

  1. https://huggingface.co/blog/rlhf
  2. https://huggingface.co/docs/peft/index