iT邦幫忙

2024 iThome 鐵人賽

DAY 24
1
AI/ ML & Data

一個Kaggle金牌解法是如何誕生的?跟隨Kaggle NLP競賽高手的討論,探索解題脈絡系列 第 24

[Day24]Try and Error! 淺談整合 Tool-Integrated Reasoning 和 Code Debugging 能力的 Decode 策略

  • 分享至 

  • xImage
  •  

第一名由 Numina 和 Hugging Face 的大佬們合作拿下,解決了private test set 中的 29/50 個問題,最終喜提美金 $131,072 而歸!
第二名和第三名分別解出 22 道和 21 道題目,所以第一名解出 29 題可以說是大幅度領先其他參賽者的~

我們今天就一起來欣賞一下第一名的作法吧!

🥇 1st Solution

第一名的解法大致分成三個部分:

  1. 一個針對 DeepSeekMath-Base 7B 微調的訓練方法,使其能作為「推理代理」(Reasoning Agent) 結合自然語言與 Python REPL(一個交互式的 Python 解釋器環境) 解決數學問題。
  2. 一個結合工具推理與代碼執行回饋的 tool-integrated reasoning (TIR)解碼算法,用於推理過程中生成候選的解決方案。
  3. 多個內部驗證集,用來確認要選擇哪一個模型泛化能力比較好,避免overfitting在public leaderboard score上。

Training Recipe

昨天我們做 "Zero-shot MMOS-DeepSeekMath-7B with Self-Consistency" 的實驗時,發現有時候 LLM 沒有辦法順利把問題成「可執行的代碼」,例如有時候轉出來的 code 我們一執行就會跳出 Syntax Error,這時候就沒辦法 run 這個壞掉的程式,只能依靠 LLM 的推論然後我們擷取它回覆末尾的答案當作這題的輸出。

但不知道大家有沒有這樣的經驗:有時候我們讓 GPT-4o 幫忙寫一段程式,執行後發現有問題,把 error message 丟回去叫它修改一下,不要太複雜並且給予充足上下文資訊的話,通常兩三回 GPT-4o 就可以修復問題給出可執行的 code。

那我們是不是也可以應用這套思路呢? 不要 DeepSeekMath-Base 7B 給出壞掉的 code 我們就 return -1 跳出 function,我們可以把錯誤訊息回傳給 LLM 多給他幾次機會修正,就有機會得到可以執行的 program ,以及程式跑出來的精確答案。

image

他們的訓練流程如上圖分成兩個部分:

  • Stage I. 提升模型讀題與拆解數學問題的能力
    他們自己擴增了一個 MuMath Dataset,從 GSM8K 和 MATH 這兩個公開數學數據集收集題目,再利用題目改寫(換數字、增加條件)等他們設計了一系列方法,擴增一批包含數學問題以及詳細推理過程的數據集。
    在這個階段,他們先讓 DeepSeekMath-Base 7B 在這個擴增版的 chain-of-thoughts 數學問題繼續 fine-tuned。
  • Stage II. 提升模型的 Code Debugging 能力
    為了訓練模型可以把數學問題轉化成代碼,他們創建一個 "MuMath-Code" 的 Dataset,其中他們參考 ToRA這篇paper的作法,將每個問題的解法分解成:
    image
  1. Chain-og-Thoughts 理解題目後的初始推理與解題邏輯。如下圖(c)的$r_1$部分,制定一個初始的方案,也就是“先用 Sympy 計算 x+y 可能的數值“
  2. 根據解題邏輯轉化成 programming-based 的 method。如下圖(c)的$a_1$部分,開始實際用 Sympy 將題目轉化成代碼
  3. 結合外部工具例如 Python Interpretor 執行代碼並得到結果
  4. 結合初始推理邏輯、代碼、代碼執行結果一起進行解讀,最後推理得出解答。如下圖(c)的$r_2$部分,最終推理得出的解答在 \boxed{} 中。

