from __future__ import division
import numpy as np
import sys
caffe_root = '../../'
sys.path.insert(0, caffe_root + 'python') # 确保已经 make pycaffe 了,也可以直接把路径加到 $PYTHONPATH 里
import caffe
# make a bilinear interpolation kernel
# credit @longjon
def upsample_filt(size):
factor = (size + 1) // 2 # ‘//’ 确保了结果是整数,和‘/’不一样
if size % 2 == 1:
center = factor - 1
else:
center = factor - 0.5
og = np.ogrid[:size, :size]
return (1 - abs(og[0] - center) / factor) * \
(1 - abs(og[1] - center) / factor)
# set parameters s.t. deconvolutional layers compute bilinear interpolation
# N.B. this is for deconvolution without groups
# N.B. 啥意思?:
# Derived from the Latin (and italian) nota bene, meaning note well (take notice).:
# It is used to draw the attention to a certain aspect.
def interp_surgery(net, layers):
for l in layers:
m, k, h, w = net.params[l][0].data.shape
if m != k:
print 'input + output channels need to be the same'
raise
if h != w:
print 'filters need to be square'
raise
filt = upsample_filt(h)
# 对 layer l 的 weights 进行设置(设置一个 filter)
net.params[l][0].data[range(m), range(k), :, :] = filt
x = [[1, 2], [3, 4]]
print x
mask = upsample_filt(2)
print mask
[[1, 2], [3, 4]] [[ 0.25 0.25] [ 0.25 0.25]]
# base net -- follow the editing model parameters example to make
# a fully convolutional VGG16 net.
# http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/net_surgery.ipynb
base_weights = '5stage-vgg.caffemodel'
# init
caffe.set_mode_gpu()
caffe.set_device(0)
solver = caffe.SGDSolver('solver.prototxt')
!cat solver.prototxt
net: "train_val.prototxt" test_iter: 0 test_interval: 1000000 # lr for fine-tuning should be lower than when starting from scratch #debug_info: true base_lr: 0.000001 lr_policy: "step" gamma: 0.1 iter_size: 10 # stepsize should also be lower, as we're closer to being done stepsize: 10000 display: 20 max_iter: 30001 momentum: 0.9 weight_decay: 0.0002 snapshot: 1000 snapshot_prefix: "hed" # uncomment the following to default to CPU mode solving # solver_mode: CPU
# do net surgery to set the deconvolution weights for bilinear interpolation
interp_layers = [k for k in solver.net.params.keys() if 'up' in k]
interp_surgery(solver.net, interp_layers)
print interp_layers
interp_surgery?
['upsample_2', 'upsample_4', 'upsample_8', 'upsample_16']
# copy base weights for fine-tuning
# solver.restore('dsn-full-res-3-scales_iter_29000.solverstate')
solver.net.copy_from(base_weights)
# solve straight through -- a better approach is to define a solving loop to
# 1. take SGD steps
# 2. score the model by the test net `solver.test_nets[0]`
# 3. repeat until satisfied
# solver.step(100000)
# step?
solver.step?
Docstring:
step( (Solver)arg1, (int)arg2) -> None :
C++ signature :
void step(caffe::Solver<float> {lvalue},int)
Type: instancemethod
上面最后一句,会跑很久。一路生成很多 model 文件和 solvestate 文件,比如
hed_iter_41000.caffemodel
, hed_iter_41000.solverstate
。过程会很慢。