1) 载入模块
import matplotlib.pyplot as plt
from pylab import *
# %matplotlib inline
caffe_root = '/home/cc/caffe-master/examples/' # this file should be run from {caffe_root}/examples (otherwise change this line)
import sys
# sys.path.insert(0, caffe_root + 'python')
# sys.path.insert(0, caffe_root + 'examples')
# sys.path.insert(0, caffe_root)
import caffe
# 网络结构:需要两个文件:
# lenet.prototxt:定义结构,指明训练,测试数据的维度
# solver.prototxt:定义参数
from caffe import layers as L, params as P
2) 定义网络
def lenet(lmdb, batch_size):
# our version of LeNet: a series of linear and simple nonlinear transformations
n = caffe.NetSpec()
n.data, n.label = L.Data(batch_size=batch_size, backend=P.Data.LMDB, source=lmdb,
transform_param=dict(scale=1. / 255), ntop=2)
n.conv1 = L.Convolution(n.data, kernel_size=5, num_output=20, weight_filler=dict(type='xavier'))
n.pool1 = L.Pooling(n.conv1, kernel_size=2, stride=2, pool=P.Pooling.MAX)
n.conv2 = L.Convolution(n.pool1, kernel_size=5, num_output=50, weight_filler=dict(type='xavier'))
n.pool2 = L.Pooling(n.conv2, kernel_size=2, stride=2, pool=P.Pooling.MAX)
n.fc1 = L.InnerProduct(n.pool2, num_output=500, weight_filler=dict(type='xavier'))
n.relu1 = L.ReLU(n.fc1, in_place=True)
n.score = L.InnerProduct(n.relu1, num_output=10, weight_filler=dict(type='xavier'))
n.loss = L.SoftmaxWithLoss(n.score, n.label)
return n.to_proto()
with open(caffe_root+'mnist/lenet_auto_train.prototxt', 'w') as f:
f.write(str(lenet(caffe_root+'mnist/mnist_train_lmdb', 64)))
with open(caffe_root+'mnist/lenet_auto_test.prototxt', 'w') as f:
f.write(str(lenet(caffe_root+'mnist/mnist_test_lmdb', 100)))
3) 定义求解器
# caffe.set_device(0)
# caffe.set_mode_gpu()
caffe.set_mode_cpu()
### load the solver and create train and test nets
solver = None # ignore this workaround for lmdb data (can't instantiate two solvers on the same data)
solver = caffe.SGDSolver(caffe_root+'mnist/lenet_auto_solver.prototxt') #默认SGD方法
4) 中间结果输出
# each output is (batch size, feature dim, spatial dim)
# [(k, v.data.shape) for k, v in solver.net.blobs.items()]
for k, v in solver.net.blobs.items():
print k, v.data.shape
# just print the weight sizes (we'll omit the biases)
for k, v in solver.net.params.items():
print '(k,v)', (k, v[0].data.shape)
solver.net.forward() # train net
solver.test_nets[0].forward() # test net (there can be more than one) #输出最后一层loss
# {'loss': array(2.3258860111236572, dtype=float32)}
# we use a little trick to tile the first eight images
# reshape按照行排列:[1 2 3 5]-->[[1 2],[3, 5]], 将图片(28,28,8)个按照一行排列(28,8*28)
plt.imshow(solver.net.blobs['data'].data[:8, 0].transpose(1, 0, 2).reshape(28, 8*28), cmap='gray'); axis('off')
# plt.show()
print 'train labels:', solver.net.blobs['label'].data[:8]
imshow(solver.test_nets[0].blobs['data'].data[:8, 0].transpose(1, 0, 2).reshape(28, 8*28), cmap='gray'); axis('off')
plt.show()
print 'test labels:', solver.test_nets[0].blobs['label'].data[:8]
# take one step of SGD
solver.step(1)
# 将20张图片按照4行5列排列
plt.imshow(solver.net.params['conv1'][0].diff[:, 0].reshape(4, 5, 5, 5)
.transpose(0, 2, 1, 3).reshape(4*5, 5*5), cmap='gray'); axis('off')
plt.show()
5)定义迭代次数,选取结果输出
#% % time
niter = 200
test_interval = 25
# losses will also be stored in the log
train_loss = zeros(niter)
test_acc = zeros(int(np.ceil(niter / test_interval))) #每隔多少次测试一次
output = zeros((niter, 8, 10)) #保存8个样本输出结果
# the main solver loop
for it in range(niter):
solver.step(1) # SGD by Caffe
# store the train loss
train_loss[it] = solver.net.blobs['loss'].data
# store the output on the first test batch
# (start the forward pass at conv1 to avoid loading new data)
solver.test_nets[0].forward(start='conv1') #
output[it] = solver.test_nets[0].blobs['score'].data[:8]#提取前8个输出(8,10) #(64,10)
# run a full test every so often
# (Caffe can also do this for us and write to a log, but we show here
# how to do it directly in Python, where more complicated things are easier.)
if it % test_interval == 0:
print 'Iteration', it, 'testing...'
correct = 0
for test_it in range(100):
solver.test_nets[0].forward()
correct += sum(solver.test_nets[0].blobs['score'].data.argmax(1)
== solver.test_nets[0].blobs['label'].data)
test_acc[it // test_interval] = correct / 1e4
# plot the train loss and test accuracy
plt.figure()
ax1 = subplot()
ax2 = ax1.twinx()
ax1.plot(arange(niter), train_loss)
ax2.plot(test_interval * arange(len(test_acc)), test_acc, 'r')
ax1.set_xlabel('iteration')
ax1.set_ylabel('train loss')
ax2.set_ylabel('test accuracy')
ax2.set_title('Test Accuracy: {:.2f}'.format(test_acc[-1]))
plt.show()
for i in range(8):
figure(figsize=(2, 2))
plt.imshow(solver.test_nets[0].blobs['data'].data[i, 0], cmap='gray')
figure(figsize=(10, 2))
plt.imshow(output[:50, i].T, interpolation='nearest', cmap='gray')
plt.show()
xlabel('iteration')
ylabel('label')
for i in range(8):
figure(figsize=(2, 2))
imshow(solver.test_nets[0].blobs['data'].data[i, 0], cmap='gray')
figure(figsize=(10, 2))
imshow(exp(output[:50, i].T) / exp(output[:50, i].T).sum(0), interpolation='nearest', cmap='gray')
plt.show()
xlabel('iteration')
ylabel('label')
6)按照上文创建自己的网络:
path_examples = '/home/cc/caffe-master/examples/'
train_net_path = path_examples + 'mnist/custom_auto_train.prototxt'
test_net_path = path_examples + 'mnist/custom_auto_test.prototxt'
solver_config_path = path_examples + 'mnist/custom_auto_solver.prototxt'
### define net
def custom_net(lmdb, batch_size):
# define your own net!
n = caffe.NetSpec()
# keep this data layer for all networks
n.data1, n.label = L.Data(batch_size=batch_size, backend=P.Data.LMDB, source=lmdb,
transform_param=dict(scale=1. / 255), ntop=2)
# 结果输出:
layer {
name: "data"
type: "Data"
top: "data1"
top: "label"
transform_param {
scale: 0.00392156885937
}
data_param {
source: "/home/cc/caffe-master/examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
}
# n.data定义了name和top, L.Data定义了layer和type, data_param, ntop数目:n.data, n.label
# EDIT HERE to try different networks
# this single layer defines a simple linear classifier
# (in particular this defines a multiway logistic regression)
# n.score = L.InnerProduct(n.data1, num_output=10, weight_filler=dict(type='xavier'))
# n.score定义了name和top, L.InnerProduct定义了type和inner_product_param. n.data输入数定义了bottom的数目
# EDIT HERE this is the LeNet variant we have already tried
n.conv1 = L.Convolution(n.data1, kernel_size=5, num_output=20, weight_filler=dict(type='xavier'))
n.pool1 = L.Pooling(n.conv1, kernel_size=2, stride=2, pool=P.Pooling.MAX)
n.conv2 = L.Convolution(n.pool1, kernel_size=5, num_output=50, weight_filler=dict(type='xavier'))
n.pool2 = L.Pooling(n.conv2, kernel_size=2, stride=2, pool=P.Pooling.MAX)
n.fc1 = L.InnerProduct(n.pool2, num_output=500, weight_filler=dict(type='xavier'))
# EDIT HERE consider L.ELU or L.Sigmoid for the nonlinearity
n.relu1 = L.ReLU(n.fc1, in_place=True)
n.score = L.InnerProduct(n.fc1, num_output=10, weight_filler=dict(type='xavier'))
#
# # keep this loss layer for all networks
n.loss = L.SoftmaxWithLoss(n.score, n.label)
return n.to_proto()
#调用函数进行初始化
with open(train_net_path, 'w') as f:
f.write(str(custom_net(path_examples + 'mnist/mnist_train_lmdb', 64)))
with open(test_net_path, 'w') as f:
f.write(str(custom_net(path_examples + 'mnist/mnist_test_lmdb', 100)))
### define solver
from caffe.proto import caffe_pb2
s = caffe_pb2.SolverParameter()
# Set a seed for reproducible experiments:
# this controls for randomization in training.
s.random_seed = 0xCAFFE
# Specify locations of the train and (maybe) test networks.
s.train_net = train_net_path #定义训练.prototxt文件所在路径
s.test_net.append(test_net_path)
s.test_interval = 500 # Test after every 500 training iterations.
s.test_iter.append(100) # Test on 100 batches each time we test. 每次100个样本测试
s.max_iter = 10000 # no. of times to update the net (training iterations)
# EDIT HERE to try different solvers
# solver types include "SGD", "Adam", and "Nesterov" among others.
s.type = "SGD"
# Set the initial learning rate for SGD.
s.base_lr = 0.01 # EDIT HERE to try different learning rates
# Set momentum to accelerate learning by
# taking weighted average of current and previous updates.
s.momentum = 0.9
# Set weight decay to regularize and prevent overfitting
s.weight_decay = 5e-4
# Set `lr_policy` to define how the learning rate changes during training.
# This is the same policy as our default LeNet.
s.lr_policy = 'inv'
s.gamma = 0.0001
s.power = 0.75
# EDIT HERE to try the fixed rate (and compare with adaptive solvers)
# `fixed` is the simplest policy that keeps the learning rate constant.
# s.lr_policy = 'fixed'
# Display the current training loss and accuracy every 1000 iterations.
s.display = 1000
# Snapshots are files used to store networks we've trained.
# We'll snapshot every 5K iterations -- twice during training.
s.snapshot = 5000
s.snapshot_prefix = path_examples + 'mnist/custom_net' #快照保存文件名和地址
# Train on the GPU
# s.solver_mode = caffe_pb2.SolverParameter.GPU
s.solver_mode = caffe_pb2.SolverParameter.CPU
# Write the solver to a temporary file and return its filename.
with open(solver_config_path, 'w') as f:
f.write(str(s))
### load the solver and create train and test nets
solver = None # ignore this workaround for lmdb data (can't instantiate two solvers on the same data)
solver = caffe.get_solver(solver_config_path)# load the solver in python
# 也可以采用solver = caffe.SGDSolver('solver.prototxt')#但它只用SGD算法,不管文件里设置什么
### solve
niter = 250 # EDIT HERE increase to train for longer
test_interval = niter / 10
# losses will also be stored in the log
train_loss = zeros(niter)
test_acc = zeros(int(np.ceil(niter / test_interval)))
# the main solver loop
for it in range(niter):
solver.step(1) # SGD by Caffe
#只进行一步前向,反向和梯度更新. solver.step()会执行所有的步数
#solver.step():可以采用如下命令代替:
# solver.net.forward()#train net solver.test_nets[0].forward()#test net
# solver.net.backward()
# store the train loss
train_loss[it] = solver.net.blobs['loss'].data
# run a full test every so often
# (Caffe can also do this for us and write to a log, but we show here
# how to do it directly in Python, where more complicated things are easier.)
if it % test_interval == 0:
print 'Iteration', it, 'testing...'
correct = 0
for test_it in range(100):
solver.test_nets[0].forward()
correct += sum(solver.test_nets[0].blobs['score'].data.argmax(1)
== solver.test_nets[0].blobs['label'].data)
test_acc[it // test_interval] = correct / 1e4
ax1 = subplot()
ax2 = ax1.twinx()
ax1.plot(arange(niter), train_loss)
ax2.plot(test_interval * arange(len(test_acc)), test_acc, 'r')
plt.show()
ax1.set_xlabel('iteration')
ax1.set_ylabel('train loss')
ax2.set_ylabel('test accuracy')
ax2.set_title('Custom Test Accuracy: {:.2f}'.format(test_acc[-1]))