Day 7 把全域 D̂ 除以保守標準誤,得到 ζ=D̂/SE。現在終於能回答一個很實際的問題:這份信心訊號,夠不夠格改動多數決?
TACT 的答案偏保守。證據落在預先設定的範圍內,γ 就留在 0,投票器走回原本的 Self-Consistency。
這塊範圍就是 dead zone,中文我會叫它「死區」。
ν 是證據門檻。TACT-dev 使用 ν=1.2816,大致對應標準常態分布的單尾 90% 分位數。若真實 D 為 0,|ζ|≤1.2816 約涵蓋中央 80% 的波動,因此多數純雜訊估計會停在死區內。
無標籤版本使用更嚴格的 ν=2.326。它依賴多數答案產生的偽標籤,方向判錯的代價比有標籤開發集高,所以需要更強的證據才允許加權。在標準常態近似下,中央死區約為 98%。
這兩個門檻必須在看測試結果前固定。若每次看到準確率不好就調低 ν,死區很快會變成另一種超參數搜尋。
最粗暴的寫法是硬門檻:死區內設 0,一跨過 ν 就直接使用完整 D̂。假設 ζ 從 1.2815 變成 1.2817,只差一點點,信任強度卻突然從 0 跳到完整值。這種不連續很難接受。
TACT 使用 positive-part James–Stein 收縮:
D̃ 是收縮後的辨別度。證據剛跨過門檻時,它從 0 平順地長出來;|ζ| 越大,收縮比例越小。估計很穩時,D̃ 才會逐漸接近 D̂。
同一條公式也能寫成乘法增益:
(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 拉。
程式只有幾行,但邊界條件要寫清楚:
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 plug-in posterior mean。先估計訊號變異:
當 D̂²≤SE²,估出的訊號變異是 0,posterior mean 也回到 0。TACT-dev 的 ν 大於 1,等於把這個概念再往保守方向推一點。
這段解讀能說明收縮從哪裡來,但不代表資料真的完全符合常態先驗。實作需要的是它幾個可檢查的性質:奇函數、在邊界連續、強度不超過 |D̂|,以及 SE 變大時不會變得更敢加權。

圖:合成邊界掃描。左圖量測票重是否真的拉開,右圖量測相同 K 下相對 SC 的準確率增益。若結構沒有留下可利用空間,死區讓 γ 回到 0,避免憑噪音製造差異。
看到 TACT 和 Self-Consistency 同分,很容易說「安全機制成功擋住了壞訊號」。這句話可能太早。
同樣的結果還有另一種解釋:資料裡存在能改善投票的訊號,估計器卻沒抓到。兩種情況都會得到 γ=0,只看最終準確率分不出來。
後面的實驗會用兩種控制把它們拆開:
D̃ 何時離開 0。真實資料沒啟動、植入足夠訊號後會啟動,才能支持「原資料證據不足」;若強訊號也抓不到,問題就在估計器的檢定力。還要另外記錄 false activation 和 missed activation,不能只報最後答對幾題。死區的工作是決定何時不動手,評估方式也得直接測這個決策。
Day 9 會處理死區外的下一步:把 D̃ 經由 probit 與 Bayes-discriminant link 映射成投票指數 γ。那一步會說明為什麼 γ 的大小可以推導,而不必再開一個網格搜尋。
論文預印本:TACT: Trust-Anchored Confidence Tempering for Self-Consistency Voting in Large Language Models