關於caffe中的solver:
cafffe中的sover的方法都有:
- Stochastic Gradient Descent (
type: "SGD"
),- AdaDelta (
type: "AdaDelta"
),- Adaptive Gradient (
type: "AdaGrad"
),- Adam (
type: "Adam"
),- Nesterov’s Accelerated Gradient (
type: "Nesterov"
) and- RMSprop (
type: "RMSProp"
)solver都干了點什么?
1,創建訓練網絡與測試網網絡.
2,進行前向傳播與誤差反向傳播,更新參數,優化網絡.
3, 間歇地進行用驗證集進行測試test網絡.
4, 在優化過程中,可以選擇進行快照,進行保存中間狀態.
數據輸入層 (data layer):
在caffe中, 數據通過caffe進入.通常情況下,數據可以直接從內存中讀中,可以從高效的LevelDB/LMDBD Database 中讀入, 也可以從HDF5格式的硬盤文件中讀去或着通常的圖片文件.
通常我們對數據的預處理,我們可以參考TransformationParams里的設定.
Database 層: 類型為Data
這就是從LMDB/LeverlDB文件中讀取數據的層;
In-Memory層: type:MemoryData
當我們想直接從內存中讀取數據的話,那就需要調用MemoryDataLayer::Reset(c++程序)或Net.input_arrays(python程序),來指明數據源.
HDF5 Input層,類型為:HDF5Data
它的作用為從HDF5文件類型里讀放數據,我們就看一個例子哦
2 layer { 3 name: "mnist" 4 type: "HDF5Data" 5 top: "data" 6 top: "label" 7 include { 8 phase: TRAIN 9 } 13 hdf5_data_param { 14 source: "mydata/train_list.txt" //是個坑哦,下面下面解釋; 15 batch_size: 200 17 }上面的代碼需要一地方解釋:在定義.proto文件里的data層時注意,hdf5_data_param的source不要直接寫我們生成的HDF5文件的路徑,而是寫一個.txt文件的,並在.txt文件里寫入你生成的HDF5文件的路經,一個HDF5文件路徑占一行,一定要這樣哦。原因是因為,我們可以要讀入多個HDF5文件,所以要這樣寫哦。
HDF5 Output層 類型為:HDF5Output
它的作用為把數據寫成HDF5格式
另外還有,Images, Windows, Dummy.
激活函數層: 如果要用激活函數的話,就相當於增加一層哦
ReLU激活函數(rectified-linear and Leaky-ReLU):類型為ReLU.
在標准的ReLU激活函數中,當輸入為x時,如果x>0,則輸出 x,如果輸入<=0,則輸出0,即輸出為max(0,x).
在非標准的ReLU激活函數中,當輸入x<=0時, 輸出為x * negative_slop(它是一個參數,默認為0).
sigmoid激活函數:類型為 Sigmoid.
這個不用多解釋了.
tanh激活函數,類型為: TanH.
這個也不用多解釋了.
Abolute Value:類型為 AbsVal.
計算絕對值的函數.
power激活函數:類型為:Power.
The
Power
layer computes the output as (shift + scale * x) ^ power for each input element x.
BNLL激活函數:類型為 BNLL.
The
BNLL
(binomial normal log likelihood) layer computes the output as log(1 + exp(x)) for each input element x.
caffe中的layer:
convolution層:
layer的類型為:Convolution.,它有很參數,具體可以看caffe.proto里的message ConvolutionParam{}的定義.
num_output :輸出的 feature map的個數啦,是否有偏置項啦,是否有把圖像的邊緣補充/卷積核的大小./步長/權值如何填充/偏置如何填充等.
看一個例子:
layer { name: "conv1" type: "Convolution" bottom: "data" top: "conv1" # learning rate and decay multipliers for the filters param { lr_mult: 1 decay_mult: 1 } # learning rate and decay multipliers for the biases param { lr_mult: 2 decay_mult: 0 } convolution_param { num_output: 96 # learn 96 filters kernel_size: 11 # each filter is 11x11 stride: 4 # step 4 pixels between each filter application weight_filler { type: "gaussian" # initialize the filters from a Gaussian std: 0.01 # distribution with stdev 0.01 (default mean: 0) } bias_filler { type: "constant" # initialize the biases to zero (0) value: 0 } } }pooling層:類型為:Pooling
這一層也有很多參數選擇, 如pooling的核的大小/步長/pad(即上面的是否為邊界加一些默認的值), 還有pooling的方法:現在有max/ average/stochastic三個方法.,具體看一下caffe.proto里的定義.
layer { name: "pool1" type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { pool: MAX kernel_size: 3 # pool over a 3x3 region stride: 2 # step two pixels (in the bottom blob) between pooling regions } }
LRN層:,類型為LRN. 即local response normalizaiton,它的作用是通過normalizing 局部輸入區域,達到側向抑制的目的(為什么,還不確定,記得在論文里看到過類似的方法).它分為兩種模式,一種是across-channels,一種是within_channels .在arcoss-channel里, 分選擇在相鄰的feature-map之間進行,它的區域差不多為local_size *1 *1, 如果選擇within_channels的話,該操作會選擇在同一個feature map上操作,它的區域相當於 1* local_size * local_size.
Inner Product 層: 類型為:InnerProduct
它就是我們據說的全連接層.
caffe中的dropout 層
對於dropout層,說一下(論文中我們都會看到當我們有訓練過程中dropout為(比如)0.3時,我們在測試時我們不會進行dropout,而是把輸出乘以0.7。所以呢,caffe是怎么實現的呢?
當我們定義的net.prorotxt文件中,有了dropout這一層的時候,然后呢,caffe會根據你是訓練還是測試進行不同的操作,當訓練時,我們有一部分的神經元被dropout,然后,剩余的乘以1/(1-0.3). 然后,在測試時,dropout直接把數據進行從上一層復制到下一層,不進行操作。
明白了吧。。所以,我們不用在網絡中進行定義 乘以0.7這一步。。你只需要分成訓練還是測試就可以了。下面是一個dropout的例子:
layer { name: "drop1" type: "Dropout" bottom: "ip11" top: "ip11" dropout_param { dropout_ratio: 0.3 } }
loss層:
在caffe中,默認的以loss結尾的layer可以作為loss層,但是中間的層同樣可以作為loss層.原因是這樣的:
有一個和這個相關的參數:loss_weight,它決定了你的每個loss層占最好的loss的大小.
在以loss結尾的layer里面, loss_wight的大小為1. 在不是以loss結尾的layer里面,它的loss_weight為0.
如:
layer { name: "loss" type: "SoftmaxWithLoss" bottom: "pred" bottom: "label" top: "loss" loss_weight: 1 #這個是默認的,可以不寫的. }如果我們想在一個net里,包含多個loss層的話,我們就可以設置他們對應的loss_weight在大小,這就相當於一個權值.(如一個網絡中,我們即用softmaxWithloss用來分類,也用EuclideanLoss用來計算重構輸入的loss).
最后在計算總的loss的時候,它的輸出可以用下面的偽代碼表示:
loss := 0 for layer in layers: for top, loss_weight in layer.tops, layer.loss_weights: loss += loss_weight * sum(top)
softmax: 類型為:SoftmaxWithLoss
它的類型為:SoftmaxWithLoss.它其實就是一個 softmax層,然后跟了個multinomial logistic loss層. 它比單獨用softmax層可以使梯度值更穩定.
sum-of-squares/也叫euclidean:
就是平時我們說的平方差代價函數.
hinge Loss: 類型:HingeLoss
最常用在 SVM 中的最大化間隔分類中等. hinge loss常分為1vs all hinge和squared hinge loss,即 L1 與L2hange.
# L1 Norm layer { name: "loss" type: "HingeLoss" bottom: "pred" bottom: "label" } # L2 Norm layer { name: "loss" type: "HingeLoss" bottom: "pred" bottom: "label" top: "loss" hinge_loss_param { norm: L2 } }
sigmoid cross-entropy loss:
就是平常所見的交叉熵損失函數. 類型:SigmoidCrossEntropyLoss
infogain loss:信息增益損失函數: ,類型:InfogainLoss
一些功能的layer:
splitting(把一個輸入分成多個輸出),類型:splitting
在caffe.proto里為什么沒有找到呢.它的作用就是把一個輸入復制為多個輸入哦;
Flattening:類型為:Flatten
偏平的意思,如 flattens an input of shape
n * c * h * w
to a simple vector output of shapen * (c*h*w))。
Reshape:(重新調整維度),類型為:Reshape
Cocatenation(把多個輸入可以串聯起來):類型為:Concat
Slicing(可以對輸入進行切片)
類型為:Slice: 它的作用是把輸入按維度進行切片。具體看一個例子哈:
layer { name: "slicer_label" type: "Slice" bottom: "label" ## 假設label的維度是:N x 5 x 1 x 1 top: "label1" top: "label2" top: "label3" top: "label4" slice_param { axis: 1 # 指定維度,維度應該是從0開始的; slice_point: 1 # 將label[~][:1][~][~]賦給label1 slice_point: 2 # 將label[~][1:3][~][~]賦給label2 slice_point: 3 # 將label[~][3:4][~][~]賦給label3 slice_point: 4 # 將label[~][4:][~][~]賦給label3 } }
還有,切片的位置數,肯定比最后切出來的片數少一個哈。不用解釋的啦。
另外還有:Elementwise Operations(類型為Eltwise), Argmax(類型為ArgMax), Softmax(類型為Softmax),
Mean-Variance Normalization(類型為MVN)
由於以上內容我只用到了一少部分,所以大部分沒有詳細寫叱 ,隨着不斷的深入學習,我會再詳細補充的,