引言:語言模型能不能自己發現錯誤、自己修正?
今天的大型語言模型非常厲害,它可以根據人類給予的回饋來修正自己的行為——你給它一個輸入,它產生一個輸出,然後你告訴它「你做錯了」、指出錯在哪裡,語言模型往往有能力更正它原有的錯誤行為。
但這堂課要探討的核心問題是:能不能在沒有人力介入的情況下,讓語言模型輸出答案之後,自己發覺自己是錯的,並且自己修正自己的行為?
這個主題在機器學習 2023 年的課程中第一次被提及——那是 ChatGPT 剛問世的年代,也就是人類文明剛剛建立的年代。當時人們就已經發現,這些語言模型某種程度上擁有自我反省的能力。而今天的課程內容,有很大一部分是 2024 年機器學習第七講(關於模型 reasoning 能力)的延伸。到了 2025 年,reasoning 已經幾乎成為每一個線上語言模型的標配,但這仍然是一個相對較新的技術領域。在過去一年中,這個領域又有了許多新的進展,而我們今天要講的,正是這些新的東西。
要讓模型做到自我修正,有三個不同的方向:
- 修改 inference 的過程
- 修改模型的工作流程(Harness)
- 直接在模型的參數上做改變——也就是大家現在常聽到的 reasoning 推理技術
第一部分:修改推理過程——Contrastive Decoding 的世界
從 Representation 中偵測錯誤
語言模型生成文本的過程大家應該很熟悉:輸入是一排 token,經過 Transformer 之後變成一排 representation,最後變成一個機率分布。我們從這個機率分布做 sampling,sample 出一個 token,這個 token 變成下一個時間點的輸入,再產生下一個機率分布,這個過程反覆繼續下去。
問題是:能不能在 inference 的過程中,從模型的 representation 和機率分布中,看出模型有可能會犯錯? 換句話說,就是自動做 error detection,然後根據 detection 的結果去修正模型最終的輸出。這整個 detection 和 correction 的過程,都假設是自動的、不需要人力介入的。
一篇 2023 年的文獻探討了這個問題。他們的做法是:收集語言模型在回答正確時的 representation,也收集回答錯誤時的 representation 。然後訓練一個二元分類器(binary classifier),讓它去分辨一個 representation 會導致正確答案還是錯誤答案。結果發現,真的能夠訓練出這樣一個 classifier,而且它具有泛化(generalize)的能力——在一堆問題上訓練,可以在另一堆問題上預測答案會不會被答對。這意味著「答案是對的還是錯的」這個訊號,是可以從 representation 中被抽取出來的,我們只是需要知道怎麼抽取而已。
True Facts:修正錯誤的可能性
2024 年有一篇論文叫做 True Facts,展示了把錯誤答案修成正確答案是有可能的。它的做法是:收集一大堆模型答錯時的 representation,以及一大堆答對時的 representation 。然後把答錯的 representation 平均、答對的 representation 平均,兩者相減,得到一個「正確與錯誤之間的差距」向量(黃色的向量)。
接下來,把這個黃色的向量加到模型本來會答錯的問題的 representation 上——模型本來看到這個問題會產生一個導致答錯的 representation,但如果你把正確與錯誤的差距向量加上去,模型就有可能給你正確的答案。
所以,偵測和修正都是有可能自動進行的。但這些方法都有一個共同的缺點:它們需要收集額外的資料。你需要先問模型一堆問題,知道它講對話和講錯話時 representation 長什麼樣子,才能做上述操作。
Contrastive Decoding:不需要額外資料的解決方案
有沒有一種方法,在不需要收集額外資料的情況下,就能偵測錯誤並進行修正?答案是 contrastive decoding 。它等於是把 error detection 和 error correction 結合在一起,但不需要收集額外的資料。
Contrastive decoding 的概念如下:你問模型一個問題,它預測下一個 token,這是模型在正常情況下得到的答案,你不太確定它是對還是錯。然後,你把同樣的問題做了一些修改(至於怎麼修改,有很多種做法),製造出讓模型「一定會答錯」的狀態。假設模型在這個修改過的輸入下非常有可能答錯,我們就知道模型答錯時的 representation 長什麼樣子。接下來,把原來模型正常情況下的 representation,跟答錯時的 representation 相減,得到正常狀況跟答錯狀況的差距(黃色向量)。再把這個黃色向量加到模型正常回答問題的向量上,希望把模型的答案離錯誤的答案推遠一點,這樣就有可能讓模型的正確率提高。
通常在做 contrastive decoding 的時候,會把正常和錯誤的向量相減之後,前面乘上一個小於 1 的參數 α。把黃色向量加上藍色向量(正常情況),也可以理解為:把正常情況的 representation 乘上(1+α)倍,然後減掉 α 倍的錯誤向量——也就是把正確的成分稍微提高,然後減掉一些錯誤的成分,希望模型的答案因此變得更正確。
這個操作需要在每一個 token 的生成過程中反覆進行:每次生成一個 token 時都要做一樣的操作,產生正常狀態和錯誤狀態、相減、乘 α、相加,然後把修正後的 token 當作下一個 time step 的輸入。
Contrastive decoding 的優點是沒有動到模型的參數,完全可以在訓練之後的 inference 階段直接套用。但缺點也很明顯:需要額外的運算。本來只要 inference 一次,現在需要多做一次額外的 inference 來產生錯誤的 representation 。所以這個方法是用額外的運算來換取可能更正確的結果。
在實作上,這個「representation」通常不是拿中間的 hidden layer,而是拿模型最終輸出的機率分布,或是在 normalized 機率分布前的數值(也就是 logit)。最常見的做法是讓正常狀態和錯誤狀態分別跑到最後,得到最終輸出的 logit 或機率分布,再把兩個機率分布相減。
Contrastive Decoding 的起源:上古時代的 GPT-2 實驗
Contrastive decoding 其實不是最近幾年才有的技術。早在 2022 年——在還沒有 ChatGPT 、人類還在茹毛飲血、還不知道用火的年代——就已經有 contrastive decoding 了。
當時的想法是:讓模型做文字接龍,句子是「歐巴馬生在檀香山,然後他生在哪一年?」要模型繼續接下去。當時比較好的模型是 GPT-2 的較大版本,它覺得機率最大的下一個字是「Hawaii」——但這其實是錯的,因為前面已經講過 Hawaii 了,正確答案應該是「1961」。
按照 contrastive decoding 的想法,要先製造一個錯誤的答案。論文的假設是:拿一個比較小的模型(GPT-2 Small),它的答案就當作是錯的。比較好的模型產生一個機率分布,比較差的模型也產生一個機率分布。雖然兩個模型都沒有辦法真的得到正確答案(連比較好的模型,機率最高的答案也不是 1961),但相減之後,機率最高的答案就變成 1961 了。所以正確 decoding 的結果,並不是好模型覺得機率最大的那個 token,而是好模型跟壞模型差距最大的那個 token 。
之所以選擇在最終輸出的 logit 上做相加相減,而不是在中間的 representation 上,原因也很直覺:兩個模型的層數根本不一樣,沒有對應的 representation 可以直接相減。這應該是文獻上最早使用「contrastive decoding」這個詞彙的論文,雖然可能不是最早運用這個概念的論文。
DoLa:Decoding by Contrasting Layers
2023 年出現了一個應用 contrastive decoding 概念的重要方法,叫做 DoLa(Decoding by Contrasting Layers)。這個方法可能是用得最廣的——甚至到今天,在 Hugging Face 的 Transformer 套件中,你可以直接設定一個 flag 讓模型在 inference 時使用 DoLa 技術。
在介紹 DoLa 之前,要先提它背後的重要概念:logit lens 。
Logit Lens:窺探模型內心的運作
Logit lens 的意思是:假設你問語言模型一個問題(例如「法文這個字的中文翻譯是什麼」),最終你得到最後一層的 representation,通過一個 LM head 給你一個機率分布。但有趣的是,你可以把 LM head 接到中間的每一層,也能得到一些有意思的 decoding 結果。
文獻上發現,當你用 Llama 2 要求它把法文翻譯成中文時,中間層的 representation decode 出來會是英文。這代表對 Llama 2 而言,它內心運作的過程是先翻成英文,再從英文翻譯成中文——也就是說,它內心思考時比較喜歡用英文。
Logit lens 這個技術並沒有一篇對應的正式論文,多數人在引用時往往引用一篇 blog 。但在那篇 blog 之前,就已經有文獻記載了跟 logit lens 一樣的技術——那是講者實驗室 2020 年發表的文章,當時覺得這個方法只是一個奇妙的發現,最後也沒有投稿到國際會議,就只是放在 arXiv 上面。 DoLa 的論文有直接引用這篇實驗室的論文,因為 DoLa 的第一作者其實是實驗室以前的專題生,後來去了 MIT,而 DoLa 是他在 Microsoft 實習時做的。
DoLa 的核心想法
DoLa 應用了 logit lens 的概念:contrastive decoding 方法的關鍵在於「怎麼找出一個錯誤的答案」,而 DoLa 假設:如果我們用 logit lens 從中間的 layer 做 decode,那中間 layer decode 出來的結果,比較有可能是錯誤的答案。
所以 DoLa 的做法是:從最後一個 layer 得到一個 distribution,也從前面的 layer 用 logit lens 產生一個 distribution,然後兩者相減,當作最後的答案。重點是:要從哪一個 layer 做 logit lens,才是最該拿來相減的?論文用了比較複雜的方法來找出合適的 layer 。
原來的 contrastive decoding 需要引入另一個小模型,耗費額外的計算和記憶體。 DoLa 的優勢在於,它是用原來模型前面的 layer 來產生錯誤答案,而前面的 layer 你本來就要跑。因此 DoLa 在 inference 時並不需要太多額外的計算,可以在非常少的 overhead 下修正模型的輸出,得到可能更正確的答案。
Layer Contrastive Decoding:應用在影像上
另外一個應用到不同 layer 之間差異的方法是 Layer Contrastive Decoding(Layer CD),發表於 2025 年,應用在影像上。
當我們使用視覺語言模型時,模型可以看一張圖片然後回答問題。舉例來說,問模型「這個機車上的人,他穿的衣服上面的字是什麼顏色的?」如果用 vision encoder 的最後一個 layer 去接給語言模型,模型會在黑色跟白色之間搖擺不定(衣服是黑色的,但問題是衣服上字的顏色,正確答案是白色)。最後一個 layer 有點聰明,知道應該是白色,但又沒有聰明到把白色排在最前面。
怎麼辦呢?把比較前面的 shallow layer 也丟給語言模型。 Shallow layer 抽取的資訊比較淺層,比較只能看到表象的東西。你問它顏色,它很直覺地回答一些奇奇怪怪的顏色,把黑色排在比較上面、白色排在比較下面。然後把兩個機率相減之後,白色的機率就變成最高的機率,模型就可以得到正確答案。這就是 Layer CD 的做法。
其他製造錯誤答案的方法
除了靠不同 layer 來製造錯誤答案之外,還有其他方法:
Instruction Contrastive Decoding(ICD):降智咒語
這個方法非常直接:在模型的輸入後面多加一句「你都給錯誤的答案」或「你是一個很糟糕的模型」。真的就這樣,模型就變得比較笨,答案就比較有可能是錯的。再把錯誤的答案跟原來的答案相減,希望得到更正確的答案。
Context-Aware Decoding(CAD)
CAD 最早應用在 RAG(Retrieval-Augmented Generation)上。 RAG 的概念是:語言模型有時無法及時更新知識,所以你問一個問題時,會順便去網路上查相關文章,把問題跟相關文章一起丟給語言模型。但有些比較厲害的模型往往不去讀那些文章,因為它覺得「我已經知道答案了,何必讀這些文章?」——比如它不知道美國總統已經換人了,仍用參數中的舊知識來回答。
CAD 的想法是:乾脆把這些搜尋到的文章不給語言模型看,先得到語言模型在沒有這些文章時會得到的答案(這個答案可能是錯的),再把這個可能是錯誤的答案跟語言模型讀了文章之後會得到的答案相減,得到一個比較可能是正確的答案。這也是一個非常古老的技術,2023 年就有了。
CAD 在影像上的直觀例子——黑色香蕉
CAD 用在影像上的例子,可能是最直觀、最能說服人這個方法確實有效的例子。
當我們使用影像模型時,給它一張黑色香蕉的圖片,問它「圖中的香蕉是什麼顏色?」模型會有一點猶豫——它直覺覺得香蕉應該是黃色的,但看影像又告訴它是黑色的,於是它就會在黃色和黑色之間猶豫不決。
這是因為這些視覺語言模型往往是從文字模型微調過來的,帶有大量的文字 prior(先入為主的概念)。它從文字那邊學到「香蕉就是黃色的」,有時甚至不太管圖片的細節,就憑著直覺給答案。
那怎麼去除這些先入為主的概念呢?故意不給它圖片,或者把圖片加上很強的雜訊讓它看不清楚,然後問它「圖片的香蕉是什麼顏色?」這時候它覺得「根本就沒有香蕉啊,那我就憑著先入為主的概念來回答好了」,答案就是黃色——正好得到錯誤的答案。再把錯誤的答案跟原來的答案相減,模型就有可能得到正確答案。
另一個例子:給模型一張海灘的照片,問它海灘上有什麼東西。模型說看到人、看到陽傘(這都沒問題),但它也說看到衝浪板——但照片中其實沒有衝浪板。衝浪板很容易出現在海灘上,所以模型先入為主地覺得海灘照片就應該有衝浪板,給衝浪板很高的機率。然後做 CAD:給模型一張很模糊的圖,因為太模糊了,模型懶得看圖片,直接憑先入為主的觀念給衝浪板很高的機率。兩者相減之後,衝浪板的機率就變得很低了。
原始的論文是在圖片上加一般的雜訊,後續研究則開始探討加什麼樣的雜訊特別有效。例如今年的一篇論文不是加雜訊,而是把圖片切成一塊一塊再打亂,發現效果更好。另一篇今年六月的論文則先分析模型看的是圖片中的哪些位置、哪些物件最重要,把重要的物件抹去之後再做 contrastive decoding 。這些方法有種種變形。
Audio-Aware Decoding:應用到語音上
這個技術既然可以用在影像上,也可以用在語音上。有一篇論文是普渡大學的學生在講者實驗室訪問時做的研究成果,做了 Audio-Aware Decoding 。概念跟在影像上一樣:給模型正常的音訊、問它問題,然後故意把音訊拿掉或換成 silence,再做 decoding 。把正確答案乘上(1-α),錯誤答案乘上 α 相減,得到最終輸出。這一招確實在語音上也發揮了作用。
MTI:減少額外運算的嘗試
Contrastive decoding 的缺點是用算力換取較好的表現。 MTI(Minimum Test-Time Intervention) 這篇論文希望減少需要的額外運算。
它有一個假設:當模型在做 decode 的時候,可能只有某幾個 token 是特別關鍵的——就像人生一樣,有幾個特別關鍵的轉折點(選讀哪個學校、跟誰結婚),但多數抉擇(早餐吃什麼、下午穿什麼衣服)可能都不會影響最後結果。所以能不能不要每個 token 都修改機率,只修改那些特別重要的 token?
什麼樣的 token 最關鍵?一個很直覺的想法是:如果某個位置的機率分布特別平均(有特別高的 entropy),也就是模型特別沒辦法決定接下來要 decode 哪一個 token 的時候,也許就是該開啟 contrastive decoding 的時機。
但仔細想想,這招其實沒有節省到運算,因為你要一直 decode 到那個位置,同樣需要把整個 sequence 都跑過才能得到錯誤的答案。
所以 MTI 用到了一個重要概念:KV Cache 。還記得 KV Cache 嗎?假設有一個句子「大家好我是大金」,模型跑過後可以把每個位置的 K 和 V 存起來。下次模型要處理一個非常像的句子(例如「大家好我是小金」),前面「大家好我是」這五個 token 可以直接從另一個句子的 KV copy 過來,不需要額外運算——但只有 prefix 一樣時才能用。
MTI 的做法是:它不在輸入的前面搞亂模型,而是在最後面加上兩個 token「Output Error」,然後看看模型會輸出哪一個 token,這個 token 就當作錯誤的答案,去跟正常產生的機率分布相減。這樣做的好處是:前面那一大段都可以利用 KV Cache,不需要重新運算,唯一需要重新運算的只有「Output Error」這兩個 token 的位置。
這招聽起來很離奇,但 performance 上確實有效:正常情況下正確率只有 62%,慎選參數後可以進步到 72% 。論文還測試了不同的降智咒語,發現「Output Error」效果不錯,「Output Correct」就差一點(因為我們要的是錯誤結果),「Status Error」也不錯,「Status True」就差一點,「Invalid Logic」也有一定程度的效果。但如果加一些怪怪的字(Monkey 、三個點、驚嘆號、 Apple),結果都會很差。
修改在不同位置的做法
到目前為止講的 contrastive decoding 方法,都是直接改在 output 的機率分布或最後一層的 logits 上。但也有一些論文嘗試改在其他地方。
例如今年一月的文章比較了不同修改位置的做法。過去有一個叫 VISTA 的做法,是改在 latent 的 representation 上。另外一篇叫 ACG 的論文則主張改在 attention 上最有效——用有影像也有文字的情況得到的 attention,減掉只有文字沒有影像時的 attention,並且不是在 logits 上相減,而是在 attention weight 上相減,發現可以比只改在 logits 上得到更好的結果。所以不一定只能改在 logits 上,至於改在什麼地方最有效,仍然是現在可以研究的問題。
總結:Contrastive Decoding 的技術全景
總結各式各樣的 contrastive decoding 方法,有兩個需要考量的因素:怎麼拿到錯誤的答案,以及要改在哪裡。
怎麼拿到錯誤的答案:
| 方法 | 如何製造錯誤答案 |
|---|---|
| Contrastive Decoding(原始) | 小模型輸出的就是錯的 |
| DoLa | 淺層用 logit lens decode 的結果就是錯的 |
| LayerCD | 淺層 image encoder 的結果就是錯的 |
| ICD | 加降智咒語,答案就是錯的 |
| CAD | 做 RAG 時不給它 retrieved document,答案就是錯的 |
| Visual Contrastive Decoding | 把輸入影像拿掉、加雜訊、或蓋住重要部分 |
| Audio-Aware Decoding | 把輸入聲音拿掉、變成 silence 、或加上雜訊 |
| MTI | 用降智咒語,且能利用 KV Cache 減少算力消耗 |
| 部分方法 | 改在中間的 latent representation,而非 output 位置 |
Contrastive decoding 是不需要訓練模型的技術,所以假設你做一做不知道可以做什麼了,反正不用訓練模型,跑一下也沒有什麼損失。
第二部分:修改工作流程——Generation + Verification
什麼是 Generation + Verification?
修改 workflow 讓模型做得更好的概念,在去年課程的第七講已經非常詳盡地討論過了。這裡只講最基本的概念:Generation 加 Verification 。
模型得到一個答案之後,接下來給它一個要求它反思的指令。這個步驟不需要人類介入,因為反思的指令通常是一個非常泛用的指令,跟前面的問題和答案都沒有關係,比如說「再多想想,再檢查一下」。這個指令是由程式自動插入的,不需要由人類來輸入。所以這樣的方法仍然算是模型的自我修正。
為什麼反思可能有用?兩個直覺
很多人會覺得這樣的想法太離奇了——模型一開始的答案就是錯的,憑什麼認為它反思之後就能得到正確答案?這裡提供兩個直覺上的想法:
第一,批判比生成容易。 就像你我不會寫小說,但還是可以知道一個小說好不好看;我沒有辦法寫出金庸小說,但我知道金庸小說特別好看。有時候模型在生成時沒發現自己的錯誤,但回過頭來再檢查一下,它是有可能發現錯誤的。
第二,生成的過程無法回頭。 生成的時候模型需要做 sampling,有時候擲骰子就是會擲到錯誤的答案。但對模型來說,一旦第一個 token 錯了,這是一個覆水難收的事情——你只能一步錯、步步錯,不斷用錯誤的答案硬掰下去。這也可以解釋為什麼模型明明答錯了,還是要瞎掰答錯的理由。但如果我們在生成的過程中插入「再檢查一下」,對模型來說(它真正知道的事情就是文字接龍),在網路上大量海量資料中,「再檢查一下」這個句子後面往往就是接著修正這件事情。所以插入這個句子,給了模型一個機會,讓它後面可以接出修正前面答案的內容。
但這些只是人類的直覺,不一定是對的。比如說「批判比生成容易」,對人類來說如此,但對模型來說呢?事實上有一篇文章試了模型批判與生成能力的差異:讓模型生成出好多答案(有些正確、有些錯誤),再拿去給模型自己問「這邊有兩個答案,你覺得哪一個比較對?」結果發現模型沒有辦法挑出正確答案,除非正確跟錯誤的差距非常大。所以對模型來說,批判不一定比生成容易。
但這個實驗也有可以批評的地方:它把批判當作選擇題來看待(給模型四個選項問哪個最好),你怎麼確定是模型沒有批判能力,還是模型沒有做選擇題的能力?尤其那是一兩年前的論文,那時候模型有時候答不對不是因為沒有能力,而是它做不了這種題型(不知道要選 ABCD 四個代號)。所以那篇論文講的也不一定是對的。總之,這邊有很多研究的空間。
反思的實證研究
雖然直覺不一定是對的,我們可以來看看實驗上的實證結果。
一篇去年十月的論文做了大規模實驗,在各種模型和各種 benchmark 上測試自我反思是否有用。結果顯示:
- 內部反思(internal):很多情況下反思還是有用的,但不是很穩定的方法——在很多狀況下,反思反而會讓模型變差。
- 外部回饋(external):給模型一些外部回饋(例如寫程式的話把程式拿去跑一跑,看 error message;或者讓模型去網路搜尋額外知識再用來答題),這種方法是比較穩定的。外部回饋小於 0 的 case 比較少,就算有小於 0 的 case,也不會掉非常多。
另一篇一個月後的論文(RefineBench)也支持這個想法。他們用 Claude 3.5 Sonnet 和 Gemini 1.5 Pro 做實驗:
- 對於很強的模型而言,自我反思帶來的進步非常少。
- 如果給模型外部的 checklist(檢查每個項目是不是對的),光是給模型看一半的 feedback 就有很大的進展;給完整的 checklist 讓模型知道「我們會檢查什麼內容」也可以大幅影響結果;最好的結果是給模型完整的回饋。
結論是:自我反思沒那麼有用,只能給予小幅進步;給模型真正的、來自人工或外部系統的回饋,往往才是最有效的。
自我修正的四種狀況
一篇論文仔細分析了模型在自我修正時的行為,區分出四種狀況:
- 修正前是錯的,修正後是對的:最樂見的狀況
- 修正前是對的,修正後還是對的:只是耗費算力而已
- 修正前是錯的,修正後也是錯的:也沒什麼損失,只是耗費算力
- 修正前是對的,修正後反而改錯了:最不樂見的狀況——想太多反而改錯
論文定義了兩個指標:
- Confidence Level(信心程度):修正前對、修正後也對的機率。代表模型對自己的答案有多大的信心。
- Critic Score(接受批評的能力):修正前錯、修正後對的機率。代表模型接受批評反思的能力。
兩個指標跟修改前後的正確率有直接關係:
修改後正確率 = 修改前正確率 × Confidence Level + (1 - 修改前正確率) × Critic Score
實際分析各種模型後發現:
- 多數模型都有比較高的 Confidence Level,模型通常對自己的答案蠻有信心的,不太會把對的答案因為想太多而改錯。
- 很多模型的 Critic Score 非常低,意思是它們比較固執,很少把錯的答案改對。
- 模型是有不同個性的:DeepSeek 和 Mixtral 是特別頑固的模型,很少修改答案;Llama 3 70B 在 GSM8K 上就很常修改答案;GPT-3.5 和 GPT-4 也有比較高的機率修改答案。
- 「頑固」和「接受批判」這兩件事情看起來有點互斥:頑固的模型不容易接受批評,容易接受批評的模型就沒辦法堅持自己正確的答案。
反思指令的影響
我們說要讓模型做自我反思,得插入一個句子(例如「請檢查自己的答案」)。論文分析了這個插入的句子會怎麼影響模型的行為。
他們試了三種指令:
- 中性指令:叫模型再做一次
- Confidence:鼓勵模型說「你應該是對的,只是再給我一次答案」
- Question it:告訴它「你確定嗎?你最好再想一想」,暗示它答案應該是錯的
在 Llama 3 上測試三個不同的 corpus 後發現:
- 肯定模型時,Confidence Level 上升,模型變得比較有信心、比較固執
- 質疑模型時,Confidence Level 下降,Critic Score(修改答案的可能性)上升
所以插入的那個句子——雖然不是人插入的,只是一個稻草人、由程式自動插入的——對模型的行為是有很大影響的。
這也許可以解釋為什麼文獻上對於「反思到底有沒有用」的結論有時候是 mixed 的:可能不同文獻插入了不同的指令,而每個模型本身又有不同的個性。有些模型總是特別有信心,你就應該常常批判它;有些模型很容易沒有信心,你就要多給它肯定。不同論文在處理反思指令和使用的模型都不一樣,這可能是結論不一致的原因。
反思 vs. 多產生幾個答案:哪個更划算?
反思需要耗費額外的算力,這個投資到底划不划算?與其花額外算力讓模型修改舊答案,會不會讓它直接多 sample 幾次、產生各種不同的答案,然後再做 majority vote(多數決),反而更有效率?
一篇論文做了這個實驗。如果只看「同樣產生答案的次數」下,加上反思確實結果比較好——甚至加上反思後,可以只用原來四分之一的 sample 就得到一樣的正確率。但這裡的橫軸不是算力,所以不能直接比較。
當把橫軸換成運算資源時,結果就不一樣了:
- 在投入有限算力的情況下,通常沒有反思反而結果比較好——與其讓模型再去檢查之前的答案,還不如用同樣的算力來多產生一些答案。
- 多產生答案的方法在投入一定程度的算力後會達到極限,之後再投入額外的算力做 verification/反思,才能發揮作用。
- 要得到 3.8% 的進步,需要投入 100 倍以上的運算資源。
所以這篇論文的結論是:做 verification 像是一個奢侈品——它是在你已經投入大量算力達到極限之後,再做 verification 才能發揮作用。前期你應該花更多運算資源來產生更多不同類型的答案,直到這件事達到飽和後,再加上 reflection/verification 才有意義。
這個教訓是:假設你今天要提出新的 reflection workflow 方法,你要想想投入的額外運算資源是不是划算的。最基本的 baseline 就是要跟 majority vote 比——如果你沒比 majority vote,實驗結果很可能會被大力質疑。
第三部分:修改模型參數——Reasoning(推理)
從 Workflow 到 Reasoning
在 workflow 的做法中,我們需要插入一個額外的指令來要求模型反思。從 workflow 到 reasoning 的差別在於:能不能直接把這個額外插入的指令拿掉,讓模型自己在生出答案之後,如果需要修改就自己一定會修改,不需要修改時就不修改。
雖然 workflow 和 reasoning 都是自動的、都不需要真的人工介入,但 reasoning 還有額外的好處:workflow 每次都會硬插一個額外的指令,逼模型不管答案對錯都一定要做額外的思考、產生額外的 token,這是比較浪費資源的做法。如果是 reasoning,你期待模型自己可以學到:該修改答案時就修改,不該修改時就不修改,這樣可以更節省算力。能夠做到 reasoning 的模型,顯然比需要被提醒才能修改答案的模型更加 intelligent 。
正確的知識 ≠ 自我修正的能力
有一個很直覺的想法是:給模型越來越強、教它更多東西,有了更多正確知識之後,也許它就更能修改自己的答案。
但一篇論文否定了這個想法,他們發現正確的知識並不等同於能夠自我修正。論文舉了一個例子:問語言模型「告訴我一個出生在紐約的政治家」,模型回答「希拉蕊」。你可能會想說模型是不是不知道希拉蕊在哪裡出生的?但你問同一個模型「希拉蕊在哪裡出生的」,它會知道希拉蕊是在芝加哥出生,不是在紐約出生。
最奇怪的地方是:它明明有這個正確的知識,但當它回答出錯誤答案的時候,竟然沒有驚覺自己的答案是錯的,而去修正自己原來的答案。
論文中還有更多實驗,他們發現自我修正是一個獨特的能力,不見得跟模型的知識有關聯。自我修正是一種狀態,可以被抽成一個 steering vector 。抽出那個 vector 之後,你甚至可以把 vector 加到模型裡面,讓模型在不需要修正的時候也會自我修正。
所以修正的能力跟有沒有知識不一定能畫上等號,這是一種特別的狀態,可能需要額外做訓練才能具備。
REVISE:分開學習錯誤偵測與修正
一篇叫做 REVISE 的論文發現,自我修正可以分成兩部分:先做錯誤偵測,再做錯誤修正。他們發現這兩件事情合在一起學比較難學,分開來學效果比較好。
第一步:教錯誤偵測。 收集模型在不同輸入時的答案(有答對也有答錯),然後教模型:看到錯誤的答案時輸出一個「Refine Token」;看到正確的答案時直接輸出結束的符號(模型就不需要再反思修改下去)。
第二步:學習如何修正。 給模型自己的輸入、它自己錯誤的輸出、和 Refine 這個 token,因為手上有訓練資料(正確答案),所以可以告訴模型正確答案長什麼樣子,要求它學會:看到錯誤的輸出、後面接 Refine token 之後,要能夠輸出正確的答案。
直接教自我修正的問題
一篇 2024 年的論文指出了一個問題:當你教模型能夠看到自己錯誤的輸出然後輸出 Refine Token 、再接正確答案之後,因為模型被 fine-tune 了,所以它的參數就變了——它就不再是同一個模型了。它會犯的錯不一樣了。
在 inference 的時候,本來模型看到某個輸入會給一個特定的錯誤輸出(綠色的錯誤),但現在模型不一樣了,你給它同一個輸入,它甚至不會給你綠色的輸出,而是給你一個紅色的輸出——雖然可能還是錯的,但是不一樣的錯誤。而模型在訓練時只看過怎麼修改綠色的錯誤,看到紅色的錯誤(訓練時沒看過的)可能就無能為力,反而會做得更差。
所以直接教模型自我修正可能是有問題的。需要把產生答案跟自我修正這一整套 pipeline 綜合起來一起做訓練。
Reinforcement Learning 方法:RLVR
後來業界常用的做法就是直接做 reinforcement learning(RL)。概念非常直覺:給模型一個輸入,然後它就開始做 reasoning 、輸出一長串 token——要輸出什麼不重要,讓它自己想,最後反正只要答案是對的就好了。如果最後答案是對的,得到 positive reward;如果是錯的,得到 negative reward 。
這種方法比較常用在數學或程式題上,因為數學和程式有非常明確的方法驗證答案是對還是錯(尤其是數學,答案就是個數字,一翻兩瞪眼)。這種可以直接提供回饋的方法,現在有一個名詞叫做 Reinforcement Learning with Verifiable Reward(RLVR),也是 RL 的一種。
在整個訓練過程中,只在意最終答案是對還是錯,至於中間 reasoning 的過程發生什麼事不重要——答案對就好了。
有趣的地方是:用這種 RL 的方法讓模型做 reasoning process 以後再產生正確答案,模型似乎蠻自然地就產生了 verification 的行為——它會自己先提第一個答案,然後回頭看看「我這個答案對嗎?」,發現有錯就去修改自己的答案。看起來這整個 reasoning 過程,有機會讓模型學到自我修正這件事。
為什麼不一口氣直接答對?
你可能會想:為什麼模型做 RL 時還要學自我修正,為什麼不一口氣就直接答對?
想想看,對人類來說,很多時候往往也是先犯錯才答對的。在學校這十幾年來,講者發現往往學生都會犯非常類似的錯誤——學長回去會斥責學弟「你怎麼在實驗的時候會犯這種錯誤」,隔年那個學弟變成學長,又去斥責另一個學弟「你怎麼會犯一樣的錯誤」,都忘了去年自己也是被斥責的那個人。
有一些錯誤好像就是會反覆發生,你沒有經歷過就是沒有辦法修正,就是要自己先踩個雷,才有辦法把雷排掉。用旁人來提醒,就是沒有辦法意識到這個錯誤。會不會 reasoning 也是一樣?有些問題在回答時就是很難一次答對,就是要先犯錯,然後才把錯誤答案修正,才能答對。
思考的代價
有一篇心理學論文叫做「Cost of Thinking」,它說思考就是要付代價。這篇論文叫語言模型和人類去解一樣的問題,然後量語言模型耗費的 token 數和人類耗費的時間,發現在某些任務上,兩者呈現某種程度的正比關係。也許這就告訴我們:不管是碳基生物還是矽基生物,思考本身就是需要有一些代價,你就是很難一次就答對。
(當然,拿 token 數和時間來對比也是有爭議的——也許對人類來說,對應到語言模型 token 的部分,應該是讓那個人拿一張計算紙,看他在計算紙上寫多少字,這樣比較能夠類比。)
為什麼 Reasoning 有用?分解步驟降低訓練資料需求
2025 年初,reasoning 剛剛流行時,有一系列論文試圖解釋為什麼 reasoning 會有用。想法是這樣的:
我們可以要求模型一次就做對(看到輸入立刻給答案),也可以要求模型做 reasoning(把解題過程分成 T 個步驟,最後得到答案)。假設在做 reasoning 時,每一步有 K 種不同的變化,每種變化模型都要看過才能答對——那需要 K 筆資料。
但如果我們把 reasoning 的步驟拿掉,全部綜合起來,輸入跟輸出就會有 K 的(T+1)次方種變化。假設每種變化都需要一筆訓練資料,那需要非常大量的資料。而分成 T 個步驟,每步只有 K 個變化,每個步驟都只需要少量資料就可以訓練起來,總體只需要 K×(T+1) 筆資料。
所以今天如果要叫模型一步做對,變化會是指數級增長,需要非常大量資料;如果把問題分成多個步驟再綜合起來,模型需要的訓練資料就比較少。
具體例子:Parity Check
用一個具體例子來說明。 Parity check 意思是:給你一串 0101 的二進位數字,要判斷有奇數個 1 還是偶數個 1(奇數輸出 1,偶數輸出 0)。
假設輸入固定是六個數字,輸入跟輸出有 2 的 6 次方,總共 64 種對應關係。如果一個很笨的模型只會死背訓練資料,需要 64 筆資料把所有可能性背起來才能做 parity check 。
但如果我們不要求模型直接得到答案,而是分成多個步驟來解:先把前兩個數字做 XOR 、結果跟下一個數字再做 XOR……重複五次。每一個步驟輸入兩個數字、輸出一個數字,只有四種變化(00→0, 01→1, 10→1, 11→0)。模型只要記得這個操作就可以解所有問題,總共五步只需要 20 個 sample 。
所以當我們教模型做 reasoning 時,其實是讓模型用更少的訓練資料就可以學會一個任務;或者在同樣的訓練資料下,可能可以學得更好、有更好的泛化能力。事實上很多文獻指出:如果處理的是 in-domain 問題(訓練和測試分布一樣),你不需要 reasoning,直接叫模型輸出答案、硬背起來就好。但如果你要的是更聰明、有泛化能力的模型,就需要教模型做 reasoning,用更少量資料學到更多不同題型的解法。
RL 到底學到了什麼?兩派爭論
有一系列的論文在探討:當我們用 RL 教模型做 reasoning 的時候,它到底學到了什麼?
第一派說法:模型本來就會
其實模型能夠做 reasoning 和 reflection 這件事,早在 RL 之前就已經會了。我們用樹狀圖來理解:模型在產生答案時有很多不同路徑(每次在某個節點 sample 到不同 token 就走不同路徑)。正確的路徑其實早在做 RL 之前,base model 就已經有機會 sample 到。 RL 做的事情只是把這些本來就已經存在的路徑的機率提高,讓它更容易被 sample 出來——RL 並沒有創造出模型本來無法輸出的東西。
一篇去年四月的文章支持這個說法。他們用 pass@k(讓模型做同一個問題 K 次,只要有一次答對就算對)來評估:
- 如果只能做一次(K=1),有做 RL 遠比沒有做 RL 好
- 但如果 sample 次數非常多(K=256),有沒有做 RL 其實差不多,甚至有做 RL 的 performance 還差一點
所以正確答案是模型本來在做 sampling 時就有可能產生出來的,只是因為被其他錯誤路徑所覆蓋。這就好像佛教華嚴經中佛陀開悟後說的:「奇哉奇哉,大地眾生本具如來智慧德相,只因妄想執著而不能得證。」每個人本來都有佛性,只是被無明妄想覆蓋了。對語言模型來說也是一樣——它本來就可以得到正確答案,只是因為有太多可能性干擾它。
這個發現的重要性是:既然本來就可以得到正確答案,有沒有可能透過更好的 sampling 方法(不需要訓練模型),就把正確答案 sample 出來?就像禪宗頓教講的「人人本具佛性,放下一個清淨就可以直接開悟,不需要長時間修習」。
果然,去年十月有人提出了一個新的 sampling 方法,可以逼出原來模型的 reasoning 能力。在沒有做 RL 的模型上,只改了 sampling 演算法,就能在許多狀況逼近 RL 的結果,甚至在某些狀況超過 RL 的結果。
第二派說法:RL 真的教了模型新能力
另外一派說法認為,RL 真的可以讓模型學會額外的能力——有些 reasoning 過程是不存在於模型本來能產生的路徑之中的,RL 過程中確實學到了新的推理技巧。
一篇去年六月的論文支持這個觀點。他們先復現了「pass@k 在 sample 量很大時,有沒有 RL 非常接近」的實驗。但他們提出一個質疑:最後答案是對的,真的代表模型有比較強的 reasoning 能力嗎?有沒有可能它就只是猜對而已?Sample 那麼多次,答案的數字範圍有限(比如 1 到 10),你 sample 1024 次,每個數字都 sample 過了,難怪可以答對。
所以他們做了另一個實驗:不只要求最終答案正確,還要去檢查計算過程是否正確(COTPath)。把這個額外限制加進去後,沒有做 RL 的模型就不如有做 RL 的模型了。這表示做 RL 還是教了模型新的能力——有做 RL 的模型,比較有可能在計算過程中也是對的。
(當然這個實驗也有可以批評的地方:怎麼知道計算過程是對的?Sample 1024 次難道是人看的嗎?不是,是另一個語言模型看的。那語言模型看的能算是對的嗎?這就不好說了。)
第三派說法:兩者都有
還有一篇論文專門探討這個爭執,標題就是「Debate on RL VR Reasoning Capability Boundary」。他們的結論是:兩者都有,在不同的訓練階段模型學到不同的事情。
- 訓練初期:模型比較容易利用現有的 path,只是改變它的機率
- 訓練後期:RL 訓練得夠久,模型也有機會展現新的能力
現在比較大的問題是:到底什麼樣的 RL 訓練演算法、要給模型什麼樣的 reward signal,比較能夠激發它展現新的能力?這也是一個尚在研究中、在爭辯中的問題。
結語
這堂課講了讓語言模型做到自我修正的三個方向:
- 修改 inference 過程:透過 contrastive decoding 等技術,在不需要訓練模型、也不需要人力介入的情況下,從模型的 representation 或機率分布中偵測錯誤並修正最終輸出。這個方法不需要動到模型參數,但缺點是需要額外的運算。
- 修改工作流程:透過 Generation + Verification 的 workflow,讓模型在產生答案後自動反思。這個方法有時有效但不太穩定,外部回饋往往比純自我反思更有效。而且在算力有限的情況下,多產生幾個答案做 majority vote 可能比反思更划算。
- 修改模型參數(Reasoning):透過 Reinforcement Learning 訓練,讓模型自己學會在推理過程中發現錯誤並修正。自我修正是一種獨特的能力,與知識量不一定相關。而模型到底是在 RL 中學會了新能力,還是只是提高了本來就存在的正確路徑的機率,目前仍然是一個活躍的研究議題。
這三個方向各有優缺點,也有許多可以深入研究的空間——這正是當代語言模型研究最令人興奮的領域之一。