Tensorflow學習(3)-損失函數

激活函數去線性化

常用的有tf.nn.relu、tf.sigmoid(0~1)、tf.tanh(-1~1)。

經典損失函數-分類問題(交叉熵cross entropy)

cross_entropy = -tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1)))

注意這裏的y_,y可能爲一個矩陣,需要注意的是要使用“*”而不是使用tf.matmul(),因爲我們不是想要使用矩陣乘法。具體區別在書77頁。

得到一個n x m大小的矩陣後,n是batch_size,m爲分類的類數。reduce_mean來取平均值。

有個疑問就是按照交叉熵的公式應該是把n * m個數加起來除以n,但是如果使用reduce_mean是除以n*m。

Tensorflow的封裝

因爲交叉熵一般會與softmax迴歸一起使用,所以進行了封裝

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

在只有一個正確答案的分類問題中,下面這個函數可以進一步加速計算過程  //sparse:稀少的,稀疏的

cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y_,logits=y)

經典損失函數-迴歸問題(均方誤差MES,mean squared error)

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

自定義損失函數

例如:在預測商品銷量時,如果預測多了廠家會損失成本,預測少了廠家會損失利潤,但是每個產品成本只有一塊,而利潤有十塊,這時均方誤差就不能很好的最大化銷售利潤。

這時的損失函數可以設定爲當y(預測數據)>y_,loss = 1(y - y_);當y<_y,loss = 10(y - y_)。通過這樣的自定義損失函數的優化,模型提供的預測值更有可能最大化收益。

可以通過以下代碼來實現這個損失函數  //reduce有縮小的意思,可以理解爲縮小維度

loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * 1, (y_ - y) * 10))

使用下面的程序測試以下這個損失函數的效果

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_), loss_more * (y - y_), loss_less * (y_ - y)))

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

# 通過隨機數生成一個模擬數據集
rdm = RandomState(1)
data_size = 128
X = rdm.rand(data_size, 2)
# 設置迴歸的正確值爲兩個輸入的和加上一個隨機量
# 加上隨機量的是因爲避免最後能完全正確預測,不同的損失函數的效果就看不出來了
Y = [[x1 + x2 + rdm.random() / 10.0 - 0.05] for (x1, x2) in X]

# 訓練神經網絡
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    STEP = 20000
    for i in range(STEP):
        start = (i * batch_size) % data_size
        end = min(start + batch_size, data_size)
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
        if i % 1000 == 0:
            print(sess.run(w1))

最後可以發現w1的值都比[1,1]要大。可以通過改變loss_less,loss_more的值來感受區別。

 

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