利用Caffe訓練模型(solver、deploy、train_val) + python如何使用已訓練模型

 

版權聲明:博主原創文章,微信公衆號:素質雲筆記,轉載請註明來源「素質雲博客」,謝謝合做!! https://blog.csdn.net/sinat_26917383/article/details/54141697

本文部份內容來源於CDA深度學習實戰課堂,由唐宇迪老師授課javascript

  • 若是你企圖用CPU來訓練模型,那麼你就瘋了…
  • 訓練模型中,最耗時的因素是圖像大小size,通常227*227用CPU來訓練的話,訓練1萬次可能要超過1周的時間。
  • 不一樣的網絡結構,可能會有不一樣圖片尺寸的需求,因此訓練以前須要瞭解一下,在生成LMDB環節就直接符合上模型的數據要求。
  • 若是你本身DIY了框架,那麼不知道如何檢驗框架與通用框架比較,是否優質,能夠去benchmarks網站,跟別人的PK一下:http://human-pose.mpi-inf.mpg.de/
  • Caffe官網: Examples:主要集中在訓練模型 Notebook Examples:集中在fun-tuning模型

1、訓練文件配置詳情

一、參數文件solver.prototxt

以caffeNet爲例,參數解讀:php

net: "/caffe/examples/lmdb_test/train/bvlc_reference_caffenet/train_val.prototxt" # 訓練的prototxt在哪,路徑 test_iter: 1000 # 測試要迭代多少個Batch test_iter * batchsize(測試集的)= 測試集的大小 test_interval: 500 # 每500次迭代,就在用測試集進行測試 base_lr: 0.01 # 設置初始化的學習率爲0.01 lr_policy: "step" # 權重衰減策略。 gamma: 0.1 stepsize: 100000 # 初始的學習率爲0.01,而且每100000次迭代中進行學習率降低 display: 20 # 每20次epoch就顯示出一些數據信息 max_iter: 50000 # 迭代次數 momentum: 0.9 # 一直都是0.9,固定不變;迭代的數據更快,步伐更快 weight_decay: 0.0005 # 權重衰減因子爲0.0005 snapshot: 10000 # 每10000次迭代中,就生成當前狀態的快照 snapshot_prefix: "/caffe/examples/lmdb_test/train/bvlc_reference_caffenet" # 模型快照保存 solver_mode: CPU # 能夠設定GPU仍是cpu

 

快照的大用途:若是出了什麼意外中斷了訓練,那真是天都要塌了,因此快照存儲了訓練的中間結果,這個設計真是人性化,當再次訓練時,就能夠從快照中恢復數據了。直接在最後的執行文件,調用已經訓練的快照就行,用-snapshotcss

二、框架文件,train_val.prototxt

框架文件每一層參數具體含義是什麼?可參考caffe官方連接:http://caffe.berkeleyvision.org/tutorial/layers.htmlhtml

訓練文件:配置訓練階段的圖片數據集、配置訓練階段的標籤數據集、配置測試階段的圖片數據集 、配置測試階段的標籤數據集 、 多標籤損失函數(博客:Caffe中LMDB接口實現多標籤數據準備及訓練)java

網絡的配置文件——定義網絡python

Name:」」 #隨便寫 Layer { Name:」」 #名稱 Type:」」 #很嚴格 Top:」label」 # 接最後的內容,最後全鏈接層會出現"bottom:"label"" } Transform.param # 1/256,歸一化,多少大小通常都須要進行歸一化處理 Batch_size:64 #一次迭代多少個樣本 Layer {data} # 兩個數據層,一個訓練層,一個驗證層 Layer { Conv1 }

須要注意的是:linux

1. 最後全鏈接輸出,時候你是幾分類,就要填幾:c++

多分類數量就看訓練時候的分類個數。sql

