【Caffe代码分析】DataLayer
函数功能:
DataLayer 用于将数据库上的内容,一个batch一个batch的读入到相对应的Blob中,
首先查看其继承关系
注意其不是直接继承于BaseDatalayer,因为,它需要并行的读取数据库上的数据,需要新开线程来预先读入数据。
DataLayer 有两个指针成员用来存放数据库和游标,
shared_ptr<db::DB> db_;shared_ptr<db::Cursor> cursor_;
- 1
- 2
其继承自基类的成员变量有
protected:Blob<Dtype> prefetch_data_;Blob<Dtype> prefetch_label_;Blob<Dtype> transformed_data_;
- 1
- 2
- 3
- 4
用于保存预读取的数据,标签,以及转换过的数据
继承自BaseDataLayer的成员变量有:
bool output_labels_;
其成员函数InternalThreadEntry()
用于真正的数据读入操作,
其中
Dtype* top_data = this->prefetch_data_.mutable_cpu_data();Dtype* top_label = NULL; // suppress warnings about uninitialized variables
- 1
- 2
指针用于保留输入的批数据。
数据库里面的数据依然是先转化为Datum,
Datum datum;
datum.ParseFromString(cursor_->value());
int offset = this->prefetch_data_.offset(item_id);
this->transformed_data_.set_cpu_data(top_data + offset);
top_label[item_id] = datum.label();
其读取数据库输入也是通过游标来操作,cursor_->Next();
,注意这里都是按照顺序读入的,所以,需要自己保证在输入存入数据库的时候确保其是无序的。
=============
源代码:
#include <opencv2/core/core.hpp>#include <stdint.h>#include <string>
#include <vector>#include "caffe/common.hpp"
#include "caffe/data_layers.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/benchmark.hpp"
#include "caffe/util/io.hpp"
#include "caffe/util/math_functions.hpp"
#include "caffe/util/rng.hpp"namespace caffe {template <typename Dtype>
DataLayer<Dtype>::~DataLayer<Dtype>() {this->JoinPrefetchThread();
}template <typename Dtype>
void DataLayer<Dtype>::DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) {// Initialize DBdb_.reset(db::GetDB(this->layer_param_.data_param().backend()));db_->Open(this->layer_param_.data_param().source(), db::READ);cursor_.reset(db_->NewCursor());// Check if we should randomly skip a few data pointsif (this->layer_param_.data_param().rand_skip()) {unsigned int skip = caffe_rng_rand() %this->layer_param_.data_param().rand_skip();LOG(INFO) << "Skipping first " << skip << " data points.";while (skip-- > 0) {cursor_->Next();}}// Read a data point, and use it to initialize the top blob.Datum datum;datum.ParseFromString(cursor_->value());bool force_color = this->layer_param_.data_param().force_encoded_color();if ((force_color && DecodeDatum(&datum, true)) ||DecodeDatumNative(&datum)) {LOG(INFO) << "Decoding Datum";}// imageint crop_size = this->layer_param_.transform_param().crop_size();if (crop_size > 0) {top[0]->Reshape(this->layer_param_.data_param().batch_size(),datum.channels(), crop_size, crop_size);this->prefetch_data_.Reshape(this->layer_param_.data_param().batch_size(),datum.channels(), crop_size, crop_size);this->transformed_data_.Reshape(1, datum.channels(), crop_size, crop_size);} else {top[0]->Reshape(this->layer_param_.data_param().batch_size(), datum.channels(),datum.height(), datum.width());this->prefetch_data_.Reshape(this->layer_param_.data_param().batch_size(),datum.channels(), datum.height(), datum.width());this->transformed_data_.Reshape(1, datum.channels(),datum.height(), datum.width());}LOG(INFO) << "output data size: " << top[0]->num() << ","<< top[0]->channels() << "," << top[0]->height() << ","<< top[0]->width();// labelif (this->output_labels_) {vector<int> label_shape(1, this->layer_param_.data_param().batch_size());top[1]->Reshape(label_shape);this->prefetch_label_.Reshape(label_shape);}
}// This function is used to create a thread that prefetches the data.
template <typename Dtype>
void DataLayer<Dtype>::InternalThreadEntry() {CPUTimer batch_timer;batch_timer.Start();double read_time = 0;double trans_time = 0;CPUTimer timer;CHECK(this->prefetch_data_.count());CHECK(this->transformed_data_.count());// Reshape on single input batches for inputs of varying dimension.const int batch_size = this->layer_param_.data_param().batch_size();const int crop_size = this->layer_param_.transform_param().crop_size();bool force_color = this->layer_param_.data_param().force_encoded_color();if (batch_size == 1 && crop_size == 0) {Datum datum;datum.ParseFromString(cursor_->value());if (datum.encoded()) {if (force_color) {DecodeDatum(&datum, true);} else {DecodeDatumNative(&datum);}}this->prefetch_data_.Reshape(1, datum.channels(),datum.height(), datum.width());this->transformed_data_.Reshape(1, datum.channels(),datum.height(), datum.width());}Dtype* top_data = this->prefetch_data_.mutable_cpu_data();Dtype* top_label = NULL; // suppress warnings about uninitialized variablesif (this->output_labels_) {top_label = this->prefetch_label_.mutable_cpu_data();}for (int item_id = 0; item_id < batch_size; ++item_id) {timer.Start();// get a blobDatum datum;datum.ParseFromString(cursor_->value());cv::Mat cv_img;if (datum.encoded()) {if (force_color) {cv_img = DecodeDatumToCVMat(datum, true);} else {cv_img = DecodeDatumToCVMatNative(datum);}if (cv_img.channels() != this->transformed_data_.channels()) {LOG(WARNING) << "Your dataset contains encoded images with mixed "<< "channel sizes. Consider adding a 'force_color' flag to the "<< "model definition, or rebuild your dataset using "<< "convert_imageset.";}}read_time += timer.MicroSeconds();timer.Start();// Apply data transformations (mirror, scale, crop...)int offset = this->prefetch_data_.offset(item_id);this->transformed_data_.set_cpu_data(top_data + offset);if (datum.encoded()) {this->data_transformer_->Transform(cv_img, &(this->transformed_data_));} else {this->data_transformer_->Transform(datum, &(this->transformed_data_));}if (this->output_labels_) {top_label[item_id] = datum.label();}trans_time += timer.MicroSeconds();// go to the next itercursor_->Next();if (!cursor_->valid()) {DLOG(INFO) << "Restarting data prefetching from start.";cursor_->SeekToFirst();}}batch_timer.Stop();DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << " ms.";DLOG(INFO) << " Read time: " << read_time / 1000 << " ms.";DLOG(INFO) << "Transform time: " << trans_time / 1000 << " ms.";
}INSTANTIATE_CLASS(DataLayer);
REGISTER_LAYER_CLASS(Data);} // namespace caffe
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
其相对应的头文件信息:
template <typename Dtype>
class BaseDataLayer : public Layer<Dtype> {public:explicit BaseDataLayer(const LayerParameter& param);virtual ~BaseDataLayer() {}// LayerSetUp: implements common data layer setup functionality, and calls// DataLayerSetUp to do special data layer setup for individual layer types.// This method may not be overridden except by the BasePrefetchingDataLayer.virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top);virtual void DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) {}// Data layers have no bottoms, so reshaping is trivial.virtual void Reshape(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top) {}virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {}virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {}protected:TransformationParameter transform_param_;shared_ptr<DataTransformer<Dtype> > data_transformer_;bool output_labels_;
};template <typename Dtype>
class BasePrefetchingDataLayer :public BaseDataLayer<Dtype>, public InternalThread {public:explicit BasePrefetchingDataLayer(const LayerParameter& param): BaseDataLayer<Dtype>(param) {}virtual ~BasePrefetchingDataLayer() {}// LayerSetUp: implements common data layer setup functionality, and calls// DataLayerSetUp to do special data layer setup for individual layer types.// This method may not be overridden.void LayerSetUp(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top);virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top);virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,const vector<Blob<Dtype>*>& top);virtual void CreatePrefetchThread();virtual void JoinPrefetchThread();// The thread's functionvirtual void InternalThreadEntry() {}protected:Blob<Dtype> prefetch_data_;Blob<Dtype> prefetch_label_;Blob<Dtype> transformed_data_;
};template <typename Dtype>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
版权声明:本文为博主原创文章,未经博主允许不得转载。
【Caffe代码分析】DataLayer相关推荐
- caffe中loss函数代码分析--caffe学习(16)
接上篇:caffe中样本的label一定要从序号0开始标注吗?–caffe学习(15) A: 1:数学上来说,损失函数loss值和label从0开始还是从1或者100开始是没有直接联系的,以欧式距离损 ...
- Caffe代码导读(0):路线图
转载自: Caffe代码导读(0):路线图 - 卜居 - 博客频道 - CSDN.NET http://blog.csdn.net/kkk584520/article/details/41681085 ...
- Caffe代码解读2--检测程序解读
在上一篇文章Caffe代码解读1--从一段命令行开始,我们说了如何训练一个神经网络,并以SSD网络为例,对用到的python脚本进行了分析.在这篇文章中,我们开始分析,如何使用神经网络进行目标检测,依 ...
- 20145236《网络攻防》Exp4 恶意代码分析
20145236<网络攻防>Exp4 恶意代码分析 一.基础问题回答 如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作有哪些 ...
- C#中类的继承 override virtual new的作用以及代码分析
继承中override virtual new的作用 virtual 父类中需要注明允许重写的方法: override 子类中必须显示声明该方法是重写的父类中的方法: new 子类中忽略父类的已存在的 ...
- 2017.4.18 静态代码分析工具sonarqube+sonar-runner的安装配置及使用
配置成功后的代码分析页面: 可以看到对复杂度.语法使用.重复度等等都做了分析,具体到了每一个方法和每一句代码. 四种使用方式: sonarqube + sonar-runner sonarqube + ...
- lighttpd1.4.18代码分析
lighttpd1.4.18代码分析(八)--状态机(2)CON_STATE_READ状态 posted @ 2008-09-24 10:50 那谁 阅读(2225) | 评论 (1) 编辑 lig ...
- Device Tree(三):代码分析
2019独角兽企业重金招聘Python工程师标准>>> 一.前言 Device Tree总共有三篇,分别是: 1.为何要引入Device Tree,这个机制是用来解决什么问题的?(请 ...
- 使用Hadoop和ELK进行业务代码分析!分分钟捉到Bug!
大数据是计算领域的新高地,它有望提供一种方法来应对二十一世纪不断增长的数据生成.越来越多的大数据爱好者正在涌现,越来越多的公司正在采用各种大数据平台,并希望提出以客户为中心的解决方案,帮助他们在竞争激 ...
- 20145328 《网络对抗技术》恶意代码分析
20145328 <网络对抗技术>恶意代码分析 ------看到这句话说明还没写完-------- 实践内容: 使用schtasks指令监控系统运行 使用sysmon工具监控系统运行 使用 ...
最新文章
- golang用数组作为函数参数
- codeforce 609A - USB Flash Drives
- C语言嵌入式系统编程修炼之四:屏幕操作
- mq多个消费者消费一个消息_ActiveMQ多个消费者消费不均匀问题
- rzsz for linux,linux下如何安装rzsz
- mac最好用的markdown_「建议收藏」PCMaclinux,最好用Markdown编辑器清单
- 递归和循环两种方式求解连续数的相加
- CSS3魔法堂:说说Multi-column Layout
- 通过ICE轻松部署WES7镜像
- 微信小程序图片显示以及动态数据修改(五六)
- 20135202闫佳歆——信息安全系统设计基础第九周学习总结
- Python&Opencv手势识别系统(完整源码&自定义UI操作界面&视频教程)
- 斐讯音箱控制扫地机器人_【斐讯 R1 智能音箱使用体验】操作|功能|音质|识别_摘要频道_什么值得买...
- mmdetection使用目标检测工具箱训练,测试
- 姜小白的Python日记Day9 变量与递归
- 闯荡Linux帝国:nginx的创业故事
- OpenStack 归档 - 虚拟机临时存储与块存储
- NAMD靶向分子动力学模拟Target molecular dynamic stimulation(附conf文件)
- Throughput Latency
- arrays 和array的区别 blogbus