Caffe学习--Blob分析
Caffe_blob
1.基本数据结构
Blob为模板类,可以理解为四维数组,n * c * h * w的结构,Layer内为blob输入data和diff,Layer间的blob为学习的参数.内部封装了SyncedMemory类,该类负责存储分配和主机与设备的同步
protected:
shared_ptr<SyncedMemory> data_; // data指针
shared_ptr<SyncedMemory> diff_; // diff指针
vector<int> shape_; // blob形状
int count_; // blob的nchw
// 当前的Blob容量,当Blob reshape后count> capacity_时,capacity_ = count_;
// 重新new 然后 reset data和 diff
int capacity_;
2.常用函数
Blob类中常用的函数如下所示
Blob<float>test;
//explicit关键字的作用是禁止单参数构造函数的隐式转换
explicit Blob(const int num, const int channels, const int height,
const int width);
test.shape_string();//初始为空 0 0 0 0
//Reshape函数将num,channels,height,width传递给vector shape_
test.Reshape(1,2,3,4);// shape_string() 1,2,3,4
test.shape(i);// NCHW
test.count(int start_axis,int end_axis); // start_axis---end_axis .x* shape[i]
test.count();// nchw count(1) chw count(2) hw.....
//shared_ptr<SyncedMemory> data_->cpu_data();
const float* data = test.cpu_data();
const float* diff = test.cpu_diff();
float* data_1 = test.mutable_cpu_data();//mutable修饰的表示可以修改内部值
float* diff_1 = test.mutable_cpu_diff();
test.asum_data();//求和 L1范数
test.sumsq_data();//平方和 L2范数
test.Update();//data = data-diff;
a.ToProto(BlobProto& bp,true/false);//(FromProto)
// if < 0 ,return num_axis()+axis_index;//索引序列
int index = a.CanonicalAxisIndex(int axis_index);
int offset(n,c,h,w);//((n*channels()+c)*height()+h)*width()+w
float data_at(n,c,h,w);//return cpu_data()[offset(n,c,h,w)];
float diff_at(n,c,h,w);//return cpu_diff()[offset(n,c,h,w)];
inline const shared_ptr<SyncedMemory>& data() const{return _data};
void scale_data(Dtype scale_factor);// data乘以一个标量。同理 scale_diff();
void CopyFrom(const Blob<Dtype>& source, bool copy_diff = false,
bool reshape = false); // copy_diff是否复制diff
3.写入磁盘操作
//Blob内部值写入到磁盘
Blob<float>a;
a.Reshape(1,2,3,4);
const int count = a.count();
for (size_t i = 0; i < count; i++) {
a[i] = i;//init the test Blob
}
BlobProto bp,bp2;
a.ToProto(&bp,true);//写入data和diff到bp中
WriteProtoToBinaryFile(bp,"a.blob");//写入磁盘
ReadProtoFromBinaryFile("a.blob",&bp2);//从磁盘读取blob
Blob<float>b;
b.FromProto(bp2,true);//序列化对象bp2中克隆b,完整克隆
for (size_t n = 0; n < b.num(); n++) {
for (size_t c = 0; c < b.channels(); c++) {
for (size_t h = 0; h < b.height(); h++) {
for (size_t w = 0; w < b.width(); w++) {
cout<<"b["<<n<<"]["<<c<<"]["<<h<<"]["<<w<<"]["<<w<<"]="<<
b[(((n*b.channels()+c)*b.height)+h)*b.width()+w]<<endl;
//(((n*c+ci)*h+hi)*w+wi)
}
}
}
}
4.部分函数的具体实现
本部分的实现未考虑参数是否合理。一般操作blob需要分CPU和GPU,采用math_functions具体计算
template <typename Dtype>
void Blob<Dtype>::Reshape(const vector<int>& shape){//reshape操作
count_ = 1;//初始count_ NCHW;
shape_.resize(shape.size());
for (size_t i = 0; i < shape.size(); i++) {
count_ *= shape[i];
shape_[i] = shape[i];
if (count_ > capacity_) { //reshape的size大于了目前的最大容量
capacity_ = count_;
data_.reset(new SyncedMemory(capacity_*sizeof(Dtype)));
diff_.reset(new SyncedMemory(capacity_*sizeof(Dtype)));
}
}
}
template <typename Dtype>
void Blob<Dtype>::Reshape(int n,int c,int h ,int w){//reshape操作
vector<int>shape(4);
shape[0] = n;
shape[1] = c;
shape[2] = h;
shape[3] = w;
Reshape(shape);
}
template <typename Dtype>
const Dtype* Blob<Dtype>::cpu_data(){
//实际调用的shared_ptr<SyncedMemory>data_->cpu_data();,同理cpu_diff();
CHECK(data_);
return (const Dtype*)data_->cpu_data();
}
template <typename Dtype>
void Blob<Dtype>::Updata(){ //data = data-diff;需要判断cpu OR gpu
switch (data_->head()) {
case SyncedMemory::HEAD_AT_CPU:
caffe_axpy<Dtype>(count_,Dtype(-1),
static_cast<const<Dtype*>(diff_->cpu_data()),
static_cast<Dtype*>(data_->mutable_cpu_data()));
}
case SyncedMemory::HEAD_AT_GPU://在gpu或者CPU/GPU已经同步
case SyncedMemory::SYNCED:
#ifndef CPU_ONLY
caffe_gpu_axpy<Dtype>(count_.Dtype(-1),
static_cast<const<Dtype*>(diff_->gpu_data()),
static_cast<Dtype*>(data_->mutable_gpu_data()))
}
template <typename Dtype> //从source 拷贝数据,copy_diff控制是拷贝diff还是data
void Blob<Dtype>::CopyFrom(const Blob& source, bool copy_diff, bool reshape) {
if (source.count() != count_ || source.shape() != shape_) {
if (reshape) {
ReshapeLike(source);
}
}
switch (Caffe::mode()) {
case Caffe::GPU:
if (copy_diff) { //copy diff
caffe_copy(count_, source.gpu_diff(),
static_cast<Dtype*>(diff_->mutable_gpu_data()));
} else {
caffe_copy(count_, source.gpu_data(),
static_cast<Dtype*>(data_->mutable_gpu_data()));
}
break;
case Caffe::CPU:
if (copy_diff) {
caffe_copy(count_, source.cpu_diff(),
static_cast<Dtype*>(diff_->mutable_cpu_data()));
} else {
caffe_copy(count_, source.cpu_data(),
static_cast<Dtype*>(data_->mutable_cpu_data()));
}
break;
default:
LOG(FATAL) << "Unknown caffe mode.";
}
}
template <typename Dtype>
void Blob<Dtype>::ToProto(BlobProto* proto,bool write_diff){
proto->clear_shape();
for (size_t i = 0; i < shaoe_.size(); i++) {
proto->mutable_shape()->add_dim(shape_[i]);
}
proto->clear_data();
proto->clear_diff();
const Dtype* data_vec = cpu_data();
for (size_t i = 0; i < count_; i++) {
proto->add_data(data_vec[i]);//data写入proto
}
if (write_diff) {
const Dtype* diff_vec = cpu_diff();
for (size_t i = 0; i < count_; i++) {
proto->add_diff(diff_vec[i]);//diff写入proto
}
}
}
5.说明
/*Blob作为一个最基础的类,其中构造函数开辟一个内存空间来存储数据,Reshape
函数在Layer中的reshape或者forward操作中来调整top的输出维度。同时在改变Blob
大小时, 内存将会被重新分配如果内存大小不够了,并且额外的内存将不会被释放。
对input的blob进行reshape, 若立马调用Net::Backward是会出错的,因为reshape
之后,要么Net::forward或者Net::Reshape就会被调用来将新的input shape传播
到高层 */
Caffe学习--Blob分析的更多相关文章
- Caffe学习--Layer分析
Caffe_Layer 1.基本数据结构 //Layer层主要的的参数 LayerParamter layer_param_; // protobuf内的layer参数 vector<share ...
- Caffe学习--Net分析
Caffe_Net 1.基本数据 vector<shared_ptr<Layer<Dtype> > > layers_; // 记录每一层的layer参数 vect ...
- Caffe学习笔记(三):Caffe数据是如何输入和输出的?
Caffe学习笔记(三):Caffe数据是如何输入和输出的? Caffe中的数据流以Blobs进行传输,在<Caffe学习笔记(一):Caffe架构及其模型解析>中已经对Blobs进行了简 ...
- Caffe学习笔记(一):Caffe架构及其模型解析
Caffe学习笔记(一):Caffe架构及其模型解析 写在前面:关于caffe平台如何快速搭建以及如何在caffe上进行训练与预测,请参见前面的文章<caffe平台快速搭建:caffe+wind ...
- Caffe学习笔记2--Ubuntu 14.04 64bit 安装Caffe(GPU版本)
0.检查配置 1. VMWare上运行的Ubuntu,并不能支持真实的GPU(除了特定版本的VMWare和特定的GPU,要求条件严格,所以我在VMWare上搭建好了Caffe环境后,又重新在Windo ...
- Caffe学习系列(23):如何将别人训练好的model用到自己的数据上
caffe团队用imagenet图片进行训练,迭代30多万次,训练出来一个model.这个model将图片分为1000类,应该是目前为止最好的图片分类model了. 假设我现在有一些自己的图片想进行分 ...
- Caffe 学习系列
学习列表: Google protocol buffer在windows下的编译 caffe windows 学习第一步:编译和安装(vs2012+win 64) caffe windows学习:第一 ...
- Caffe学习笔记(二):Caffe前传与反传、损失函数、调优
Caffe学习笔记(二):Caffe前传与反传.损失函数.调优 在caffe框架中,前传/反传(forward and backward)是一个网络中最重要的计算过程:损失函数(loss)是学习的驱动 ...
- caffe 学习(2)——基本原理
参考 http://caffe.berkeleyvision.org/tutorial/ 表达:models和optimizations使用纯文本文档形式定义,不是用代码定义: 速度:适用于工业和科研 ...
随机推荐
- 互联网智能门锁,手机蓝牙APP成为首选
随着互联网门锁在行业中的普及,大家越加关注到门锁的实施和维护成本.我们在互联网智能门锁的调研中发现,网关联网的智能门锁,使用时需要依赖房间内的宽带上网线路,而断线后客户反馈问题较多.据某家分散式公寓的 ...
- iOS开发-测量APP启动耗时
冷启动 冷启动就是App被kill掉以后一切从头开始启动的过程. 热启动 当用户按下home键的时候,iOS的App并不会马上被kill掉,还会继续存活若干时间.理想情况下,用户点击App的图标再次回 ...
- 关于函数调用约定-thiscall调用约定
函数调用约定描述了如何以正确的方式调用某些特定类型的函数.包括了函数参数在栈上的分配顺序.有哪些参数将通过寄存器传入,以及在函数返回时函数栈的回收方式等. 函数调用约定的几种类型 stdcall,cd ...
- adb屏幕截屏
import subprocess #执行结果使用管道输出,对于参数是字符串,需要指定shell=Trueprocess = subprocess.Popen('adb shell screencap ...
- Git的初始化设置
Git安装成功之后,新建一个初始化的仓库以及配置GitHub仓库 Git配置GitHub账户 安装完成之后要进行git的配置,这里配置的是GitHub账户 MisSa@DESKTOP-PIQ06QO ...
- kvm三个kernel相关的调优
今天在杭州参加淘宝嘉年华技术沙龙,主题是虚拟化和云计算,三个讲演: 淘宝网子团分享淘宝kvm技术的使用 华为的杨晓伟介绍虚拟化技术 阿里云郑永升介绍弹性云计算技术 其中KVM 调优,三点值得关注的: ...
- T^T OJ 2144 并查集( 并查集... )
链接:传送门 思路:增加num[] 记录集合中的个数,maxx[] 记录集合中最大值,挺不错的并查集练习题,主要是 unite 函数里如何改变一些东西,挺好的题,能用C尽量不用C++,效率差蛮大的! ...
- frp(升级版)教程
注:之前的教程是按照官网文档亲自实践操作汇总而成的,所需的软件也是从官网下载的. 但是有一个问题,若是运行在有公网IP的frps程序被其他人所知道,他们就可以直接在他们电脑上运行frpc客户端, 简而 ...
- SparkSql初级编程实践
1.Spark SQL 基本操作将下列 JSON 格式数据复制到 Linux 系统中,并保存命名为 employee.json.{ "id":1 , "name" ...
- 论文阅读《End-to-End Learning of Geometry and Context for Deep Stereo Regression》
端到端学习几何和背景的深度立体回归 摘要 本文提出一种新型的深度学习网络,用于从一对矫正过的立体图像回归得到其对应的视差图.我们利用问题(对象)的几何知识,形成一个使用深度特征表示的代价量(c ...