21天实战caffe(3)数据结构

caffe中一个CNN模型由Net表示,Net由多个Layer堆叠而成。

caffe的万丈高楼(Net)是由图纸(prototxt),用blob这些砖块筑成一层层(Layer),最后通过SGD方法(Solver)进行简装修(train)、精装修(finetune)实现的。

Blob

Blob在内存中表示为4维数组,维度从低到高为(width_,height_,channels_,num_)。用于存储数据(data)或权值增量(diff)。

Blob中封装里SyncedMemory类。Bolob作为基本单元服务Layer、Net、Solver等。

接下来看看blob.hpp:

#include "caffe/proto/caffe.pb.h"

#include "caffe/syncedmem.hpp"

const int kMaxBlobAxes = 32;

namespace caffe {

/**

* @brief A wrapper around SyncedMemory holders serving as the basic

*        computational unit through which Layer%s, Net%s, and Solver%s

*        interact.

*

* TODO(dox): more thorough description.

*/

template <typename Dtype>

class Blob {

public:

Blob()

: data_(), diff_(), count_(0), capacity_(0) {}

/// @brief Deprecated; use <code>Blob(const vector<int>& shape)</code>.

explicit Blob(const int num, const int channels, const int height,

const int width);

explicit Blob(const vector<int>& shape);

/// @brief Deprecated; use <code>Reshape(const vector<int>& shape)</code>.

void Reshape(const int num, const int channels, const int height,

const int width);

/**

* @brief Change the dimensions of the blob, allocating new memory if

*        necessary.

*

* This function can be called both to create an initial allocation

* of memory, and to adjust the dimensions of a top blob during Layer::Reshape

* or Layer::Forward. When changing the size of blob, memory will only be

* reallocated if sufficient memory does not already exist, and excess memory

* will never be freed.

*

* Note that reshaping an input blob and immediately calling Net::Backward is

* an error; either Net::Forward or Net::Reshape need to be called to

* propagate the new input shape to higher layers.

*/

void Reshape(const vector<int>& shape);

void Reshape(const BlobShape& shape);

void ReshapeLike(const Blob& other);

inline string shape_string() const {

ostringstream stream;

for (int i = 0; i < shape_.size(); ++i) {

stream << shape_[i] << " ";

}

stream << "(" << count_ << ")";

return stream.str();

}

inline const vector<int>& shape() const { return shape_; }

/**

* @brief Returns the dimension of the index-th axis (or the negative index-th

*        axis from the end, if index is negative).

*

* @param index the axis index, which may be negative as it will be

*        "canonicalized" using CanonicalAxisIndex.

*        Dies on out of range index.

*/

inline int shape(int index) const {

return shape_[CanonicalAxisIndex(index)];

}

inline int num_axes() const { return shape_.size(); }

inline int count() const { return count_; }

/**

* @brief Compute the volume of a slice; i.e., the product of dimensions

*        among a range of axes.

*

* @param start_axis The first axis to include in the slice.

*

* @param end_axis The first axis to exclude from the slice.

*/

inline int count(int start_axis, int end_axis) const {

CHECK_LE(start_axis, end_axis);

CHECK_GE(start_axis, 0);

CHECK_GE(end_axis, 0);

CHECK_LE(start_axis, num_axes());

CHECK_LE(end_axis, num_axes());

int count = 1;

for (int i = start_axis; i < end_axis; ++i) {

count *= shape(i);

}

return count;

}

/**

* @brief Compute the volume of a slice spanning from a particular first

*        axis to the final axis.

*

* @param start_axis The first axis to include in the slice.

*/

inline int count(int start_axis) const {

return count(start_axis, num_axes());

}

/**

* @brief Returns the ‘canonical‘ version of a (usually) user-specified axis,

*        allowing for negative indexing (e.g., -1 for the last axis).

*

* @param axis_index the axis index.

*        If 0 <= index < num_axes(), return index.

*        If -num_axes <= index <= -1, return (num_axes() - (-index)),

*        e.g., the last axis index (num_axes() - 1) if index == -1,

*        the second to last if index == -2, etc.

*        Dies on out of range index.

*/

inline int CanonicalAxisIndex(int axis_index) const {

CHECK_GE(axis_index, -num_axes())

<< "axis " << axis_index << " out of range for " << num_axes()

<< "-D Blob with shape " << shape_string();

CHECK_LT(axis_index, num_axes())

<< "axis " << axis_index << " out of range for " << num_axes()

<< "-D Blob with shape " << shape_string();

if (axis_index < 0) {

return axis_index + num_axes();

}

return axis_index;

}

/// @brief Deprecated legacy shape accessor num: use shape(0) instead.

inline int num() const { return LegacyShape(0); }

/// @brief Deprecated legacy shape accessor channels: use shape(1) instead.

inline int channels() const { return LegacyShape(1); }

/// @brief Deprecated legacy shape accessor height: use shape(2) instead.

inline int height() const { return LegacyShape(2); }

/// @brief Deprecated legacy shape accessor width: use shape(3) instead.

inline int width() const { return LegacyShape(3); }

inline int LegacyShape(int index) const {

CHECK_LE(num_axes(), 4)

<< "Cannot use legacy accessors on Blobs with > 4 axes.";

CHECK_LT(index, 4);

CHECK_GE(index, -4);

if (index >= num_axes() || index < -num_axes()) {

// Axis is out of range, but still in [0, 3] (or [-4, -1] for reverse

// indexing) -- this special case simulates the one-padding used to fill

// extraneous axes of legacy blobs.

return 1;

}

return shape(index);

}

inline int offset(const int n, const int c = 0, const int h = 0,

const int w = 0) const {

CHECK_GE(n, 0);

CHECK_LE(n, num());

CHECK_GE(channels(), 0);

CHECK_LE(c, channels());

CHECK_GE(height(), 0);

CHECK_LE(h, height());

CHECK_GE(width(), 0);

CHECK_LE(w, width());

return ((n * channels() + c) * height() + h) * width() + w;

}

inline int offset(const vector<int>& indices) const {

CHECK_LE(indices.size(), num_axes());

int offset = 0;

for (int i = 0; i < num_axes(); ++i) {

offset *= shape(i);

if (indices.size() > i) {

CHECK_GE(indices[i], 0);

CHECK_LT(indices[i], shape(i));

offset += indices[i];

}

}

return offset;

}

/**

* @brief Copy from a source Blob.

*

* @param source the Blob to copy from

* @param copy_diff if false, copy the data; if true, copy the diff

* @param reshape if false, require this Blob to be pre-shaped to the shape

*        of other (and die otherwise); if true, Reshape this Blob to other‘s

*        shape if necessary

*/

void CopyFrom(const Blob<Dtype>& source, bool copy_diff = false,

bool reshape = false);

inline Dtype data_at(const int n, const int c, const int h,

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 {

CHECK(data_);

return data_;

}

inline const shared_ptr<SyncedMemory>& diff() const {

CHECK(diff_);

return diff_;

}

const Dtype* cpu_data() const;

void set_cpu_data(Dtype* data);

const int* gpu_shape() const;

const Dtype* gpu_data() const;

void set_gpu_data(Dtype* data);

const Dtype* cpu_diff() const;

const Dtype* gpu_diff() const;

Dtype* mutable_cpu_data();

Dtype* mutable_gpu_data();

Dtype* mutable_cpu_diff();

Dtype* mutable_gpu_diff();

void Update();

void FromProto(const BlobProto& proto, bool reshape = true);

void ToProto(BlobProto* proto, bool write_diff = false) const;

/// @brief Compute the sum of absolute values (L1 norm) of the data.

Dtype asum_data() const;

/// @brief Compute the sum of absolute values (L1 norm) of the diff.

Dtype asum_diff() const;

/// @brief Compute the sum of squares (L2 norm squared) of the data.

Dtype sumsq_data() const;

/// @brief Compute the sum of squares (L2 norm squared) of the diff.

Dtype sumsq_diff() const;

/// @brief Scale the blob data by a constant factor.

void scale_data(Dtype scale_factor);

/// @brief Scale the blob diff by a constant factor.

void scale_diff(Dtype scale_factor);

/**

* @brief Set the data_ shared_ptr to point to the SyncedMemory holding the

*        data_ of Blob other -- useful in Layer%s which simply perform a copy

*        in their Forward pass.

*

* This deallocates the SyncedMemory holding this Blob‘s data_, as

* shared_ptr calls its destructor when reset with the "=" operator.

*/

void ShareData(const Blob& other);

/**

* @brief Set the diff_ shared_ptr to point to the SyncedMemory holding the

*        diff_ of Blob other -- useful in Layer%s which simply perform a copy

*        in their Forward pass.

*

* This deallocates the SyncedMemory holding this Blob‘s diff_, as

* shared_ptr calls its destructor when reset with the "=" operator.

*/

void ShareDiff(const Blob& other);

bool ShapeEquals(const BlobProto& other);

protected:

shared_ptr<SyncedMemory> data_;

shared_ptr<SyncedMemory> diff_;

shared_ptr<SyncedMemory> shape_data_;

vector<int> shape_;

int count_;

int capacity_;

DISABLE_COPY_AND_ASSIGN(Blob);

};  // class Blob

时间: 2024-11-05 14:45:00

21天实战caffe(3)数据结构的相关文章

《深度学习-21天实战Caffe》高清带标签完整PDF版下载

近期做深度学习的项目用到了Caffe框架,需要系统地学习一下,特别是源码.经同事地推荐,了解熟悉了一本经典地好书 -- <深度学习-21天实战Caffe>,现在发现一个可以下载高清完整PDF版本地链接,比一般的都清晰,现在发出来这个下载链接. 百度云盘下载链接:<深度学习-21天实战Caffe> 这本高清的书基本长这个样子: 本书一共分为21天的知识点,在内容上分为上篇--<初见>.中篇--<热恋>.下篇--<升华>.作者以一种生动有趣的组织语言

21天实战caffe笔记_第二天

1 传统机器学习 传统机器学习:通过人工设计特征提取器,将原始数据转化为合适的中间表示形式或者特征向量,利用学习系统(通常为分类器)可以对输入模式进行检测或者分类.流程如下: 传统机器学习的局限在于需要人工设计特征提取器,而且要求较高.而深度学习则不需要,可以由机器自动学习获取,适应性较强. 2 从表示学习到深度学习 表示学习:原始数据->自动发现用于检测和分类的表示,如下图 : 深度学习:是一种多层表示学习方法,用简单的非线性模块构建而成:这些模块将上一层表示(从原始数据开始)转化为更高层.更

21天实战caffe(4)数据结构 blob

namespace caffe { //变维函数,将(num,channels,height,width)参数转换维vector<int>,然后调用重载的变维函数void Blob<Dtype>::Reshape(const vector<int>& shape) template <typename Dtype> void Blob<Dtype>::Reshape(const int num, const int channels, c

【21天实战Caffe】学习笔记(一)Ubuntu16.04+Caffe环境搭建

安装前准备工作: sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler sudo apt-get install --no-install-recommends libboost-all-dev sudo apt-get install libatlas-base-dev sudo apt-get install th

21天实战caffe笔记_第三天

1 深度学习工具汇总 (1)  caffe : 由BVLC开发的基于C++/CUDA/Python实现的卷积神经网络,提供了面向命令行.Matlab和Python的绑定接口.特性如下: A 实现了前馈卷积神经网络(CNN),不是递归网络结构(RNN) : B 速度快,利用MKL/OpenBLAS.cuBlas计算库,支持GPU加速 ; C 适合特征提取,实际上适合做二维图像数据的特征提取 ; caffe其他特性: A 完全开源,遵循BSD-2协议 ; B 提供了一整套工具集,可用于模型训练.预测

21天实战caffe(1)

convolutionLayer:卷积层实现 InnerProductLayer:全连接实现 CPR值 早发现就好了,论文都写完了又发现了.. 如果上层传过来的特征图是20*12*12,本层卷积层大小为50*5*5,本层输出50*8*8,那么单样本前向传播计算量为: calculations(MAC)=5*5*8*8*20*50=1600 000MAC 参数数量: params=50*5*5*20=25000 那么CPR: CPR=calculations/params=1600 000/250

21天学习caffe(二)

本文大致记录使用caffe的一次完整流程 Process 1 下载mnist数据集(数据量很小),解压放在data/mnist文件夹中:2 运行create_mnist.sh,生成lmdb格式的数据(data+label):$CAFFEROOT/build/tools/convert_imageset 可以用来做把原始图片转换为LevelDB或者 Lmdb格式. 3 运行build/tools/caffe train --solver=examples/mnist/lenet_solver.pr

2017.2.21 activiti实战--第七章--Activiti与容器集成

学习资料:<Activiti实战> 第七章 Activiti与容器集成 本章讲解activiti-spring可以做的事情,如何与现有系统集成,包含bean的注入.统一事务管理等. 7.1 流程引擎工厂 7.1.1 ProcessEngine 创建processEngine的方法有三种: 1 通过配置文件 2 测试中通过ActivitiRule 3 通过ProcessEngines类 7.1.2 ProcessEngineFactory 与spring集成的目的有两个: 1 通过spring统

21天学习caffe(一)

ubuntu环境安装caffe1 安装依赖 apt-get install libatlas-base-dev apt-get install python-dev apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev 等等等2 编译生成bin文件mv Makefile.config.example Makefile.config   #改名make or make -j2 排错:解决/boot空间不足问题 system mon