什麼是 Softmax 與交叉熵?將 Logits 轉為機率與訓練損失

作者 쉬었음.com

Softmax 與交叉熵的組合,讓多類別神經網路能夠以機率表達多個候選類別中哪一類正確,並以數值評估該預測與正確答案之間的差異。Softmax 會將模型稱為 logits 的原始輸出轉換為總和為 1 的機率分布。交叉熵則將此機率分布與目標分布之間的差異計算為損失。訓練就是調整模型權重以降低此損失的過程。

例如,假設您要將影像分類為貓、狗或鳥其中之一。模型起初通常不會回答「貓的機率是 70%」之類的結果,而是產生 logits,也就是三個類別的相對分數。Softmax 會將這些分數正規化為可比較的機率,而交叉熵會依模型賦予實際答案多少機率來給予懲罰。一起理解這兩者,有助於減少對最終輸出層、標籤格式及損失函數設定的常見困惑。

Softmax 函數的作用是什麼?

Softmax 是將 KK 個類別的 logits 向量 z=(z1,,zK)z=(z_1,\dots,z_K) 轉換為類別機率 p=(p1,,pK)p=(p_1,\dots,p_K) 的函數。類別 ii 的機率計算如下。

pi=softmax(z)i=ezij=1Kezjp_i=\operatorname{softmax}(z)_i= \frac{e^{z_i}}{\sum_{j=1}^{K}e^{z_j}}

其中,指數函數 ezie^{z_i} 會讓分數較大的類別得到較高的相對權重。由於分母是所有類別指數化分數的總和,每個輸出都會落在 0 與 1 之間,且總機率會加總為 1。因此,softmax 輸出會將輸入屬於各類別的相對可能性表示為單一機率分布。PyTorch 文件同樣將 softmax 描述為把每個輸入元素重新縮放到 0 至 1 的範圍,並使所有元素總和為 1。docs.pytorch.org

當候選類別是互斥時,softmax 特別適用。也就是說,若其中一類為真,其他類別就不可能是正確答案。例如,將主要動物恰好是貓、狗或鳥其中之一的影像分類,或將一句話指派至恰好一個預先定義的情緒類別。

相對地,softmax 機率彼此並不獨立。若貓的機率上升,狗或鳥的機率就必須相對下降,才能維持三者總和為 1。對於可同時有多個標籤為真的情況,例如一張影像中可同時出現人物與自行車的問題,這項特性通常不適合。在此情況下,應考慮對每個類別獨立套用 sigmoid。

Logits 與機率有何不同?

Logit 是最終線性層或類似元件產生的未正規化分數。Logits 可以是負數或大於 1,而跨類別 logits 的總和沒有特定意義。例如,[2,1,0][2,1,0] 可以是一組三類別的 logits,但它不是機率向量。

Logits 的重要特性是,類別之間的差異比其絕對值更重要。為每個 logit 加上相同常數 cc,不會改變 softmax 的結果。

softmax(z)i=softmax(z+c)i\operatorname{softmax}(z)_i= \operatorname{softmax}(z+c)_i

這是因為分子與分母都會乘上共同因子 ece^c,而該因子會相消。因此,logits [2,1,0][2,1,0][102,101,100][102,101,100] 看起來可能是不同的原始分數,卻會產生相同的 softmax 機率。Softmax 會將候選類別之間的相對差異,而不是分數的基準點,轉換為機率。

交叉熵衡量什麼?

交叉熵是一種損失,用來表示實際目標分布 yy 與模型預測分布 pp 有多大的差異。其基本多類別形式如下。

H(y,p)=i=1KyilogpiH(y,p)=-\sum_{i=1}^{K}y_i\log p_i

其中,yiy_i 是實際標籤指派給類別 ii 的權重,pip_i 是模型對類別 ii 預測的機率。損失越小,表示預測分布越接近目標分布。使用自然對數時,單位為 nat。

這個公式不只是把正確與錯誤答案區分為 0 或 1 的計算。它不僅反映模型是否答對,也反映模型對答案正確有多大的信心。若兩個預測中,正確類別的機率分別為 0.51 與 0.99,只要兩者的最高機率類別都正確,準確率可以相同。然而,交叉熵會給後者較低的損失。因此,訓練會鼓勵模型不只是將正確答案排在第一位,還要為它賦予更高機率。

為何 one-hot 標籤能使公式簡化?

互斥分類的目標通常以 one-hot 向量表示。若三個類別中第一類正確,標籤為 [1,0,0][1,0,0]。由於只有目標類別 ttyt=1y_t=1,其餘皆為 0,交叉熵可化簡為下式。

L=logptL=-\log p_t

