均方誤差(Mean Square Error),應該是最常用的誤差計算方法了,數學公式為:
其中,
import tensorflow as tfy = tf.random.uniform((5,),maxval=5,dtype=tf.int32) # 假設這是真實值print(y)
y = tf.one_hot(y,depth=5) # 轉為熱獨編碼print(y)tf.Tensor([2 4 4 0 2], shape=(5,), dtype=int32)
tf.Tensor(
[[0. 0. 1. 0. 0.]
[0. 0. 0. 0. 1.]
[0. 0. 0. 0. 1.]
[1. 0. 0. 0. 0.]
[0. 0. 1. 0. 0.]], shape=(5, 5), dtype=float32)<tf.Tensor: id=7, shape=(5, 5), dtype=float32, numpy=
array([[0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1.],
[0., 0., 0., 0., 1.],
[1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0.]], dtype=float32)>pred = tf.random.uniform((5,),maxval=5,dtype=tf.int32) # 假設這是預測值pred = tf.one_hot(pred,depth=5) # 轉為熱獨編碼print(pred)tf.Tensor(
[[0. 1. 0. 0. 0.]
[0. 0. 0. 1. 0.]
[1. 0. 0. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]], shape=(5, 5), dtype=float32)loss1 = tf.reduce_mean(tf.square(y-pred))loss1<tf.Tensor: id=19, shape=(), dtype=float32, numpy=0.4>
在tensorflow的losses模塊中,提供能MSE方法用於求均方誤差,注意簡寫MSE指的是一個方法,全寫MeanSquaredError指的是一個類,通常通過方法的形式調用MSE使用這一功能。MSE方法返回的是每一對真實值和預測值之間的誤差,若要求所有樣本的誤差需要進一步求平均值:
loss_mse_1 = tf.losses.MSE(y,pred)loss_mse_1<tf.Tensor: id=22, shape=(5,), dtype=float32, numpy=array([0.4, 0.4, 0.4, 0.4, 0.4], dtype=float32)>
loss_mse_2 = tf.reduce_mean(loss_mse_1)loss_mse_2<tf.Tensor: id=24, shape=(), dtype=float32, numpy=0.4>
一般而言,均方誤差損失函數比較適用於回歸問題中,對於分類問題,特別是目標輸出為One-hot向量的分類任務中,下面要說的交叉熵損失函數就要合適的多。
2 交叉熵損失函數交叉熵(Cross Entropy)是資訊理論中一個重要概念,主要用於度量兩個概率分布間的差異性信息,交叉熵越小,兩者之間差異越小,當交叉熵等於0時達到最佳狀態,也即是預測值與真實值完全吻合。先給出交叉熵計算公式:
其中,
是真實分布的概率, 是模型通過數據計算出來的概率估計。 不理解?沒關係,我們通過一個例子來說明。假設對於一個分類問題,其可能結果有5類,由
表示,有一個樣本 ,其真實結果是屬於第2類,用One-hot編碼表示就是 ,也就是上面公司中的 。現在有兩個模型,對樣本 的預測結果分別是 和 ,也就是上面公式中的 。從直覺上判斷,我們會認為第一個模型預測要準確一些,因為它更加肯定 屬於第二類,不過,我們需要通過科學的量化分析對比來證明這一點: 第一個模型交叉熵:
第二個模型交叉熵:
可見,
,所以第一個模型的結果更加可靠。 在TensorFlow中,計算交叉熵通過tf.losses模塊中的categorical_crossentropy()方法。
tf.losses.categorical_crossentropy([0,1,0,0,0],[0.1, 0.7, 0.05, 0.05, 0.1])<tf.Tensor: id=41, shape=(), dtype=float32, numpy=0.35667497>
tf.losses.categorical_crossentropy([0,1,0,0,0],[0, 0.6, 0.2, 0.1, 0.1])<tf.Tensor: id=58, shape=(), dtype=float32, numpy=0.5108256>
模型在最後一層隱含層的輸出可能並不是概率的形式,不過可以通過softmax函數轉換為概率形式輸出,然後計算交叉熵,但有時候可能會出現不穩定的情況,即輸出結果是NAN或者inf,這種情況下可以通過直接計算隱藏層輸出結果的交叉熵,不過要給categorical_crossentropy()方法傳遞一個from_logits=True參數。
x = tf.random.normal([1,784])w = tf.random.normal([784,2])b = tf.zeros([2])logits = x@w + b # 最後一層沒有激活函數的層稱為logits層logits<tf.Tensor: id=75, shape=(1, 2), dtype=float32, numpy=array([[ 5.236802, 18.843138]], dtype=float32)>
prob = tf.math.softmax(logits, axis=1) # 轉換為概率的形式prob<tf.Tensor: id=77, shape=(1, 2), dtype=float32, numpy=array([[1.2326591e-06, 9.9999881e-01]], dtype=float32)>
tf.losses.categorical_crossentropy([0,1],logits,from_logits=True) # 通過logits層直接計算交叉熵<tf.Tensor: id=112, shape=(1,), dtype=float32, numpy=array([1.1920922e-06], dtype=float32)>
tf.losses.categorical_crossentropy([0,1],prob) # 通過轉換後的概率計算交叉熵<tf.Tensor: id=128, shape=(1,), dtype=float32, numpy=array([1.1920936e-06], dtype=float32)>