【TensorFlow-windows】部分損失函數測試

前言

在TensorFlow中提供了挺多損失函數的,這裏主要測試一下均方差與交叉熵相關的幾個函數的計算流程。主要是測試來自於tf.nntf.lossesmean_square_errorsigmoid_cross_entrysoftmax_cross_entrysparse_softmax_cross_entry

國際慣例,參考博客:

官方文檔

一文搞懂交叉熵在機器學習中的使用,透徹理解交叉熵背後的直覺

TensorFlow中多標籤分類

預備

單熱度編碼one-hot

先複習一下one_hot編碼,就是將真實標籤轉換爲01標籤,需要注意的是tf的one_hot編碼中標籤0代表的是1,0,0...而非0,0,0...

labels_n=np.array([0,1,2])
labels_oh=tf.one_hot(labels_n,depth=3)
with tf.Session() as sess:
    print(sess.run(labels_oh))
 '''
 [[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
 '''

softmax

通常將最後的輸出規整到和爲1的形式:

softmax = tf.exp(logits) / tf.reduce_sum(tf.exp(logits), axis)

設輸出爲z=(z1,z2, ,zn)z=(z_1,z_2,\cdots,z_n),則
σ(z)j=ezji=1nezk \sigma(z)_j=\frac{e^{z_j}}{\sum_{i=1}^n e^{z_k}}

sigmoid

激活函數:
f(x)=11+ex f(x)=\frac{1}{1+e^{-x}}

交叉熵

多標籤分類(每個樣本可能屬於多個標籤),最後一層使用sigmoid激活:

ylog(P(y))(1y)log(1P(y)) -y\log(P(y))-(1-y)\log(1-P(y))

單標籤分類(每個樣本只可能屬於一個標籤),最後一層使用softmax激活:
i=1nyilog(P(yi)) -\sum_{i=1}^n y_i\log(P(y_i))

準備測試

進入測試之前,需要先引入相關的包

import numpy as np
import tensorflow as tf

交叉熵相關函數的測試,使用的變量是

labels=np.array([[1,0,0],[0,1,0],[0,0,1]],dtype='float32')
preds=np.array([[5,6,3],[7,5,1],[1,2,8]],dtype='float32')

均方差損失-MSE

原理

對應項相減的平方和的均值,通常用來做迴歸,計算預測值與真實值的誤差

代碼測試

定義相關變量:

ori_labels=np.array([[1,2,3]],dtype='float32')
pred_labels=np.array([[5,3,3]],dtype='float32')

調用原本函數測試:

mse_op=tf.losses.mean_squared_error(labels=ori_labels,predictions=pred_labels)
with tf.Session() as sess:
    print(sess.run(mse_op))
 '''
 5.6666665
 '''

手動實現過程:

with tf.Session() as sess:
    print(sess.run(tf.reduce_mean(tf.square(ori_labels-pred_labels))))
'''
5.6666665
'''

總結

原理就是求原標籤與預測標籤的平方和損失的均值。

sigmoid_cross_entry

原理

使用sigmoid激活的交叉熵,毫無疑問,玩得多標籤分類,流程是:

  • 將輸出用sigmoid激活
  • 使用多標籤分類的交叉熵計算損失

代碼測試

使用tf.losses中的交叉熵損失

tf_sce=tf.losses.sigmoid_cross_entropy(labels,preds)
with tf.Session() as sess:
    print(sess.run(tf_sce))
#2.3132434

使用tf.nn中的交叉熵損失:

tf_sce1=tf.nn.sigmoid_cross_entropy_with_logits(labels=labels,logits=preds)
with tf.Session() as sess:
    print(sess.run(tf_sce1))
'''
 [[6.7153485e-03 6.0024757e+00 3.0485873e+00]
 [7.0009112e+00 6.7153485e-03 1.3132617e+00]
 [1.3132617e+00 2.1269281e+00 3.3540637e-04]]
'''

使用流程實現:

