tensorflow 基礎學習三:損失函數講解


交叉熵損失:

給定兩個概率分布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))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM