Tensorflow學習筆記:機器學習必備API
前一節介紹了一些最基本的概念和使用方法。因為我個人的最終目的還是在深度學習上,所以一些深度學習和機器學習模組是必須要了解的,這其中包括了tf.train 、tf.contrib.learn、還有如訓練神經網路必備的tf.nn等API。這裡準備把常用的API和使用方法按照使用頻次進行一個排列,可以當做一個以後使用參考。這一節介紹的內容可以有選擇的看。而且最全的資訊都在TensorFlow的API裡面了,但是裡面的方法函數千千萬,所以主要都是根據其Python API Guide中的內容所寫。
一、必備API之train
train提供了一系列幫助模型訓練類和函式。其內容大致可以分為以下幾類:1、Optimizer類(優化器),2、GradientComputation梯度計算,3、Gradient Clipping梯度剪下(截斷),4、Decaying thelearning rate學習率降低方法,5、Moving Averages滑動平均,6、Coordinator and QueueRunne協調器和佇列執行器, 7、Distributed execution分佈執行 8、Training Hooks本意是“鉤子”的意思應該是相當於流程控制吧這個可以看
1、Optimizer
這個是最常用的了,其中包含了一個tf.train.Optimizer的基本的優化類和對應的一些常用的子類,如梯度下降、動量更新等等(常用:GradientDescentOptimizer,
AdagradOptimizer, or MomentumOptimizer)。這裡有兩種使用方法,可以想象的是我們通常流程都是得到一個損失函式-->計算梯度--->
這裡用官方API中的例子,假設已經有了一個損失函式Loss:
# Create an optimizerwith the desired parameters.建立一個梯度下降的Operation
opt =GradientDescentOptimizer(learning_rate=0.1)
# Add Ops to thegraph to minimize a cost by updating a list of variables.
# "cost" isa Tensor, and the list of variables contains tf.Variable
# objects.利用上面的優化器加入一個最小化代價函式的Operation
opt_op =opt.minimize(cost, var_list=<list of variables>
在訓練過程中只要run上面的這個opt_op(優化操作)的Operation就可以了。
還可以分開計算,上面是用了minimize()把計算梯度和把梯度應用在變數上兩個步驟合在了一起,也可以分成三步做,這主要用在梯度檢測上,可以看每一步的梯度計算情況:
# Create anoptimizer.一樣需要建立一個優化器
opt =GradientDescentOptimizer(learning_rate=0.1)
# Compute thegradients for a list of variables.計算列表中變數的梯度,注意返回值是一個元組列表
grads_and_vars =opt.compute_gradients(loss, <list of variables>)
# grads_and_vars is alist of tuples (gradient, variable). Dowhatever you
# need to the'gradient' part, for example cap them, etc.把得到的元組列表轉換成可用的結構,這個怎麼轉的不太清楚求指教
capped_grads_and_vars= [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]
# Ask the optimizerto apply the capped gradients.
opt.apply_gradients(capped_grads_and_vars)
這裡的minimize()和compute_gradients計算還有一些可選項稱為Gating Gradients,這個可以控制梯度及計算的方式,預設是GATE_OP也就是對於每個Op確保在這個操作被執行時所有被使用的變數的梯度已經計算好了。更細緻的介紹如下:
**GATE_NONE :並行地計算和應用梯度。提供最大化的並行執行,但是會導致有的資料結果沒有再現性。比如兩個matmul操作的梯度依賴輸入值,使用GATE_NONE可能會出現有一個梯度在其他梯度之前便應用到某個輸入中,導致出現不可再現的(non-reproducible)結果
**GATE_OP: 對於每個操作Op,確保每一個梯度在使用之前都已經計算完成。這種做法防止了那些具有多個輸入,並且梯度計算依賴輸入情形中,多輸入Ops之間的競爭情況出現。
**GATE_GRAPH: 確保所有的變數對應的所有梯度在他們任何一個被使用前計算完成。該方式具有最低級別的並行化程度,但是對於想要在應用它們任何一個之前處理完所有的梯度計算時很有幫助的。
最常用的優化方法就是上面提到的那些,還有下面這些:
2、GradientComputation
這個一般沒必要單獨用,因為上面的優化器已經用到了這些函式,大致是計算梯度或hessians的一些函式
3、GradientClipping
用來在圖中加入梯度截斷,這個主要用於梯度消失或是梯度爆炸的情況,可以增加一些泛化效能增加稀疏性,和nn中的dropout的原理是類似的。這個以後再考慮吧
4、Decaying thelearning rate
這個很常用,方法也就這幾個看看部落格什麼的就知道怎麼回事了,以指數衰減為例:其計算公式如下
decayed_learning_rate= learning_rate *
decay_rate ^(global_step / decay_steps)
我們需要的就是給定一個遞增的變數global_step和一個衰減率decay_rate和一個衰減週期decay_steps。下面以簡單的程式碼為例:
...
global_step =tf.Variable(0, trainable=False)
starter_learning_rate= 0.1
learning_rate =tf.train.exponential_decay(starter_learning_rate, global_step,
100000, 0.96, staircase=True)
# Passing global_stepto minimize() will increment it at each step.
learning_step = (
tf.train.GradientDescentOptimizer(learning_rate)
.minimize(...my loss...,global_step=global_step)
)
這個的意思是在這10000個步驟中每次衰減率為0.96,這裡也有一個例子可以參考一下(程式寫的一般)。
5、待補充
還有一些滑動平均和並行化的方法,後面用到會在整理。
二、必備API之contrib
這個是一些在基本的TensorFlow基礎上由第三方開發的一些API,可以看成是一些高等級的TensorFlow庫(比如原來的Keras現在就直接包含在這裡面了,還有一些傳統機器學習用的一些包),裡面有很多東西挺有用的不過東西太多了而且有的東西還不是很完善還有很多重複的內容,在contrib地址有詳細介紹,。
這裡東西很多,都是一些可以簡化tensorflow的一些API如:
- TF Learn(tf.contrib.learn):可以幫助使用者近似sklearn式的寫法
- TF Slim(tf.contrib.slim):這是一個輕量級的庫,可以用來定義、訓練和評估tensorflow中的複雜模型
- 高等級的API:Keras(中文非官方,英文官方)這個現在直接在tf.contrib.keras中就有了。
- 高等級的API:TFlearn(官方網站)
- 高等級API:Tensorlayer
- 還有包括tf.contrib.layers應該是tf.nn的一些組合形式可以減少很多程式碼,
寫著寫著突然發現了好多東西其實要直接去github對應的地方去看,那裡面介紹的比較清楚。這裡tf.contrib.learn(其地址如下),先放下這是不是TFLearn。因為感覺內容比較多,所以決定用單獨的章節帶著例子介紹這些contrib中的內容。
三、必備API之nn
1、 ActivationFunctions啟用函式
首先提供了一些常用的非線性啟用函式,如tf.nn.relu(feature, name=None)輸入一個tensor返回一個tensor。可以分為非線性平滑的啟用函式(sigmoid,tanh, elu, softplus, and softsign)和不是處處可微的(relu, relu6, crelu and relu_x)。
這裡很特殊的把dropout也放在這裡面了。還有一個要注意的地方,就是sigmoid和tanh不在這裡面,而是直接呼叫就可以(tf.sigmoid、tf.tanh),還有一個tf.nn.bias_add(value,bias,data_format=None,name=None)也被放到了這個類別裡,這個和tf.add很像但是偏差固定是一維的。
2、Convolution卷積層
這裡面針對generic vs. specific filters(普遍和特殊濾波器的權衡)產生了三類不同的卷積方式:
**conv2d: Arbitrary filters that can mixchannels together.任意卷積核同時在不同通道上進行卷積
**depthwise_conv2d:Filters that operate on each channelindependently.卷積核在每個通道上獨立工作
**separable_conv2d: A depthwise spatial filterfollowed by a pointwise filter.沒懂
上面這三個目前不是很懂。
(1)卷積過程用到的引數
我們都知道卷積有步長stride引數,這裡假設輸入的x的維度為[batch,in_height,in_weight,channel]的格式,這裡注意TensorFlow的維度是可選的下面介紹函式的時候會介紹到,而且這裡定義的stride是四維的因為通常理解的卷積核滑動步長都是二維的在長寬兩個維度,這裡的height和weight方向的滑動步長由strides[1]和strides[2]兩位決定,而其餘兩位都是0。
還有一個卷積上的問題是padding補零問題。tf.nn的卷積提供了兩種不同的補零方法:‘SAME’和‘VALID’,其中valid就是不補零,而且還會截斷一些資料防止出現不能滑動的情況(其實可以看成是補零的反面:刪資料),而‘SAME’是通過補零使資料恰好能夠進行卷積,而且TensorFlow和其他框架不同其他框架定義補零時候上下或補零數量一致的,但在TensorFlow中可出現上下共補5個0(上面2個,下面3個)的情況。不過不知道為什麼沒有輸入輸出尺寸相同的那種補零方式。
(2)例子
上面都是籠統的說的,現在用一個例子來分析一下。我們最常用的函式就是tf.nn.conv2d,用於計算給定四維輸入和四維卷積核的二維卷積(也就是我們圖片上常用的那種)主要建構函式如下:
例子1、tf.nn.conv2d
conv2d(
input,輸入資料共四個維度,維度的構成有下面的data_format決定
filter,卷積核四維,維度構成總是[filter_height高, filter_width寬, in_channels輸入通道數, out_channels輸入通道數]
strides,上面介紹過,是一個int列表長度為4,其維度構成也是由data_format決定的
padding,補零格式
use_cudnn_on_gpu=None,是不是用gpu訓練
data_format=None,資料格式
name=None 這個Operation的名字
)
這裡說一下data_format這是一個string格式的總共有:"NHWC", "NCHW"兩種,其中預設的是"NHWC"也就是資料按照[batch, height, width, channels]的格式輸入的,而'NCHW'顧名思義是按照[batch, channels, height, width]輸入的。預設情況下輸入是[batch, in_height, in_width, in_channels],卷積核是[filter_height, filter_width, in_channels,out_channels]
例2、tf.nn.conv3d
為了和上面的2d作對比,這裡舉一個conv3d的例子,文件中說Conv3D是一種交叉互相換的形式。
conv3d(
input,輸入格式為[batch, in_depth, in_height, in_width, in_channels]
filter,[filter_depth, filter_height,filter_width, in_channels, out_channels]
strides,這裡要求strides[0] = strides[4] = 1.和cov2d一樣,都有兩個是1
padding,
name=None
)
例3、tf.nn.depthwise_conv2d
上面沒弄懂的這裡詳細解釋一下。這個和tf.nn.conv2d的區別在於conv2的卷積核的輸入通道數與資料的通道數是一樣的,也就是每個卷積核同時作用於所有層然後累加得出一個輸出層的的結果,而這裡的depthwise_conv2d每個卷積核的輸入維度是1也就是說不同的卷積核作用在每個輸入通道上,按照輸入的通道數一層一層處理。更通俗的說就是我們假設有4個輸入通道數是1的卷積核,然後把這4個卷積核一層一層的作用在一個3通道的輸入資料上,這樣就得到了一個12個輸出,把這12個輸出並起來就可以了。
depthwise_conv2d(
input,設輸入是[batch,in_height, in_width, in_channels]
filter,尺寸是[filter_height, filter_width, in_channels, channel_multiplier].
strides,[1, stride, stride, 1]
padding,
rate=None,
name=None,
data_format=None
)
這裡有兩個圖幫助理解,第一個是conv2,第二個是depthwise_conv2d,圖片來自一個blog突然找不到了。
(3)反向傳播
因為還有反向傳播過程,所以還有兩個函式用於得到反向傳播的結果,但是tensorflow是隱形的進行反向傳播,所以這個暫時不用瞭解
3、Pooling池化
這裡定義了一些池化方法,大致有2種:平均池化,最大池化。目前通常用最大池化,tf.nn還提供了帶有返回argmax最大值位置的池化方法。以最大池化為例:
max_pool(
value,尺寸如下[batch, height, width, channels],而且要型別為tf.float32
ksize,池化的尺寸也是一個4維的第一位和最後一位為1
strides,
padding,
data_format='NHWC',
name=None
)
4、Morphologicalfiltering形態學濾波
這是用在影象預處理上的一種非線性濾波方法,具體原理不是很瞭解,有機會再看吧。
5、Normalization正則化
這個非常重要,是能夠讓神經元避免出現飽和而且能夠增加模型的泛化能力。最簡單的是L2-norm,在深度學習影象中用的最多的目前應該是batch_normalization,這裡的L2-norm其實就是output = x / sqrt(max(sum(x**2), epsilon))這樣一個表示式。因為用的多所以把batch_norm的正則化函式寫在這:
batch_normalization(
x,
mean,均值
variance,方差
offset,偏移量
scale,尺度
variance_epsilon,用於避免除零
name=None
)
可以看出這個還要自己輸入均值和方差,還是比較麻煩的,均值方差可以用tf.nn.normalize_moments計算,不過還是後面直接用API比較好。
6、Losses損失
Loss用於計算兩個tensor之間的誤差,這裡的損失是指的迴歸中會用到的,只有兩個:L2損失output = sum(t ** 2) / 2(不過不知道為什麼只有一個輸入,這個有點沒用),還有一個是tf.nn.log_poisson_loss計算泊松損失,這個不是很瞭解,不過這個需要輸入的確實是兩個tensor並計算一種損失。
7、Classification
這裡面都是一些分類需要用到的損失函式。
(1) 首先第一個就是tf.nn.softmax,這個就是計算一個tensor的softmax輸出,輸入為[batchsize,feature],輸出為[batchsize,num_classes]
(2) 這裡重點介紹一下tf.nn.softmax_cross_entropy_with_logits,計算logits和labels之間的softmax cross entropy。
softmax_cross_entropy_with_logits(
_sentinel=None,
labels=None,logits:就是神經網路最後一層的輸出,如果有batch的話,它的大小就是[batchsize,num_classes],單樣本的話,大小就是num_classes
logits=None,logits:labels:實際的標籤,和logits的尺寸相同
dim=-1,
name=None
)
這裡簡單的說一下計算流程,首先根據權重得到softmax的輸出值,然後計算softmax輸出值與真實標籤之間的交叉熵誤差,具體公式見這裡。
(3)還有計算logsoftmax的函式tf.nn.log_softmax
計算公式為logsoftmax = logits -log(reduce_sum(exp(logits), dim)) ,這裡的reduce_sum()是求和的operat。
8、embedding
很常用這裡其實是提供的一個lookup embedding的函式tf.nn.embedding_lookup,函式的用法主要是選取一個張量裡面索引對應的元素。具體的內容可以百度一下。
9、其他
還有一些其他的內容:
(1)Recurrent Neural Networks 提供了幾個方法用於幫助rnn構建,需要結合tf.contrib.rnn
(2)Connectionist Temporal Classification:這個主要用在Seq2Seq的問題通常結合LSTM+CTC,這裡有個介紹
(3)Evaluation:用於估計網路的效能,包括兩個方法:tf.nn.top_k(計算前k個最大值)和tf.nn.in_top_k(判斷目標是不是前k個值中的一個)
(4)Candidate Sampling:這是一種取樣方法,具體的含義見這裡,主要用在語義及相關分析上