交叉熵損失:
給定兩個概率分布p和q,通過q來表示p的交叉熵為:
從上述公式可以看出交叉熵函數是不對稱的,即H(p,q)不等於H(q,p)。
交叉熵刻畫的是兩個概率分布之間的距離,它表示通過概率分布q來表示概率分布p的困難程度。所以使用交叉熵作為
神經網絡的損失函數時,p代表的是正確答案,q代表的是預測值。當兩個概率分布越接近時,它們的交叉熵也就越小。
由於神經網絡的輸出並不是一個概率分布,所以需要先使用softmax將網絡輸出變成一個概率分布,再計算交叉熵。
比如,原始的神經網絡輸出為y1,y2,……,yn,那么經過softmax處理后的輸出為:
小例子:
以一個三分類為例,比如某個樣本正確答案為(1,0,0)。某模型經過softmax回歸后的預測答案為(0.5,0.4,0.1),則這個預測值和正確答案之間的交叉熵為:
H((1,0,0),(0.5,0.4,0.1))=-(1*log0.5+0*log0.4+0*log0.1))=0.3
假設另外一個模型的預測值是(0.8,0.1,0.1),則該預測值和真實值之間的交叉熵為:
H((1,0,0),(0.8,0.1,0.1))=-(1*log0.8+0*log0.1+0*log0.1)=0.1
從上述結果可以看出第二個預測答案要由於第一個。
tensorflow中實現交叉熵,如下所示:
cross_entropy=-tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0)))
其中y_代表正確結果,y代表預測結果。tf.clip_by_value函數可以將一個張量中的數值限制在一個范圍內,這樣可以避免
一些運算錯誤(比如log0是無效的)。下面講解使用tf.clip_by_value函數的簡單樣例。
v=tf.constant([[1.0,2.0,3.0],[4.0,5.0,6.0]]) with tf.Session() as sess: print(tf.clip_by_value(v,2.5,4.5).eval())
'''
輸出為
[[ 2.5 2.5 3. ]
[ 4. 4.5 4.5]]
'''
# tensorflow中提供的直接計算交叉熵損失的函數,y代表神經網絡的輸出結果,y_表示真實類別
cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=y,y_)
均方誤差(MSE,mean squared error):
常用於回歸問題中。它的具體定義如下:
$MES(y,y^{'})=\frac{\sum _{i=1}^{n}(y_{i}-y_{i}^{'})^{2}}{n}$
其中,yi表示一個batch中第i個樣本的真實類別,yi'為神經網絡輸出的預測值。tensorflow代碼實現如下:
mse=tf.reduce_mean(tf.square(y_-y))
自定義損失函數:
tensorlfow支持自定義損失函數,以下演示一個簡單的示例:
首先定義一個分段損失函數,然后提供它的代碼實現:
$Loss(y,y^{'})=\sum_{i=1}^{n}f(y_{i},y_{i}^{'}), f(x,y)=\left\{\begin{matrix}a(x-y)
& x>y \\
b(y-x) & x\leqslant y
\end{matrix}\right. $
loss=tf.recue_sum(tf.where(tf.greater(v1,v2),(v1-v2)*a,(v2-v1)*b))
tf.where和tf.greater函數用法如下:
# tf.where和tf.greater函數的用法 v1=tf.constant([1.0,2.0,3.0,4.0]) v2=tf.constant([4.0,3.0,2.0,1.0]) with tf.Session() as sess: print(tf.greater(v1,v2).eval()) # 輸出 [False False True True] print(.where(tf.greater(v1,v2),v1,v2).eval()) # 輸出 [ 4. 3. 3. 4.]
使用自定義損失函數實現一個簡單的神經網絡
該網絡只有兩個輸入節點和一個輸出節點,相當於實現了一個回歸。
import tensorflow as tf from numpy.random import RandomState batch_size=8 # 定義兩個輸入節點 x=tf.placeholder(tf.float32,shape=(None,2),name='x-input') # 回歸問題一般只有一個輸出節點 y_=tf.placeholder(tf.float32,shape=(None,1),name='y-input') # 定義一個單層的神經網絡 w1=tf.Variable(tf.random_normal([2,1],stddev=1,seed=1)) y=tf.matmul(x,w1) # 使用上述自己定義的損失函數 a=1;b=10 loss=tf.reduce_sum(tf.where(tf.greater(y,y_),(y-y_)*a,(y_-y)*b)) train_step=tf.train.AdamOptimizer(0.001).minimize(loss) # 隨機生成一個模擬數據集 rdm=RandomState(1) dataset_size=128 X=rdm.rand(dataset_size,2) # 設置隨機噪聲,范圍在-0.05~0.05 Y = [[x1+x2+rdm.rand()/10.0-0.05] for (x1,x2) in X] # 訓練神經網路 with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) STEPS=5000 for i in range(STEPS): start=(i*batch_size) % dataset_size end = min(start+batch_size,dataset_size) sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]}) print(sess.run(w1))