Caffe官方教程翻译(3):Siamese Network Training with Caffe
前言
最近打算重新跟著官方教程學習一下caffe,順便也自己翻譯了一下官方的文檔。自己也做了一些標注,都用斜體標記出來了。中間可能額外還加了自己遇到的問題或是運行結果之類的。歡迎交流指正,拒絕噴子! 
 官方教程的原文鏈接:http://caffe.berkeleyvision.org/gathered/examples/siamese.html
Siamese Network Training with Caffe
這個示例將會展示給你如何使用權重分享和對比損失函數,來學習在Caffe中使用一個siamese網絡。
我們默認你已經成功編譯了caffe的源碼。如果沒有,請查Installation page。這個例子是在MNIST tutorial的基礎之上做的,所以在閱讀這篇教程之前最好先看下那篇教程。
我們指定所有的路徑并假設所有的命令都是在caffe的根目錄下的。
準備數據集
首先你需要從MNIST網站下載并轉換數據集格式。為了做到這個,運行下面的命令:
./data/mnist/get_mnist.sh ./examples/siamese/create_mnist_siamese.sh在運行這些腳本后你會看到多出來了兩個數據集:./examples/siamese/mnist_siamese_train_leveldb和./examples/siamese/mnist_siamese_test_leveldb。
模型
首先,我們要定義后面在訓練想要使用的siamese網絡的模型。我們會使用定義在./examples/siamese/mnist_siamese.prototxt中的卷積神經網絡。這個模型基本上與LeNet model中的模型是一樣的,唯一的區別就是我們將頂層對應10個手寫數字類別概率的輸出更換成了線性“特征”層,只有2個輸出了(補充:siamese與LeNet的不同在于,輸入變成了一對圖片,不是預測單個樣本對應的標簽,而是判斷這一對樣本是否是來自同一個類,是則結果為0,不是則結果為1)。
layer {name: "feat"type: "InnerProduct"bottom: "ip2"top: "feat"param {name: "feat_w"lr_mult: 1}param {name: "feat_b"lr_mult: 2}inner_product_param {num_output: 2} }定義Siamese網絡
在這個部分我們將要定義siamese網絡,并用于訓練。網絡定義在./examples/siamese/mnist_siamese_train_test.prototxt。
讀入一對數據
我們最開始需要定義一個data層,而data層會從我們之前創建的LevelDB數據庫讀取數據。這個數據庫的每個條目都包含了一對圖像(pair_data)和一個二進制標簽,表示它們是否是來自同一個類或是不同的類(sim)。
layer {name: "pair_data"type: "Data"top: "pair_data"top: "sim"include { phase: TRAIN }transform_param {scale: 0.00390625}data_param {source: "examples/siamese/mnist_siamese_train_leveldb"batch_size: 64} }為了從數據庫中取出一對圖片打包送到同一個blob中,我們對每一個通道都打包一個圖像。我們想要分別處理這兩個圖像,所以在data層之后添加了一個slice層。它會接受pair_data的數據,并將其根據通道維度切分開來,然后我們會在data和它成對的圖像data_p上得到一個單一的圖像。
layer {name: "slice_pair"type: "Slice"bottom: "pair_data"top: "data"top: "data_p"slice_param {slice_dim: 1slice_point: 1} }建立Siamese網絡的第一邊
現在我們可以指定siamese網絡的第一邊了。這一邊的網絡處理的是data(補充:輸入是data層),生成的是feat(輸出是feat層)。剛開始,我們在./examples/siamese/mnist_siamese.prototxt中加入了默認的權重初始值。然后,我們給卷積層和內積層(全連接層)進行命名。對參數進行命名,就相當于告訴Caffe這些層上的參數在兩邊的siamese網絡上共享。就像這樣定義:
... param { name: "conv1_w" ... } param { name: "conv1_b" ... } ... param { name: "conv2_w" ... } param { name: "conv2_b" ... } ... param { name: "ip1_w" ... } param { name: "ip1_b" ... } ... param { name: "ip2_w" ... } param { name: "ip2_b" ... } ...建立Siamese網絡的第二邊
現在我們需要創建第二邊網絡,而這一邊的網絡處理的是data_p,生成的是feat_p。這一邊跟第一邊基本上是一模一樣的。因此,直接復制粘貼就行。然后我們要改一下每一層的名字、輸入、輸出,在名字后面加上“_p”來跟原始的區分一下。
添加對比損失函數
為了訓練網絡,我們要對一個對比損失函數進行優化,由Raia Hadsell, Sumit Chopra和 Yann LeCun在“Dimensionality Reduction by Learning an Invariant Mapping”中提出。這個損失函數會使得在特征空間中相互匹配的樣本更加接近,同時也會使得不匹配的樣本更遠。這個損耗函數在CONTRASTIVE_LOSS層聲明了:
layer {name: "loss"type: "ContrastiveLoss"contrastive_loss_param {margin: 1.0}bottom: "feat"bottom: "feat_p"bottom: "sim"top: "loss" }定義解決方案
除了給解決方案指定正確的模型文件之外,沒有什么特別的需要做的了。解決方案定義在:./examples/siamese/mnist_siamese_solver.prototxt。
訓練和測試模型
在你已經寫好了網絡定義的protobuf和解決方案的protobuf之后,訓練模型變得很簡單了。運行:./examples/siamese/train_mnist_siamese.sh:
./examples/siamese/train_mnist_siamese.sh繪制結果
首先,通過運行下面的命令,我們可以畫出模型和siamese網絡,畫出來.prototxt文件中定義的DAGs:
./python/draw_net.py \./examples/siamese/mnist_siamese.prototxt \./examples/siamese/mnist_siamese.png./python/draw_net.py \./examples/siamese/mnist_siamese_train_test.prototxt \./examples/siamese/mnist_siamese_train_test.png接著,我們可以在iPython notebook中導入訓練好的模型并畫出特征:
ipython notebook ./examples/siamese/mnist_siamese.ipynb補充:ipython notebook太老了,可以直接換成jupyter notebook。指令如下:
jupyter notebook ./examples/siamese/mnist_siamese.ipynb運行結果截圖
這些是我在自己筆記本上運行的結果,僅供參考。 
 運行代碼:
生成的網絡結構的圖片: 
 
運行代碼:
./python/draw_net.py \./examples/siamese/mnist_siamese_train_test.prototxt \./examples/siamese/mnist_siamese_train_test.png生成的網絡結構的圖片: 
 
運行代碼:
jupyter notebook ./examples/siamese/mnist_siamese.ipynb直接看圖就知道了,每種顏色分別對應一個手寫數字,正好10種吧。 
 
總結
以上是生活随笔為你收集整理的Caffe官方教程翻译(3):Siamese Network Training with Caffe的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Caffe官方教程翻译(2):Web d
 - 下一篇: Caffe官方教程翻译(4):CIFAR