關於categorical cross entropy 和 binary cross entropy的比較,差別通常體如今不一樣的分類(二分類、多分類等)任務目標,能夠參考文章keras中兩種交叉熵損失函數的探討,其結合keras的API討論了二者的計算原理和應用原理。python
本文主要是介紹TF中的接口調用方式。git
對應的是網絡輸出單個節點,這個節點將被sigmoid處理,使用閾值分類爲0或者1的問題。此類問題logits和labels必須具備相同的type和shape。網絡
設x = logits
, z = labels
.
logistic loss 計算式爲: 其中交叉熵(cross entripy)基本函數式dom
z * -log(sigmoid(x)) + (1 - z) * -log(1 - sigmoid(x))
= z * -log(1 / (1 + exp(-x))) + (1 - z) * -log(exp(-x) / (1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (-log(exp(-x)) + log(1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x))
= (1 - z) * x + log(1 + exp(-x))
= x - x * z + log(1 + exp(-x))函數
對於x<0時,爲了不計算exp(-x)時溢出,咱們使用如下這種形式表示學習
x - x * z + log(1 + exp(-x))
= log(exp(x)) - x * z + log(1 + exp(-x))
= - x * z + log(1 + exp(x))spa
綜合x>0和x<0的狀況,並防止溢出咱們使用以下公式,code
max(x, 0) - x *z + log(1 + exp(-abs(x)))對象
import numpy as np import tensorflow as tf input_data = tf.Variable(np.random.rand(1, 3), dtype=tf.float32) # np.random.rand()傳入一個shape,返回一個在[0,1)區間符合均勻分佈的array output = tf.nn.sigmoid_cross_entropy_with_logits(logits=input_data, labels=[[1.0, 0.0, 0.0]]) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output)) # [[ 0.5583781 1.06925142 1.08170223]]
對應的是網絡輸出多個節點,每一個節點表示1個class的得分,使用Softmax最終處理的分類問題。blog
cross_entropy = -tf.reduce_mean(y * tf.log(tf.clip_by_value(y_pre, 1e-10, 1.0))
調用一下:
import tensorflow as tf input_data = tf.Variable([[0.2, 0.1, 0.9], [0.3, 0.4, 0.6]], dtype=tf.float32) labels=tf.constant([[1,0,0], [0,1,0]], dtype=tf.float32) cross_entropy = -tf.reduce_mean(labels * tf.log(tf.clip_by_value(input_data, 1e-10, 1.0))) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output))
softmax以後,計算輸出層所有節點各自的交叉熵(輸出向量而非標量)
cross_entropy_mean = tf.reduce_mean( tf.nn.sparse_softmax_cross_entropy_with_logits( labels=tf.argmax(labels,1), logits=logits), name='cross_entropy') cross_entropy_mean = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits( logits=logits, labels=labels), name='cross_entropy')
函數的參數label是稀疏表示的,好比表示一個3分類的一個樣本的標籤,稀疏表示的形式爲[0,0,1]這個表示這個樣本爲第3個分類,而非稀疏表示就表示爲2,同理[0,1,0]就表示樣本屬於第2個分類,而其非稀疏表示爲1。
import tensorflow as tf input_data = tf.Variable([[0.2, 0.1, 0.9], [0.3, 0.4, 0.6]], dtype=tf.float32) output = tf.nn.softmax_cross_entropy_with_logits(logits=input_data, labels=[[1,0,0], [0,1,0]]) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output))
此函數大體與tf.nn.softmax_cross_entropy_with_logits的計算方式相同,
適用於每一個類別相互獨立且排斥的狀況,一幅圖只能屬於一類,而不能同時包含一條狗和一隻大象
可是在對於labels的處理上有不一樣之處,labels從shape來講此函數要求shape爲[batch_size],
labels[i]是[0,num_classes)的一個索引, type爲int32或int64,即labels限定了是一個一階tensor,
而且取值範圍只能在分類數以內,表示一個對象只能屬於一個類別
import tensorflow as tf input_data = tf.Variable([[0.2, 0.1, 0.9], [0.3, 0.4, 0.6]], dtype=tf.float32) output = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=input_data, labels=[0, 2]) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output)) # [ 1.36573195 0.93983102]
比tf.nn.softmax_cross_entropy_with_logits多了一步將labels稀疏化的操做。由於深度學習中,圖片通常是用非稀疏的標籤的,因此tf.nn.sparse_softmax_cross_entropy_with_logits()的頻率比tf.nn.softmax_cross_entropy_with_logits高。
不過二者輸出尺寸等於輸入shape去掉最後一維(上面輸入[2*3],輸出[2]),因此均常和tf.reduce_mean()連用。