http://ethereon.github.io/netscope/#/editor 在線可視化模型結構,shift+enterhtml
寫模型結構代碼的時候能夠直接使用這個功能來所見即所得python
xx.prototxtlinux
除了第一行設置該模型的名字,其他全是layer的設置c++
layer應該時沒有順序的,由於layer中要設置bottom和top,分別表示輸入端和輸出端,可是編寫代碼按模型順序寫會更加易讀git
layer中的不一樣type須要不一樣的參數github
http://caffe.berkeleyvision.org/tutorial/layers.html 能夠看到全部不一樣的type數組
type: Python 時須要增長網絡
python_param {app
module: ''" python文件名ide
layer: '' python中class的名字
param_str: "{'xx':,..... }"
include {
phase: TRAIN/TEST
}
}
Caffe can be told to include or exclude a layer when running a network in a particular phase
通常也就是輸入會有這個設定了,對於TRAIN或者TEST對應不一樣的輸入層
注意通常layer中param會定義兩個用以定義lr和decay,不是覆蓋的關係,雖然名字都同樣,可是對應的表示不同,通常第一個描述filter,第二個描述bias,以下:
1 layer { 2 name: "conv1" 3 type: "Convolution" 4 bottom: "data" 5 top: "conv1" 6 # learning rate and decay multipliers for the filters 7 param { lr_mult: 1 decay_mult: 1 } 8 # learning rate and decay multipliers for the biases 9 param { lr_mult: 2 decay_mult: 0 } 10 convolution_param { 11 num_output: 96 # learn 96 filters 12 kernel_size: 11 # each filter is 11x11 13 stride: 4 # step 4 pixels between each filter application 14 weight_filler { 15 type: "gaussian" # initialize the filters from a Gaussian 16 std: 0.01 # distribution with stdev 0.01 (default mean: 0) 17 } 18 bias_filler { 19 type: "constant" # initialize the biases to zero (0) 20 value: 0 21 } 22 } 23 }
在可視化模型結構的過程當中,只有layer中的name表明的層可視化出來了,其餘的top,bottom取的名字其實表明着數據流,也就是blob,具體指代的圖中的邊
若是輸入輸出的邊相同,說明這兩個結點能夠合成
注意對於單個結點,通常都是top名和layer名同樣
參考: http://blog.leanote.com/post/braveapple/Caffe-%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7
caffe的運行提供三種接口: C++接口(命令行), Python接口, 和Matlab接口
C++接口(命令行);
./build/tools/caffe train --solver=xx.prototxt
caffe <command> <args>
caffe中自帶程序可對圖像數據轉換成db(leveldb/lmdb)文件
./build/tools/convert_imageset [FLAGS] ROOTFOLDER/LISTFILE DB_NAME
FLAGS: 圖片參數組,後面詳細介紹
ROOTFOLDER/: 圖片存放的絕對路徑,從linux系統根目錄開始
LISTFILE: 圖片文件列表清單,通常爲一個txt文件,一行一張圖片
DB_NAME: 最終生成的db文件存放目錄
若是咱們本地有訓練數據集,.jpg格式,那咱們須要本身建立一個圖片列表清單,本身寫腳本
python接口使用方法;
https://blog.csdn.net/l691899397/article/details/76202178
訓練的方式
提取特徵的方式
使用輸入圖片到deploy
怎麼計算均值文件
1. 二進制格式的均值計算
caffe中使用的均值數據格式時binaryproto,caffe自帶計算均值代碼
./build/tools/compute_image_mean examples/mnist/mnist_train_lmdb examples/mnist/mean.binaryproto
第一個參數,是須要計算均值的數據,格式爲lmdb的訓練數據,第二個參數,計算出來的結果保存文件
2. python格式的均值計算
咱們先按1計算出二進制格式的均值,而後轉換成python格式的均值。
1 #!/usr/bin/env python 2 import numpy as np 3 import sys,caffe 4 if len(sys.argv)!=3: 5 print "Usage: python convert_mean.py mean.binaryproto mean.npy" 6 sys.exit() 7 blob = caffe.proto.caffe_pb2.BlobProto() 8 bin_mean = open( sys.argv[1] , 'rb' ).read() 9 blob.ParseFromString(bin_mean) 10 arr = np.array( caffe.io.blobproto_to_array(blob) ) 11 npy_mean = arr[0] 12 np.save( sys.argv[2] , npy_mean )
保存爲convert_mean.py
運行: Python convert_mean.py mean.binaryproto mean.npy
*.caffemodel文件裏面存放的就是各層的參數,即net.params,裏面沒有數據net.blobs. *.solverstate時用來恢復訓練的,防止意外終止而保存的快照
咱們能夠提出caffemodel裏面保存的參數進行可視化
參考連接: http://blog.leanote.com/post/braveapple/Caffe-%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7
python/draw_net.py能夠將網絡模型由prototxt變成一張圖片
sudo apt-get install GraphViz
sudo pip install pydot
採用的也是jupyter notebook進行曲線繪製
若是不須要繪製曲線,只須要訓練出一個 caffemodel,直接調用 solver.solve()
就能夠了。若是要繪製曲線,就須要把迭代過程當中的值保存下來,所以不能直接調用 solver.solve()
, 須要迭代。在迭代過程當中,每迭代200次測試一次
一樣代碼參考連接
下載caffemodel文件和均值文件
在測試階段,須要把測試數據減去均值
synset_words.txt文件
分類方法:
c++方式
./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
python接口
參考連接
使用別人訓練好的參數,此處有一個大坑,那就是必須和別人用同一個 network ,由於參數是根據 network 而來的。固然,最後一層,咱們是能夠修改的,由於咱們的數據可能並無1000類,而只有幾類。咱們把最後一層的輸出類別改一下,而後把層的名稱改一下就能夠了。最後用別人的參數、修改後的 network 和咱們本身的數據,再進行訓練,使得參數適應咱們的數據,這樣一個過程,一般稱之爲微調 (fine tuning)。
修改data層:
把均值文件(mean_file)、數據源文件 (source)、批次大小 (batch_size)和數據源格式 (backend) 這四項做相應的修改。
修改最後一個全鏈接層:
只須要修改兩個地方,一個name,一個時num_output,看本身的分類任務時多少類
咱們能夠看下模型的一些參數和一些中間輸出
看下如何讀取網絡的結構:
對於每一層,其結構構成爲:(batch_size, channel_dim, height, width)
# 對於每一層,顯示輸出類型。 for layer_name, blob in net.blobs.iteritems(): print layer_name + '\t' + str(blob.data.shape) data (50, 3, 227, 227) conv1 (50, 96, 55, 55) pool1 (50, 96, 27, 27) norm1 (50, 96, 27, 27) conv2 (50, 256, 27, 27) pool2 (50, 256, 13, 13) norm2 (50, 256, 13, 13) conv3 (50, 384, 13, 13) conv4 (50, 384, 13, 13) conv5 (50, 256, 13, 13) pool5 (50, 256, 6, 6) fc6 (50, 4096) fc7 (50, 4096) fc8 (50, 1000) prob (50, 1000)
看下參數的形狀: net.params索引[0]表示weights, [1]表示爲biases
參數形狀爲(output_channels, input_channels, filter_height,filter_width) 時weights
(output_channels,)爲biases
for layer_name, param in net.params.iteritems(): print layer_name + '\t' + str(param[0].data.shape), str(param[1].data.shape) conv1 (96, 3, 11, 11) (96,) conv2 (256, 48, 5, 5) (256,) conv3 (384, 256, 3, 3) (384,) conv4 (384, 192, 3, 3) (384,) conv5 (256, 192, 3, 3) (256,) fc6 (4096, 9216) (4096,) fc7 (4096, 4096) (4096,) fc8 (1000, 4096) (1000,)
能夠定義一個函數來幫助可視化特徵
def vis_square(data): """輸入一個形如:(n, height, width) or (n, height, width, 3)的數組,並對每個形如(height,width)的特徵進行可視化sqrt(n) by sqrt(n)""" # 正則化數據 data = (data - data.min()) / (data.max() - data.min()) # 將濾波器的核轉變爲正方形 n = int(np.ceil(np.sqrt(data.shape[0]))) padding = (((0, n ** 2 - data.shape[0]), (0, 1), (0, 1)) # 在相鄰的濾波器之間加入空白 + ((0, 0),) * (data.ndim - 3)) # 不擴展最後一維 data = np.pad(data, padding, mode='constant', constant_values=1) # 擴展一個像素(白色) # tile the filters into an image data = data.reshape((n, n) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1))) data = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:]) plt.imshow(data) plt.axis('off') plt.show()
看下第一個卷積層的輸出特徵
# 參數爲一個[weights, biases]的列表 filters = net.params['conv1'][0].data vis_square(filters.transpose(0, 2, 3, 1))