換句話說,損失只由模型對正確類別所預測的機率 ptp_t 決定。當 ptp_t 趨近於 1,logpt-\log p_t 趨近於 0。相反地,當 ptp_t 變小,損失會迅速增加。基於這項特性,對正確答案賦予低機率的預測,尤其是以極高信心預測錯誤答案時,在訓練期間會受到較大的懲罰。

理論上,若正確類別的機率恰好為 0,log0\log 0 未定義,且損失會發散至無限大。實際的神經網路實作通常使用以 logits 為基礎的穩定計算,避免先明確產生機率 0 再取其對數。

Softmax 與交叉熵如何連結?

典型多類別模型的最後部分可分為三個步驟理解。

  1. 最終線性層輸出類別 logits zz
  2. Softmax 將 logits 轉換為機率 pp
  3. 交叉熵將機率 pp 與目標標籤 yy 比較,計算損失 LL

對於 one-hot 目標,這個連結可展開如下。

L=log(eztj=1Kezj)=zt+logj=1KezjL=-\log\left(\frac{e^{z_t}}{\sum_{j=1}^{K}e^{z_j}}\right) =-z_t+\log\sum_{j=1}^{K}e^{z_j}

這個式子通常稱為 softmax 交叉熵或類別交叉熵。第一項 zt-z_t 會隨正確類別 logit 提高而變小;第二項 logjezj\log\sum_j e^{z_j} 則同時考慮每個競爭類別的分數。因此,模型會學習提高正確類別的分數,並使它相對於錯誤類別更突出。

在此,應從概念上區分 softmax 與交叉熵。Softmax 是改變輸出表示方式的函數,交叉熵則是量化訓練目標的損失。不過,在實務框架中,這兩個步驟常被提供為一個組合式損失函數,因此看起來像是單一函數。

以數字計算能看出什麼?

考慮一個有三個類別、logits 為 [2,1,0][2,1,0] 的問題。套用 softmax 後,可得到約為 [0.665,0.245,0.090][0.665,0.245,0.090] 的機率。TensorFlow 的 softmax 範例對這些 logits 也呈現相同的近似機率。docs.pytorch.org

若第一類正確,one-hot 標籤為 [1,0,0][1,0,0],損失如下。

L=log(0.665)0.408L=-\log(0.665)\approx0.408

第一類在三個候選類別中有最高機率,且該機率約為 0.665,因此損失相對較小。不過,「小」並不代表有絕對的及格門檻。適當的損失大小會因類別數量、資料難度、標籤不確定性,以及損失是在一個 batch 內加總還是平均而異。

若在相同 logits 下,實際正確的是第三類,損失將為 log(0.090)-\log(0.090),因此大得多。模型將第三類視為最不可能的候選類別。透過這種方式,交叉熵能敏感反映預測不僅是否錯誤,也反映錯得多有信心。

為何應同時考量機率排序與損失值?

準確率通常選取機率最大的單一類別,並判斷其是否與正確答案相符。因此,當第一類正確時,預測 [0.34,0.33,0.33][0.34,0.33,0.33] 與預測 [0.99,0.005,0.005][0.99,0.005,0.005] 都會被計為一次正確預測。

交叉熵不會將兩者視為相同。第一個預測幾乎無法區分三個類別,第二個預測則對正確答案賦予極高機率。相反地,當最高機率類別錯誤時,損失也會依正確類別機率有多低而有所不同。因此,訓練通常會最小化交叉熵,而評估時也會依任務目標檢查準確率等其他指標。

為何應將 logits 直接傳入訓練損失函數?

許多深度學習框架的組合式損失函數接收的是logits,而非 softmax 機率。例如,TensorFlow 的 softmax_cross_entropy_with_logits 顧名思義接受 logits,並在內部進行相當於 softmax 與交叉熵的計算。其文件警告,不要提供已經套用 softmax 的輸出。www.tensorflow.org

若違反此規則,在模型末端套用 softmax 後又將結果傳給預期接收 logits 的損失函數,這些機率可能會被再次當成 logits 解讀,而非依預期只套用一次 softmax。這會改變損失及其梯度的意義,導致訓練設定不正確。損失函數「是否在內部包含 softmax」或「是否接收已轉換的機率」,應根據 API 的輸入契約確認,而非只看函數名稱。

推論或顯示的用途則不同。訓練完成後,若要顯示類別機率或執行以機率為基礎的後處理,可以對 logits 套用 softmax。重點並不是永遠不該使用 softmax,而是應在訓練損失預期的輸入階段恰好套用一次

為何數值穩定性很重要?

Softmax 公式包含指數與對數。若 logits 極大或極小,計算 ezie^{z_i} 可能超出電腦可表示的範圍,造成溢位或下溢風險。先計算機率再分別套用對數,可能容易受到這些問題影響。

組合式損失函數與 log_softmax 系列實作,一般會以穩定的方式計算 logjezj\log\sum_j e^{z_j}。PyTorch 文件也說明,log_softmax 的數值特性優於分別計算 softmax 與對數。docs.pytorch.org

