8000 Improved matcaffe by sguada · Pull Request #223 · BVLC/caffe · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Improved matcaffe #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 2, 2014
64 changes: 0 additions & 64 deletions examples/imagenet/imagenet_deploy.prototxt
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ layers {
num_output: 96
kernel_size: 11
stride: 4
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
layers {
Expand Down Expand Up @@ -69,14 +61,6 @@ layers {
pad: 2
kernel_size: 5
group: 2
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 1
}
}
}
layers {
Expand Down Expand Up @@ -120,14 +104,6 @@ layers {
num_output: 384
pad: 1
kernel_size: 3
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
layers {
Expand All @@ -150,14 +126,6 @@ layers {
pad: 1
kernel_size: 3
group: 2
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 1
}
}
}
layers {
Expand All @@ -180,14 +148,6 @@ layers {
pad: 1
kernel_size: 3
group: 2
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 1
}
}
}
layers {
Expand Down Expand Up @@ -218,14 +178,6 @@ layers {
weight_decay: 0
inner_product_param {
num_output: 4096
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 1
}
}
}
layers {
Expand Down Expand Up @@ -254,14 +206,6 @@ layers {
weight_decay: 0
inner_product_param {
num_output: 4096
weight_filler {
type: "gaussian"
std: 0.005
}
bias_filler {
type: "constant"
value: 1
}
}
}
layers {
Expand Down Expand Up @@ -290,14 +234,6 @@ layers {
weight_decay: 0
inner_product_param {
num_output: 1000
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
}
}
layers {
Expand Down
95 changes: 83 additions & 12 deletions matlab/caffe/matcaffe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static int init_key = -2;
//
// The actual forward function. It takes in a cell array of 4-D arrays as
// input and outputs a cell array.

static mxArray* do_forward(const mxArray* const bottom) {
vector<Blob<float>*>& input_blobs = net_->input_blobs();
CHECK_EQ(static_cast<unsigned int>(mxGetDimensions(bottom)[0]),
Expand All @@ -67,8 +68,11 @@ static mxArray* do_forward(const mxArray* const bottom) {
const vector<Blob<float>*>& output_blobs = net_->ForwardPrefilled();
mxArray* mx_out = mxCreateCellMatrix(output_blobs.size(), 1);
for (unsigned int i = 0; i < output_blobs.size(); ++i) {
mxArray* mx_blob = mxCreateNumericMatrix(output_blobs[i]->count(),
1, mxSINGLE_CLASS, mxREAL);
// internally data is stored as (width, height, channels, num)
// where width is the fastest dimension
mwSize dims[4] = {output_blobs[i]->width(), output_blobs[i]->height(),
output_blobs[i]->channels(), output_blobs[i]->num()};
mxArray* mx_blob = mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL);
mxSetCell(mx_out, i, mx_blob);
float* data_ptr = reinterpret_cast<float*>(mxGetPr(mx_blob));
switch (Caffe::mode()) {
Expand All @@ -88,11 +92,63 @@ static mxArray* do_forward(const mxArray* const bottom) {
return mx_out;
}

static mxArray* do_backward(const mxArray* const top_diff) {
vector<Blob<float>*>& output_blobs = net_->output_blobs();
vector<Blob<float>*>& input_blobs = net_->input_blobs();
CHECK_EQ(static_cast<unsigned int>(mxGetDimensions(top_diff)[0]),
output_blobs.size());
// First, copy the output diff
for (unsigned int i = 0; i < output_blobs.size(); ++i) {
const mxArray* const elem = mxGetCell(top_diff, i);
const float* const data_ptr =
reinterpret_cast<const float* const>(mxGetPr(elem));
switch (Caffe::mode()) {
case Caffe::CPU:
memcpy(output_blobs[i]->mutable_cpu_diff(), data_ptr,
sizeof(float) * output_blobs[i]->count());
break;
case Caffe::GPU:
cudaMemcpy(output_blobs[i]->mutable_gpu_diff(), data_ptr,
sizeof(float) * output_blobs[i]->count(), cudaMemcpyHostToDevice);
break;
default:
LOG(FATAL) << "Unknown Caffe mode.";
} // switch (Caffe::mode())
}
// LOG(INFO) << "Start";
net_->Backward();
// LOG(INFO) << "End";
mxArray* mx_out = mxCreateCellMatrix(input_blobs.size(), 1);
for (unsigned int i = 0; i < input_blobs.size(); ++i) {
// internally data is stored as (width, height, channels, num)
// where width is the fastest dimension
mwSize dims[4] = {input_blobs[i]->width(), input_blobs[i]->height(),
input_blobs[i]->channels(), input_blobs[i]->num()};
mxArray* mx_blob = mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL);
mxSetCell(mx_out, i, mx_blob);
float* data_ptr = reinterpret_cast<float*>(mxGetPr(mx_blob));
switch (Caffe::mode()) {
case Caffe::CPU:
memcpy(data_ptr, input_blobs[i]->cpu_diff(),
sizeof(float) * input_blobs[i]->count());
break;
case Caffe::GPU:
cudaMemcpy(data_ptr, input_blobs[i]->gpu_diff(),
sizeof(float) * input_blobs[i]->count(), cudaMemcpyDeviceToHost);
break;
default:
LOG(FATAL) << "Unknown Caffe mode.";
} // switch (Caffe::mode())
}

return mx_out;
}

static mxArray* do_get_weights() {
const vector<shared_ptr<Layer<float> > >& layers = net_->layers();
const vector<string>& layer_names = net_->layer_names();

// Step 1: count the number of layers
// Step 1: count the number of layers with weights
int num_layers = 0;
{
string prev_layer_name = "";
Expand Down Expand Up @@ -142,16 +198,12 @@ static mxArray* do_get_weights() {
// where width is the fastest dimension
mwSize dims[4] = {layer_blobs[j]->width(), layer_blobs[j]->height(),
layer_blobs[j]->channels(), layer_blobs[j]->num()};
mxArray* mx_weights = mxCreateNumericArray(4, dims, mxSINGLE_CLASS,
mxREAL);

mxArray* mx_weights =
mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL);
mxSetCell(mx_layer_cells, j, mx_weights);
float* weights_ptr = reinterpret_cast<float*>(mxGetPr(mx_weights));

// mexPrintf("layer: %s (%d) blob: %d %d: (%d, %d, %d) %d\n",
// layer_names[i].c_str(), i, j, layer_blobs[j]->num(),
// layer_blobs[j]->height(), layer_blobs[j]->width(),
// layer_blobs[j]->channels(), layer_blobs[j]->count());

switch (Caffe::mode()) {
case Caffe::CPU:
memcpy(weights_ptr, layer_blobs[j]->cpu_data(),
Expand Down Expand Up @@ -220,13 +272,21 @@ static void init(MEX_ARGS) {
mxFree(param_file);
mxFree(model_file);

// NOLINT_NEXT_LINE(runtime/threadsafe_fn)
init_key = rand();
init_key = random();

if (nlhs == 1) {
plhs[0] = mxCreateDoubleScalar(init_key);
}
}

static void reset(MEX_ARGS) {
if (net_) {
net_.reset();
init_key = -2;
LOG(INFO) << "Network reset, call init before use it again";
}
}

static void forward(MEX_ARGS) {
if (nrhs != 1) {
LOG(ERROR) << "Only given " << nrhs << " arguments";
Expand All @@ -236,6 +296,15 @@ static void forward(MEX_ARGS) {
plhs[0] = do_forward(prhs[0]);
}

static void backward(MEX_ARGS) {
if (nrhs != 1) {
LOG(ERROR) << "Only given " << nrhs << " arguments";
mexErrMsgTxt("Wrong number of arguments");
}

plhs[0] = do_backward(prhs[0]);
}

static void is_initialized(MEX_ARGS) {
if (!net_) {
plhs[0] = mxCreateDoubleScalar(0);
Expand All @@ -255,6 +324,7 @@ struct handler_registry {
static handler_registry handlers[] = {
// Public API functions
{ "forward", forward },
{ "backward", backward },
{ "init", init },
{ "is_initialized", is_initialized },
{ "set_mode_cpu", set_mode_cpu },
Expand All @@ -264,6 +334,7 @@ static handler_registry handlers[] = {
{ "set_device", set_device },
{ "get_weights", get_weights },
{ "get_init_key", get_init_key },
{ "reset", reset },
// The end.
{ "END", NULL },
};
Expand Down
76 changes: 76 additions & 0 deletions matlab/caffe/matcaffe_batch.m
C8A1
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
function [scores,list_im] = matcaffe_batch(list_im, use_gpu)
% scores = matcaffe_batch(list_im, use_gpu)
%
% Demo of the matlab wrapper using the ILSVRC network.
%
% input
% list_im list of images files
% use_gpu 1 to use the GPU, 0 to use the CPU
%
% output
% scores 1000 x num_images ILSVRC output vector
%
% You may need to do the following before you start matlab:
% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64
% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6
% Or the equivalent based on where things are installed on your system
%
% Usage:
% scores = matcaffe_batch({'peppers.png','onion.png'});
% scores = matcaffe_batch('list_images.txt', 1);
if nargin < 1
% For test purposes
list_im = {'peppers.png','onions.png'};
end
if ischar(list_im)
%Assume it is a file contaning the list of images
filename = list_im;
list_im = read_cell(filename);
end
% Adjust the batch size to match with imagenet_deploy.prototxt
batch_size = 10;
% Adjust dim to the output size of imagenet_deploy.prototxt
dim = 1000;
disp(list_im)
if mod(length(list_im),batch_size)
warning(['Assuming batches of ' num2str(batch_size) ' images rest will be filled with zeros'])
end

% init caffe network (spews logging info)
if exist('use_gpu', 'var')
matcaffe_init(use_gpu);
else
matcaffe_init();
end

d = load('ilsvrc_2012_mean');
IMAGE_MEAN = d.image_mean;

% prepare input

num_images = length(list_im);
scores = zeros(dim,num_images,'single');
num_batches = ceil(length(list_im)/batch_size)
initic=tic;
for bb = 1 : num_batches
batchtic = tic;
range = 1+batch_size*(bb-1):min(num_images,batch_size * bb);
tic
input_data = prepare_batch(list_im(range),IMAGE_MEAN,batch_size);
toc, tic
fprintf('Batch %d out of %d %.2f%% Complete ETA %.2f seconds\n',...
bb,num_batches,bb/num_batches*100,toc(initic)/bb*(num_batches-bb));
output_data = caffe('forward', {input_data});
toc
output_data = squeeze(output_data{1});
scores(:,range) = output_data(:,mod(range-1,batch_size)+1);
toc(batchtic)
end
toc(initic);

if exist('filename', 'var')
save([filename '.probs.mat'],'list_im','scores','-v7.3');
end



Loading
0