caffe 框架梳理(待续)
本文更多資料來源于羅韻北京深度學習資料和Ian Goodfellow的書籍《Deep Learning》
鏈接: http://pan.baidu.com/s/1jIRJ6mU
提取密碼:xehi
caffe:全稱Convolutional Architecture for Fast Feature Embedding,是一個計算CNN 相關算法的框架,用C++和Python實現的。
Caffe的優點與局限性
優點:
? 1. 第一個主流的工業級深度學習工具。
? 2. 專精于圖像處理
? 局限性:
? 1. 它有很多擴展,但是由于一些遺留的架構問題,不夠靈活且對遞歸網絡和語言建模的支持很差。
? 2. 基于層的網絡結構,其擴展性不好,對于新增加的層,需要
自己實現(forward, backward and gradient update)
Caffe目錄結構
? data/ 用于存放下載的訓練數據
? docs/ 幫助文檔
? examples/ 代碼樣例
? matlab/ MATLAB接文件
? python/ PYTHON接文件
? models/ 一些配置好的模型參數
? scripts/ 一些文檔和數據會用到的腳本核心代碼
? tools/ 保存的源碼是用于生成二進制處理程序的,caffe在訓練時實際是直接調用這些二進制文件
? include/ Caffe的實現代碼的頭文件
? src/ 實現Caffe的源文件
src/ 文件結構
gtest/ google test 一個用于測試的庫,你make runtest時看見的很多綠?色RUN OK就是它,這個與caffe的學習無關,不過是個有用的庫
caffe/ 關鍵代碼
? test/ 用gtest測試caffe的代碼
? util/ 數據轉換時用的一些代碼。caffe速度快,很大程度得益于內存設計上的優化(blob數據結構采用proto)和對卷積的優化(部分與im2col相
關)
? proto/ 即所謂的“Protobuf”,全稱“Google Protocol Buffer”,是一種數據存儲格式,幫助caffe提速
? layers/ 深度神經網絡中的基本結構就是一層層互不相同的網絡了,這個
文件夾下的源文件以及目前位置“src/caffe”中包含所有.cpp文件就是caffe的核心目錄下的核心代碼了。
Caffe核心代碼
? blob[.cpp .h] 基本的數據結構Blob類
? common[.cpp .h] 定義Caffe類
? internal_thread[.cpp .h] 使用boost::thread線程庫
? net[.cpp .h] 網絡結構類Net
? solver[.cpp .h] 優化方法類Solver
? data_transformer[.cpp .h] 輸入數據的基本操作類DataTransformer
? syncedmem[.cpp .h] 分配內存和釋放內存類CaffeMallocHost,用于同步GPU,CPU數據
? layer[.cpp .h] 層類Layer
? layers/ 此文件夾下面的代碼全部至少繼承了類Layer, 從layer_factory中注冊繼承
1. Caffe三級結構(Blobs,Layers,Nets)
? Blob:用于數據的保存、交換和操作,Caffe基礎存儲結構
? Layer:用于模型和計算的基礎
? Net:整合連接Layers
1.1 Blobs結構
? 在內存中表示4維數組,在caffe/blob.hpp中,維度包括
(width_,height_,channels_,num_)
? num_用于存儲數據或權值(data)和權值增量(diff)
? Blob 在caffe源碼 blob.hpp中是一個模板類。
? protected 的成員變量有:data_ , diff_ , shape_ , count_ , capacity_ ,其中data_ 和diff_ 是共享SyncedMemory 類(在syncedmem的源碼中定義)的智能指針,shape_是int型的vector,count_ 和capacity_ 是整型變量。
? 其成員函數主要有:Reshape 、ReshapeLike、SharedData、 Updata 等等
? blob.hpp 包含了caffe.pb.h ,說明caffe protobuf 會向blob 傳遞參數。
“caffe/proto/caffe.pb.h”
? caffe.pb.h是google protocol buffer根據caffe.proto自動生成的,可以到src/caffe/proto/caffe.proto里看下caffe里面用到的各個數據的定義,比如BlobProto,Datum,NetParameter等。使用這個protocol buffer看起來確實方便,一方面可以用文本文件定義結構化的數據類型,另一方面可以生成查詢效率更高、占空間更小的二進制文件。
“caffe/common.hpp”
? 主要singleton化Caffe類,并封裝了boost和CUDA隨機數生成的函數,提供了統一的接口。
“caffe/syncedmem.hpp”
? 定義了以下的接?口:
? inline void CaffeMallocHost(void** ptr, size_t size)
? inline void CaffeFreeHost(void* ptr)
? 主要是分配內存和釋放內存的。而class SyncedMemory定義了內存分配管理和CPU與GPU之間同步的函數。
“caffe/util/math_functions.hpp”
? 封裝了很多cblas矩陣運算
caffe.proto里面BlobProto的定義
message BlobProto {optional BlobShape shape = 7;repeated float data = 5 [packed = true];repeated float diff = 6 [packed = true];repeated double double_data = 8 [packed = true];repeated double double_diff = 9 [packed = true];// 4D dimensions -- deprecated. Use "shape" instead.optional int32 num = 1 [default = 0];optional int32 channels = 2 [default = 0];optional int32 height = 3 [default = 0];optional int32 width = 4 [default = 0]; }? 對于BlobProto,可以看到定義了四個optional的int32類型的名字(name)num、channels、height和width,optional意味著Blob可以有一個或者沒有這個參數,每個名字(name)后面都有一個數字,這個數字是其名字的一個標簽。這個數字就是用來在生成的二進制文件中搜索查詢的標簽。關于這個數字,1到15會花費1byte的編碼空間,16到2047花費2byte。所以?一般建議把那些頻繁使用的名字的標簽設為1到15之間的值。而后面的repeated意味著float類型的data和diff可以重復任意次,而加上[packed = true]是為了更高效的編碼。 ? 主要數據有兩個data和diff,用num、channels、height和width這四個維度來確定數據的具體位置,做一些數據查詢和Blob reshape的操作。Blobs封裝了運行時的數據信息,提供了CPU和GPU的同步。從數學上來說, Blob就是一個N維數組。它是caffe中的數據操作基本單位,就像matlab中以矩陣為基本操作對象一樣。只是矩陣是二維的,而Blob是N維的。N可以是2,3,4等等。
對于圖片數據來說,Blob可以表示為(N*C*H*W)這樣一個4D數組。其中N表示圖片的數量,C表示圖片的通道數,H和W分別表示圖片的高度和寬度。
當然,除了圖片數據,Blob也可以用于非圖片數據。比如傳統的多層感知機,就是比較簡單的全連接網絡,用2D的Blob,調用innerProduct層來計算就可以了。
在模型中設定的參數,也是用Blob來表示和運算。它的維度會根據參數的類型不同而不同。比如:在一個卷積層中,輸入一張3通道圖片,有96個卷積核,每個核大小為11*11,因此這個Blob是96*3*11*11. 而在一個全連接層中,假設輸入1024通道圖片,輸出1000個數據,則Blob為1000*1024。
1.2 Layer的五種類型
? Layer
? 所有的Pooling,Convolve,apply nonlinearities等操作都在這里實現。在Layer中input data用bottom表示,output data用top表示。每一層定義了三種操作setup(Layer初始化), forward(正向傳導,根據input計算output), backward(反向傳導計算,根據output計算input的梯度)。forward和backward有GPU和CPU兩個版本的實現。
層是網絡模型的組成要素和計算的基本單位。層的類型比較多,如Data,Convolution,Pooling,ReLU,Softmax-loss,Accuracy等,一個層的定義大至如下圖:
從bottom進行數據的輸入 ,計算后,通過top進行輸出。圖中的黃色多邊形表示輸入輸出的數據,藍色矩形表示層。
每一種類型的層都定義了三種關鍵的計算:setup,forward and backword
setup: 層的建立和初始化,以及在整個模型中的連接初始化。
forward: 從bottom得到輸入數據,進行計算,并將計算結果送到top,進行輸出。
backward: 從層的輸出端top得到數據的梯度,計算當前層的梯度,并將計算結果送到bottom,向前傳遞。
正向傳播的是數據,反向傳播的是誤差損失和梯度。
? 5種衍生Layers:
? data_layer
layer {name: "cifar"type: "Data"top: "data"top: "label"include {phase: TRAIN}transform_param {mean_file: "examples/cifar10/mean.binaryproto"}data_param {source: "examples/cifar10/cifar10_train_lmdb"batch_size: 100backend: LMDB} } name: 表示該層的名稱,可隨意取type: 層類型,如果是Data,表示數據來源于LevelDB或LMDB。根據數據的來源不同,數據層的類型也不同。一般都是采 用的LevelDB或LMDB數據,因此層類型設置為Data。top或bottom: 每一層用bottom來輸入數據,用top來輸出數據。如果只有top沒有bottom,則此層只有輸出,沒有輸入。反之亦然。如果有多個 top或多個bottom,表示有多個blobs數據的輸入和輸出。data 與 label: 在數據層中,至少有一個命名為data的top。如果有第二個top,一般命名為label。 這種(data,label)配對是分類模型所必需的。include: 一般訓練的時候和測試的時候,模型的層是不一樣的。該層(layer)是屬于訓練階段的層,還是屬于測試階段的層,需要用include來指定。如果沒有include參數,則表示該層既在訓練模型中,又在測試模型中。Transformations: 數據的預處理,可以將數據變換到定義的范圍內。如設置scale為0.00390625,實際上就是1/255, 即將輸入數據由0-255歸一化到0-1之間mirror # 1表示開啟鏡像,0表示關閉,也可用ture和false來表示 crop_size: 227剪裁一個 227*227的圖塊,在訓練階段隨機剪裁,在測試階段從中間裁剪
data_layer主要包含與數據有關的文件。在官方文檔中指出data是caffe數據的入口是網絡的最低層,并且支持多種格式,在這之中又有5種LayerType
? DATA 用于LevelDB或LMDB數據格式的輸入的類型,輸入參數有source,batch_size, (rand_skip), (backend)。后兩個是可選。
數據來自于數據庫(如LevelDB和LMDB)
層類型(layer type):Data
必須設置的參數:
source: 包含數據庫的目錄名稱,如examples/mnist/mnist_train_lmdb
batch_size: 每次處理的數據個數,如64
可選的參數:
rand_skip: 在開始的時候,路過某個數據的輸入。通常對異步的SGD很有用。
backend: 選擇是采用LevelDB還是LMDB, 默認是LevelDB.
? MEMORY_DATA 這種類型可以直接從內存讀取數據使用時需要調用MemoryDataLayer::Reset,輸入參數有batch_size, channels, height, width。
數據來自于內存層類型:MemoryData必須設置的參數:
batch_size:每一次處理的數據個數,比如2,channels:通道數
height:高度,width: 寬度
示例:
? HDF5_DATA HDF5數據格式輸入的類型,輸入參數有source, batch_size。
? HDF5_OUTPUT HDF5數據格式輸出的類型,輸入參數有file_name。
數據來自于HDF5
層類型:HDF5Data
必須設置的參數:
source: 讀取的文件名稱
batch_size: 每一次處理的數據個數
示例:
? IMAGE_DATA 圖像格式數據輸入的類型,輸入參數有source, batch_size,(rand_skip), (shuffle), (new_height), (new_width)。
數據來自于圖片
層類型:ImageData
必須設置的參數:
source: 一個文本文件的名字,每一行給定一個圖片文件的名稱和標簽(label)
batch_size: 每一次處理的數據個數,即圖片數
可選參數:
rand_skip: 在開始的時候,路過某個數據的輸入。通常對異步的SGD很有用。
shuffle: 隨機打亂順序,默認值為false
new_height,new_width: 如果設置,則將圖片進行resize
示例:
? 其實還有兩種WINDOW_DATA, DUMMY_DATA?用于測試和預留的接?口,不重要。
數據來源于Windows
層類型:WindowData
必須設置的參數:
source: 一個文本文件的名字
batch_size: 每一次處理的數據個數,即圖片數
示例:
? neuron_layer
同樣是數據的操作層,neuron_layer實現里大量激活函數,主要是元素級別的操作,具有相同的bottom,top size。
? Caffe中實現了大量激活函數GPU和CPU的都有很多。它們的父類都是
NeuronLayer
1、Sigmoid
對每個輸入數據,利用sigmoid函數執行操作。這種層設置比較簡單,沒有額外的參數。
層類型:Sigmoid
示例
layer {name: "encode1neuron"bottom: "encode1"top: "encode1neuron"type: "Sigmoid" }2、ReLU / Rectified-Linear and Leaky-ReLU
ReLU是目前使用最多的激活函數,主要因為其收斂更快,并且能保持同樣效果。
標準的ReLU函數為max(x, 0),當x>0時,輸出x; 當x<=0時,輸出0
f(x)=max(x,0)層類型:ReLU
可選參數:
negative_slope:默認為0. 對標準的ReLU函數進行變化,如果設置了這個值,那么數據為負數時,就不再設置為0,而是用原始數據乘以negative_slope
一般的參數設置格式如下(以ReLU為例)
layers { name: "relu1" type: RELU bottom: "conv1" top: "conv1" }RELU層支持in-place計算,這意味著bottom的輸出和輸入相同以避免內存的消耗。
3、TanH / Hyperbolic Tangent
利用雙曲正切函數對數據進行變換。
層類型:TanH
layer {name: "layer"bottom: "in"top: "out"type: "TanH" }4、Absolute Value
求每個輸入數據的絕對值。
f(x)=Abs(x)層類型:AbsVal
layer {name: "layer"bottom: "in"top: "out"type: "AbsVal" }5、Power
對每個輸入數據進行冪運算
f(x)= (shift + scale * x) ^ power層類型:Power
可選參數:
power: 默認為1
scale: 默認為1
shift: 默認為0
6、BNLL
binomial normal log likelihood的簡稱
f(x)=log(1 + exp(x))層類型:BNLL
layer {name: "layer"bottom: "in"top: "out"type: “BNLL” }? loss_layer
Loss層計算網絡誤差,loss_layer.hpp頭文件調用情況
? #include “caffe/blob.hpp" ? #include “caffe/common.hpp" ? #include “caffe/layer.hpp" ? #include “caffe/neuron_layers.hpp" ? #include “caffe/proto/caffe.pb.h"可以看見調用了neuron_layers.hpp,估計是需要調用里面的函數計算Loss,一般來說Loss放在最后一層。caffe實現了大量loss function,它們的父類都是LossLayer。
? template <typename Dtype> ? class LossLayer : public Layer<Dtype>softmax-loss
softmax-loss層和softmax層計算大致是相同的。softmax是一個分類器,計算的是類別的概率(Likelihood),是Logistic Regression 的一種推廣。Logistic Regression 只能用于二分類,而softmax可以用于多分類。
softmax與softmax-loss的區別:
softmax計算公式:
而softmax-loss計算公式
關于兩者的區別更加具體的介紹,可參考:softmax vs. softmax-loss
用戶可能最終目的就是得到各個類別的概率似然值,這個時候就只需要一個 Softmax層,而不一定要進行softmax-Loss 操作;或者是用戶有通過其他什么方式已經得到了某種概率似然值,然后要做最大似然估計,此時則只需要后面的 softmax-Loss 而不需要前面的 Softmax 操作。因此提供兩個不同的 Layer 結構比只提供一個合在一起的 Softmax-Loss Layer 要靈活許多。
不管是softmax layer還是softmax-loss layer,都是沒有參數的,只是層類型不同而也
layer {name: "loss"type: "SoftmaxWithLoss"bottom: "ip1"bottom: "label"top: "loss" }softmax layer: 輸出似然值
layers {bottom: "cls3_fc"top: "prob"name: "prob"type: “Softmax" }? common_layer
這一層主要進行的是vision_layer的連接
聲明了9個類型的common_layer,部分有GPU實現
Inner Product
全連接層,把輸入當作成一個向量,輸出也是一個簡單向量(把輸入數據blobs的width和height全變為1)。
輸入: n*c0*h*w
輸出: n*c1*1*1
全連接層實際上也是一種卷積層,只是它的卷積核大小和原數據大小一致。因此它的參數基本和卷積層的參數一樣。
層類型:InnerProduct
lr_mult: 學習率的系數,最終的學習率是這個數乘以solver.prototxt配置文件中的base_lr。如果有兩個lr_mult, 則第一個表示權值的學習率,第二個表示偏置項的學習率。一般偏置項的學習率是權值學習率的兩倍。
必須設置的參數:
num_output: 過濾器(filfter)的個數
其它參數:
weight_filler: 權值初始化。 默認為“constant",值全為0,很多時候我們用"xavier"算法來進行初始化,也可以設置為”gaussian"bias_filler: 偏置項的初始化。一般設置為"constant",值全為0。bias_term: 是否開啟偏置項,默認為true, 開啟
layer {name: "ip1"type: "InnerProduct"bottom: "pool2"top: "ip1"param {lr_mult: 1}param {lr_mult: 2}inner_product_param {num_output: 500weight_filler {type: "xavier"}bias_filler {type: "constant"}} }accuracy
輸出分類(預測)精確度,只有test階段才有,因此需要加入include參數。
層類型:Accuracy
reshape
在不改變數據的情況下,改變輸入的維度。
層類型:Reshape
示例如下
有一個可選的參數組shape, 用于指定blob數據的各維的值(blob是一個四維的數據:n*c*w*h)。
dim:0 表示維度不變,即輸入和輸出是相同的維度。
dim:2 或 dim:3 將原來的維度變成2或3
dim:-1 表示由系統自動計算維度。數據的總量不變,系統會根據blob數據的其它三維來自動計算當前維的維度值 。
假設原數據為:64*3*28*28, 表示64張3通道的28*28的彩色圖片
經過reshape變換:
輸出數據為:64*3*14*56
Dropout
Dropout是一個防止過擬合的trick。可以隨機讓網絡某些隱含層節點的權重不工作。
先看例子:
layer {name: "drop7"type: "Dropout"bottom: "fc7-conv"top: "fc7-conv"dropout_param {dropout_ratio: 0.5} }只需要設置一個dropout_ratio即可。
? vision_layer
主要是實現Convolution和Pooling操作, 主要有以下幾個類:
? ConvolutionLayer 最常用的卷積操作
更多細節可見卷積步長
卷積中的卷
示例
layer {name: "conv1"type: "Convolution"bottom: "data"top: "conv1"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 20kernel_size: 5stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}} }? Im2colLayer 與MATLAB里面的im2col類似,即image-tocolumn
transformation,轉換后方便卷積計算
? LRNLayer 全稱local response normalization layer,在Hinton論文中有詳細介紹ImageNet Classification with Deep Convolutional Neural Networks 。
此層是對一個輸入的局部區域進行歸一化,達到“側抑制”的效果。 參數:全部為可選,沒有必須local_size: 默認為5。如果是跨通道LRN,則表示求和的通道數;如果是在通道內LRN,則表示求和的正方形區域長度。alpha: 默認為1,歸一化公式中的參數。beta: 默認為5,歸一化公式中的參數。norm_region: 默認為ACROSS_CHANNELS。有兩個選擇,ACROSS_CHANNELS表示在相鄰的通道間求和歸一化。WITHIN_CHANNEL表示在一個通道內部特定的區域內進行求和歸一化。與前面的local_size參數對應。歸一化公式:對于每一個輸入, 去除以 ,得到歸一化后的輸出
layers {name: "norm1"type: LRNbottom: "pool1"top: "norm1"lrn_param {local_size: 5alpha: 0.0001beta: 0.75} }? PoolingLayer Pooling操作
池化層,為了減少運算量和數據維度而設置的一種層。 層類型:Pooling 必須設置的參數:kernel_size: 池化的核大小。也可以用kernel_h和kernel_w分別設定。 其它參數:pool: 池化方法,默認為MAX。目前可用的方法有MAX, AVE, 或STOCHASTICpad: 和卷積層的pad的一樣,進行邊緣擴充。默認為0stride: 池化的步長,默認為1。一般我們設置為2,即不重疊。也可以用stride_h和stride_w來設置。示例
layer {name: "pool1"type: "Pooling"bottom: "conv1"top: "pool1"pooling_param {pool: MAXkernel_size: 3stride: 2} }pooling層的運算方法基本是和卷積層是一樣的。輸入:n*c*w0*h0 輸出:n*c*w1*h1 和卷積層的區別就是其中的c保持不變w1=floor((w0+2*pad-kernel_size)/stride)+1;向下取整h1=floor((h0+2*pad-kernel_size)/stride)+1;向下取整 如果設置stride為2,前后兩次卷積部分不重疊。100*100的特征圖池化后,變成50*50. 由pad, kernel_size和stride三者共同決定。
更多細節可見卷積步長
池化層
1.3 Nets結構
Net由一系列的Layer組成(無回路有向圖DAG),Layer之間的連接由一個文本文件描述。模型初始化Net::Init()會產生blob和layer并調用Layer::SetUp。在此過程中Net會報告初始化進程。這里的初始化與設備無關,在初始化之后通過Caffe::set_mode()設置Caffe::mode()來選擇運行
平臺CPU或GPU,結果是相同的。
Net
就像搭積木一樣,一個net由多個layer組合而成。
現給出 一個簡單的2層神經網絡的模型定義( 加上loss 層就變成三層了),先給出這個網絡的拓撲。
第一層:name為mnist, type為Data,沒有輸入(bottom),只有兩個輸出(top),一個為data,一個為label
第二層:name為ip,type為InnerProduct, 輸入數據data, 輸出數據ip
第三層:name為loss, type為SoftmaxWithLoss,有兩個輸入,一個為ip,一個為label,有一個輸出loss,沒有畫出來。
對應的配置文件prototxt就可以這樣寫:
第一行將這個模型取名為LogReg, 然后是三個layer的定義,參數都比較簡單,只列出必須的參數。
卷積神經網絡示例
優化求解過程Solver
solver算是caffe的核心的核心,它協調著整個模型的運作。caffe程序運行必帶的一個參數就是solver配置文件。運行代碼一般為
./build/tools/caffe train --solver=examples/myfile/solver.prototxt -gpu all &> examples/myfile/output/output.log #或者 ./build/tools/caffe train -solver examples/myfile/solver.prototxt -gpu all &> examples/myfile/output/output.log在Deep Learning中,往往loss function是非凸的,沒有解析解,我們需要通過優化方法來求解。
? 求解器Solver是什么?
? Caffe的重中之重(核心)——Solver
? 負責對模型優化,讓損失函數(loss function)達到全局最小。
? solver的主要作用就是交替調用前向(forward)算法和后向(backward)算法來更新參數,實際上就是一種迭代的優化算法。
優化算法
caffe提供了六種優化算法來求解最優參數,在solver配置文件中,通過設置type類型來選擇。
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. 設計好需要優化的對象,以及用于學習的訓練網絡和用于評估的測試網絡。(通過調用另外一個配置文件prototxt來進行)2. 通過forward和backward迭代的進行優化來跟新參數。3. 定期的評價測試網絡。 (可設定多少次訓練后,進行一次測試)4. 在優化過程中顯示模型和solver的狀態在每一次的迭代過程中,solver做了這幾步工作:
? 1、調用forward算法來計算最終的輸出值,以及對應的loss ? 2、調用backward算法來計算每層的梯度 ? 3、根據選用的slover方法,利用梯度進行參數更新 ? 4、記錄并保存每次迭代的學習率、快照,以及對應的狀態。示例
net: "examples/mnist/lenet_train_test.prototxt" test_iter: 100 test_interval: 500 base_lr: 0.01 momentum: 0.9 type: SGD weight_decay: 0.0005 lr_policy: "inv" gamma: 0.0001 power: 0.75 display: 100 max_iter: 20000 snapshot: 5000 snapshot_prefix: "examples/mnist/lenet" solver_mode: CPU設置深度網絡模型。每一個模型就是一個net,需要在一個專門的配置文件中對net進行配置,每個net由許多的layer所組成。注意的是:文件的路徑要從caffe的根目錄開始,其它的所有配置都是這樣。
net: "examples/mnist/lenet_train_test.prototxt"也可用train_net和test_net來對訓練模型和測試模型分別設定。例如:
train_net:"examples/hdf5_classification/logreg_auto_train.prototxt" test_net: "examples/hdf5_classification/logreg_auto_test.prototxt"test_iter要與test layer中的batch_size結合起來理解。mnist數據中測試樣本總數為10000,一次性執行全部數據效率很低,因此我們將測試數據分成幾個批次來執行,每個批次的數量就是batch_size。假設我們設置batch_size為100,則需要迭代100次才能將10000個數據全部執行完。因此test_iter設置為100。執行完一次全部數據,稱之為一個epoch
test_iter: 100測試間隔。也就是每訓練500次,才進行一次測試。
test_interval: 500下面四行用于學習率的設置。只要是梯度下降法來求解優化,都會有一個學習率,也叫步長。base_lr用于設置基礎學習率,在迭代的過程中,可以對基礎學習率進行調整。怎么樣進行調整,就是調整的策略,由lr_policy來設置。
base_lr: 0.01 lr_policy: "inv" gamma: 0.0001 power: 0.75lr_policy可以設置為下面這些值,相應的學習率的計算為:
- fixed: 保持base_lr不變. - step: 如果設置為step,則還需要設置一個stepsize, 返回 base_lr * gamma ^ (floor(iter / stepsize)),其中iter表示當前的迭代次數 - exp: 返回base_lr * gamma ^ iter, iter為當前迭代次數 - inv: 如果設置為inv,還需要設置一個power, 返回base_lr * (1 + gamma * iter) ^ (- power) - multistep: 如果設置為multistep,則還需要設置一個stepvalue。這個參數和step很相似,step是均勻等間隔變化,而multistep則是根據 stepvalue值變化 - poly: 學習率進行多項式誤差, 返回 base_lr (1 - iter/max_iter) ^ (power) - sigmoid: 學習率進行sigmod衰減,返回 base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))multistep示例:
base_lr: 0.01 momentum: 0.9 weight_decay: 0.0005 # The learning rate policy lr_policy: "multistep" gamma: 0.9 stepvalue: 5000 stepvalue: 7000 stepvalue: 8000 stepvalue: 9000 stepvalue: 9500momentum上一次梯度更新的權重
momentum :0.9優化算法選擇。這一行可以省掉,因為默認值就是SGD,總共有六種方法可選擇。
type: SGD權重衰減項,防止過擬合的一個參數。
weight_decay: 0.0005每訓練100次,在屏幕上顯示一次。如果設置為0,則不顯示。
display: 100最大迭代次數。這個數設置太小,會導致沒有收斂,精確度很低。設置太大,會導致震蕩,浪費時間。
max_iter: 20000快照。將訓練出來的model和solver狀態進行保存,snapshot用于設置訓練多少次后進行保存,默認為0,不保存。snapshot_prefix設置保存路徑。
還可以設置snapshot_diff,是否保存梯度值,默認為false,不保存。
也可以設置snapshot_format,保存的類型。有兩種選擇:HDF5 和BINARYPROTO ,默認為BINARYPROTO
設置運行模式。默認為GPU,如果你沒有GPU,則需要改成CPU,否則會出錯。
solver_mode: CPUsolver優化方法
caffe的六種優化方法:
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就是用來使loss最小化的優化方法。對于一個數據集D,需要優化的目標函數是整個數據集中所有數據loss的平均值。
其中,fW(x(i)) 計算的是數據 x(i) 上的 loss, 先將每個單獨的樣本 x 的 loss 求出來,然后求和,最后求均值。 r(W) 是正則項(weight_decay),為了減弱過擬合現象。
如果采用這種Loss 函數,迭代一次需要計算整個數據集,在數據集非常大的這情況下,這種方法的效率很低,這個也是我們熟知的梯度下降采用的方法。
在實際中,通過將整個數據集分成幾批(batches), 每一批就是一個mini-batch,其數量(batch_size)為N<<|D|,此時的loss 函數為
有了loss函數后,就可以迭代的求解loss和梯度來優化這個問題。在神經網絡中,用forward pass來求解loss,用backward pass來求解梯度。
在caffe中,默認采用的Stochastic Gradient Descent(SGD)進行優化求解。后面幾種方法也是基于梯度的優化方法(like SGD),因此本文只介紹一下SGD。
1、Stochastic gradient descent(SGD)
隨機梯度下降(Stochastic gradient descent)是在梯度下降法(gradient descent)的基礎上發展起來的,梯度下降法也叫最速下降法。SGD在通過負梯度和上一次的權重更新值Vt的線性組合來更新W,迭代公式如下:
其中, α 是負梯度的學習率(base_lr),μ 是上一次梯度值的權重(momentum),用來加權之前梯度方向對現在梯度下降方向的影響。這兩個參數需要通過tuning來得到最好的結果,一般是根據經驗設定的。
在深度學習中使用SGD,比較好的初始化參數的策略是把學習率設為0.01左右(base_lr: 0.01),在訓練的過程中,如果loss開始出現穩定水平時,對學習率乘以一個常數因子(gamma),這樣的過程重復多次。對于momentum,一般取值在0.5--0.99之間。通常設為0.9,momentum可以讓使用SGD的深度學習方法更加穩定以及快速。關于更多的momentum,請參看Hinton的《A Practical Guide to Training Restricted Boltzmann Machines》。
示例
base_lr: 0.01 lr_policy: "step" gamma: 0.1 stepsize: 1000 max_iter: 3500 momentum: 0.9lr_policy設置為step,則學習率的變化規則為 base_lr * gamma ^ (floor(iter / stepsize))
lr_policy設置為step,則學習率的變化規則為 base_lr * gamma ^ (floor(iter / stepsize))
即前1000次迭代,學習率為0.01; 第1001-2000次迭代,學習率為0.001; 第2001-3000次迭代,學習率為0.00001,第3001-3500次迭代,學習率為10-5
上面的設置只能作為一種指導,它們不能保證在任何情況下都能得到最佳的結果,有時候這種方法甚至不work。如果學習的時候出現diverge(比如,你一開始就發現非常大或者NaN或者inf的loss值或者輸出),此時你需要降低base_lr的值(比如,0.001),然后重新訓練,這樣的過程重復幾次直到你找到可以work的base_lr。
2、AdaDelta
AdaDelta是一種”魯棒的學習率方法“,是基于梯度的優化方法(like SGD)。
具體的介紹文獻:
M. Zeiler ADADELTA: AN ADAPTIVE LEARNING RATE METHOD. arXiv preprint, 2012.
示例
net: "examples/mnist/lenet_train_test.prototxt" test_iter: 100 test_interval: 500 base_lr: 1.0 lr_policy: "fixed" momentum: 0.95 weight_decay: 0.0005 display: 100 max_iter: 10000 snapshot: 5000 snapshot_prefix: "examples/mnist/lenet_adadelta" solver_mode: GPU type: "AdaDelta" delta: 1e-6從最后兩行可看出,設置solver type為Adadelta時,需要設置delta的值。
3、AdaGrad
自適應梯度(adaptive gradient)是基于梯度的優化方法(like SGD)
自適應梯度(adaptive gradient)是基于梯度的優化方法(like SGD)
具體的介紹文獻:
Duchi, E. Hazan, and Y. Singer. Adaptive Subgradient Methods for Online Learning and Stochastic Optimization. The Journal of Machine Learning Research, 2011.
示例
net: "examples/mnist/mnist_autoencoder.prototxt" test_state: { stage: 'test-on-train' } test_iter: 500 test_state: { stage: 'test-on-test' } test_iter: 100 test_interval: 500 test_compute_loss: true base_lr: 0.01 lr_policy: "fixed" display: 100 max_iter: 65000 weight_decay: 0.0005 snapshot: 10000 snapshot_prefix: "examples/mnist/mnist_autoencoder_adagrad_train" # solver mode: CPU or GPU solver_mode: GPU type: "AdaGrad"4、Adam
是一種基于梯度的優化方法(like SGD)。
具體的介紹文獻:
D. Kingma, J. Ba. Adam: A Method for Stochastic Optimization. International Conference for Learning Representations, 2015.
5、NAG
Nesterov 的加速梯度法(Nesterov’s accelerated gradient)作為凸優化中最理想的方法,其收斂速度非??臁?/p>
具體的介紹文獻:
I. Sutskever, J. Martens, G. Dahl, and G. Hinton. On the Importance of Initialization and Momentum in Deep Learning. Proceedings of the 30th International Conference on Machine Learning, 2013.
示例
net: "examples/mnist/mnist_autoencoder.prototxt" test_state: { stage: 'test-on-train' } test_iter: 500 test_state: { stage: 'test-on-test' } test_iter: 100 test_interval: 500 test_compute_loss: true base_lr: 0.01 lr_policy: "step" gamma: 0.1 stepsize: 10000 display: 100 max_iter: 65000 weight_decay: 0.0005 snapshot: 10000 snapshot_prefix: "examples/mnist/mnist_autoencoder_nesterov_train" momentum: 0.95 # solver mode: CPU or GPU solver_mode: GPU type: "Nesterov"6、RMSprop
RMSprop是Tieleman在一次 Coursera課程演講中提出來的,也是一種基于梯度的優化方法(like SGD)
具體的介紹文獻:
T. Tieleman, and G. Hinton. RMSProp: Divide the gradient by a running average of its recent magnitude. COURSERA: Neural Networks for Machine Learning.Technical report, 2012.
示例
net: "examples/mnist/lenet_train_test.prototxt" test_iter: 100 test_interval: 500 base_lr: 1.0 lr_policy: "fixed" momentum: 0.95 weight_decay: 0.0005 display: 100 max_iter: 10000 snapshot: 5000 snapshot_prefix: "examples/mnist/lenet_adadelta" solver_mode: GPU type: "RMSProp" rms_decay: 0.98最后兩行,需要設置rms_decay值。
2. Caffe 的 I/O 模塊
將圖片數據轉化為LMDB數據
■ 第一步:創建圖片文件列表清單,一般為一個txt文件,一行一張圖片
■ 第二步:使用Caffe工具命令
convert_imageset [FLAGS] [ROOTFOLDER/] [LISTFILE] [DB_NAME]
需要帶四個參數:
FLAGS: 圖片參數組
-gray: 是否以灰度圖的方式打開圖片。程序調用opencv庫中的imread()函數來打開圖片,默認為false
-shuffle: 是否隨機打亂圖片順序。默認為false
-backend:需要轉換成的db文件格式,可選為leveldb或lmdb,默認為lmdb
-resize_width/resize_height: 改變圖片的大小。在運行中,要求所有圖片的尺寸一致,因此需要改變圖片大小。 程序調用
opencv庫的resize()函數來對圖片放大縮小,默認為0,不改變
-check_size: 檢查所有的數據是否有相同的尺寸。默認為false,不檢查
-encoded: 是否將原圖片編碼放入最終的數據中,默認為false
示例文件及代碼見首行中的百度云共享。
#Image to txt:at the path of "scripts" ls IO2LMDB/blue | sed "s:^:blue/:" | sed "s:$: 0:" >> data.txt ls IO2LMDB/red | sed "s:^:red/:" | sed "s:$: 1:" >> data.txt#txt to LMDB : at the path of "OI2LMDB" convert_imageset -shuffle:'true' ./data.txt db_train_lmdb對Layer做參數配置(Data Layer參數配置為例)
layer {name: "cifar" type: "Data"top: "data"top: "label"include {phase: TRAIN}transform_param {mean_file: "examples/cifar10/mean.binaryproto"}data_param {source: "examples/cifar10/cifar10_train_lmdb"batch_size: 100backend: LMDB} }name: 表示該層的名稱,可隨意取。
type: 層類型,如果是Data,表示數據來源于LevelDB或LMDB。根
據數據的來源不同,數據層的類型也不同(后面會詳細闡述)。一
般在練習的時候,我們都是采用的LevelDB或LMDB數據,因此層
類型設置為Data。
top或bottom: 每一層用bottom來輸入數據,用top來輸出數據。如
果只有top沒有bottom,則此層只有輸出,沒有輸?入。反之亦然。如
果有多個 top或多個bottom,表示有多個blobs數據的輸入和輸出。
data 與 label: 在數據層中,至少有一個命名為data的top。如果有
第二個top,一般命名為label。 這種(data,label)配對是分類模型所
必需的。
include: 一般訓練的時候和測試的時候,模型的層是不一樣的。該
層(layer)是屬于訓練階段的層,還是屬于測試階段的層,需要用
include來指定。如果沒有include參數,則表示該層既在訓練模型
中,又在測試模型中。
Transformations: 數據的預處理,可以將數據變換到定義的范圍
內。如設置scale為0.00390625,實際上就是1/255, 即將輸入數據由0-255歸一化到0-1之間。
所有數據預處理都在這里設置:
通常數據的預處理(如減去均值, 放大縮小, 裁剪和鏡像等),Caffe使用OpenCV做處理
layer {name: "cifar"type: "Data"top: "data"top: "label"include {phase: TEST}transform_param {mean_file: "examples/cifar10/mean.binaryproto"#用一個配置?文件來進行均值操作 mirror: 1 # 1表示開啟鏡像,0表示關閉,也可用ture和false來表示 crop_size: 227 # 剪裁一個227*227的圖塊,在訓練階段隨機剪裁,在測試階段從中間裁剪}data_param {source: "examples/cifar10/cifar10_test_lmdb"batch_size: 100backend: LMDB} }3. Caffe 中五種層的實現和參數配置
3.1 卷積層參數配置
layer { name: "conv2" type: "Convolution" bottom: "pool1" top: "conv2" param { lr_mult: 1 #學習率1,和權值更新相關 } param { lr_mult: 2 #學習率2,和權值更新相關 } convolution_param { num_output: 50 # 50個輸出的map kernel_size: 5 #卷積核大小為5*5 stride: 1 #卷積步?長為1 weight_filler { #權值初始化方式 type: “xavier" #默認為“constant",值全為0,很多時候我們也可以?用"xavier"或者”gaussian"來進行初始化 } bias_filler { #偏置值的初始化?方式 type: “constant"#該參數的值和weight_filler類似, ?一般設置為"constant",值全為0 } } }3.2 池化層參數配置
layer { name: "pool1" type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { pool: MAX #Pool為池化方式,默認值為MAX,可以選擇的參數有MAX、AVE、STOCHASTIC kernel_size: 2 #池化區域的大小,也可以用kernel_h和kernel_w分別設 置長和寬 stride: 2 #步長,即每次池化區域左右或上下移動的距離,一般和kernel_size相同,即為不重疊池化。也可以也可以小于kernel_size,即為重疊池化,Alexnet中就用到了重疊池化的方法 } }3.3 全連接層參數配置
#參數和卷積層表達?一樣 layer { name: "ip1" type: "InnerProduct" bottom: "pool2" top: "ip1" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 500 weight_filler { type: "xavier" } bias_filler { type: "constant" } } }3.4 激活函數層參數配置
激活函數作用:激活函數是用來引入非線性因素的。
激活函數一般具有以下性質:
■ 非線性: 線性模型的不足我們前邊已經提到。
■ 處處可導:反向傳播時需要計算激活函數的偏導數,所以要求激活函數除個別點外,處處可導。
■ 單調性:當激活函數是單調的時候,單層網絡能夠保證是凸函數。
■ 輸出值的范圍: 當激活函數輸出值是有限的時候,基于梯度的優化方法會更加穩定,因為特征的表示受有限權值的影響更顯著
Type為該層類型,可取值分別為:
(1)ReLU:表示我們使用relu激活函數,relu層支持in-place計算,這意味
著該層的輸入和輸出共享一塊內存,以避免內存的消耗。
(2)Sigmoid:代表使用sigmoid函數;
(3) TanH:代表使用tanh函數;
(4) AbsVal:計算每個輸入的絕對值f(x)=Abs(x)
(5)power對每個輸入數據進行冪運算
f(x)= (shift + scale * x) ^
power
層類型:Power
可選參數:
power: 默認為1
scale: 默認為1
shift:默認值為0
3.5 softmax層
#可以計算給出每個樣本 對應的損失函數值 layer { name: "loss" type: "SoftmaxWithLoss" bottom: "ip2" bottom: "label" top: "loss" }#輸出為每個類別的概率值 layers { name: "prob" type: “Softmax" bottom: " ip2" top: "prob" }4. Caffe的可視化
4.1 網絡結構可視化和特征可視化
可參考
http://blog.csdn.net/jiandanjinxin/article/details/50686461
http://blog.csdn.net/jiandanjinxin/article/details/50410290
4.2 可視化loss和accurary 曲線
cd caffer-master sh data/mnist/get_mnist.sh sh examples/mnist/create_mnist.sh sh examples/mnist/train_lenet.sh &> output.log plot_training_log.py.example -h #可查看用法 ./tools/extra/plot_training_log.py.example 0 testaccuracyvsiters.png output.log ./tools/extra/plot_training_log.py.example 2 testaccuracyvsiters.png output.log使用訓練好的模型
均值文件mean file
■ 將所有訓練樣本的均值保存為文件
■ 圖片減去均值后,再進?行訓練和測試,會提高速度和精度
■ 運行方法:(使用Caffe?工具)
compute_image_mean [train_lmdb] [mean.binaryproto]
fine-turn微調網絡
■ 1. 準備新數據的數據庫(如果需要用mean file,還要準備對應的新的mean file), 具體方法和圖片轉換lmdb方式一樣。
■ 2. 調整網絡層參數:
■ 將來訓練的網絡配置prototxt中的數據層source換成新數據的數據庫。
■ 調整學習率,因為最后一層是重新學習,因此需要有更快的學習速率相比較其他層,因此我們將,weight和bias的學習速率加快。
■ 3. 修改solver參數
■ 原來的數據是從原始數據開始訓練的,因此一般來說學習速率、步長、迭代次數都比較大,fine turning微調時,因為數據量可能減少了,所以一般來說,test_iter,base_lr,stepsize都要變小一點,其他的策略可以保持不
變。
■ 4. 重新訓練時,要指定之前的權值文件:
■ # caffe train –solver [新的solver文件] –weights [舊的caffemodel]
5. 深度學習模型訓練 Tricks
更多trick可見書籍《Neural Networks: Tricks of the Trade》
5.1 數據準備與擴增
1.1 數據準備:
一般數據集可能不會給出驗證集,所以自?己會從給的訓練集中按照一定比例(9:1)分離出驗證集。
1.2 數據的擴增
因為深度網絡需要在大規模的訓練圖像上來滿足性能,所以當原始圖像中的訓練數據集規模不夠多時,較好的辦法是擴增數據來提升模型性能。換言之,數據擴增對于訓練深度網絡來說是必須的。
常用的方法:
1. 沿著x軸將圖片左右翻轉
2. 隨機的剪切、縮放、旋轉
3. 顏色抖動
4. 提高圖像中像素的飽和度和值(即 HSV顏色空間的 S 和 V 成分)到 0.250.25 和44 之間(在一個樣本圖像內要保證各個像素該值是一樣的),再在圖像上加上一個范圍在 [?0.1,0.1][?0.1,0.1] 之間的值給 H( hue ,即 HSV 中的色調)這個成分。
5. 用pca來改變RGB的強度值,產生分別對應的特征值和特征向量,然后用均值為0方差為0.1的隨機數與特征值和特征向量相乘得到新的數據。(《ImageNet Classification with Deep Convolutional Neural Networks》)
5.2 圖像預處理
常見的是減均值、除方差,還有變化到-1?1,主要針對不同尺度的特征,進行尺度變換normaliz。
常用的預處理方法:
1. 去均值和規范化
通常作為第一步且較簡單的一種方式是去均值(zero-centered ,通俗地說:讓每個樣本都減去整體樣本的均值,使整體樣本的新均值為 0),并規范化(normalize)它們。
另一種在預處理用于規范化(normalize)數據的方法是將每一個維度的最大最小值分別限定為1 和 ?1 。
在此過程中,數據先經過去均值,然后計算出(能刻畫數據內部相關結果的)協方差矩陣:
>>> X -= np.mean(X, axis = 0) # 去均值 >>> cov = np.dot(X.T, X) / X.shape[0] # 計算協?方差矩陣之后對數據去相關,?方法是將(剛剛去均值后的)原始數據投影到特征基(eigenbasis )上:
>>> U,S,V = np.linalg.svd(cov) # 對數據的協?方差矩陣計算 SVD 分解 >>> Xrot = np.dot(X, U) # 對數據去相關最后一步是白化,它對去相關后的數據在每個維度上的特征值做尺度規范化處理:
>>> Xwhite = Xrot / np.sqrt(S + 1e-5) # 除以特征值(其實是奇異值的開平方根)5.3 參數初始化
■ 訓練網絡前對參數做初始化。
■ 常用的初始化方法:
1. 全零初始化 —> 錯誤
2. 小隨機數初始化
是一種接近 0 但不是 0的權重初始化方法。
做法是初始化權重為接近 0 的隨機小數,因為很接近 0 但不相等,這也被稱為“對稱破缺”( symmetry breaking )。
在訓練中計算出的更新是不同的,并在之后整合自己的“貢獻”作為整個
網絡的不同部分。權重初始化的過程多少有點像 weights0.001×N(0,1),其中 N(0,1)N表示均值為 0 ,標準差為 1 的高斯分布。當然也可以使用服從均勻分布的隨機小數,但在二者在實際中的性能表現上只有很微弱的差別。
先前通過校準神經元上的方差來初始化參數并未考慮使用 ReLUs這樣的激活函數。最近一篇論?文《Surpassing Human-Level Performance on ImageNet Classification》討論了如何為 ReLUs這樣的激活函數做參數初始化,從而使網絡中神經元的方差為 2.0/n,初始化?方式如下:
5.4 卷積參數的Tricks
■ 1. 圖片輸入是2的冪次方,例如32、64、96、224等。
■ 2. 卷積核大小是3*3或者5*5。
■ 3. 輸入圖片上下左右需要用0補充,即padding,且假如卷積核大小是5
那么padding就是2(圖?片左右上下都補充2),卷積核大小是3padding
大小就是1。
5.5 池化層參數初始化Tricks
■ 1. poolin層也能防?止過擬合,使用overlapped pooling,即用來池化
的數據有重疊,但是pooling的?大小不要超過3,常用的池化是2X2。
■ 2. max pooling比avg pooling效果會好一些。
5.6 學習率
■ 1. 0.1是學習率的常用值
■ 2. 在實際中,如果在驗證集上看不到性能的提升(如損失函數值下降或者準確率上升),那就可以對當前的學習率除以 2(或 5 )看看效果并循環這一過程,或許能給你一個驚喜。
5.7 正則化:防止過擬合
過擬合,就是擬合函數需要顧忌每一個點,最終形成的擬合函數波動很大。在某些很小的區間里,函數值的變化很劇烈。這就意味著函數在某些小區間里的導數值(絕對值)非常大,由于自變量值可大可小,所以只有系數足夠大,才能保證導數值很大。而正則化是通過約束參數的范數使其不要太大,所以可以在一定程度上減少過擬合情況。
常用防止過擬合方式:
1. L2正則化
2. L1正則化
3. 最大模限制
4. Dropout
Dropout 是一個超級有效、簡單且是前陣子由 Srivastava 等人提出
《Dropout: A Simple Way to Prevent Neural Networks from
Overfitting》的,它是其它正則方法(如 L1 、 L2 、 最大模限制 )的
補充。在訓練中, dropout 可理解為對整個神經網絡進行抽樣(出的
網絡),并基于輸入數據僅僅更新抽樣網絡的參數。(因為這些抽樣
得到的網絡是共享參數的,所以這些抽樣出的網絡的權重參數并非是
獨立的)。
5.8 觀察損失曲線:學習率
5.9 放大損失曲線:學習率、batch大小
5.10 觀察準確率曲線
5.11 fine-turn的方法
■ 如果你的數據量有限,那么,一般不建議自己完全從頭訓練起caffe
模型。一般是找相關的項目或者模型,先finetuning一下,之后再慢
慢的調整。一般fine tuning的方式,都是把learning rate(solver.prototxt)調低(為原來的十分之一),之后把訓練模型的
最后一層或者兩層的學習速率調大一點————這就相當于,把模
型的前面那些層的學習調低,使得參數更新的慢一點以達到微調的目的。
■ 微調的時候,有時候訓練數據特別少,而且希望模型的前面幾層的
參數保持不變。方法是使得這幾個層的學習速率為0就可以了,比
如設定lr_mult為0。
5.12 模型集成
■ 在機器學習中,集成方法( ensemble methods )是指訓練多個學習器并在之后將它們組合使用,最終得到一個強有力的分類器的方法。
■ 幾種集成方式的技巧:
■ 1. 集成不同初始化的模型
使用交叉驗證集來確定最佳的超參數,再在基于最佳超參數的情況下,使用不同的隨機初始化方法來初始化權重來訓練多個模型。該方法的風險在于權重初始化方法的不同產生的差異。
■ 2.集成 topN 表現的模型
使用交叉驗證集確定了最佳的超參數后,再選取表現最佳的前 topN 個模型進行集成。這可以提升集成模型的多樣性,但?風險就是這幾個模型都是局部最優模型。實際實踐中,這種做法可以達到不錯的性能,因為不需要(在交叉驗證后)對模型進行額外的重新訓練。實際上,可以直接在 Caffe Model Zoo 中選擇表現性能在 topN 的幾個深度模型進行集成。
總結
以上是生活随笔為你收集整理的caffe 框架梳理(待续)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云中神殿露峥嵘!《新大话3》年度资料片倒
- 下一篇: 战争雷霆9月3日抗日胜利纪念日活动