先前說明的常數平移特性也可用於穩定化。從每個 logit 減去最大值 m=maxjzjm=\max_j z_j,不會改變 softmax 結果。

softmax(z)i=ezimjezjm\operatorname{softmax}(z)_i= \frac{e^{z_i-m}}{\sum_j e^{z_j-m}}

如此會使最大的指數項變為 e0=1e^0=1,減少處理不必要大數值的需求。然而在正式程式碼中,通常更建議使用框架提供、以 logits 為基礎的組合式損失,或穩定的 log-softmax 運算,而非自行分別實作各個元件。

標籤應使用 one-hot 向量還是整數?

標籤表示方式與損失函數的輸入契約相關。常見格式包括 one-hot 或機率標籤,以及稀疏整數標籤。

標籤格式三個類別中第一類正確時的範例特性
One-hot 標籤[1, 0, 0]長度與類別數相同的向量;只有正確位置為 1。
機率標籤[0.8, 0.1, 0.1]元素皆為非負且總和為 1 的目標分布。
稀疏整數標籤0僅儲存正確類別的索引。

One-hot 標籤直接對應基本交叉熵公式。稀疏整數標籤可更精簡地儲存相同資訊,在類別很多時可能很有用。不過,兩種格式的 tensor 形狀與資料型別不同,因此必須使用特定損失函數所要求的格式。

TensorFlow 對以 logits 為基礎的 softmax 交叉熵文件說明,標籤向量必須是有效的機率分布,並區分互斥分類的相關標籤格式。www.tensorflow.org例如,直接將單一整數傳入 one-hot 損失函數,或將 one-hot 向量傳入稀疏整數標籤函數,可能無法計算出預期的量。

機率標籤放寬了恰好一個類別必須為 1 的假設。但這不等同於多個類別可獨立為真的多標籤問題。在 softmax 分類中,機率標籤仍表示元素總和為 1 的單一分布。

二元分類、多類別分類與多標籤分類有何差異?

不應只根據類別數量選擇輸出函數與損失。請先判斷目標事件能否同時發生。以下區分在實務上很有用。

問題結構範例典型輸出表示典型損失
互斥多類別分類貓、狗或鳥其中之一跨所有類別的 SoftmaxSoftmax 交叉熵
二元分類真/假、核准/拒絕一個 sigmoid 或雙類別 softmax二元交叉熵或 softmax 交叉熵
多標籤分類一張照片同時包含人物與自行車逐類別 sigmoid逐類別二元交叉熵

在多類別分類中,類別機率總和為 1 是自然的。若一張影像是貓的機率提高,同一張影像是狗或鳥的機率就應相對下降。TensorFlow 文件同樣區分標籤互斥時使用 softmax 交叉熵的情況,以及需要不同設定的獨立多標籤情況。www.tensorflow.org

在多標籤分類中,每個輸出更接近一個獨立問題:「有沒有人物?」「有沒有自行車?」「有沒有樹?」都可同時回答「是」。若 softmax 強制總和為 1,提高一個標籤的機率就會壓低其他標籤的機率,這可能不符合問題結構。對每個類別套用 sigmoid,能使每個項目的機率獨立處理。

二元分類尤其容易令人困惑,因為兩種方法看起來都可行。對單一輸出套用 sigmoid,可直接表示正類的機率。對兩個 logits 套用 softmax,則會將正類與負類表示為總和為 1 的雙類別分布。無論選擇哪種做法,標籤編碼與損失函數都必須與該輸出格式相符。

最小化交叉熵代表匹配分布嗎?

當目標 yy 與預測 pp 都是有效的機率分布時,交叉熵可透過其與熵及 KL 散度的關係表示如下。

H(y,p)=H(y)+DKL(yp)H(y,p)=H(y)+D_{\mathrm{KL}}(y\Vert p)

其中,H(y)H(y) 是表示真實分布自身不確定性的熵,DKL(yp)D_{\mathrm{KL}}(y\Vert p) 是表示真實分布 yy 與預測分布 pp 差異的 KL 散度。若訓練資料中的目標分布 yy 固定,H(y)H(y) 不會隨模型參數改變。因此,除了該常數之外,降低交叉熵可解釋為降低 yypp 之間的 KL 散度。

這項解釋顯示交叉熵為何廣泛作為機率分布的學習目標。模型不僅被要求將正確類別放在最高位置,也會被推動讓機率分配接近觀察到的目標分布。

不過,這個等式有前提條件。yypp 都必須是機率分布:其分量必須位於適當範圍內且總和為 1。Logits 本身並非機率分布,因此不能直接代入此關係。Logits 是透過 softmax 或以 logits 為基礎的組合式損失,連結到機率分布計算。

