TensorFlow損失函數、優化器API及其在簡單卷積網絡上的比較

Loss

1. L2損失

tf.nn.l2_loss(t, name=None)

output = sum(t ** 2) / 2

2. 交叉熵損失

C=1nx[ylna+(1y)ln(1a)]C=-\frac{1}{n}\sum_{x}[y\ln a +(1-y)\ln(1-a)]
a是經過sigmoid激活的a=σ(jwjxj+b)a=\sigma (\sum_{j}w_jx_j + b),在0到1之間
交叉熵爲什麼能作爲代價函數?
首先,它是非負的,加號裏的每一項都是負的,整個式子前面是負的,負負得正
其次,實際輸出值很接近期望輸出值時,交叉熵會非常接近0
它有均方代價函數不具備的特徵,能夠避免學習速率降低的問題
TensorFlow四個交叉熵函數

tf.nn.sigmoid_cross_entrogy_with_logits
tf.nn.softmax_cross_entrogy_with_logits
tf.nn.sparse_softmax_cross_entrogy_with_logits
tf.nn.weighted_cross_entrogy_with_logits

(1)

tf.nn.sigmoid_cross_entrogy_with_logits(logits, targets, name=None)
	# logits: 網絡模型中的W*X矩陣,不需要經過sigmoid
	# targets: 標籤值,可包含多個1或0,和logits的shape相同

不能用於多分類問題,例如一個實際取值範圍爲0-4,目標標籤y也是0-4,實際取值經過sigmoid後取值範圍變爲0-1,ln(.)是負的,公式中(1-y)會出現負數,而且-yln(a)有可能會非常大

(2)

對於單目標多分類問題,分類之間是獨立且互斥的,這時候就要用 softmax的交叉熵函數

  • 先看softmax激活:
tf.nn.softmax(logits, dim=-1, name=None)
	# logits:Tensor
	# dim: 默認爲-1,最後一個維度

softmax = exp(logits) / reduce_sum(exp(logits), dim)
softmax輸出0-1之間的概率分佈

  • logsoftmax激活:
tf.nn.log_softmax(logits, dim=-1, name=None)

logsoftmax = logits - log(reduce_sum(exp(logits), dim))

  • softmax交叉熵損失:
tf.nn.softmax_cross_entrogy_with_logits(logits, labels, dim=-1, name=None)

注意:只適合單目標二分類或者多分類問題
對於多分類問題,我們需要對輸入進行編碼,例如我們的年齡分爲5類,人工編碼爲0,1,2,3,4,因爲輸出值是5維特徵,因此我們需要人工做onehot encoding,分別編碼爲00001,00010,00100,01000,10000,作爲函數的輸入

(3)

tf.nn.sparse_softmax_cross_entrogy_with_logits(logits, labels, name=None)
	# logits: shape=[batch_size, num_classes]
	# labels: shape=[batch_size, num_classes] num_classes從0開始編碼

softmax_cross_entrogy_with_logits的易用版本,對於CIFAR-10、ImageNet都是多類單標籤問題,label都是0,1,2,3,…每次轉成onehot encoding比較麻煩,使用sparse_softmax_cross_entrogy_with_logits,TensorFlow內部進行編碼

(4)

tf.nn.weights_cross_entrogy_with_logits(targets, logits, pos_weight, name=None)

let x = logits, z = targets q = pos_weights
softmax_cross_entrogy_with_logits的拓展版,pos_weight的目的是增加或者減少正樣本在算Cross Entropy的損失,原理:在正樣本算出的值前面乘以一個係數

loss = qz * -log(sigmoid(x)) + (1 - z) *  -log(1 - sigmoid(x))
    	 =(1 - z) * x + (1 +  (q - 1) * z) *   log(1 + exp( - x))

Optimizer

兩個作用:計算損失的梯度,將梯度應用到變量的更新中去
Optimizer是一個基類:class tf.train.Optimizer
使用的時候,需要實例化它的一個子類,如下面的例子:

# 傳入學習率參數創建一個優化器類的對象實例
opt = GradientDescentOptimizer(learning_rate=0.1)
# 添加一系列操作節點到計算圖最小化cost來更新變量
opt_op = opt.minimize(cost, var_list=<list of variables>)  # 傳入損失函數和變量列表,var_list不傳的話更新的是所有的變量

用處理的梯度更新模型參數
調用minimize()有兩個連續步驟:計算梯度,應用到變量上,如下:

  1. 使用comepute_gradients()計算梯度
  2. 使用apply_gradients()把處理過的梯度用來更新varibles

如果想在應用在變量之前對梯度做一些特別處理時,需要在這兩步之間再加上一些處理:

  1. 使用comepute_gradients()計算梯度
  2. 根據需求對計算出的梯度做一些處理
  3. 使用apply_gradients()把處理過的梯度用來更新varibles

例子:

# 傳入學習率參數創建一個優化器類的對象實例
opt = GradientDescentOptimizer(learning_rate=0.1)
# 計算梯度 
# grads_and_vars是一個元組列表(變量所對應的梯度, 變量)
grads_and_vars = opt.compute_gradients(loss, <list of variables>)
# 對梯度元組中的每一個值進行操作
capped_grads_and_vars = [(MyCapper(gc[0]), gv[1]) for gv in grads_and_vars]
# 用新的梯度更新參數
opt.apply_gradients(capped_grads_and_vars) 

優化器子類:

10個

tf.train.GradientDescentOptimizer()
tf.train.ProximalGradientDescentOptimizer()
tf.train.AdagradOptimizer()
tf.train.ProximalAdagradOptimizer()
tf.train.AdagradDAOptimizer()
tf.train.AdadeltaOptimizer()
tf.train.AdamOptimizer()
tf.train.RMSPropOptimizer()
tf.train.FtrlOptimizer()
tf.train.MomentumOptimizer()

這篇也有講:https://blog.csdn.net/fzp95/article/details/83018744

比較

conv+relu+maxpool+linear_fc
tf.train.GradientDescentOptimizer()
在這裏插入圖片描述
tf.train.ProximalGradientDescentOptimizer()
在這裏插入圖片描述
tf.train.AdagradOptimizer()
在這裏插入圖片描述
tf.train.ProximalAdagradOptimizer()
在這裏插入圖片描述
tf.train.AdagradDAOptimizer()
在這裏插入圖片描述
tf.train.AdadeltaOptimizer() 在小網絡上表現很差
在這裏插入圖片描述
tf.train.AdamOptimizer() 學習率選取很重要,不能太小,也不能太大,合適的學習率優化效果好。
在這裏插入圖片描述
tf.train.FtrlOptimizer() 最優學習率爲0.1 不能太小
在這裏插入圖片描述
tf.train.MomentumOptimizer() 對於小學習率能夠快速下降
在這裏插入圖片描述
tf.train.RMSPropOptimizer() 對學習率變化不太敏感 而且優化效果好
在這裏插入圖片描述

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