#先計算sigmoid,再計算交叉熵
preds_sigmoid=tf.sigmoid(preds)
ce=-labels*tf.log(preds_sigmoid)-(1-labels)*(tf.log(1-preds_sigmoid))
# ce= - tf.reduce_sum(labels*tf.log(preds_sigmoid),-1)
with tf.Session() as sess:
    print(sess.run(ce))
    print(sess.run(tf.reduce_mean(ce)))
'''
[[6.7153242e-03 6.0024934e+00 3.0485876e+00]
 [7.0009704e+00 6.7153242e-03 1.3132617e+00]
 [1.3132617e+00 2.1269276e+00 3.3539196e-04]]
2.3132522
'''

總結

  • 多標籤分類,輸入是原始和預測標籤的編碼

  • tf.losses中的計算結果是tf.nn中計算結果的均值

softmax_cross_entry

原理

使用softmax激活,顯然就是單標籤分類的情況,流程是:

  • 將輸出用softmax激活
  • 計算單標籤分類的交叉熵損失

代碼測試

使用tf.losses中的函數:

tf_sce=tf.losses.softmax_cross_entropy(labels,preds)
with tf.Session() as sess:
    print(sess.run(tf_sce))
#1.160502

使用tf.nn中的函數:

tf_sce1=tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits=preds)
with tf.Session() as sess:
    print(sess.run(tf_sce1))
#[1.3490121  2.129109   0.00338493]

使用流程計算:

#先計算softmax,再計算交叉熵
preds_sigmoid=tf.nn.softmax(preds)
ce= - tf.reduce_sum(labels*tf.log(preds_sigmoid),-1)
# ce=-labels*tf.log(preds_sigmoid)-(1-labels)*(tf.log(1-preds_sigmoid))
with tf.Session() as sess:
    print(sess.run(ce))
    print(sess.run(tf.reduce_mean(ce)))
'''
[1.3490121  2.129109   0.00338495]
1.1605021
'''

總結

  • 用於單標籤分類,輸入是真實和預測標籤的單熱度編碼
  • tf.losses中的計算結果是tf.nn中計算結果的均值

sparse_softmax_cross_entry

原理

還是看到softmax,依舊是單標籤分類,但是多了個sparse,代表輸入標籤可以是非單熱度標籤,流程:

  • 將原標籤轉爲單熱度編碼
  • 將輸出用softmax激活
  • 計算單標籤分類的交叉熵

代碼測試

假設原始標籤的非單熱度編碼是:

labels_n=np.array([0,1,2])

利用tf.losses中的損失函數:

tf_scen=tf.losses.sparse_softmax_cross_entropy(labels=labels_n,logits=preds)
with tf.Session() as sess:
    print(sess.run(tf_sce))
#1.160502

利用tf.nn中的損失函數:

tf_sce1=tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels_n,logits=preds)
with tf.Session() as sess:
    print(sess.run(tf_sce1))
    print(sess.run(tf.reduce_mean(tf_sce1)))
'''
[1.3490121  2.129109   0.00338493]
1.160502
'''

利用流程實現:

labels_onehot=tf.one_hot(labels_n,depth=3)
preds_sigmoid=tf.nn.softmax(preds)
ce= - tf.reduce_sum(labels_onehot*tf.log(preds_sigmoid),-1)
# ce=-labels*tf.log(preds_sigmoid)-(1-labels)*(tf.log(1-preds_sigmoid))
with tf.Session() as sess:
    print(sess.run(labels_onehot))
    print(sess.run(ce))
    print(sess.run(tf.reduce_mean(ce)))  
    
'''
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
[1.3490121  2.129109   0.00338495]
1.1605021
'''

總結

  • sparse代表原始標籤不用轉成單熱度編碼
  • 適用於單標籤分類
  • tf.lossestf.nn中函數的均值

總結

本文主要對比了:

  • tf.nntf.losses中同一類損失函數的使用方法與區別
  • 分析計算流程,並實現驗證
  • 瞭解TensorFlow中迴歸、單標籤分類、多標籤分類的損失函數的選擇

博客代碼:

鏈接:https://pan.baidu.com/s/1b40rNxjdOIIE2g7_Afctiw
提取碼:0sb0

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