常見誤解與錯誤有哪些?

第一個誤解是logits 就是機率。最大 logit 的類別也具有最大 softmax 機率,但 logit 值本身不能當成百分比解讀。例如 2 與 1 的 logit 差異會轉換成多大的機率差異,必須在連同其他所有 logits 一起套用 softmax 後才能確定。

第二個誤解是分類訓練只有在模型末端加入 softmax 才能運作。若使用接受 logits 的組合式交叉熵損失,訓練時通常不會明確加入最終 softmax。這有助於內部計算與數值穩定性。www.tensorflow.orgdocs.pytorch.org

第三個誤解是softmax 交叉熵適合所有分類問題。當類別互斥時,這種損失組合很自然。若一個樣本可同時具有多個正確標籤,將總類別機率限制為 1 的 softmax 可能無法正確表示資料的意義。

第四個誤解是交叉熵與準確率是相同指標。準確率通常只看單一最高機率類別,而交叉熵反映賦予正確答案的完整機率。因此,兩個具有相同準確率的模型可能有不同的交叉熵值。這也是訓練損失下降時,準確率不一定在每個步驟都單調上升的原因之一。

第五個錯誤是只根據單一損失值判斷模型好壞。交叉熵值會受到類別數量、任務難度、標籤格式及彙總方法影響。較合適的做法是觀察相同任務與設定下的變化、驗證資料的損失,以及適合該任務的獨立評估指標。

設定模型前應檢查什麼?

在套用 softmax 與交叉熵前,依序檢查以下問題會很有幫助。

  1. **每個樣本是否恰好有一個正確類別?**若是,則可考慮以 softmax 為基礎的多類別分類。若多個標籤可同時為真,請先考慮逐類別 sigmoid 與二元損失。
  2. **模型的最終輸出是 logits 還是已經是機率?**Logits 是沒有約束的原始分數,機率則是正規化的值。若組合式損失預期 logits,請勿預先套用 softmax。
  3. **標籤格式是否符合損失函數?**確認其接受 one-hot 或機率向量,還是整數索引。除了格式,也要檢查 batch 維度與類別維度的位置。
  4. **是否已區分訓練與推論的用途?**訓練時,使用穩定的 logits 型損失進行計算。推論時,若需要顯示機率或套用機率型規則,再使用 softmax。
  5. **是否分別解讀損失與評估指標?**交叉熵是反映機率預測品質的訓練目標;準確率則衡量最終選擇是否符合目標。請依任務將兩者一併解讀。

這份檢查清單不侷限於特定函式庫。然而,即使實際 API 名稱相似,它們在預期輸入為 logits、機率或整數標籤上仍可能不同。實作前,請查閱所使用函數的官方文件,以確認輸入形式及其是否包含內部啟用函數。

結論:依角色理解機率轉換與損失計算

Softmax 會將多個 logits 轉換為總和為 1 的機率分布,表示互斥類別的相對可能性。交叉熵則將該預測分布與目標分布的差異計算為損失,對賦予正確答案低機率的預測給予較大懲罰。對於 one-hot 目標,損失可化簡為 logpt-\log p_t,使提高正確類別機率的學習目標更加明確。

在實務中,softmax 與交叉熵常不會分開計算,而是使用接受 logits 的組合式損失函數。這能保留數學目標,同時實現更具數值穩定性的計算。然而,這種組合最適合的問題結構是「恰好有一個正確答案的多類別分類」。選擇輸出與損失時,關鍵是在考慮類別數量之前,先確認標籤是否互斥,以及損失函數預期何種輸入。

常見問題

softmax 和交叉熵一定要一起使用嗎?

不一定。它們常一起用於需要從多個互斥類別中選出一個類別的分類任務。但對於可同時有多個項目為真的多標籤問題,通常會改用逐類別 sigmoid 與二元交叉熵。

訓練時應避免直接在模型最後一層加入 softmax 嗎?

這取決於您使用的損失函數。若使用預期接收 logits 的組合式交叉熵函數,應直接傳入 logits,而不要先套用 softmax。該函數會在內部處理必要的計算。

交叉熵為 0 代表什麼?

對於 one-hot 目標,當正確類別被賦予機率 1 時,損失為 0。在以有限 logits 計算的模型中,該機率通常會非常接近 1,而非恰好等於 1。

準確率很高時,交叉熵也可能很高嗎?

可以。準確率只檢查預測機率最高的類別是否正確;交叉熵還會反映分配給正確類別的機率大小。即使預測正確,若正確類別的機率偏低,損失仍可能相對較高。

稀疏整數標籤與 one-hot 標籤有何差異?

稀疏整數標籤只儲存正確類別的索引;one-hot 標籤則是在正確位置填入 1、其他位置均為 0 的向量。對於相同的分類任務,請選擇所使用損失函數要求的格式。