From ee80bcda8818cc4474dbaf2fd959a8307ae09d5d Mon Sep 17 00:00:00 2001 From: shicai Date: Sun, 9 Aug 2015 15:05:55 +0800 Subject: [PATCH 1/9] Update test_caffe_manual.cpp --- test_caffe_manual.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test_caffe_manual.cpp b/test_caffe_manual.cpp index 27a0bea..3d06015 100644 --- a/test_caffe_manual.cpp +++ b/test_caffe_manual.cpp @@ -101,6 +101,11 @@ int main(int argc, char** argv) { boost::shared_ptr > layer; boost::shared_ptr > blob; + // show input blob size + Blob* input_blobs = net->input_blobs()[0]; + std::cout << "\nInput blob size:\n"; + PRINT_SHAPE2(input_blobs); + // processing blobs of each layer, namely, weights and bias const float *mem_ptr; CHECK(layers.size() == layer_names.size()); From 7852be107773d835dcb42127285a5dcb2ec7ab35 Mon Sep 17 00:00:00 2001 From: shicai Date: Sun, 9 Aug 2015 15:33:44 +0800 Subject: [PATCH 2/9] Create test_caffe_manual_output.log --- test_caffe_manual_output.log | 121 +++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 test_caffe_manual_output.log diff --git a/test_caffe_manual_output.log b/test_caffe_manual_output.log new file mode 100644 index 0000000..b9b1314 --- /dev/null +++ b/test_caffe_manual_output.log @@ -0,0 +1,121 @@ +read image mean succeeded +196608 +1 3 256 256 +110.177 110.459 + +Input blob size: +10 3 227 227 + +#Layers: 23 + +[1] layer name: conv1, type: Convolution +#Blobs: 2 +96 3 11 11 +-0.00121359 0.00323653 +96 1 1 1 +-0.504212 -0.188764 + +[2] layer name: relu1, type: ReLU +#Blobs: 0 + +[3] layer name: pool1, type: Pooling +#Blobs: 0 + +[4] layer name: norm1, type: LRN +#Blobs: 0 + +[5] layer name: conv2, type: Convolution +#Blobs: 2 +256 48 5 5 +-0.0111258 0.0218567 +256 1 1 1 +0.982103 0.994344 + +[6] layer name: relu2, type: ReLU +#Blobs: 0 + +[7] layer name: pool2, type: Pooling +#Blobs: 0 + +[8] layer name: norm2, type: LRN +#Blobs: 0 + +[9] layer name: conv3, type: Convolution +#Blobs: 2 +384 256 3 3 +-0.000527019 0.00534925 +384 1 1 1 +-0.000547366 -0.00652369 + +[10] layer name: relu3, type: ReLU +#Blobs: 0 + +[11] layer name: conv4, type: Convolution +#Blobs: 2 +384 192 3 3 +0.00378311 0.000618855 +384 1 1 1 +0.884884 1.02955 + +[12] layer name: relu4, type: ReLU +#Blobs: 0 + +[13] layer name: conv5, type: Convolution +#Blobs: 2 +256 192 3 3 +-0.0134502 -0.0174268 +256 1 1 1 +0.982957 1.04293 + +[14] layer name: relu5, type: ReLU +#Blobs: 0 + +[15] layer name: pool5, type: Pooling +#Blobs: 0 + +[16] layer name: fc6, type: InnerProduct +#Blobs: 2 +4096 9216 1 1 +0.00639847 0.00915686 +4096 1 1 1 +0.983698 1.00962 + +[17] layer name: relu6, type: ReLU +#Blobs: 0 + +[18] layer name: drop6, type: Dropout +#Blobs: 0 + +[19] layer name: fc7, type: InnerProduct +#Blobs: 2 +4096 4096 1 1 +0.0125212 -0.0134137 +4096 1 1 1 +1.09399 0.999266 + +[20] layer name: relu7, type: ReLU +#Blobs: 0 + +[21] layer name: drop7, type: Dropout +#Blobs: 0 + +[22] layer name: fc8, type: InnerProduct +#Blobs: 2 +1000 4096 1 1 +0.000160601 -0.010393 +1000 1 1 1 +-0.196648 -0.100678 + +[23] layer name: prob, type: Softmax +#Blobs: 0 + +weights and bias from layer: conv1 +-0.00121359 0.00323653 +-0.504212 -0.188764 + +new weights and bias from layer: conv1 +1.1111 2.2222 + +#Features: 2904000 +0 0 +END From 7e8e561ac31f39794d827bf4daca4c51868b3529 Mon Sep 17 00:00:00 2001 From: shicai Date: Mon, 10 Aug 2015 18:27:32 +0800 Subject: [PATCH 3/9] Create get_features.cpp this code is to show how to get features from pretrained models. --- get_features.cpp | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 get_features.cpp diff --git a/get_features.cpp b/get_features.cpp new file mode 100644 index 0000000..447ca71 --- /dev/null +++ b/get_features.cpp @@ -0,0 +1,189 @@ +/*** + usage: + get_features.exe feat.prototxt H:\Models\Caffe\bvlc_reference_caffenet.caffemodel 6 + conv1,fc7,prob,argmax conv1.dat,fc7.dat,prob.dat,argmax.dat GPU 0 + + for feat.prototxt, see the following example: + name: "CaffeNet" + state { + phase: TEST + } + layer { + name: "data" + type: "ImageData" + top: "data" + top: "label" + transform_param { + mirror: false + crop_size: 227 + mean_file: "imagenet_mean.binaryproto" + } + image_data_param { + source: "file_list.txt" + batch_size: 1 + new_height: 256 + new_width: 256 + } + } + layer { + name: "conv1" + type: "Convolution" + bottom: "data" + top: "conv1" + convolution_param { + num_output: 96 + kernel_size: 11 + stride: 4 + } + } + ################################################################################# + ######some lines are ignored here for simplicity, complete them by yourself###### + ################################################################################# + layer { + name: "fc8" + type: "InnerProduct" + bottom: "fc7" + top: "fc8" + inner_product_param { + num_output: 1000 + } + } + layer { + name: "prob" + type: "Softmax" + bottom: "fc8" + top: "prob" + } + layer { + name: "argmax" + type: "ArgMax" + bottom: "prob" + top: "argmax" + argmax_param { + top_k: 1 + } + } + + for file_list.txt, see the following example: + H:\Data\ILSVRC2012\n01440764\n01440764_18.JPEG 0 + H:\Data\ILSVRC2012\n01440764\n01440764_297.JPEG 0 + H:\Data\ILSVRC2012\n01443537\n01443537_395.JPEG 1 + H:\Data\ILSVRC2012\n01443537\n01443537_693.JPEG 1 + H:\Data\ILSVRC2012\n01518878\n01518878_103.JPEG 9 + H:\Data\ILSVRC2012\n01518878\n01518878_477.JPEG 9 + + How to load features in Matlab? use the following function, see: + prob = sc_load('prob.dat'); + + function data = sc_load(filename, type) + if ~exist('type', 'var') || isempty(type) + type = 'single'; + end + + fid = fopen(filename, 'r'); + rows = fread(fid, 1, type); + cols = fread(fid, 1, type); + data = fread(fid, rows * cols, type); + fclose(fid); + + data = reshape(data, rows, cols); + switch type + case 'int32' + data = int32(data); + case 'single' + data = single(data); + end + end + +***/ + +#include +#include +#include "boost/algorithm/string.hpp" +#include "caffe/caffe.hpp" +using boost::shared_ptr; +using std::string; +using namespace caffe; + +#define MAX_FEAT_NUM 16 + +int main(int argc, char** argv) +{ + if (argc < 6) + { + LOG(ERROR) << "get_features proto_file model_file iterations blob_name1[,name2] save_name1[,name2]" + << "[CPU/GPU] [Device ID]"; + return 1; + } + + Phase phase = TEST; + if (argc >= 7 && strcmp(argv[6], "GPU") == 0) + { + Caffe::set_mode(Caffe::GPU); + int device_id = 0; + if (argc == 8) + { + device_id = atoi(argv[7]); + } + Caffe::SetDevice(device_id); + LOG(ERROR) << "Using GPU #" << device_id; + } else { + LOG(ERROR) << "Using CPU"; + Caffe::set_mode(Caffe::CPU); + } + + boost::shared_ptr > feature_net; + feature_net.reset(new Net(argv[1], phase)); + feature_net->CopyTrainedLayersFrom(argv[2]); + + int total_iter = atoi(argv[3]); + LOG(ERROR) << "Running " << total_iter << " iterations."; + + std::string feature_blob_names(argv[4]); + std::vector blob_names; + boost::split(blob_names, feature_blob_names, boost::is_any_of(",")); + + std::string save_file_names(argv[5]); + std::vector file_names; + boost::split(file_names, save_file_names, boost::is_any_of(",")); + CHECK_EQ(blob_names.size(), file_names.size()) << + " the number of blob names and dataset names must be equal"; + + size_t num_features = blob_names.size(); + for (size_t i = 0; i < num_features; i++) + { + CHECK(feature_net->has_blob(blob_names[i])) + << "Unknown feature blob name " << blob_names[i] << " in the network"; + } + + FILE *fp[MAX_FEAT_NUM]; + for (size_t i = 0; i < num_features; i++) + { + fp[i] = fopen(file_names[i].c_str(), "wb"); + } + + for (int i = 0; i < total_iter; ++i) + { + feature_net->ForwardPrefilled(); + for (int j = 0; j < num_features; ++j) + { + const boost::shared_ptr > feature_blob = feature_net->blob_by_name(blob_names[j]); + float num_imgs = feature_blob->num() * total_iter; + float feat_dim = feature_blob->count() / feature_blob->num(); + const float* data_ptr = (const float *) feature_blob->cpu_data(); + + if (i == 0) + { + fwrite(&feat_dim, sizeof(float), 1, fp[j]); + fwrite(&num_imgs, sizeof(float), 1, fp[j]); + } + fwrite(data_ptr, sizeof(float), feature_blob->count(), fp[j]); + } + } + + for (size_t i = 0; i < num_features; i++) + { + fclose(fp[i]); + } + return 0; +} From 7b2665c317c96ee2b787aad9ee43f364d0725b4c Mon Sep 17 00:00:00 2001 From: shicai Date: Mon, 10 Aug 2015 18:45:55 +0800 Subject: [PATCH 4/9] Update ReadMe.md add descriptions for get_features.cpp file --- ReadMe.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index 72d63eb..00c4ca2 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -87,6 +87,18 @@ by Shicai Yang([@星空下的巫师](http://weibo.com/shicaiyang))on 2015/08 unsigned int num_data = blob->count(); /* NCHW=10x96x55x55 */ const float *blob_ptr = (const float *) blob->cpu_data(); +### 根据文件列表,获取特征,并存为二进制文件 + +详见**get_features.cpp**文件: +> 主要包括三个步骤 +- 生成文件列表,格式与训练用的类似,每行一个图像 +包括文件全路径、空格、标签(没有的话,可以置0) +- 根据train_val或者deploy的prototxt,改写生成feat.prototxt +主要是将输入层改为image_data层,最后加上prob和argmax(为了输出概率和Top1/5预测标签) +- 根据指定参数,运行程序后会生成若干个二进制文件,可以用MATLAB读取数据,进行分析 + + + ### 根据Layer的名字获取其在网络中的Index //! Note: Layer包括神经网络所有层,比如,CaffeNet共有23层 From 33933cc721876caa1adc6d49b5c2480ab3cfdd8c Mon Sep 17 00:00:00 2001 From: shicai Date: Mon, 10 Aug 2015 18:49:00 +0800 Subject: [PATCH 5/9] Create sc_load.m --- sc_load.m | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 sc_load.m diff --git a/sc_load.m b/sc_load.m new file mode 100644 index 0000000..222dda7 --- /dev/null +++ b/sc_load.m @@ -0,0 +1,17 @@ +function data = sc_load(filename, type) + if ~exist('type', 'var') || isempty(type) + type = 'single'; + end + fid =fopen(filename, 'r'); + rows = fread(fid, 1, type); + cols = fread(fid, 1, type); + data = fread(fid, rows * cols, type); + fclose(fid); + data = reshape(data, rows, cols); + switch type + case 'int32' + data = int32(data); + case 'single' + data = single(data); + end +end From 39a19c0f91f1f7a49e6eabccae2e8daf5d451160 Mon Sep 17 00:00:00 2001 From: shicai Date: Mon, 10 Aug 2015 18:54:49 +0800 Subject: [PATCH 6/9] Update get_features.cpp fix some typos --- get_features.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get_features.cpp b/get_features.cpp index 447ca71..f502c39 100644 --- a/get_features.cpp +++ b/get_features.cpp @@ -147,7 +147,7 @@ int main(int argc, char** argv) std::vector file_names; boost::split(file_names, save_file_names, boost::is_any_of(",")); CHECK_EQ(blob_names.size(), file_names.size()) << - " the number of blob names and dataset names must be equal"; + " the number of feature blob names and save file names must be equal"; size_t num_features = blob_names.size(); for (size_t i = 0; i < num_features; i++) From fe598a53687bd0dc154fd49ffc1ca8479bc2d01a Mon Sep 17 00:00:00 2001 From: shicai Date: Thu, 19 Nov 2015 15:47:09 +0800 Subject: [PATCH 7/9] Update ReadMe.md --- ReadMe.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index 00c4ca2..81b60ab 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -22,6 +22,23 @@ by Shicai Yang([@星空下的巫师](http://weibo.com/shicaiyang))on 2015/08 char *model = "H:\\Models\\Caffe\\bvlc_reference_caffenet.caffemodel"; net->CopyTrainedLayersFrom(model); +### 读取模型中的每层的结构配置参数(如name,type,kernel size,pad,stride等) + + char *model = "H:\\Models\\Caffe\\bvlc_reference_caffenet.caffemodel"; + ReadNetParamsFromBinaryFileOrDie(model, ¶m); + int num_layers = param.layer_size(); + for (int i = 0; i < num_layers; ++i) + { + LOG(ERROR) << "Layer " << i << ":" << param.layer(i).name() << "\t" << param.layer(i).type(); + if (param.layer(i).type() == "Convolution") + { + ConvolutionParameter conv_param = param.layer(i).convolution_param(); + LOG(ERROR) << "\t\tkernel size: " << conv_param.kernel_size() + << ", pad: " << conv_param.pad() + << ", stride: " << conv_param.stride(); + } + } + ### 读取图像均值 char *mean_file = "H:\\Models\\Caffe\\imagenet_mean.binaryproto"; From f7efeef66d9756eebb739964c03f6239fffeca2d Mon Sep 17 00:00:00 2001 From: shicai Date: Thu, 19 Nov 2015 15:48:33 +0800 Subject: [PATCH 8/9] Update ReadMe.md --- ReadMe.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 81b60ab..55411b2 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -22,13 +22,14 @@ by Shicai Yang([@星空下的巫师](http://weibo.com/shicaiyang))on 2015/08 char *model = "H:\\Models\\Caffe\\bvlc_reference_caffenet.caffemodel"; net->CopyTrainedLayersFrom(model); -### 读取模型中的每层的结构配置参数(如name,type,kernel size,pad,stride等) +### 读取模型中的每层的结构配置参数 char *model = "H:\\Models\\Caffe\\bvlc_reference_caffenet.caffemodel"; ReadNetParamsFromBinaryFileOrDie(model, ¶m); int num_layers = param.layer_size(); for (int i = 0; i < num_layers; ++i) { + // 结构配置参数:name,type,kernel size,pad,stride等 LOG(ERROR) << "Layer " << i << ":" << param.layer(i).name() << "\t" << param.layer(i).type(); if (param.layer(i).type() == "Convolution") { From 8e0c3a8c980a6d5149b394531e62b75a6bd01332 Mon Sep 17 00:00:00 2001 From: shicai Date: Thu, 19 Nov 2015 15:51:56 +0800 Subject: [PATCH 9/9] Update ReadMe.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 读取模型中的每层的结构配置参数 --- ReadMe.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReadMe.md b/ReadMe.md index 55411b2..ebb500b 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -25,6 +25,7 @@ by Shicai Yang([@星空下的巫师](http://weibo.com/shicaiyang))on 2015/08 ### 读取模型中的每层的结构配置参数 char *model = "H:\\Models\\Caffe\\bvlc_reference_caffenet.caffemodel"; + NetParameter param; ReadNetParamsFromBinaryFileOrDie(model, ¶m); int num_layers = param.layer_size(); for (int i = 0; i < num_layers; ++i)