損失函數

4.2.1 經典損失函數

1. 交叉熵(給定兩個概率分佈p和q)

H(p,q)=−∑xp(x)logq(x)

cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
#其中y代表正確結果,y_代表預測結果

分別解釋上述程序的四個運算

1. tf.clip_by_value:將一個張量的數值限定在一個範圍內,可以避免一些錯誤的運算(如log0無效)
clip_by_value(t,clip_value_min,clip_value_max,name=None)

舉例:

import tensorflow as tf
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())
#eval(str [,globals [,locals ]])函數將字符串str當成有效Python表達式來求值,並返回計算結果。

[[ 2.5  2.5  3. ]
 [ 4.   4.5  4.5]]
#小於2.5的都變爲了2.5
#大於4.5的都變爲了4.5

2. tf.log:對張量中的所有元素依次求對數

import tensorflow as tf
v=tf.constant([1.0,2.0,3.0])
with tf.Session() as sess:
    print(tf.log(v).eval())

[ 0.          0.69314718  1.09861231]

3. tf.matmul:矩陣元素點乘

import tensorflow as tf
v1=tf.constant([[1.0,2.0],[3.0,4.0]])
v2=tf.constant([[5.0,6.0],[7.0,8.0]])

with tf.Session() as sess:
    print((v1*v2).eval())
    #輸出:[[  5.  12.],[ 21.  32.]](矩陣對應位置元素相乘)
    print(tf.matmul(v1, v2).eval())
    #輸出:[[ 19.  22.],[ 43.  50.]](矩陣相乘)

通過這三步計算得到每一個樣例中的每一個類別的交叉熵,是一個n×mn×m矩陣:

nn爲一個batch中的樣例數量,mm爲分類的類別數量。

如何獲得交叉熵:將每行的mm個結果相加得到所有樣例的交叉熵,再對nn行取平均得到一個batch的平均交叉熵

簡化:分類問題的類別數量不變,故可以直接對整個矩陣做平均而不改變計算結果的意義,用tf.reduce_mean實現

import tensorflow as tf
v1=tf.constant([[1.0,2.0,3.0],[4.0,5.0,6.0]])
with tf.Session() as sess:
    print(tf.reduce_mean(v1).eval())

output:3.5

交叉熵一般會和softmax迴歸同時使用,所以TensorFlow對其進行了封裝,可以直接獲得softmax之後的交叉熵函數

cross_entropy=tf.nn.softmax_cross_entropy_with_logits(y,y_)

2. 均方誤差(MSE,Mean Squared Error)

迴歸問題是對具體數值的預測,解決迴歸問題的神經網絡一般只有一個節點,該節點的值就是預測值,迴歸問題最常見的的損失函數是均方誤差函數,定義如下:
MSE(y,y′)=∑ni=1(yi−y′i)2n
MSE(y,y′)=∑i=1n(yi−yi′)2n

其中,yiyi是一個batch中的第ii個數據的正確結果,y′iyi′爲預測結果
TensorFlow實現均方誤差函數

mse=tf.reduce_mean(tf.square(y_-y))

4.2.2 自定義損失函數

自定義一個損失函數(預測值多於真實值和預測值少於真實值的損失函數不同)
Loss(y,y′)=∑i=1nf(yi,y′i);ifx>y,f(x,y)=a(x−y);ifx<=y,f(x,y)=b(y−x)

loss=tf.reduce_sum(tf.select(tf.greater(v1,v2),(v1-v2)*a,(v2-v1)*b))

對其中的兩個函數進行說明:

tf.select(condition,a,b)  
# condition:一個張量tensor,類型爲bool
# a:一個張量tensor,shape與condition一致,類型一般爲float32, float64, int32, int64.
# b:一個張量tensor,類型和shape與a一致。

# 當condition爲True時,選擇第二個參數a,否則選擇第三個參數b(在元素級別進行)


tf.greater(a,b)
# 比較兩個值的大小,當a>b時,返回True;當a<b時,返回False

損失函數對模型訓練結果的影響

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)

#定義預測多了/少了的樣本
loss_less=10
loss_more=1
loss=tf.reduce_sum(tf.where(tf.greater(y,y_),(y-y_)*loss_more,(y_-y)*loss_less))

train_step=tf.train.AdamOptimizer(0.001).minimize(loss)

#通過隨機數產生一個模擬數據集
rdm=RandomState(1)
dataset_size=128
X=rdm.rand(dataset_size,2)

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))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章