上一篇我們開始用 Accuracy、Precision、Recall 和 F1-score 來評估模型的表現,而在 Day15 訓練 CNN 時,其實還有一個數值一直出現在畫面上,就是 loss 和 val_loss
假設現在有一張圖片,真正的 Label 是 nv
模型 A 預測:nv 0.9、 mel 0.03、bkl 0.02、其他 0.05
代表模型成功預測成 nv
再來看看模型 B:nv 0.30、mel 0.29、bkl 0.20 其他 0.21
模型 B 最後一樣會選 nv
所以如果只看 Accuracy 兩個完全一樣,但很明顯,兩個模型的「信心」並不相同,模型 A 給真正答案 nv 很高的機率,而模型 B 雖然最後猜對了,但其實非常不確定
因此模型訓練時不能只知道答對或答錯,還需要一個數值描述這次的預測到底錯得多嚴重?這就是 Loss
Loss Function(損失函數)就是用來衡量模型預測結果和正確答案之間差異的函數,可以先簡單理解成:
** 模型預測 ⮕ 和正確 Label 比較 ⮕ Loss Function ⮕ 得到一個 Loss**
一般來說 Loss 較小,預測結果與正確答案較接近;Loss 較大,預測結果與正確答案差距較大,因此模型訓練的重要目標之一,就是想辦法讓 Loss 越來越小
回到我們前面寫過的程式:
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
其中 loss="sparse_categorical_crossentropy" 就是我們目前使用的 Loss Function,它和 Categorical Cross-Entropy(類別交叉熵)屬於同一類多類別分類損失;sparse 版本的主要差別在於,我們的 Label 是直接使用整數編碼
前面我們的模型最後一層是:
tf.keras.layers.Dense( 7, activation="softmax")
因此模型會產生 7 個類別的機率
假設正確答案是 nv
nv 0.9nv 0.5nv 0.1Cross-Entropy 會特別關注模型分配給正確類別的機率,正確類別機率越高,Loss 通常越小;正確類別機率越低,Loss 通常越大
對單一樣本、單一正確類別來說,可以簡化成 Loss = -log(正確類別的預測機率)
假設正確答案是 nv,如果模型預測:
| 正確類別的預測機率 | Loss |
|---|---|
| 0.9 | 約 0.105 |
| 0.5 | 約 0.693 |
| 0.1 | 約 2.303 |
所以模型如果對正確答案給出很低的機率,Loss 就會變得比較大
這裡有一個很有趣的地方,假設真正答案是 nv,但模型卻預測:mel 是 0.95、nv是 0.01,也就是模型不但答錯,而且對錯誤答案非常有信心
因為真正的 nv 只有 0.01,所以 Loss = -log(0.01) ≈ 4.605,Loss 就會非常大
這表示 Cross-Entropy 不只是看你有沒有答對,它還會考慮你給真正答案多少機率?
所以即使兩個模型都答錯,Loss 也可能完全不同
| 指標 | 主要用途 |
|---|---|
| Accuracy | 看模型最後有多少比例分類正確 |
| Loss | 衡量預測結果與正確答案之間的差異 |
Loss 算出來之後,模型就知道現在預測得有多不好,接下來會利用這個 Loss 計算參數應該往哪個方向調整,再由 Optimizer 更新 Weight 和 Bias
整個訓練流程可以簡化成:
輸入圖片模型預測 ⮕ Softmax ⮕ 和真正 Label 比較 ⮕ 計算 Loss
⮕ 計算參數需要調整的方向 ⮕ Optimizer 更新 Weight / Bias ⮕ 再次預測
這個流程會不斷重複
因此我們前面看到模型會跑的Epoch ,其實背後就是不斷進行類似的:
預測 ⮕ 計算 Loss ⮕ 更新參數 ⮕ 再預測
我們 Day15 的 history = model.fit(...) 其實已經把每個 Epoch 的 Loss 記錄下來了,所以不用重新訓練,可以直接畫:
import matplotlib.pyplot as plt
plt.plot(history.history["loss"], label="Training Loss")
plt.plot(history.history["val_loss"], label="Validation Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.title("CNN Baseline Model Loss")
plt.legend()
plt.show()
這樣就可以同時觀察 Training Loss、Validation Loss,理想情況下,模型開始學習後 Training Loss 通常會逐漸下降,但是 Validation Loss 是否也一起下降,就不一定了
如果之後出現 Training Loss 持續下降、Validation Loss 開始上升,就代表模型雖然越來越會處理 Training Data,但對 Validation Data 的表現反而開始變差,這又會回到我們前面曾經提過的一個問題:Overfitting(過擬合)