【caffe源代码的梳理之四】caffe数据I/O模块——数据读取层DataLayer
来源:互联网 发布:韦德公牛数据 编辑:程序博客网 时间:2024/05/01 10:00
作者:JackGao24 博客园
作者:JackGao16 CSDN
文章链接:http://blog.csdn.net/u013108511/article/details/76804540
邮箱:gshuai16@mail.ustc.edu.cn
数据读取层
caffe的数据读取层(DataLayer)是Layer的一个派生类,除了读取LMDB和LEVELDB之外,也可以从原始图像直接读取(ImageDataLayer)。
1、数据结构的描述
// Message存储的参数供DataLayer层使用message DataParameter { //输入数据使用DB类型 enum DB{ LEVELDB = 0; LMDB = 1; } //源数据的路径 optional string source = 1; //一个批量数据包含的图片数目 optional uint32 batch_size = 4; //以下四个参数均为旧版本的参数,现在已经转移到TransformationParameter optional float scale = 2 [default = 1]; optional string mean_file = 3; optional uint32 crop_size = 5 [default = 0]; optional bool mirror = 6 [default = false]; //随机的跳过一些图片,跳跃的数目是rand_skip *rand(0,1) optional uint32 rand_skip = 7 [default = 0]; //默认输入的数据使用DB的类型,默认为LEVELDB optional DB backend = 8[dafault=LEVELDB] //强制编码图像为三通道的彩色图像 optional bool force_encoded_color = 9[default = false] //预取队列(预先放到主机内存中的批量数,默认为4个Batch) optional uint32 prefetch = 10[default = 4]}
2、数据读取层的实现
数据读取层位于include/caffe/data_layer.hpp中
#ifndef CAFFE_DATA_LAYERS_HPP_#define CAFFE_DATA_LAYERS_HPP_#include <vector>#include "caffe/blob.hpp"#include "caffe/data_transformer.hpp"#include "caffe/internal_thread.hpp"#include "caffe/layer.hpp"#include "caffe/proto/caffe.pb.h"#include "caffe/util/blocking_queue.hpp"namespace caffe {/** * @brief Provides base for data layers that feed blobs to the Net. * * TODO(dox): thorough documentation for Forward and proto params. *///基本数据层,派生于Layertemplate <typename Dtype>class BaseDataLayer : public Layer<Dtype> { public: //显式的构造函数 explicit BaseDataLayer(const LayerParameter& param); // This method may not be overridden except by the BasePrefetchingDataLayer. //通用层配置功能。之后调用DataLayerSetUp进行数据读取层的特殊配置 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) {} //数据读取层没有输入Bottom Blob,变形操作不是很重要 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 Batch { public: Blob<Dtype> data_, label_;//两个Blob分别用来存储图片数据和标签};//带预取功能的数据读取层,派生于BaseDataLayer和InternalThreadtemplate <typename Dtype>class BasePrefetchingDataLayer : public BaseDataLayer<Dtype>, public InternalThread { public: //显式的构造函数 explicit BasePrefetchingDataLayer(const LayerParameter& param); //通用数据层层配置功能。之后调用DataLayerSetUp进行特定的数据读取层的特殊配置 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); //预取得数据批数量数目 static const int PREFETCH_COUNT = 3; protected: virtual void InternalThreadEntry();//内部线程入口 virtual void load_batch(Batch<Dtype>* batch) = 0;//载入批量数据,纯虚函数 vector<shared_ptr<Batch<Dtype> > > prefetch_ [PREFETCH_COUNT];//预取Buffer BlockingQueue<Batch<Dtype>*> prefetch_free_;//空闲Batch队列 BlockingQueue<Batch<Dtype>*> prefetch_full_;//已加载Batch队列 Batch<Dtype>* prefetch_current_; Blob<Dtype> transformed_data_;//变换后的数据};} #endif
数据读取层的具体实现位于src/caffe/layers/base_data_layer.cpp中:
#include <boost/thread.hpp>#include <vector>#include "caffe/blob.hpp"#include "caffe/data_transformer.hpp"#include "caffe/internal_thread.hpp"#include "caffe/layer.hpp"#include "caffe/layers/base_data_layer.hpp"#include "caffe/proto/caffe.pb.h"#include "caffe/util/blocking_queue.hpp"namespace caffe {//构造函数。初始化Layer参数、数据变换器参数template <typename Dtype>BaseDataLayer<Dtype>::BaseDataLayer(const LayerParameter& param) : Layer<Dtype>(param), transform_param_(param.transform_param()) {}//BaseDataLayer层设置template <typename Dtype>void BaseDataLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { if (top.size() == 1) {//判断输出Blob数目。1则只输出data,2则输出data和label output_labels_ = false; } else { output_labels_ = true; } //初始化数据变换器对象 data_transformer_.reset( new DataTransformer<Dtype>(transform_param_, this->phase_)); data_transformer_->InitRand(); // The subclasses should setup the size of bottom and top DataLayerSetUp(bottom, top);//子类负责设置Top Blob形状}//BasePrefetchingDataLayer构造函数template <typename Dtype>BasePrefetchingDataLayer<Dtype>::BasePrefetchingDataLayer( const LayerParameter& param) : BaseDataLayer<Dtype>(param), prefetch_(param.data_param().prefetch()), prefetch_free_(), prefetch_full_(), prefetch_current_() { for (int i = 0; i < prefetch_.size(); ++i) { prefetch_[i].reset(new Batch<Dtype>()); prefetch_free_.push(prefetch_[i].get());//将batch对象都放入空闲队列 }}//BasePrefetchingDataLayer层配置函数template <typename Dtype>void BasePrefetchingDataLayer<Dtype>::LayerSetUp( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { BaseDataLayer<Dtype>::LayerSetUp(bottom, top); //在开启数据预取线程前,通过调用Blob相应函数先进行cudaMalloc, //避免多线程情况下同时进行cudaMalloc,会导致cuda API调用失败 for (int i = 0; i < prefetch_.size(); ++i) { prefetch_[i]->data_.mutable_cpu_data(); if (this->output_labels_) { prefetch_[i]->label_.mutable_cpu_data(); } } //如果编译选项没有CPU_ONLY代码,则需要编译GPU代码#ifndef CPU_ONLY if (Caffe::mode() == Caffe::GPU) { for (int i = 0; i < prefetch_.size(); ++i) { prefetch_[i]->data_.mutable_gpu_data(); if (this->output_labels_) { prefetch_[i]->label_.mutable_gpu_data(); } } }#endif DLOG(INFO) << "Initializing prefetch"; this->data_transformer_->InitRand(); StartInternalThread();//开启内部预取线程 DLOG(INFO) << "Prefetch initialized.";}//内部线程入口template <typename Dtype>void BasePrefetchingDataLayer<Dtype>::InternalThreadEntry() {//创建CUDA Stream,非阻塞类型#ifndef CPU_ONLY cudaStream_t stream; if (Caffe::mode() == Caffe::GPU) { CUDA_CHECK(cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking)); }#endif try { while (!must_stop()) {//循环载入批量数据 Batch<Dtype>* batch = prefetch_free_.pop();//得到一个空闲batch load_batch(batch);//载入批量数据#ifndef CPU_ONLY if (Caffe::mode() == Caffe::GPU) { batch->data_.data().get()->async_gpu_push(stream); if (this->output_labels_) { batch->label_.data().get()->async_gpu_push(stream); } CUDA_CHECK(cudaStreamSynchronize(stream));//同步到GPU }#endif prefetch_full_.push(batch);//加入到带负载的Batch队列中 } } catch (boost::thread_interrupted&) {//捕获到异常则退出循环 // Interrupted exception is expected on shutdown }#ifndef CPU_ONLY if (Caffe::mode() == Caffe::GPU) { CUDA_CHECK(cudaStreamDestroy(stream));//销毁CUDA Stream }#endif}//前向传播函数template <typename Dtype>void BasePrefetchingDataLayer<Dtype>::Forward_cpu( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { if (prefetch_current_) { prefetch_free_.push(prefetch_current_); } //从带负载的Batch中取出一个Batch对象 prefetch_current_ = prefetch_full_.pop("Waiting for data"); // Reshape to loaded data.输出Top Blob根据Batch形状进行变形 top[0]->ReshapeLike(prefetch_current_->data_); top[0]->set_cpu_data(prefetch_current_->data_.mutable_cpu_data()); if (this->output_labels_) {//如果需要输出便签数据 // Reshape to loaded labels. top[1]->ReshapeLike(prefetch_current_->label_);//Top Blob根据Batch中lable_形状进行变形 top[1]->set_cpu_data(prefetch_current_->label_.mutable_cpu_data()); } //将一个Batch的数据送入Net,完成任务,返回空闲队列接受下一批量的数据 perfetch_free_.push(batch);}#ifdef CPU_ONLYSTUB_GPU_FORWARD(BasePrefetchingDataLayer, Forward);#endifINSTANTIATE_CLASS(BaseDataLayer);INSTANTIATE_CLASS(BasePrefetchingDataLayer);} // namespace caffe
阅读全文
0 0
- 【caffe源代码的梳理之四】caffe数据I/O模块——数据读取层DataLayer
- 【caffe源代码的梳理之五】caffe数据I/O模块——数据变换器Data_Transformer
- Caffe框架源码剖析(3)—数据层DataLayer
- Caffe框架源码剖析—数据层DataLayer
- Caffe框架源码剖析(3)—数据层DataLayer
- Caffe 数据层 ImageDataLayer DataLayer WindowDataLayer等
- caffe源码阅读之layer(2)——DataLayer层
- caffe源码阅读之layer(2)——DataLayer层(2)
- 【caffe源代码的梳理之二】Layer
- 【caffe源代码的梳理之三】Net
- caffe源码 之 数据层
- Caffe源码解读(六): Caffe的I/O模块
- 【深度学习】【Caffe源代码解读4】笔记22 Caffe框架中I/O模块的代码初探
- caffe mnist数据层
- Caffe(2)-数据层
- caffe数据层
- caffe 数据层
- caffe 读取数据
- 使用ActiveMQ进行C++与C#的通信1
- 前端防止xss攻击的最直接方式,分享一下
- 持有对象(集合)
- handler传递多种复杂数据
- vue双向绑定原理
- 【caffe源代码的梳理之四】caffe数据I/O模块——数据读取层DataLayer
- [学习笔记]微信非80端口网页授权
- android 权限申请
- 第二个项目:多线程
- tensorflow加载saver.restore目录报错
- 计算器(1)
- 计算机网络相关知识总结
- IntelliJ IDEA部署项目时找不到artifact
- MySQL存储引擎