如何在caffe中提取图层的blob信息?
How to extract layers' blob information in caffe?
我在 C++
.
中使用 caffe 进行机器学习
作为net_->Forward();
通过网络后,我喜欢提取个别层的信息。
我做的是
net_->Forward();
//Extract layer information
cout << "Num layers:" << "'" << net_->layer_names().size() << "'"<< endl;
for (int layer_index = 0; layer_index < net_->layer_names().size(); ++layer_index)
{
// get that layer blob and its dimension
const boost::shared_ptr<Blob<float> > blob = net_->blob_by_name(net_->blob_names()[layer_index]);
int batch_size = blob->num();
int dim_features = blob->count() / batch_size;
std::cout << "Layer name:" << "'" << net_->layer_names()[layer_index] << "'" << " Blob name:" << "'" <<net_->blob_names()[layer_index] << "'" << " batch size " << "'" << batch_size << "'" << " dim_features:" << "'" << dim_features << "'" << std::endl;
}
我可以看到所有图层名称和尺寸。
Layer name'image' Blob name'image' batch_size'1' dim_features'921600'
Layer name'conv1/7x7_s2' Blob name'conv1/7x7_s2' batch_size'1' dim_features'4915200'
Layer name'conv1/relu_7x7' Blob name'pool1/3x3_s2' batch_size'1' dim_features'1228800'
Layer name'pool1/3x3_s2' Blob name'pool1/norm1' batch_size'1' dim_features'1228800'
Layer name'pool1/norm1' Blob name'conv2/3x3_reduce' batch_size'1' dim_features'1228800'
Layer name'conv2/3x3_reduce' Blob name'conv2/3x3' batch_size'1' dim_features'3686400'
Layer name'conv2/relu_3x3_reduce' Blob name'conv2/norm2' batch_size'1' dim_features'3686400'
但在这里我还需要更深入的信息。
当前维度为 921600,即批大小 x 通道 x 高 x 宽 = 921600。
(1)所以我的第一个问题是如何拆分信息?
(2)假设我有这个信息 batch size x channels x height x width = 1 x 3 x 480 x 640。然后
如何提取像 1 x 1 x 480 x 640 这样的 blob 中的每一层,以便我可以打印或绘图。
我可以在 Python 中做的那种事情,比如
for layer_name, blob in net.blobs.iteritems():
print layer_name + '\t' + str(blob.data.shape)
mydata = net.blobs[layer_name].data[0,0,:,:]
#cv2.imshow("mydata",mydata);
#cv2.waitKey(1)
layer_name = layer_name.replace('/', '_')
np.savetxt("printdata/"+layer_name+".csv", mydata, delimiter=",")
但现在,我喜欢 C++
.
对于问题 1:
如果您查看 blob.hpp
文件,它有几种获取 blob 尺寸的方法。您可以调用 shape()
returns const vector<int>&
或已弃用的方法,例如 num()
、channels()
、height()
、width()
returnsint
。所以对于你的情况应该是这样的:
int batch_size = blob->num();
int channels = blob->channels();
int height = blob->height();
int width = blob->width();
std::cout << "Layer name:" << "'" << net_->layer_names()[layer_index] << "'" << " Blob name:" << "'" <<net_->blob_names()[layer_index] << "'" << " batch size " << "'" << batch_size << "'" << " channels:" << "'" << channels << "'" << " height:" << "'" << height << "'" << " width:" << "'" << width << "'" << std::endl;
编辑:
对于问题2:
如果图层有 3 个通道,那么您可以这样做以显示为图像:
// assign channels
std::vector<cv::Mat> ccs;
cv::Size ss(width, height);
float* data = blob->mutable_cpu_data();
for (int i = 0; i < channels; ++i) {
cv::Mat channel(ss, CV_32FC1, data);
ccs.push_back(channel);
data += ss.area();
}
cv::Mat res,dst;
// merge them
cv::merge(ccs, res);
// optional add mean if needed
cv::normalize(res, dst, 0, 1, cv::NORM_MINMAX);
cv::namedWindow("Display window");
cv::imshow("Display window", dst);
cv::waitKey(0);
我在 C++
.
作为net_->Forward();
通过网络后,我喜欢提取个别层的信息。
我做的是
net_->Forward();
//Extract layer information
cout << "Num layers:" << "'" << net_->layer_names().size() << "'"<< endl;
for (int layer_index = 0; layer_index < net_->layer_names().size(); ++layer_index)
{
// get that layer blob and its dimension
const boost::shared_ptr<Blob<float> > blob = net_->blob_by_name(net_->blob_names()[layer_index]);
int batch_size = blob->num();
int dim_features = blob->count() / batch_size;
std::cout << "Layer name:" << "'" << net_->layer_names()[layer_index] << "'" << " Blob name:" << "'" <<net_->blob_names()[layer_index] << "'" << " batch size " << "'" << batch_size << "'" << " dim_features:" << "'" << dim_features << "'" << std::endl;
}
我可以看到所有图层名称和尺寸。
Layer name'image' Blob name'image' batch_size'1' dim_features'921600'
Layer name'conv1/7x7_s2' Blob name'conv1/7x7_s2' batch_size'1' dim_features'4915200'
Layer name'conv1/relu_7x7' Blob name'pool1/3x3_s2' batch_size'1' dim_features'1228800'
Layer name'pool1/3x3_s2' Blob name'pool1/norm1' batch_size'1' dim_features'1228800'
Layer name'pool1/norm1' Blob name'conv2/3x3_reduce' batch_size'1' dim_features'1228800'
Layer name'conv2/3x3_reduce' Blob name'conv2/3x3' batch_size'1' dim_features'3686400'
Layer name'conv2/relu_3x3_reduce' Blob name'conv2/norm2' batch_size'1' dim_features'3686400'
但在这里我还需要更深入的信息。
当前维度为 921600,即批大小 x 通道 x 高 x 宽 = 921600。
(1)所以我的第一个问题是如何拆分信息?
(2)假设我有这个信息 batch size x channels x height x width = 1 x 3 x 480 x 640。然后
如何提取像 1 x 1 x 480 x 640 这样的 blob 中的每一层,以便我可以打印或绘图。
我可以在 Python 中做的那种事情,比如
for layer_name, blob in net.blobs.iteritems():
print layer_name + '\t' + str(blob.data.shape)
mydata = net.blobs[layer_name].data[0,0,:,:]
#cv2.imshow("mydata",mydata);
#cv2.waitKey(1)
layer_name = layer_name.replace('/', '_')
np.savetxt("printdata/"+layer_name+".csv", mydata, delimiter=",")
但现在,我喜欢 C++
.
对于问题 1:
如果您查看 blob.hpp
文件,它有几种获取 blob 尺寸的方法。您可以调用 shape()
returns const vector<int>&
或已弃用的方法,例如 num()
、channels()
、height()
、width()
returnsint
。所以对于你的情况应该是这样的:
int batch_size = blob->num();
int channels = blob->channels();
int height = blob->height();
int width = blob->width();
std::cout << "Layer name:" << "'" << net_->layer_names()[layer_index] << "'" << " Blob name:" << "'" <<net_->blob_names()[layer_index] << "'" << " batch size " << "'" << batch_size << "'" << " channels:" << "'" << channels << "'" << " height:" << "'" << height << "'" << " width:" << "'" << width << "'" << std::endl;
编辑:
对于问题2: 如果图层有 3 个通道,那么您可以这样做以显示为图像:
// assign channels
std::vector<cv::Mat> ccs;
cv::Size ss(width, height);
float* data = blob->mutable_cpu_data();
for (int i = 0; i < channels; ++i) {
cv::Mat channel(ss, CV_32FC1, data);
ccs.push_back(channel);
data += ss.area();
}
cv::Mat res,dst;
// merge them
cv::merge(ccs, res);
// optional add mean if needed
cv::normalize(res, dst, 0, 1, cv::NORM_MINMAX);
cv::namedWindow("Display window");
cv::imshow("Display window", dst);
cv::waitKey(0);