按照上面的流程,他們將 MuMath 的題目拿去問 GPT-4 ,並特別收集 GPT-4 給出錯誤代碼,然後人工反饋錯誤訊息給 GPT-4,GPT-4 再根據這些信息給出修正版本的代碼。
他們特別收集這種情況過程中的對話到 MuMath-Code 的資料集中,使得第二階段的模型可以透過這些訓練資料,學會根據編譯器的錯誤訊息來回修正代碼,在和 python interpretor 的多次交互中,達到 self-improvement 的目的。

下面是他們 NuminaMath 使用階段一和階段一二全流程訓練後的模型,在 MATH 這個 banchmark 的 performance 比較。

image

看起來只有階段一的訓練還是不太夠,結合階段一和階段二才突然拉開與其他 Baseline 的差距。所以重點還是在提升模型 code debugging 能力後,之前試一次失敗就掰掰的題目現在有更多機會從錯誤中學習。

不過他們的模型,全部都是「全參數訓練」,沒有用 quantization 也沒有用 LORA,總共在八張 H100 GPU 訓練大約十小時。

哎,這對一般參賽者來說真的還滿難有這樣的硬體條件去 reproduce 他們的結果,或是採用類似的策略 QQ

不過說到這裡,不知道大家會不會有個疑惑:

🤔 到底什麼時候要用 LoRA/QLoRA fine-tuned,什麼時候要用 FFT(全參數微調)呢?兩者需要的算力相差甚巨,但在不同規模的領域資料上微調,performance實際上又會有多大的差距呢?

其實我也不知道,希望之後有時間可以去 survey 看看~

Self-Consistency with Tool-Integrated Reasoning (SC-TIR)

接下來,為了增加模型回覆的穩定性,他們在 Inference 的時候結合 Self-Consistency 和 TIR 的方式來 prompt 模型。

image

其實講簡單一點,就是同一道問題會讓模型多 inference 幾次,然後每次 inference 都會讓模型寫 code 執行他自己寫的 code,如果 code compile 不通過或是執行中遇到問題,就反饋 error message 給模型叫模型重新改一版 code,重複這個流程直到模型產生可正確執行的程式碼或是達到最大嘗試次數。

假設每道問題都會 inferencen n 次,這 n 次中都會反覆提出code、執行 code、修改 code,最後得到執行結果也就是該次 inference 的答案,我們再從這 n 個答案做 majority vote 就可以了!

這個模型本身在 stage2 訓練的時候,就已經很習慣做這些事了(反覆提出可行的代碼、發現錯誤、重新修正再執行),所以 inference 的時候結合 self-consistency 和 TIR ,還是可以 align 到模型訓練時候學到的東西。

不知道你看到這邊會不會覺得...
好像...還滿直覺的呦!

確實有不少參賽者都發現像是昨天 zero-shot + Sympy 常常模型寫的程式有問題,那我們就跟他說問題在哪裡叫他改一改應該也會有一樣的效果吧!

但問題就是,多數參賽者使用的 7B 模型沒有經過前面 Stage 2 的訓練,往往沒辦法根據 error 做出適當的修正。
所以前面 Stage2 的訓練在這樣的思路下,還是有其必要性在~

Good Validation Sets Are All You Need

看這麼多 Kaggle 賽題的解法,我會覺得對每個開發團隊來說,最重要的事情就是----

📌 "Build a reliable local validation strategy!"

