TensorFlow2.0(8):偏差計算——損失函數總結

 

注:本系列全部博客將持續更新併發布在github上,您能夠經過github下載本系列全部文章筆記文件。javascript

 

1 均方差損失函數:MSE

 

均方偏差(Mean Square Error),應該是最經常使用的偏差計算方法了,數學公式爲: $$loss = \frac{1}{N}\sum {{{(y - pred)}^2}} $$css

 

其中,$y$是真實值,$pred$是預測值,$N$一般指的是batch_size,也有時候是指特徵屬性個數。html

In [1]:
import tensorflow as tf
y = 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)
In [2]:
y
Out[2]:
<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)>
In [3]:
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)
In [4]:
loss1 = tf.reduce_mean(tf.square(y-pred))
loss1
Out[4]:
<tf.Tensor: id=19, shape=(), dtype=float32, numpy=0.4>
 

在tensorflow的losses模塊中,提供能MSE方法用於求均方偏差,注意簡寫MSE指的是一個方法,全寫MeanSquaredError指的是一個類,一般經過方法的形式調用MSE使用這一功能。 MSE方法返回的是每一對真實值和預測值之間的偏差,若要求全部樣本的偏差須要進一步求平均值:html5

In [5]:
loss_mse_1 = tf.losses.MSE(y,pred)
loss_mse_1
Out[5]:
<tf.Tensor: id=22, shape=(5,), dtype=float32, numpy=array([0.4, 0.4, 0.4, 0.4, 0.4], dtype=float32)>
In [6]:
loss_mse_2 = tf.reduce_mean(loss_mse_1)
loss_mse_2
Out[6]:
<tf.Tensor: id=24, shape=(), dtype=float32, numpy=0.4>
 

通常而言,均方偏差損失函數比較適用於迴歸問題中,對於分類問題,特別是目標輸出爲One-hot向量的分類任務中,下面要說的交叉熵損失函數就要合適的多。java

 

2 交叉熵損失函數

 

交叉熵(Cross Entropy)是信息論中一個重要概念,主要用於度量兩個機率分佈間的差別性信息,交叉熵越小,二者之間差別越小,當交叉熵等於0時達到最佳狀態,也便是預測值與真實值徹底吻合。先給出交叉熵計算公式:node

 
$$H(p,q) = - \sum\limits_i {p(x)\log q(x)} $$
 

其中,$p(x)$是真實分佈的機率,$q(x)$是模型經過數據計算出來的機率估計。python

 

不理解?不要緊,咱們經過一個例子來講明。假設對於一個分類問題,其可能結果有5類,由$[1,2,3,4,5]$表示,有一個樣本$x$,其真實結果是屬於第2類,用One-hot編碼表示就是$[0,1,0,0,0]$,也就是上面公司中的$p(x)$。如今有兩個模型,對樣本$x$的預測結果分別是$[0.1, 0.7, 0.05, 0.05, 0.1]$ 和 $[0, 0.6, 0.2, 0.1, 0.1]$,也就是上面公式中的$q(x)$。從直覺上判斷,咱們會認爲第一個模型預測要準確一些,由於它更加確定$x$屬於第二類,不過,咱們須要經過科學的量化分析對比來證實這一點:jquery

 

第一個模型交叉熵:${H_1} = - (0 \times \log 0.1 + 1 \times \log 0.7 + 0 \times \log 0.05 + 0 \times \log 0.05 + 0 \times \log 0.01) = - \log 0.7 = 0.36$linux

 

第二個模型交叉熵:${H_2} = - (0 \times \log 0 + 1 \times \log 0.6 + 0 \times \log 0.2 + 0 \times \log 0.1 + 0 \times \log 0.1) = - \log 0.6 = 0.51$android

 

可見,${H_1} < {H_2}$,因此第一個模型的結果更加可靠。

 

在TensorFlow中,計算交叉熵經過tf.losses模塊中的categorical_crossentropy()方法。

In [7]:
tf.losses.categorical_crossentropy([0,1,0,0,0],[0.1, 0.7, 0.05, 0.05, 0.1])
Out[7]:
<tf.Tensor: id=41, shape=(), dtype=float32, numpy=0.35667497>
In [8]:
tf.losses.categorical_crossentropy([0,1,0,0,0],[0, 0.6, 0.2, 0.1, 0.1])
Out[8]:
<tf.Tensor: id=58, shape=(), dtype=float32, numpy=0.5108256>
 

模型在最後一層隱含層的輸出可能並非機率的形式,不過能夠經過softmax函數轉換爲機率形式輸出,而後計算交叉熵,但有時候可能會出現不穩定的狀況,即輸出結果是NAN或者inf,這種狀況下能夠經過直接計算隱藏層輸出結果的交叉熵,不過要給categorical_crossentropy()方法傳遞一個from_logits=True參數。

In [9]:
x = tf.random.normal([1,784])
w = tf.random.normal([784,2])
b = tf.zeros([2])
In [10]:
logits = x@w + b  # 最後一層沒有激活函數的層稱爲logits層
logits
Out[10]:
<tf.Tensor: id=75, shape=(1, 2), dtype=float32, numpy=array([[ 5.236802, 18.843138]], dtype=float32)>
In [12]:
prob = tf.math.softmax(logits, axis=1)  # 轉換爲機率的形式
prob
Out[12]:
<tf.Tensor: id=77, shape=(1, 2), dtype=float32, numpy=array([[1.2326591e-06, 9.9999881e-01]], dtype=float32)>
In [13]:
tf.losses.categorical_crossentropy([0,1],logits,from_logits=True)  # 經過logits層直接計算交叉熵
Out[13]:
<tf.Tensor: id=112, shape=(1,), dtype=float32, numpy=array([1.1920922e-06], dtype=float32)>
In [14]:
tf.losses.categorical_crossentropy([0,1],prob)  # 經過轉換後的機率計算交叉熵
Out[14]:
<tf.Tensor: id=128, shape=(1,), dtype=float32, numpy=array([1.1920936e-06], dtype=float32)>
相關文章
相關標籤/搜索