iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0

Day 7 把全域 除以保守標準誤,得到 ζ=D̂/SE。現在終於能回答一個很實際的問題:這份信心訊號,夠不夠格改動多數決?

TACT 的答案偏保守。證據落在預先設定的範圍內,γ 就留在 0,投票器走回原本的 Self-Consistency。

TACT 死區條件

這塊範圍就是 dead zone,中文我會叫它「死區」。

ν 決定多難才能走出死區

ν 是證據門檻。TACT-dev 使用 ν=1.2816,大致對應標準常態分布的單尾 90% 分位數。若真實 D 為 0,|ζ|≤1.2816 約涵蓋中央 80% 的波動,因此多數純雜訊估計會停在死區內。

無標籤版本使用更嚴格的 ν=2.326。它依賴多數答案產生的偽標籤,方向判錯的代價比有標籤開發集高,所以需要更強的證據才允許加權。在標準常態近似下,中央死區約為 98%。

這兩個門檻必須在看測試結果前固定。若每次看到準確率不好就調低 ν,死區很快會變成另一種超參數搜尋。

跨過門檻也不會全額相信 D̂

最粗暴的寫法是硬門檻:死區內設 0,一跨過 ν 就直接使用完整 。假設 ζ 從 1.2815 變成 1.2817,只差一點點,信任強度卻突然從 0 跳到完整值。這種不連續很難接受。

TACT 使用 positive-part James–Stein 收縮:

positive-part James–Stein 收縮

是收縮後的辨別度。證據剛跨過門檻時,它從 0 平順地長出來;|ζ| 越大,收縮比例越小。估計很穩時, 才會逐漸接近

同一條公式也能寫成乘法增益:

以 zeta 表示的 James–Stein 增益

(x)₊ 代表 max(x, 0)。這個版本比較容易看出死區:只要 |ζ|≤ν,括號裡不大於 0,整個增益就是 0。

用幾組數字看看收縮幅度

以下都使用 TACT-dev 的 ν=1.2816

D̂       SE       ζ        D̃
 0.12    0.10     1.20      0.000
 0.30    0.25     1.20      0.000
 0.30    0.20     1.50      0.081
 0.30    0.10     3.00      0.245
-0.30    0.10    -3.00     -0.245
 0.60    0.10     6.00      0.573

前兩列的 D̂ 不一樣,標準化證據卻都只有 1.2,所以一起留在死區。第三列剛過門檻,原本的 0.30 被收縮到 0.081。到了 |ζ|=6,大部分訊號才被保留下來。

負值不會被改成正值。收縮保留方向,只把強度往 0 拉。

Python 實作

程式只有幾行,但邊界條件要寫清楚:

import math

def js_shrink(
    d_hat: float,
    se: float,
    nu: float,
) -> float:
    if not all(map(math.isfinite, [d_hat, se, nu])):
        raise ValueError("inputs must be finite")
    if se < 0:
        raise ValueError("se must be non-negative")
    if nu < 0:
        raise ValueError("nu must be non-negative")
    if se == 0:
        return d_hat

    magnitude = abs(d_hat)
    if magnitude <= nu * se:
        return 0.0

    shrunk = magnitude - nu ** 2 * se ** 2 / magnitude
    return math.copysign(shrunk, d_hat)

把剛才的案例丟進去:

NU_DEV = 1.2816

cases = [
    (0.12, 0.10),
    (0.30, 0.25),
    (0.30, 0.20),
    (0.30, 0.10),
    (-0.30, 0.10),
    (0.60, 0.10),
]

for d_hat, se in cases:
    zeta = d_hat / se
    d_tilde = js_shrink(d_hat, se, NU_DEV)
    print(f"{zeta:6.2f}  {d_tilde:7.3f}")

邊界也值得直接寫成測試:

assert js_shrink(0.30, 0.30 / NU_DEV, NU_DEV) == 0.0
assert js_shrink(0.30, 0.30 / NU_DEV * 0.999, NU_DEV) > 0.0
assert js_shrink(-0.30, 0.10, NU_DEV) < 0.0
assert abs(js_shrink(0.30, 0.10, NU_DEV)) <= 0.30

第一行正好落在死區邊界,依定義回傳 0。第二行把 SE 稍微縮小,|ζ| 才跨過門檻。

ν=1 時的 empirical Bayes 解讀

把門檻設成 1 時,這個收縮式剛好等於一個簡單 empirical Bayes plug-in posterior mean。先估計訊號變異:

James–Stein 的 empirical Bayes 形式

D̂²≤SE²,估出的訊號變異是 0,posterior mean 也回到 0。TACT-dev 的 ν 大於 1,等於把這個概念再往保守方向推一點。

這段解讀能說明收縮從哪裡來,但不代表資料真的完全符合常態先驗。實作需要的是它幾個可檢查的性質:奇函數、在邊界連續、強度不超過 |D̂|,以及 SE 變大時不會變得更敢加權。

冗餘加權的有效區域邊界

圖:合成邊界掃描。左圖量測票重是否真的拉開,右圖量測相同 K 下相對 SC 的準確率增益。若結構沒有留下可利用空間,死區讓 γ 回到 0,避免憑噪音製造差異。

γ=0 還不能證明死區有效

看到 TACT 和 Self-Consistency 同分,很容易說「安全機制成功擋住了壞訊號」。這句話可能太早。

同樣的結果還有另一種解釋:資料裡存在能改善投票的訊號,估計器卻沒抓到。兩種情況都會得到 γ=0,只看最終準確率分不出來。

後面的實驗會用兩種控制把它們拆開:

  • 隨機破壞訊號:在每題內打亂信心與正誤標籤的配對,保留信心分布和答案票數。若死區在這組資料大多回到 0,才表示它確實會拒絕已知的無訊號狀態。
  • 植入訊號階梯:從同一批真實軌跡出發,逐步增加信心與正確性的已知耦合強度,再量 何時離開 0。真實資料沒啟動、植入足夠訊號後會啟動,才能支持「原資料證據不足」;若強訊號也抓不到,問題就在估計器的檢定力。

還要另外記錄 false activation 和 missed activation,不能只報最後答對幾題。死區的工作是決定何時不動手,評估方式也得直接測這個決策。

Day 9 會處理死區外的下一步:把 經由 probit 與 Bayes-discriminant link 映射成投票指數 γ。那一步會說明為什麼 γ 的大小可以推導,而不必再開一個網格搜尋。

論文預印本:TACT: Trust-Anchored Confidence Tempering for Self-Consistency Voting in Large Language Models


上一篇
Day 7|少一題就翻盤?用 jackknife 檢查 D̂ 有多脆弱
系列文
從多數決到可信投票:30 天打造 TACT 大語言模型推理聚合方法8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言