此次试验主要通过caffe的python接口进行操作,十分方便
1,mnist.py:建立网络——建立solver——进行训练,最后还包含绘制loss和accuracy曲线的功能
# -*- coding: utf-8 -*-
import caffe
from caffe import layers as L, params as P, proto, to_proto
import numpy as np
import matplotlib.pyplot as plt
# 设定文件的路径
train_lmdb = '/home/zhaoys/myf/dataset/mnist/mnist_train_lmdb' # 设置训练集位置
test_lmdb = '/home/zhaoys/myf/dataset/mnist/mnist_test_lmdb' # 设置测试集位置
root = '/home/zhaoys/myf/lenet/lenet_pycaffe/' # 根目录位置
train_proto = root + 'train.prototxt' # 训练配置文件
test_proto = root + 'test.prototxt' # 测试配置文件
solver_proto = root + 'solver.prototxt' # 参数文件
def create_net(lmdb, batch_size, include_acc = False):
# 创建第一层:数据层。向上传递两类数据:图片数据和对应的标签数据
data, label = L.Data(source = lmdb, backend = P.Data.LMDB, batch_size = batch_size, ntop = 2,
transform_param = dict(crop_size = 28, mirror = True, scale = 0.00390625))
# 创建第二层:卷积层、激活函数层、池化层
conv1 = L.Convolution(data, kernel_size = 5, stride = 1, num_output = 16, pad = 2, weight_filler = dict(type = 'xavier'))
relu1 = L.ReLU(conv1, in_place = True)
pool1 = L.Pooling(relu1, pool = P.Pooling.MAX, kernel_size = 3, stride = 2)
# 创建第三层:卷积层、激活函数层、池化层
conv2 = L.Convolution(pool1, kernel_size = 3, stride = 1, num_output = 32, pad = 1, weight_filler = dict(type = 'xavier'))
relu2 = L.ReLU(conv2, in_place = True)
pool2 = L.Pooling(relu2, pool = P.Pooling.MAX, kernel_size = 3, stride = 2)
# 创建全连接层
fc3 = L.InnerProduct(pool2, num_output = 500, weight_filler = dict(type = 'xavier'))
relu3 = L.ReLU(fc3, in_place = True)
# 创建dropout层
drop3 = L.Dropout(relu3, in_place = True)
# 创建全连接层
fc4 = L.InnerProduct(drop3, num_output = 10, weight_filler = dict(type = 'xavier'))
# 创建一个softmax层
loss = L.SoftmaxWithLoss(fc4, label)
# 在训练阶段创建accuracy层
if include_acc:
acc = L.Accuracy(fc4, label)
return to_proto(loss, acc)
else:
return to_proto(loss)
def write_net():
# 将上面的设置写入到prototxt文件里面
with open(train_proto, 'w') as f:
f.write(str(create_net(train_lmdb, batch_size = 64)))
with open(test_proto, 'w') as f:
f.write(str(create_net(test_lmdb, batch_size = 100, include_acc = True)))
def gen_solver(solver_file, train_net, test_net):
s = proto.caffe_pb2.SolverParameter()
s.train_net = train_net
s.test_net.append(test_net)
s.test_interval = 938 # 60000 / 64 = 938,训练时,经过938次迭代进行一次测试
s.test_iter.append(100) # 10000 / 100 = 100,测试时,共进行500次迭代
s.max_iter = 20000 # 50000 / 938 = epochs
s.momentum = 0.9
s.weight_decay = 5e-4 # 参数衰减不能太大!如此精确率可达99.2%
s.base_lr = 1e-2 # 学习率相关参数
s.lr_policy = 'inv'
s.stepsize = 10000
s.gamma = 1e-4
s.power = 0.75
s.display = 200
s.snapshot = 50000
s.snapshot_prefix = root + 'snapshot/train'
s.type = 'SGD'
s.solver_mode = proto.caffe_pb2.SolverParameter.GPU
with open(solver_file, 'w') as f:
f.write(str(s))
def training(solver_proto):
caffe.set_device(0)
caffe.set_mode_gpu()
solver = caffe.SGDSolver(solver_proto)
solver.solve()
'''
# 绘制loss曲线并保存 通过VNC显示
max_iter = 20000
display = 200
test_interval = 938
loss = np.zeros(max_iter // display)
accuracy = np.zeros(max_iter // test_interval + 1)
train_loss = 0
test_accuracy = 0
for iter in range(max_iter):
solver.step(1)
train_loss += solver.net.blobs['SoftmaxWithLoss1'].data
if iter % display == 0:
loss[iter // display] = train_loss / display
train_loss = 0
if iter % test_interval == 0:
for test_iter in range(test_interval):
solver.test_nets[0].forward()
test_accuracy += solver.test_nets[0].blobs['Accuracy1'].data
accuracy[iter // test_interval] = test_accuracy / test_interval
test_accuracy = 0
plt.title('mnist loss & accuracy')
plt.xlabel(u'Iters',fontproperties='SimHei',fontsize=14)
plt.ylabel(u'loss & accuracy',fontproperties='SimHei',fontsize=14)
plt.plot(loss, 'g')
plt.plot(accuracy, 'r')
plt.savefig(root + 'loss_accuracy.png')
plt.show()
'''
if __name__ == '__main__':
# write_net()
gen_solver(solver_proto, train_proto, test_proto)
training(solver_proto)
2,制作infer.python文件,labels.txt,deploy.prototxt。最后包含查看net和blob的图。源码如下:
# -*- coding: utf-8 -*-
import os
import caffe
import numpy as np
import cv2
import sys
import matplotlib.pyplot as plt
# 文件路径设置
root = '/home/zhaoys/myf/lenet/lenet_pycaffe/' #根目录
deploy = root + 'deploy.prototxt'
caffe_model = root + 'snapshot/train_iter_50000.caffemodel'
labels = root + 'labels.txt'
# 生成网络
net = caffe.Net(deploy, caffe_model, caffe.TEST)
# 格式转换
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
# 添加类别信息
name = []
with open(labels, 'r+') as f:
for l in f.readlines():
name.append(l)
# 依次测试前5张图
for i in range(0, 5):
img = root + 'demo/test_{}.jpg'.format(i)
input_image = cv2.imread(img, cv2.IMREAD_GRAYSCALE).astype(np.float32)
net.blobs['data'].data[...] = transformer.preprocess('data', input_image)
out = net.forward() # 进行一次前向传播
prob = net.blobs['prob'].data[0].flatten() # softmax层每个类别的概率
print 'prob:' + str(prob)
maxprob = prob.argsort()[-1]
print 'class:' + str(name[maxprob])
# 查看net的参数和blob的数据
'''
for k, v in net.params.items(): # 查看各层的w参数值
print k
print v[0].data
for k, v in net.params.items(): # 查看各层的b参数值
print k
print v[1].data
for k, v in net.params.items(): # 查看各层的w参数值的维度
print k
print v[0].data.shape
for k, v in net.params.items(): # 查看各层的b参数值的维度
print k
print v[1].data.shape
w1 = net.params['Convolution1'][0].data # 查看Convolution1层的w参数值
print w1
b1 = net.params['Convolution1'][1].data # 查看Convolution1层的b参数值
print b1
for k, v in net.blobs.items(): # 查看各层的数据
print k
print v.data
for k, v in net.blobs.items(): # 查看各层的数据维度
print k
print v.data.shape
fea = net.blobs['Convolution2'].data[0, 0] # 查看第一个全连接的特征
cv2.imwrite('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/fea.png', fea)
'''
# 显示模型参数函数
'''
def show_feature(data, padsize = 1, padval = 0):
data -= data.min()
data /= data.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:])
return data
plt.rcParams['figure.figsize'] = (8, 8)
plt.rcParams['image.interpolation'] = 'nearest'
# plt.rcParams['image.cmap'] = 'gray'
for k, v in net.params.items(): # 查看各层的w参数值的维度
print k
print v[0].data.shape
weight = net.params["Convolution1"][0].data
net_conv1 = show_feature(weight.reshape(16, 5, 5))
plt.imshow(net_conv1)
plt.savefig('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/net_conv1.png')
weight = net.params["Convolution2"][0].data
net_conv2 = show_feature(weight.reshape(32 * 16, 3, 3))
plt.imshow(net_conv2)
plt.savefig('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/net_conv2.png')
for k, v in net.blobs.items(): # 查看各层的数据维度
print k
print v.data.shape
data = show_feature(net.blobs["data"].data[0])
plt.imshow(data)
plt.savefig('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/blob_data.png')
blob_conv1 = show_feature(net.blobs["Convolution1"].data[0])
plt.imshow(blob_conv1)
plt.savefig('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/blob_conv1.png')
blob_pool1 = show_feature(net.blobs["Pooling1"].data[0])
plt.imshow(blob_pool1)
plt.savefig('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/blob_pool1.png')
blob_conv2 = show_feature(net.blobs["Convolution2"].data[0])
plt.imshow(blob_conv2)
plt.savefig('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/blob_conv2.png')
blob_pool2 = show_feature(net.blobs["Pooling2"].data[0])
plt.imshow(blob_pool2)
plt.savefig('/home/zhaoys/myf/lenet/lenet_pycaffe/featuremap/blob_pool2.png')
'''
num0
num1
num2
num3
num4
num5
num6
num7
num8
num9
layer {
name: "data"
type: "Input"
top: "data"
input_param {
shape { dim: 1 dim: 1 dim: 28 dim: 28 }
}
}
layer {
name: "Convolution1"
type: "Convolution"
bottom: "data"
top: "Convolution1"
convolution_param {
num_output: 16
pad: 2
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
}
}
layer {
name: "ReLU1"
type: "ReLU"
bottom: "Convolution1"
top: "Convolution1"
}
layer {
name: "Pooling1"
type: "Pooling"
bottom: "Convolution1"
top: "Pooling1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "Convolution2"
type: "Convolution"
bottom: "Pooling1"
top: "Convolution2"
convolution_param {
num_output: 32
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "xavier"
}
}
}
layer {
name: "ReLU2"
type: "ReLU"
bottom: "Convolution2"
top: "Convolution2"
}
layer {
name: "Pooling2"
type: "Pooling"
bottom: "Convolution2"
top: "Pooling2"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "InnerProduct1"
type: "InnerProduct"
bottom: "Pooling2"
top: "InnerProduct1"
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
}
}
layer {
name: "ReLU3"
type: "ReLU"
bottom: "InnerProduct1"
top: "InnerProduct1"
}
layer {
name: "Dropout1"
type: "Dropout"
bottom: "InnerProduct1"
top: "InnerProduct1"
}
layer {
name: "InnerProduct2"
type: "InnerProduct"
bottom: "InnerProduct1"
top: "InnerProduct2"
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
}
}
layer {
name: "prob"
type: "Softmax"
bottom: "InnerProduct2"
top: "prob"
}
3,caffe学习总结
组成:Blob/layer/Net/Solver
层:SoftmaxWithLoss/Softmax/InnerProduct/Accuracy/Reshape/Dropout/
Activiation Layers:Sigmoid/ReLU/TanH/AbsVal/Power/BNLL/
Vision layers:Convolution/Pooling/LRN/im2col/
Data Layers:Data/MemoryData/HDF5Data/ImageData/WindowData/
优化方法:SGD/AdaDelta/AdaGrad/Adam/Nesterov/RMSProp/
参数设置:layer(...) solver(...)
caffe命令:caffe <command> <args> 例:sudo sh ./build/tools/caffe train --solver=examples/mnist/train_lenet.sh
command:train/test/device_query/time/
args:solver/gpu/snapshot/weights/iteration/model/sighup_effect/sigint_effect/
开发过程:
dataset->LMDB/jpg,png/
net->train.prototxt/test.prototxt/ -> caffemodel -> infer->deploy.prototxt/
solver->solver.prototxt/