caffe源码解析之Blob 及Python和C++接口调用
来源:互联网 发布:大人认字软件 编辑:程序博客网 时间:2024/06/05 11:58
一、Blob到底是什么东西?
可以理解Blob就是个4维数组,n*c*h*w;每个维度分别表示批处理数量,通道个数,高度和宽度;
这个4维数组的存在形式是以类的形式存在,可以理解为blob就是个数据存储容器。
二、Blob的数据成员
protected: shared_ptr<SyncedMemory> data_; shared_ptr<SyncedMemory> diff_; shared_ptr<SyncedMemory> shape_data_; vector<int> shape_; int count_; int capacity_;Blob的数据成员很简单,就上面的6个。
其中:
SyncedMemory是内存管理的类,现在先不管它。data_是存储内容的指针(boost库的shared_ptr共享智能指针),比如存储前向传播的图像数据;
diff_也是存储数据的指针, 但它存储的是反向传播的梯度数据;
shape_data_和shape_都是表示blob的形状, 即n,c,h,w的大小;
count_表示blob的元素数量,即:n*c*h*w;
capacity_表示当前元素容量, 因为blob可能会reshape,当count_比capacity大时,capacity会更新成count_;
三/Bolb的成员函数
3.1 构造函数:
Blob() : data_(), diff_(), count_(0), capacity_(0) {} explicit Blob(const int num, const int channels, const int height,const int width); explicit Blob(const vector<int>& shape);3个构造函数,都是操作这个blob的4维元素的大小;
3.2 Reshape函数:
void Reshape(const int num, const int channels, const int height, const int width); void Reshape(const vector<int>& shape); void Reshape(const BlobShape& shape); void ReshapeLike(const Blob& other);Reshape函数,用来重新指定Blob的4维元素大小,将每一维度的大小存放在成员变量shape_中,count_和capacity_也都赋值了,
创建SyncedMemory类, (data_和diff_在这并没有赋值,也未分配内存)
3.3 与矩阵结构有关的方法
inline const vector<int>& shape() const { return shape_; } //返回4维数组的结构 inline int shape(int index) const { return shape_[CanonicalAxisIndex(index)]; // 返回某一维度的大小; } inline int num_axes() const { return shape_.size(); } //返回维度值 inline int count() const { return count_; } //返回元素数量 inline int count(int start_axis, int end_axis) const { //返回某些维度的元素数量 inline int count(int start_axis) const { //返回从某一维度到结束的元素数量 return count(start_axis, num_axes()); } inline int CanonicalAxisIndex(int axis_index) const { } //返回数组的下标 inline int num() const { return LegacyShape(0); } //返回n维度的元素个数 inline int channels() const { return LegacyShape(1); } //返回c维度的元素个数 inline int height() const { return LegacyShape(2); } inline int width() const { return LegacyShape(3); } inline int LegacyShape(int index) const { //返回某一维度的个数 inline int offset(const int n, const int c = 0, const int h = 0) //返回指定元素相对首地址的偏移量 inline int offset(const vector<int>& indices) const { }可以发现 这些方法都是获得blob结构, 元素个数, 及维度信息等方法的。
3.4 与数据访问相关的方法
void CopyFrom(const Blob<Dtype>& source, bool copy_diff = false, //从一个Blob中复制数据到另一个blob bool reshape = false); inline Dtype data_at(const int n, const int c, const int h, //通过offset的偏移量,访问指定位置的数据 const int w) const { return cpu_data()[offset(n, c, h, w)]; } inline Dtype diff_at(const int n, const int c, const int h, //访问指定位置的梯度值 const int w) const { return cpu_diff()[offset(n, c, h, w)]; } inline Dtype data_at(const vector<int>& index) const { //返回指定元素的数据 return cpu_data()[offset(index)]; } inline Dtype diff_at(const vector<int>& index) const { //返回指定元素的梯度 return cpu_diff()[offset(index)]; } inline const shared_ptr<SyncedMemory>& data() const { //返回data_地址 CHECK(data_); return data_; } inline const shared_ptr<SyncedMemory>& diff() const { //返回diff_地址 CHECK(diff_); return diff_; } const Dtype* cpu_data() const; //分配内存,并返回首地址 void set_cpu_data(Dtype* data); //设置数据在cpu上 const int* gpu_shape() const; //内存分配,反回在gpu上的地址,share_ptr调用 const Dtype* gpu_data() const; //内存分配,反回在gpu上的地址 ,data_调用 void set_gpu_data(Dtype* data); const Dtype* cpu_diff() const; const Dtype* gpu_diff() const; Dtype* mutable_cpu_data(); //返回可以改写的data地址 Dtype* mutable_gpu_data(); Dtype* mutable_cpu_diff(); Dtype* mutable_gpu_diff(); void Update(); //data-diff这一部分是Blob的核心, 包括cpu和gpu的内存分配及访问。
3.5 Blob的其它数学计算
Dtype asum_data() const; //求data的l1范数 Dtype asum_diff() const; //求diff的l1范数 Dtype sumsq_data() const; //求data的l2范数 Dtype sumsq_diff() const; //求diff的l2范数 void scale_data(Dtype scale_factor); //缩放 void scale_diff(Dtype scale_factor); void ShareData(const Blob& other); //data共享 void ShareDiff(const Blob& other); bool ShapeEquals(const BlobProto& other); //判断是否相等。这部分的方法设计到部分数学计算。
四、总结
Blob仅仅是一个数据结构,4维矩阵, 它还同时提供了本身结构、 内存分配、访问数据、及其它一些方法。 这部分仅仅是程序相关,与算法还没有多大关系。
五、Blob在Python接口中的调用
以VGG16的模型来分析,假设预测的图片为1张,则最后输出的Blob结构为(1,1000),1 表示第一张图,而1000表示1000个分类的概率值。
output=net.forward()output_prob=output['prob'][0]output 表示前向传播结束后最后一层返回的Blob, 它是python的字典结构, 通过关键字可以访问。
即: output["prob"][0] 注意关键字prob 是网络最后一层softmax层的 名称, 而【0】 表示第一张图片的各个概率值, 从而output_prob变成了一维结构,表示第一张图片的1000个概率分布。
六、Blob在C++接口中的调用
net->Forward(); const float *out_probs = net->output_blobs()[0]->cpu_data();net是深度学习的网络, 前向传播计算,结束后, 调用output_blobs()方法, 返回net网络中的 net_output_blobs_成员变量,这是一个vector<Blob<Dtype> *>类型的, 返回的是所有网络输出的blob动态数组, 通过下标【0】 找到输出的第一个blob, 然后调用blob的cpu_data()方法(上面讲过),返回blob中data数据的指针, 将此指针赋值给out_probs, 然后利用out_probs就可以对输出的结果进行操作了。
关于其中Net网络的细节部分,等解析玩layer网络后, 在解析net网络, 请持续关注。。。
- caffe源码解析之Blob 及Python和C++接口调用
- caffe源码解析之blob
- caffe源码解析之blob(1)
- caffe源码解析之blob.hpp或blob.cpp
- caffe源码解析之blob.hpp或blob.cpp
- caffe源码解析之blob.hpp或blob.cpp
- caffe之python接口实战 :detection 官方教程源码解析
- caffe之python接口实战 :mnist_siamese 官方教程源码解析
- caffe之python接口实战 :net_surgery 官方教程源码解析
- Caffe源码解析1:Blob
- Caffe源码解析1:Blob
- Caffe源码解析1:Blob
- Caffe源码解析1:Blob
- Caffe源码解析1:Blob
- Caffe源码解析1:Blob
- caffe源码之blob.cpp
- caffe源码剖析之Blob
- caffe源码 之 Blob类
- zookeeper常用命令
- ASP.NET TreeView控件的使用
- 简单配置nginx使之支持pathinfo
- iOS11 正确控制导航leftBarButtonItems的关于 leftBarButtonItems 结构分析
- linux shell 将多行文件转换为一行
- caffe源码解析之Blob 及Python和C++接口调用
- linux下的定时任务与延时任务
- 两个二进制数相加后得到新的二进制数
- xampp链接本地数据库和PHPstudy连接数据库
- UVa1625
- opencv3.1.0+VS2013+win7 配置与测试
- flume介绍与原理
- 一些期刊的影响因子
- graph cut