inner_product_param {
    num_output: 2 weight_filler { type: "gaussian" std: 0.01

2. 本身定義層的時候 
須要本身寫不一樣的層,c++本身寫,挺麻煩的ruby

3. 圖片尺寸 
圖片尺寸是根據網絡來定義的,大型網絡都是227*227(224*224),VGG,ALEX都是這樣,譬如lenet小網絡就能夠用28*28

4. batch的做用 
Batch越大越好,通常64.小的話,能夠更好地顯示,小步迭代

三、模型執行文件train.sh

執行文件就是訓練好以後,你要在linux下運行的文件。

./build/tools/caffe train \
  # caffe這個工具在哪,通常就在tool之下
-gpu 0 \ # 沒必要須,是否用GPU,譬如你有不少塊GPU,每塊都有編號,那麼就能夠直接選擇某一塊GPU。其中若是你有四塊GPU,那麼就能夠-gpu all -model path/to/trainval.prototxt \ # 沒必要須,由於後面有solver參數文件,而參數文件裏面有trainval.prototxt文件,通常都不用寫 -solver path/to/solver.prototxt \ # 必須,prototxt文件內容在哪 -weights path/to/pretrained_weights.caffemodel # 沒必要須,-weight用來作fine-tuning,參數拿來學習。這個在fine-tuning時候用得上 --snapshot=examples/imagenet/myself/model/caffenet_train_1000.solverstate # 若是斷了,這時候就能夠用快照繼續訓練啦~ 只要在執行文件中加入snapshot的路徑

 

其中snapshot但是大殺器,筆者以爲有兩個用途:

  • 一、臨時停機了…機器訓練中斷了… 
    訓練的時候是遵循snapshot每10000次生成一次快照,若是停機就能夠繼續延續上次的內容繼續訓練,再寫一遍這個文件便可。
  • 二、要fine-tuning別人的模型,則須要先down他們的模型快照,而後繼續訓練,繼續訓練的時候可讓學習率下降到很小,把全鏈接層能夠稍微分一下。

四、驗證集文件:deploy.prototxt

這個文件是預測的時候須要用到的,跟參數trian_val.prototxt訓練文件很類似。

train_val.prototxt文件=數據輸入+卷積層+全鏈接層+loss/accuracy 
Deploy.prototxt文件=簡化版數據輸入+卷積層+全鏈接層+prob預測層

其餘真的不用改動。train_val的ImageData輸入層,須要修改成input層。

就拿AlexNet來講,不一樣之處在數據輸入部分+最後連接層

  • Deploy.prototxt的數據輸入部分:
layer {
  name: "data" type: "Input" top: "data" input_param { shape: { dim: 10 dim: 3 dim: 227 dim: 227 } } }

 

其中input_param中的參數意義爲: 
**第一個:**dim,對待識別樣本圖片進行數據增廣的數量,一個圖片會變成10個,以後輸入到網絡進行識別。若是不進行數據增廣,能夠設置成1。 
第二個:圖片的通道數,通常灰度圖片爲單通道,則值爲1,若是爲非灰度圖3通道圖片則爲3。 
第三個:圖片的高度,單位像素。 
第四個:圖片的寬度,單位像素。 
內容來源於:caffe生成lenet-5的deploy.prototxt文件

  • Deploy.prototxt的全鏈接prob部分:
layer { name: "prob" type: "Softmax" bottom: "fc8" top: "prob" }

 

輸出的是機率值,參數trian_val.prototxt集合中全鏈接層以後連接的是loss/accuracy。能夠看出訓練集要求的主要內容是輸出loss/accuracy,衡量訓練精度;而驗證集文件,主要就是將圖片分類輸出出來。


2、訓練完以後如何測試新數據

官方案例案例連接ipynb格式:打開連接

一、如何將mean.binaryproto轉mean.npy

因爲驗證的時候須要在python下,驗證新圖片的時候,是先讀入而後減去均值,這時候均值就須要一個python能夠理解的版本。 
網絡上有博客總結兩種方法(博客:Caffe均值文件mean.binaryproto轉mean.npy):mean.binaryproto轉mean.npy、已知均值狀況下用均值建立

(1)mean.binaryproto 轉化 
使用Caffe的C++接口進行操做時,須要的圖像均值文件是pb格式,例如常見的均值文件名爲mean.binaryproto;但在使用Python接口進行操做時,須要的圖像均值文件是numpy格式,例如mean.npy。因此在跨語言進行操做時,須要將mean.binaryproto轉換成mean.npy,轉換代碼以下:

import caffe
import numpy as np MEAN_PROTO_PATH = 'mean.binaryproto' # 待轉換的pb格式圖像均值文件路徑 MEAN_NPY_PATH = 'mean.npy' # 轉換後的numpy格式圖像均值文件路徑 blob = caffe.proto.caffe_pb2.BlobProto() # 建立protobuf blob data = open(MEAN_PROTO_PATH, 'rb' ).read() # 讀入mean.binaryproto文件內容 blob.ParseFromString(data) # 解析文件內容到blob array = np.array(caffe.io.blobproto_to_array(blob))# 將blob中的均值轉換成numpy格式,array的shape (mean_number,channel, hight, width) mean_npy = array[0] # 一個array中能夠有多組均值存在,故須要經過下標選擇其中一組均值 np.save(MEAN_NPY_PATH ,mean_npy)

 

(2)已知圖像均值,構造mean.npy

若是已知圖像中每一個通道的均值,例如3通道圖像每一個通道的均值分別爲104,117,123,咱們也能夠經過其構造mean.npy。代碼以下:

import numpy as np MEAN_NPY_PATH = 'mean.npy' mean = np.ones([3,256, 256], dtype=np.float) mean[0,:,:] = 104 mean[1,:,:] = 117 mean[2,:,:] = 123 np.save(MEAN_NPY, mean)

 

(3)如何加載mean.npy文件 
上面咱們用兩種方式構造了均值文件mean.npy,在使用時載入mean.npy的代碼以下:

import numpy as np

mean_npy = np.load(MEAN_NPY_PATH) mean = mean_npy.mean(1).mean(1)

 

二、利用python作預測

(1)模塊加載與設置環境

#加載模塊與圖像參數設置 import numpy as np import matplotlib.pyplot as plt plt.rcParams['figure.figsize'] = (10, 10) # large images plt.rcParams['image.interpolation'] = 'nearest' # don't interpolate: show square pixels plt.rcParams['image.cmap'] = 'gray' #模型路徑deploy import caffe import os caffe.set_mode_cpu() model_def = caffe_root + 'examples/faceDetech/deploy.prototxt' model_weights = caffe_root + 'examples/faceDetech/alexnet_iter_50000_full_conv.caffemodel' #模型加載 net = caffe.Net(model_def, # defines the structure of the model model_weights, # contains the trained weights caffe.TEST)

 

其中如何你沒有訓練好的模型那麼caffe官方有一套,利用imagenet圖片和caffenet模型訓練好了一個caffemodel, 供你們下載。要進行圖片的分類,這個caffemodel是最好不過的了。下載地址爲:http://dl.caffe.berkeleyvision.org/bvlc_reference_caffenet.caffemodel 
或者命令行下載:

# sudo ./scripts/download_model_binary.py models/bvlc_reference_caffenet

(2)模型預處理階段-不處理均值的狀況

transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) # 那麼reshape操做,就是自動將驗證圖片進行放縮 transformer.set_transpose('data', (2,0,1)) # move image channels to outermost dimension # transpose將RGB變爲BGR,都要作transpose # BGR誰放在前面,譬如3*300*100,這裏設定3在前面 transformer.set_raw_scale('data', 255) # rescale from [0, 1] to [0, 255] # 像素點rescale操做,將數據的像素點集中在[0,255]區間內 transformer.set_channel_swap('data', (2,1,0)) # CPU classification net.blobs['data'].reshape(50, # batch size 3, # 3-channel (BGR) images 227, 227) 

 

(3)單張新圖片處理與識別

image = caffe.io.load_image("/caffe/data/trainlmdb/val/test_female/image_00010.jpg") # 導入圖片 transformed_image = transformer.preprocess('data', image) # 預處理圖片 output = net.forward() # 前向傳播一次,找出參數 net.blobs['data'].data[...] = transformed_image output_prob = output['prob'][0] # 輸出機率 print 'predicted class is:', output_prob.argmax() # 輸出最大可能性

筆者訓練的一個二分類結果是:

array([ 0.34624347, 0.65375656], dtype=float32)

 


轉載:3、多張訓練循環讀取

本節主要參考博客:Caffe學習系列(20):用訓練好的caffemodel來進行分類

在caffe根目錄下的 examples/cpp-classification/ 
文件夾下面,有個classification.cpp文件,就是用來分類的。固然編譯後,放在/build/examples/cpp_classification/ 
下面

數據準備好了,咱們就能夠開始分類了,咱們給你們提供兩個版本的分類方法:

1、c++方法

在caffe根目錄下的 examples/cpp-classification/ 文件夾下面,有個classification.cpp文件,就是用來分類的。固然編譯後,放在/build/examples/cpp_classification/ 下面

咱們就直接運行命令:

# sudo ./build/examples/cpp_classification/classification.bin \ models/bvlc_reference_caffenet/deploy.prototxt \ models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel \ data/ilsvrc12/imagenet_mean.binaryproto \ data/ilsvrc12/synset_words.txt \ examples/images/cat.jpg

 

命令很長,用了不少的\符號來換行。能夠看出,從第二行開始就是參數,每行一個,共須要4個參數

運行成功後,輸出top-5結果:

---------- Prediction for examples/images/cat.jpg ---------- 0.3134 - "n02123045 tabby, tabby cat" 0.2380 - "n02123159 tiger cat" 0.1235 - "n02124075 Egyptian cat" 0.1003 - "n02119022 red fox, Vulpes vulpes" 0.0715 - "n02127052 lynx, catamount"

 

即有0.3134的機率爲tabby cat, 有0.2380的機率爲tiger cat ……

2、python方法

python接口可使用jupyter notebook來進行可視化操做,所以推薦使用這種方法。

在這裏我就不用可視化了,編寫一個py文件,命名爲py-classify.py

#coding=utf-8 #加載必要的庫 import numpy as np import sys,os #設置當前目錄 caffe_root = '/home/xxx/caffe/' sys.path.insert(0, caffe_root + 'python') import caffe os.chdir(caffe_root) net_file=caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt' caffe_model=caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel' mean_file=caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy' net = caffe.Net(net_file,caffe_model,caffe.TEST) transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) transformer.set_transpose('data', (2,0,1)) transformer.set_mean('data', np.load(mean_file).mean(1).mean(1)) transformer.set_raw_scale('data', 255) transformer.set_channel_swap('data', (2,1,0)) im=caffe.io.load_image(caffe_root+'examples/images/cat.jpg') net.blobs['data'].data[...] = transformer.preprocess('data',im) out = net.forward() imagenet_labels_filename = caffe_root + 'data/ilsvrc12/synset_words.txt' labels = np.loadtxt(imagenet_labels_filename, str, delimiter='\t') top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1] for i in np.arange(top_k.size): print top_k[i], labels[top_k[i]]

執行這個文件,輸出:

281 n02123045 tabby, tabby cat 282 n02123159 tiger cat 285 n02124075 Egyptian cat 277 n02119022 red fox, Vulpes vulpes 287 n02127052 lynx, catamount

 

caffe開發團隊實際上也編寫了一個python版本的分類文件,路徑爲 python/classify.py

運行這個文件必需兩個參數,一個輸入圖片文件,一個輸出結果文件。並且運行必須在python目錄下。假設當前目錄是caffe根目錄,則運行:

# cd python # sudo python classify.py ../examples/images/cat.jpg result.npy

 

分類的結果保存爲當前目錄下的result.npy文件裏面,是看不見的。並且這個文件有錯誤,運行的時候,會提示

Mean shape incompatible with input shape

 

的錯誤。所以,要使用這個文件,咱們還得進行修改:

一、修改均值計算:

定位到

mean = np.load(args.mean_file)

這一行,在下面加上一行:

mean=mean.mean(1).mean(1)

則能夠解決報錯的問題。

二、修改文件,使得結果顯示在命令行下:

定位到

# Classify.
    start = time.time() predictions = classifier.predict(inputs, not args.center_only) print("Done in %.2f s." % (time.time() - start)) 

 

這個地方,在後面加上幾行,以下所示:

# Classify.
    start = time.time() predictions = classifier.predict(inputs, not args.center_only) print("Done in %.2f s." % (time.time() - start)) imagenet_labels_filename = '../data/ilsvrc12/synset_words.txt' labels = np.loadtxt(imagenet_labels_filename, str, delimiter='\t') top_k = predictions.flatten().argsort()[-1:-6:-1] for i in np.arange(top_k.size): print top_k[i], labels[top_k[i]]

 

就樣就能夠了。運行不會報錯,並且結果會顯示在命令行下面。 
.


延伸一:caffe中網絡結構可視化

還有一個是python下面的接口,draw_net.py能夠根據.prototxt文件將模式用圖示的方法表示出來,博文開始的模型圖即用該接口所繪

./python/draw_net.py ./examples/siamese/mnist_siamese.prototxt ./examples/siamese/mnist_siamese.png #使用該接口進行網絡的繪製示例化

 

第一個參數爲模型文件,第二個參數爲所繪模型圖的保存地址。參考博客:Caffe使用step by step:caffe框架下的基本操做和分析

相關文章
相關標籤/搜索