天天看點

TensorFlow中的損失函數

分類問題和回歸問題是監督學習的兩大種類,本文将分别介紹分類問題和回歸問題中使用到的經典損失函數以及根據實際情況所自定義的損失函數。

同時注意損失函數定義的是損失,是以要将利潤最大化,定義損失函數應該刻畫成本或者代價。在實際情況中,可以根據具體問題自定義損失函數。

一、經典損失函數

1、分類問題

1.1、交叉熵簡介

機器學習中,在解決二分類的情況時,可以通過設定一個門檻值,大于門檻值的認為是一類,小于門檻值的認為是另外一類;然而在解決多分類的問題時,雖然設定多個門檻值在理論上是可行的,但在解決實際問題的時候往往是設定輸出n維向量,其中n為類别的個數。

那麼如何判一個輸出向量和期望的向量有多接近呢。交叉熵(cross entropy) 是最經典的評判方法之一。交叉熵刻畫了兩個機率之間的距離,他是分類問題中使用比較廣泛的一種損失函數。

M S E ( y , y ′ ) = ∑ i = 1 n ( y i − y i ′ ) 2 n MSE(y, {y}') = \frac{\sum_{i=1}^{n}(y_{i}-{y_{i}}')^{2}}{n} MSE(y,y′)=n∑i=1n​(yi​−yi​′)2​

他刻畫的是通過機率分布q來表示機率分布p的困難程度。因為正确答案是希望得到的結果,是以交叉熵作為損失函數時,p代表準确答案,q代表預測答案。

1.2、softmax簡介

如何将神經網絡前向傳播得到的結果變成機率分布呢?softmax回歸 是最常用的方法。它本身可以作為一個學習算法來優化分類結果,但在TensorFlow中,softmax回歸的參數被去掉了,他隻是一層額外的處理層,将神經網絡的輸出變成一個機率分布。

假設原始神經網絡輸出為 y 1 , y 2 , y 3 , . . . , y n y_{1},y_{2},y_{3}, ..., y_{n} y1​,y2​,y3​,...,yn​,那麼經過Softmax回歸處理之後的輸出為:

M S E ( y , y ′ ) = ∑ i = 1 n ( y i − y i ′ ) 2 n MSE(y, {y}') = \frac{\sum_{i=1}^{n}(y_{i}-{y_{i}}')^{2}}{n} MSE(y,y′)=n∑i=1n​(yi​−yi​′)2​

這樣就把神經網絡的輸出也變成了一個機率分布了,進而可以通過交叉熵來計算預測的機率分布和隻是答案分布之間的距離了。

1.3、TensorFlow實作

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

分解如下:

with tf.Session() as sess:
    v = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    # tf.clip_by_value函數将一個張量中的數值限制在一個範圍内
    # 小于2.5的換乘了2.5, 大于4.5的被換乘了4.5
    print(tf.clip_by_value(v, 2.5, 4.5).eval())
    # 輸出為:[[2.5, 2.5, 3.],[4., 4.5, 4.5]]

    v1 = tf.constant([[1.0, 2.0], [3.0, 4.0]])
    v2 = tf.constant([[5.0, 6.0], [7.0, 8.0]])
    # 元素之間對應相乘
    print((v1*v2).eval())
    # 矩陣成法
    print(tf.matmul(v1, v2).eval())
    # 對所有數值取平均數
    print(tf.reduce_mean(v1).eval())
    # 輸出為: 2.5
           

因為交叉熵一般會與softmax回歸一起使用,是以TensorFlow對這兩個功能進行了同一封裝,提供了 tf.nn.softmax_cross_entropy_with_logist() 函數。

2、回歸問題

2.1、均方誤差簡介

與分類問題不同,回歸問題解決的是對具體數值的預測,比如房價預測、銷量預測等。這些問題需要預測的不是一個事先定義好的類别,而是一個任意實數。解決回歸問題的神經網絡一般都隻有一個輸出節點。對于回歸問題,最經典的損失函數是均方誤差(MSE, mean squared error) 它的定義如下:

M S E ( y , y ′ ) = ∑ i = 1 n ( y i − y i ′ ) 2 n MSE(y, {y}') = \frac{\sum_{i=1}^{n}(y_{i}-{y_{i}}')^{2}}{n} MSE(y,y′)=n∑i=1n​(yi​−yi​′)2​

其中 y i y_{i} yi​為一個batch中第i個資料的額正确答案, 而 y i ′ {y_{i}}' yi​′為神經網絡給出的預測值。

2.2、TensorFlow實作

二、自定義損失函數

1、情景引入

TensorFlow不僅支援經典的損失函數,還可以優化任意的自定義損失函數,本小節将介紹如何通過自定義損失函數的方法,使得是經網絡優化結果更加接近實際問題的需求。

例如,在預測商品銷量時,如果預測多了(預測值大于實際值),商家損失的是生産商品的成本;如果預測少了(預測值小于實際值),損失的則是商品的利潤,因為一般商品的成本和利潤不會對等,比如:一件商品成本為1元, 利潤為10元。如果損失函數是均方誤差,那麼很有可能此模型無法最大化利潤。為了最大化利潤,需要我們根據實際情況自定義損失函數,以下公式給出了一個當預測值多于實際值和少于實際值時,有不同損失系數的損失函數:

L o s s ( y , y ′ ) = ∑ i = 1 n f ( y i , y i ′ ) , f ( x ) = { a ( x − y ) x > y b ( y − x ) x ≤ y Loss(y, {y}')=\sum_{i=1}^{n}f(y_i, {y_i}'), f(x)=\left\{\begin{matrix} a(x-y) x>y\\ b(y-x) x\leq y \end{matrix}\right. Loss(y,y′)=i=1∑n​f(yi​,yi​′),f(x)={a(x−y)x>yb(y−x)x≤y​

2、TensorFlow實作

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

分解如下:

import tensorflow as tf
with tf.Session() as sess:
	v1 = tf.constant([1.0, 2.0, 3.0, 4.0])
	v2 = tf.constant([4.0, 3.0, 2.0, 1.0])
	# tf.greater的輸入是兩個張量,他會比較這兩個張量中每一個元素的大小
	print(sess.run(tf.greater(v1, v2))
	# 輸出 [False, False, True, True]
	# tf.where與np.where相似
	print(tf.where(tf.greater(v1, v2), v1, v2).eval()
	# 輸出 [4., 3., 3., 4.] 
           

參考

TensorFlow實戰Google深度學習架構 (第2版)