昨天有提到由於模型回覆的不穩定性的關係,同樣的代碼繳交到 LB 上,分差可能會來到 4 分以上。因此第一名的團隊小心地使用四個內部 validation set 來評估模型在不同難度數學問題上的表現,避免 overfit 在 LB score 上,並從中挑選在這些 validation set 都表現得非常穩定的模型來提交。

  • AMC:他們選擇了 AMC12 競賽中 2022 和 2023 年的所有題目,並篩選出可以轉換為整數輸出的問題,最終得到 83 個題目。
    這個驗證集的設計是為了模擬 Kaggle 上的 private testset,結果顯示模型可以解出約 60-65% 的問題。為了衡量模型表現的變異性,他們每次使用 5-10 個不同的隨機種子進行評估,通常變異範圍在 1-3% 之間。

  • AIME:他們選擇了 AIME 競賽中 22、23 和 24 年的所有題目,用來測量模型在解決困難問題時的表現,並觀察模型的常見失敗模式。與 AMC 驗證集一樣,他們使用 5-10 個隨機種子來測量變異。

  • MATH 第4和第5級:他們擔心中等/困難的驗證集樣本過小,無法提供可靠的信號,因此從 MATH 測試集中篩選出有整數解的第4和第5級問題,每個級別大約有 750 個問題,並對每個模型使用單一隨機種子進行評估。

通過這四個驗證集,他們能夠在不同的訓練階段中選擇最具潛力的模型,並進一步縮小 Hyper Parameter的選擇範圍。他們發現,將小而具有代表性的驗證集與較大的驗證集結合使用,在這種競賽中特別有效,因為每次提交都會受到取樣隨機性的影響,所以觀察模型在這些不同難度的問題中是否還能保持一定的穩定性,是很重要的評估項目。

Demo

非常可惜他們的 demo 網址現在好像壞掉了沒辦法玩,我就貼一些之前別人玩過的截圖讓大家體驗看看吧~

我們問一道用來欺騙AI的入門題:一斤棉花和一斤鐵,誰比較重?
image

雖然這道題根本不用算任何東西就是考個常識,但是它真的嚴格按照分解步驟、列式子、寫代碼,最後再分析代碼執行結果得出結論:一樣重。

硬寫了一個判斷式出來滿足人類 XDD

第二題則是一道國中奧數訓練題。
甲乙二人從AB兩地出發,相向而行,在距離B地6公里處相遇,相遇後兩人又繼續按原方向、原速度前進,當他們分別到達B地,A地後,立刻返回,又在距A地4公里處相遇,求AB兩地相距多少公里?
image

哇,這次模型沒能列成正確的算式,因為第二次甲,乙走的路程分別為D+2,D-2而非D+4,D-4,因而正確答案應該是14而非模型回答的16。

(以上題目和截圖來自這裡)

第一名的解法介紹就到這邊了~
雖然第一名的作法在 LB 上取得很高的成績,但實際使用下來感覺還是很多簡單數學問題解不出來,不過也可能因為這邊是用中文問的(?,也許用英文問結果會不一樣。

個人感覺他們最大的亮點在前期的二階段訓練中產出的 MuMathMuMath-Code dataset,值得做相關領域的朋友參考他們建立資料集的方式。至於 "Self-Consistency with Tool-Integrated Reasoning (SC-TIR)" 之前有看過類似的討論了,就比較沒有經驗的感覺。
對我自己來說,因為沒辦法reproduce他們的結果,所以讀起來好像參與感(?)、沈浸感就比較少,我們明天一起來看看金牌區有沒有其他小而美的作法吧!

大家明天見~


謝謝讀到最後的你,希望你會覺得有趣!
如果喜歡這系列,別忘了按下訂閱,才不會錯過最新更新,也可以按讚⭐️給我鼓勵唷!
如果有任何回饋和建議,歡迎在留言區和我說✨✨


Kaggle - AI Mathematical Olympiad - Progress Prize 1 解法分享系列)


上一篇
[Day 23]為何LLM每次的回答都不一樣?淺談DeepSeek模型與Self-Consistency實戰應用
下一篇
[Day25]誰說打kaggle比賽一定要訓練模型?從第三名的解法看 Self-Consistency + Code Reasoning 之外的比賽工程技巧
系列文
一個Kaggle金牌解法是如何誕生的?跟隨Kaggle NLP競賽高手的討論,探索解題脈絡30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言