使用caffe的python介面實現內部引數視覺化
阿新 • • 發佈:2019-01-24
1。這裡並不介紹如何訓練cnn及caffe配置,主要介紹如何實現cnn內部引數視覺化。
#這是我訓練時使用的train.prototxt檔案,在實現視覺化之前首先需要對這個檔案進行修改,
#trian.prototxt檔案的前2層及尾部需要修改,修改成train_deploy.prototxt檔案。
name: "face_train"
layer {
name: "face"
type: "Data"
top: "data"
top: "label"
data_param {
source: "train_lmdb"
batch_size: 100
backend:LMDB
}
transform_param {
scale: 0.00390625
mirror: true
}
include: {
phase: TRAIN
}
}
layer {
name: "face"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "val_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
...........
...........
...........
layer {
name: "ip1"
type: "InnerProduct"
bottom: "contact_conv"
top: "ip1"
param {
name: "fc6_w"
lr_mult: 1
decay_mult: 1
}
param {
name: "fc6_b"
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 160
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 0.1
}
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 200
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include: {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
修改後的train_deploy.prototxt,我這裡只需要ip1輸出的資料,故刪除了ip2及後面所有的層,若需要輸出概率,可以先把ip2後的層刪除,再添加個softmax層
#train_deploy.prototxt
name: "face_train"
input: "data"
input_dim: 1 #影象個數
input_dim: 3 #通道數
input_dim: 128
input_dim: 128
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
.......
.......
.......
layer {
name: "ip1"
type: "InnerProduct"
bottom: "contact_conv"
top: "ip1"
param {
name: "fc6_w"
lr_mult: 1
decay_mult: 1
}
param {
name: "fc6_b"
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 160
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 0.1
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- train_deploy檔案已建立好,現在是python時間,這裡我是在jupyter notebook進行python程式設計,如果不是在jupyter notebook中運算的話,%matplotlib inline會報錯,請先配置好jupyter notebook,這個非常好用
import numpy as np
import matplotlib.pyplot as plt
import os,sys,caffe
%matplotlib inline
caffe_root='/home/chen/Downloads/caffe-master/'
os.chdir(caffe_root)
sys.path.insert(0,caffe_root+'python')
#載入測試圖片,並顯示
#caffe.io.load_image會把讀取的影象轉化為float32,並歸一化
im = caffe.io.load_image('examples/images/image/test_000000-000008.jpg')
print im.shape
plt.imshow(im)
plt.axis('off')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
#im的shape是(128,128,3),我們要把它轉換成(1,3,128,128)
X=np.empty((1,3,128,128))
X[0,0,:,:]=im[:,:,0]
X[0,1,:,:]=im[:,:,1]
X[0,2,:,:]=im[:,:,2]
caffe.set_mode_gpu()
#載入網路模型和caffemodel
net = caffe.Net(caffe_root + 'examples/images/train2_deploy.prototxt',
caffe_root + 'examples/images/face3_iter_40000.caffemodel',
caffe.TEST)
#將影象資料載入到網路中
net.blobs['data'].data[...] = X
#執行測試模型,並顯示各層資料資訊
net.forward()
[(k, v.data.shape) for k, v in net.blobs.items()]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
上面載入資料到網路時並沒有減去均值,因為我這裡並沒有使用均值。
# 編寫一個函式,用於顯示各層資料
def show_data(Inputdata, padsize=1, padval=0):
data=Inputdata
for i in range(data.shape[1]):
data[0,i] -= data[0,i].min()
data[0,i]/= data[0,i].max()
# force the number of filters to be square
n = int(np.ceil(np.sqrt(data.shape[0])))
padding = ((0, n ** 2 - data.shape[0]), (0, padsize), (0, padsize)) + ((0, 0),) * (data.ndim - 3)
data = np.pad(data, padding, mode='constant', constant_values=(padval, padval))
# 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.figure()
plt.imshow(data,cmap='gray')
plt.axis('off')
plt.rcParams['figure.figsize'] = (8, 8)
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
# 編寫一個函式,用於顯示各層資料
def show_data2(Inputdata, padsize=1, padval=0):
data=Inputdata
# force the number of filters to be square
n = int(np.ceil(np.sqrt(data.shape[0])))
padding = ((0, n ** 2 - data.shape[0]), (0, padsize), (0, padsize)) + ((0, 0),) * (data.ndim - 3)
data = np.pad(data, padding, mode='constant', constant_values=(padval, padval))
# 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.figure()
plt.imshow(data,cmap='gray')
plt.axis('off')
plt.rcParams['figure.figsize'] = (8, 8)
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
#顯示conv1輸出影象
show_data(net.blobs['conv1'].data[0])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
#顯示conv2輸出影象
show_data(net.blobs['conv2'].data[0])
- 1
- 2
- 1
- 2
##顯示各層的引數資訊
[(k, v[0].data.shape) for k, v in net.params.items()]
- 1
- 2
- 1
- 2
#顯示conv1所用卷積核
show_data2(net.params['conv1'][0].data.reshape(20*3,3,3))
- 1
- 2
- 1
- 2
#顯示conv2所用卷積核
show_data2(net.params['conv2'][0].data.reshape(40*20,4,4))
- 1
- 2
- 1
- 2
#我這裡只是用CNN提取特徵,故只需要ip1輸出的160維向量,
#如果需要計算概率可以在後面加上一個softmax層
out=net.blobs['ip1'].data
out.shape
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
3.總結
訓練好網路,再提取出160維的特徵。至此完成內部引數視覺化和模型呼叫,那2個顯示函式是用的別人的,會使用OpenCV的朋友可以自己寫一個更好的函式來使用。我這裡就偷下懶了,後面會考慮自己寫個顯示的函式。
有些朋友可能訓練時使用了均值檔案,請點這裡 http://www.cnblogs.com/denny402/p/5105911.html