專項練習 · 9 分鐘閱讀

Python softmax 練習:穩定性、溫度與對數損失

softmax 看起來只有兩行算術,細節卻很重要:溢出、溫度,以及機率和決策之間的區別。這些練習逐塊搭建,再連接到損失函式。

歸一化指數值

對每個 logit 取 exp,再除以總和。輸出為正且總和為一。測試中要檢查總和,因為靜默的歸一化錯誤會讓後續指標失去意義。

import math

def softmax(logits):
    exps = [math.exp(x) for x in logits]
    total = sum(exps)
    return [x / total for x in exps]

probs = softmax([1, 1])
print([round(p, 3) for p in probs])
print(round(sum(probs), 3))

檢查過的分布

減去最大值

很大的 logit 在歸一化前就會溢出。減去最大值可以在不改變比例的情況下平移所有數值。結果在數學上相同,在數值上安全。

import math

def stable_softmax(logits):
    largest = max(logits)
    exps = [math.exp(x - largest) for x in logits]
    total = sum(exps)
    return [x / total for x in exps]

print([round(p, 3) for p in stable_softmax([1000, 1000])])

同樣的答案,不再溢出

改變溫度

溫度在 softmax 前除 logits。小於一的值讓最大分數更突出;大於一的值讓分布更平緩。溫度不會增加證據,只會改變模型的確定程度。

import math

def softmax(logits, temperature=1.0):
    scaled = [x / temperature for x in logits]
    largest = max(scaled)
    exps = [math.exp(x - largest) for x in scaled]
    total = sum(exps)
    return [x / total for x in exps]

print([round(p, 3) for p in softmax([2, 0], 0.5)])
print([round(p, 3) for p in softmax([2, 0], 2.0)])

更尖銳或更平緩

計算真實類別的對數損失

如果真實類別的預測機率是 p,對數損失是 -log(p)。自信且正確時損失低;自信卻錯誤時損失很大。取對數前要把機率截斷到零以上。

import math

p_true = 0.8
loss = -math.log(max(p_true, 1e-12))
print(round(loss, 3))

為自信付出代價

argmax 是決策,不是真理

最高機率給出類別標籤,但整個分布可能很接近、很猶豫。要同時報告最高機率和第一、第二名的差距。影響重大的決定應加入人工覆核,或在低信心度時棄權。

probs = [0.46, 0.44, 0.10]
order = sorted(range(len(probs)), key=probs.__getitem__, reverse=True)
print(order[0])
print(round(probs[order[0]] - probs[order[1]], 2))

贏家加差距

你的練習清單

常見問題

softmax 只用於神經網路嗎?

不是。它是一般性的分數歸一化方法,只是神經網路分類器經常使用。

溫度能提高準確率嗎?

本身不能。它改變分布的尖銳程度,校準和評估是另外的步驟。

為什麼對數損失要截斷機率?

log(0) 無定義。截斷讓損失保持有限,但不能挽救給真值零機率的模型。

練習 softmax

12 道題,覆蓋歸一化、穩定性、溫度、argmax 和對數損失。

打開練習

繼續閱讀: