1. 首先,咱們先看一個完整的文件:lenet_train_test.prototxt算法
1 name: "LeNet" #整個網絡的名稱 2 layer { #數據層——訓練數據 3 name: "mnist" 4 type: "Data" 5 top: "data" 6 top: "label" 7 include { 8 phase: TRAIN 9 } 10 transform_param { 11 scale: 0.00390625 12 } 13 data_param { 14 source: "examples/mnist/mnist_train_lmdb" 15 batch_size: 64 16 backend: LMDB 17 } 18 } 19 20 #數據層-這裏表示測試數據 21 layer { 22 name: "mnist" 23 type: "Data" 24 top: "data" 25 top: "label" 26 include { 27 phase: TEST 28 } 29 transform_param { 30 scale: 0.00390625 31 } 32 data_param { 33 source: "examples/mnist/mnist_test_lmdb" 34 batch_size: 100 35 backend: LMDB 36 } 37 } 38 39 #第一層卷積層 40 layer { 41 name: "conv1" 42 type: "Convolution" 43 bottom: "data" 44 top: "conv1" 45 param { 46 lr_mult: 1 47 } 48 param { 49 lr_mult: 2 50 } 51 convolution_param { 52 num_output: 20 53 kernel_size: 5 54 stride: 1 55 weight_filler { 56 type: "xavier" 57 } 58 bias_filler { 59 type: "constant" 60 } 61 } 62 } 63 64 #第一層池化層 65 layer { 66 name: "pool1" 67 type: "Pooling" 68 bottom: "conv1" 69 top: "pool1" 70 pooling_param { 71 pool: MAX 72 kernel_size: 2 73 stride: 2 74 } 75 } 76 77 78 #第二層卷積 79 layer { 80 name: "conv2" 81 type: "Convolution" 82 bottom: "pool1" 83 top: "conv2" 84 param { 85 lr_mult: 1 86 } 87 param { 88 lr_mult: 2 89 } 90 convolution_param { 91 num_output: 50 92 kernel_size: 5 93 stride: 1 94 weight_filler { 95 type: "xavier" 96 } 97 bias_filler { 98 type: "constant" 99 } 100 } 101 } 102 103 #第二層池化 104 layer { 105 name: "pool2" 106 type: "Pooling" 107 bottom: "conv2" 108 top: "pool2" 109 pooling_param { 110 pool: MAX 111 kernel_size: 2 112 stride: 2 113 } 114 } 115 116 117 #第一層全鏈接層 118 layer { 119 name: "ip1" 120 type: "InnerProduct" 121 bottom: "pool2" 122 top: "ip1" 123 param { 124 lr_mult: 1 125 } 126 param { 127 lr_mult: 2 128 } 129 inner_product_param { 130 num_output: 500 131 weight_filler { 132 type: "xavier" 133 } 134 bias_filler { 135 type: "constant" 136 } 137 } 138 } 139 140 141 #第一層激活層 142 layer { 143 name: "relu1" 144 type: "ReLU" 145 bottom: "ip1" 146 top: "ip1" 147 } 148 149 150 #第二層全鏈接層 151 layer { 152 name: "ip2" 153 type: "InnerProduct" 154 bottom: "ip1" 155 top: "ip2" 156 param { 157 lr_mult: 1 158 } 159 param { 160 lr_mult: 2 161 } 162 inner_product_param { 163 num_output: 10 164 weight_filler { 165 type: "xavier" 166 } 167 bias_filler { 168 type: "constant" 169 } 170 } 171 } 172 173 174 #測試準確率層 175 layer { 176 name: "accuracy" 177 type: "Accuracy" 178 bottom: "ip2" 179 bottom: "label" 180 top: "accuracy" 181 include { 182 phase: TEST 183 } 184 } 185 186 187 #損失函數層 188 layer { 189 name: "loss" 190 type: "SoftmaxWithLoss" 191 bottom: "ip2" 192 bottom: "label" 193 top: "loss" 194 }
2. 數據層數據庫
1 layer { 2 name: "cifar" #cifar數據的名稱 3 type: "Data" 4 top: "data" #通常用bottom表示輸入,top表示輸出,多個top表明有多個輸出 5 top: "label" #數據輸出包含兩部分:圖像和標籤 6 include { 7 phase: TRAIN #訓練網絡分爲訓練階段和自測試階段,若是沒寫include則表示該層即在測試中,又在訓練中 8 } 9 transform_param { 10 mean_file: "examples/cifar10/mean.binaryproto" #用一個配置文件來進行均值的操做 11 transform_param { 12 scale: 0.00390625 #歸一化處理1/255,將圖像的像素值歸一化到0-1之間
#這裏表示數據加強
13 mirror: 1 # 1表示開啓鏡像,0表示關閉,也可用ture和false來表示 14 # 剪裁一個 227*227的圖塊,在訓練階段隨機剪裁,在測試階段從中間裁剪 15 crop_size: 227 16 } 17 } 18 data_param { 19 source: "examples/cifar10/cifar10_train_lmdb" #數據庫來源,也就是訓練數據集所在路徑 20 batch_size: 64 #每次批處理的個數 21 backend: LMDB #選用數據的類型名稱 22 } 23 } 24 25 ### 使用LMDB源 26 layer { 27 name: "mnist" 28 type: "Data" 29 top: "data" 30 top: "label" 31 include { 32 phase: TRAIN 33 } 34 transform_param { 35 scale: 0.00390625 36 } 37 data_param { 38 source: "examples/mnist/mnist_train_lmdb" 39 batch_size: 64 40 backend: LMDB 41 } 42 } 43 44 ###使用HDF5數據源 45 layer { 46 name: "data" 47 type: "HDF5Data" 48 top: "data" 49 top: "label" 50 hdf5_data_param { 51 source: "examples/hdf5_classification/data/train.txt" 52 batch_size: 10 53 } 54 } 55 56 ###數據直接來源與圖片 57 #/path/to/images/img3423.jpg 2 58 #/path/to/images/img3424.jpg 13 59 #/path/to/images/img3425.jpg 8 60 61 layer { 62 name: "data" 63 type: "ImageData" #類型 64 top: "data" 65 top: "label" 66 transform_param { 67 mirror: false 68 crop_size: 227 69 mean_file: "data/ilsvrc12/imagenet_mean.binaryproto" 70 } 71 image_data_param { 72 source: "examples/_temp/file_list.txt" 73 batch_size: 50 74 new_height: 256 #若是設置就對圖片進行resize操做 75 new_width: 256 76 }
3. 卷積層數組
1 layer { 2 name: "conv1" #卷積層名稱 3 type: "Convolution" #表示該層是卷積操做 4 bottom: "data" #bottom表示輸入,輸入的是「Data」,也就是數據層的輸出。 5 top: "conv1" #Top表示輸出,該層的輸出名稱就是「conv1」,它表示第一層卷積操做的輸出 6 param { 7 lr_mult: 1 #lr_mult: 學習率的係數,最終的學習率是這個數乘以solver.prototxt配置文件中的base_lr。若是有兩個lr_mult, 則第一個表示權值的學習率,第二個表示偏置項的學習率。通常偏置項的學習率是權值學習率的兩倍。 8 } 9 param { 10 lr_mult: 2 11 } 12 convolution_param { 13 num_output: 20 #卷積核(filter)的個數,也就是通道數(channels)。 14 kernel_size: 5 #卷積核的大小 15 stride: 1 #卷積核的步長,默認爲1 16 pad: 0 #擴充邊緣,默認爲0,不擴充 17 weight_filler { 18 type: "xavier" #權值初始化。 默認爲「constant",值全爲0,不少時候咱們用"xavier"算法來進行初始化,也能夠設置爲」gaussian" 19 } 20 bias_filler { 21 type: "constant" #偏置項的初始化。通常設置爲"constant",值全爲0 22 } 23 } 24 } 25 26 輸入:n*c0*w0*h0 27 輸出:n*c1*w1*h1 28 其中,c1就是參數中的num_output,生成的特徵圖個數 29 w1=(w0+2*pad-kernel_size)/stride+1; 30 h1=(h0+2*pad-kernel_size)/stride+1;
4. 池化層(pooling layer)網絡
1 layer { 2 name: "pool1" #池化層的名稱「pool1」 3 type: "Pooling" #表示這一層是池化操做 4 bottom: "conv1" #輸入來自於第一層的卷積「conv1」 5 top: "pool1" #輸出的就是第一層池化,其名稱是「pool1」 6 pooling_param { 7 pool: MAX #池化操做的方法,默認爲MAX-pooling。目前可用的方法有MAX-pooling, AVE-pooling 8 kernel_size: 3 #池化的核大小 9 stride: 2 #池化的步長,默認爲1。通常咱們設置爲2,即不重疊。 10 } 11 } 12 13 #pooling層的運算方法基本是和卷積層是同樣的。
5. 激活函數層ide
1 #在激活層中,對輸入數據進行激活操做,是逐元素進行運算的,在運算過程當中,沒有改變數據的大小,即輸入和輸出的數據大小是相等的。 2 3 ###Sigmoid 4 5 6 layer { 7 name: "test" 8 bottom: "conv" 9 top: "test" 10 type: "Sigmoid" 11 } 12 13 #ReLU是目前使用最多的激活函數,主要由於其收斂更快,而且能保持一樣效果。標準的ReLU函數爲max(x, 0),當x>0時,輸出x; 當x<=0時,輸出0 14 f(x)=max(x,0) 15 16 17 18 layer { 19 name: "relu1" #該層的名稱「reLu1」 20 type: "ReLU" #這一層操做的激活函數ReLu 21 bottom: "pool1" #這一層數據輸入是pool1 22 top: "pool1" 23 }
6. 全鏈接層(FC Layer)函數
1 #全鏈接層,輸出的是一個簡單向量 參數跟卷積層同樣 2 layer { 3 name: "ip1" #該層的名稱,叫作ip1,實際上是計算向量內積的操做,也就是咱們常說的全鏈接層 4 type: "InnerProduct" #這裏的類型表示操做的做用是計算先後向量的內積,即全鏈接 5 bottom: "pool2" #這一層的輸入來自於池化層「pool2」 6 top: "ip1" #輸出層的名字叫作「ip1」 7 param { 8 lr_mult: 1 #這裏表示權重學習率係數,還須要和基礎學習率相乘 9 } 10 param { 11 lr_mult: 2 #這裏表示偏置的學習率係數,也須要和基礎學習率相乘,它通常是權重學習率係數的2倍 12 } 13 inner_product_param { 14 num_output: 500 #這裏表示 全鏈接層的輸出爲500個神經元 15 weight_filler { 16 type: "xavier" #這裏是一種權重初始化的方法 17 } 18 bias_filler { #這裏表示了偏置的初始化方式 19 type: "constant" 20 } 21 } 22 } 23 #測試的時候輸入準確率 24 layer { 25 name: "accuracy" #該層的名稱是「accuracy」 26 type: "Accuracy" #這一層操做的做用就是計算測試集在模型上的準確率 27 bottom: "ip2" #這一層的輸入:第二個全鏈接層的輸出 28 bottom: "label" #這一層的第二個輸入:一個batch_size圖片的類別標籤 29 top: "accuracy" #該層的輸出的名稱是「accuracy」 30 include { 31 phase: TEST #這裏說明該層只在測試時起做用 32 } 33 }
7. soft-max loss層學習
1 #softmax-loss layer:輸出loss值 2 3 layer { 4 name: "loss" #該層的名稱是「loss」 5 type: "SoftmaxWithLoss" #這一層操做的做用是計算交叉熵損失 6 bottom: "ip1" #輸入是全鏈接層的輸出 7 bottom: "label" #輸入是類別標籤 8 top: "loss" #輸出的損失,其名稱是「loss」 9 } 10 #softmax layer: 輸出似然值 11 layers { 12 bottom: "cls3_fc" 13 top: "prob" 14 name: "prob" 15 type: 「Softmax" 16 }
7. reshape層測試
1 #在不改變數據的狀況下,改變輸入的維度 2 3 layer { 4 name: "reshape" 5 type: "Reshape" 6 bottom: "input" 7 top: "output" 8 reshape_param { 9 shape { 10 dim: 0 # copy the dimension from below 11 dim: 2 12 dim: 3 13 dim: -1 # infer it from the other dimensions 14 } 15 } 16 } 17 18 有一個可選的參數組shape, 用於指定blob數據的各維的值(blob是一個四維的數據:n*c*w*h)。 19 20 dim:0 表示維度不變,即輸入和輸出是相同的維度。 21 22 dim:2 或 dim:3 將原來的維度變成2或3 23 24 dim:-1 表示由系統自動計算維度。數據的總量不變,系統會根據blob數據的其它三維來自動計算當前維的維度值 。 25 26 假設原數據爲:32*3*28*28, 表示32張3通道的28*28的彩色圖片 27 shape { 28 dim: 0 29 dim: 0 30 dim: 14 31 dim: -1 32 } 33 輸出數據爲:32*3*14*56 34
35 #Dropout是一個防止過擬合的層,表示神經元隨機失活 36 #只須要設置一個dropout_ratio就能夠了。 37 layer { 38 name: "drop7" 39 type: "Dropout" 40 bottom: "fc7-conv" 41 top: "fc7-conv" 42 dropout_param { 43 dropout_ratio: 0.5 44 } 45 }
8. solver文件解析優化
1 #每每loss function是非凸的,沒有解析解,咱們須要經過優化方法來求解。 2 #caffe提供了六種優化算法來求解最優參數,在solver配置文件中,經過設置type類型來選擇。 3 4 Stochastic Gradient Descent (type: "SGD"), 5 AdaDelta (type: "AdaDelta"), 6 Adaptive Gradient (type: "AdaGrad"), 7 Adam (type: "Adam"), 8 Nesterov’s Accelerated Gradient (type: "Nesterov") 9 RMSprop (type: "RMSProp")
10 net: "examples/mnist/lenet_train_test.prototxt" #這裏表示訓練的網絡結構文件和測試文件的路徑 11 test_iter: 100 #這裏的表示測試的時候,batch_size= 測試樣本總量/test_iter 12 test_interval: 500 #測試間隔,表示每訓練500步,進行一次測試 13 base_lr: 0.01 #基礎的學習率 14 momentum: 0.9 #動量 15 type: SGD #優化方法選擇:隨機梯度降低 16 weight_decay: 0.0005 #權重衰減率 17 lr_policy: "inv" #學習率調整策略 18 gamma: 0.0001 19 power: 0.75 20 display: 100 #顯示,每訓練100步,在屏幕上顯示一次。 21 max_iter: 20000 #最大的迭代次數20000步,到達20000次自動中止 22 snapshot: 5000 #每隔5000步進行一次模型輸出 23 snapshot_prefix: "examples/mnist/lenet" #模型的保存位置 24 solver_mode: CPU #模型訓練在CPU上進行
#詳細解釋以下: 25 net: "examples/mnist/lenet_train_test.prototxt" #網絡位置 26 train_net: "examples/hdf5_classification/logreg_auto_train.prototxt" #也能夠分別設定train和test 27 test_net: "examples/hdf5_classification/logreg_auto_test.prototxt" 28 test_iter: 100 #迭代了多少個測試樣本呢? batch*test_iter 假設有5000個測試樣本,一次測試想跑遍這5000個則須要設置test_iter×batch=5000 29 30 test_interval: 500 #測試間隔。也就是每訓練500次,才進行一次測試。 31 32 33 base_lr: 0.01 #base_lr用於設置基礎學習率 34 35 lr_policy: "inv" #學習率調整的策略 36 37 - fixed: #保持base_lr不變. 38 - step: #若是設置爲step,則還須要設置一個stepsize, 返回 base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示當前的迭代次數 39 - exp: #返回base_lr * gamma ^ iter, iter爲當前迭代次數 40 - inv: #若是設置爲inv,還須要設置一個power, 返回base_lr * (1 + gamma * iter) ^ (- power) 41 - multistep: #若是設置爲multistep,則還須要設置一個stepvalue。這個參數和step很類似,step是均勻等間隔變化,而multistep則是根據stepvalue值變化 42 - poly: #學習率進行多項式偏差, 返回 base_lr (1 - iter/max_iter) ^ (power) 43 - sigmoid: #學習率進行sigmod衰減,返回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize)))) 44 45 momentum :0.9 #動量 46 47 display: 100 #每訓練100次,在屏幕上顯示一次。若是設置爲0,則不顯示。 48 49 max_iter: 20000 #最大迭代次數,2W次就中止了 50 51 snapshot: 5000 #快照。將訓練出來的model和solver狀態進行保存,snapshot用於設置訓練多少次後進行保存 52 snapshot_prefix: "examples/mnist/lenet" 53 54 solver_mode: CPU #設置運行模式。默認爲GPU,若是你沒有GPU,則須要改爲CPU,不然會出錯。