caffe源码分析-DataLayer

DataLayer作为caffe训练时的数据层(以多线程的方式读取数据加速solver的训练过程),继承自BaseDataLayer/BasePrefetchingDataLayer

template <typename Dtype>
class BaseDataLayer : public Layer<Dtype> {
public:
    explicit BaseDataLayer(const LayerParameter& param);
    // This method may not be overridden except by the BasePrefetchingDataLayer.
    virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top);
    // Data layers should be shared by multiple solvers in parallel
    virtual inline bool ShareInParallel() const { return true; }
    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(....) {//do nothing}
    virtual void Backward_cpu(....) {//do nothing}

protected:
    TransformationParameter transform_param_;
    shared_ptr<DataTransformer<Dtype> > data_transformer_;
    bool output_labels_;
};

data_transformer_主要是对输入的图片做crop_size,do_mirror,mean等操作.

下面看起函数定义LayerSetUp(参数初始化):

template <typename Dtype>
void BaseDataLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
                                      const vector<Blob<Dtype>*>& top) {
    if (top.size() == 1) {
        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);
}

BasePrefetchingDataLayer还继承了InternalThread

template <typename Dtype>
class BasePrefetchingDataLayer :
        public BaseDataLayer<Dtype>, public InternalThread {
public:
    explicit BasePrefetchingDataLayer(const LayerParameter& param);

 
    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);

    // Prefetches batches 
    static const int PREFETCH_COUNT = 3;

protected:
    virtual void InternalThreadEntry();
    virtual void load_batch(Batch<Dtype>* batch) = 0;

    Batch<Dtype> prefetch_[PREFETCH_COUNT];
    BlockingQueue<Batch<Dtype>*> prefetch_free_;
    BlockingQueue<Batch<Dtype>*> prefetch_full_;

    Blob<Dtype> transformed_data_;
};

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::LayerSetUp(
        const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
    BaseDataLayer<Dtype>::LayerSetUp(bottom, top);
    //.........
    DLOG(INFO) << "Initializing prefetch";
    this->data_transformer_->InitRand();
    StartInternalThread();
    DLOG(INFO) << "Prefetch initialized.";
}

其中load_batch函数被DataLayer重载.

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::InternalThreadEntry() {
        while (!must_stop()) {
            Batch<Dtype> *batch = prefetch_free_.pop();
            load_batch(batch);

            prefetch_full_.push(batch);
        }
}

DataLayer中使用线程读取Batch(image,label)push到队列中,然后pop出来前向传播:

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::Forward_cpu(
        const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {

    Batch<Dtype>* batch = prefetch_full_.pop("Data layer prefetch queue empty");
    // Reshape to loaded data.
    top[0]->ReshapeLike(batch->data_);

    // Copy the data
    caffe_copy(batch->data_.count(), batch->data_.cpu_data(),
               top[0]->mutable_cpu_data());

    if (this->output_labels_) {
        // Reshape to loaded labels.
        top[1]->ReshapeLike(batch->label_);
        // Copy the labels.
        caffe_copy(batch->label_.count(), batch->label_.cpu_data(),
                   top[1]->mutable_cpu_data());
    }

    prefetch_free_.push(batch);
}

下面看DataLayer:

template <typename Dtype>
class DataLayer : public BasePrefetchingDataLayer<Dtype> {
public:
    explicit DataLayer(const LayerParameter& param);
    virtual ~DataLayer();
    virtual void DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,
                                const vector<Blob<Dtype>*>& top);
    // DataLayer uses DataReader instead for sharing for parallelism
    virtual inline bool ShareInParallel() const { return false; }
    virtual inline const char* type() const { return "Data"; }
    virtual inline int ExactNumBottomBlobs() const { return 0; }
    virtual inline int MinTopBlobs() const { return 1; }
    virtual inline int MaxTopBlobs() const { return 2; }

protected:
    virtual void load_batch(Batch<Dtype>* batch);
    DataReader reader_;

};

DataLayerSetUp初始化参数:

template <typename Dtype>
void DataLayer<Dtype>::DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,
                                      const vector<Blob<Dtype>*>& top) {
    const int batch_size = this->layer_param_.data_param().batch_size();
    // Read a data point, and use it to initialize the top blob.
    Datum& datum = *(reader_.full().peek());

    // Use data_transformer to infer the expected blob shape from datum.
    vector<int> top_shape = this->data_transformer_->InferBlobShape(datum);
    this->transformed_data_.Reshape(top_shape);
    // Reshape top[0] and prefetch_data according to the batch_size.
    top_shape[0] = batch_size;
    top[0]->Reshape(top_shape);
    for (int i = 0; i < this->PREFETCH_COUNT; ++i) {
        this->prefetch_[i].data_.Reshape(top_shape);
    }
    
    if (this->output_labels_) {// label
        vector<int> label_shape(1, batch_size);
        top[1]->Reshape(label_shape);
        for (int i = 0; i < this->PREFETCH_COUNT; ++i) {
            this->prefetch_[i].label_.Reshape(label_shape);
        }
    }
}

load_batch在线程中轮训读取数据库(如lmdb)中的数据,并做crop_size,do_mirror,mean等操作,然后通过Forward_cpu传递给下一层.

template<typename Dtype>
void DataLayer<Dtype>::load_batch(Batch<Dtype>* batch) {
    CPUTimer batch_timer;
    batch_timer.Start();
    double read_time = 0;nnndouble trans_time = 0;
    CPUTimer timer;

    const int batch_size = this->layer_param_.data_param().batch_size();
    Datum& datum = *(reader_.full().peek());
    // Use data_transformer to infer the expected blob shape from datum.
    vector<int> top_shape = this->data_transformer_->InferBlobShape(datum);
    this->transformed_data_.Reshape(top_shape);
    // Reshape batch according to the batch_size.
    top_shape[0] = batch_size;
    batch->data_.Reshape(top_shape);

    Dtype* top_data = batch->data_.mutable_cpu_data();
    Dtype* top_label = NULL;

    if (this->output_labels_) {
        top_label = batch->label_.mutable_cpu_data();
    }
    for (int item_id = 0; item_id < batch_size; ++item_id) {
        timer.Start();
        // get a datum
        Datum& datum = *(reader_.full().pop("Waiting for data"));
        read_time += timer.MicroSeconds();
        timer.Start();
        // Apply data transformations (mirror, scale, crop...)
        int offset = batch->data_.offset(item_id);
        this->transformed_data_.set_cpu_data(top_data + offset);
        this->data_transformer_->Transform(datum, &(this->transformed_data_));
        // Copy label.
        if (this->output_labels_) {
            top_label[item_id] = datum.label();
        }
        trans_time += timer.MicroSeconds();

        reader_.free().push(const_cast<Datum*>(&datum));
    }
    timer.Stop();
    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.";
}

使用示例如下:

layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "/home/xy/caffe-master/examples/mnist/mnist_train_lmdb"
    batch_size: 64
    backend: LMDB
  }
}

proto定义如下:

message DataParameter {
  enum DB {
    LEVELDB = 0;
    LMDB = 1;
  }
  // Specify the data source.
  optional string source = 1;
  // Specify the batch size.
  optional uint32 batch_size = 4;
  optional uint32 rand_skip = 7 [default = 0];
  optional DB backend = 8 [default = LEVELDB];
  // Prefetch queue (Number of batches to prefetch to host memory.
  optional uint32 prefetch = 10 [default = 4];
}

caffe系列源码分析介绍

本系列深度学习框架caffe 源码分析主要内容如下:

1. caffe源码分析-cmake 工程构建:

caffe源码分析-cmake 工程构建主要内容:

自己从头构建一遍工程,这样能让我更好的了解大型的项目的构建。当然原始的caffe的构建感觉还是比较复杂(主要是cmake),我这里仅仅使用cmake构建,而且简化点,当然最重要的是支持CLion直接运行调试(如果需要这个工程可以评论留下你的邮箱,我给你发送过去)。

这里写图片描述

2. caffe的数据内存分配类SyncedMemory, 以及类Blob数据传输的媒介.

主要内容:
caffe源码分析-SyncedMemory
caffe源码分析-Blob
其中Blob分析给出了其直接与opencv的图片相互转化以及操作,可以使得我们更好的理解Blob.

3. caffe layer的源码分析,包括从整体上说明了layer类别以及其proto定义与核心函数.

内容如下:
caffe源码分析-layer
caffe源码分析-ReLULayer
caffe源码分析-inner_product_layer
caffe源码分析-layer_factory

首先分析了最简单的layer Relu,然后在是inner_product_layer全连接层, 最后是layer_factorycaffe中 以此工厂模式create各种Layer.

4. 数据输入层,主要是多线程+BlockingQueue的方式读取数据训练:

内容如下:
caffe源码分析-BlockingQueue
caffe源码分析-InternalThread
caffe源码分析-DataReader

5. IO处理例如读取proto文件转化为网络,以及网络参数的序列化

内容如下:
caffe源码分析-DataTransformer
caffe源码分析-db, io

6. 最后给出了使用纯C++结合多层感知机网络训练mnist的示例

内容如下:

caffe c++示例(mnist 多层感知机c++训练,测试)

类似与caffe一样按照layer、solver、loss、net等模块构建的神经网络实现可以见下面这篇blog,相信看懂了这个python的代码理解caffe框架会更简单点.

神经网络python实现


最后如果需要cmake + CLion直接运行调试caffe的代码工程,可以评论留下你的邮箱,我给你发送过去.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 安装caffe-ssd-gpu在ubuntu18.04的步骤如下: 1. 安装CUDA:从Nvidia官网下载合适的CUDA安装包,按照官方文档的指引进行安装。 2. 安装依赖:运行以下命令安装所需依赖库: ``` sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev \ libopencv-dev libhdf5-serial-dev protobuf-compiler \ libgflags-dev libgoogle-glog-dev liblmdb-dev libboost-all-dev ``` 3. 下载caffe-ssd-gpu源码并编译:从Github上下载caffe-ssd-gpu的源码,按照官方文档指引进行编译。编译时需要指定编译选项为GPU模式。 4. 运行测试:安装完成后,运行测试脚本,确保安装配置成功。 以上为简要步骤,具体操作请参考对应文档和官方指引。 ### 回答2: Ubuntu18.04是目前比较常见的Linux操作系统之一,而CAFFE-SSD-GPU是深度学习的一个工具。下面是安装caffe-ssd-gpu的步骤: 1. 安装CUDA和cuDNN 首先,您需要安装CUDA和cuDNN,这是运行深度学习框架所需的必备组件。下载安装CUDA和cuDNN之前,您需要查看您的图形卡的型号,以便选择正确的CUDA版本和cuDNN版本。 在下载和安装CUDA和cuDNN之前,您需要在NVIDIA的开发者网站上注册自己,并下载适用于您机器的CUDA和cuDNN版本。此外,您还需要在命令行界面中设置以下环境变量: export PATH=/usr/local/cuda-8.0/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:$LD_LIBRARY_PATH 2. 安装依赖项 在安装caffe之前,需要安装一些依赖项。您可以使用以下命令将这些依赖项安装到您的Ubuntu系统上: sudo apt-get update sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev libhdf5-serial-dev protobuf-compiler gfortran libjpeg62 libfreeimage-dev libatlas-base-dev git python-dev python-pip libgoogle-glog-dev libbz2-dev libxml2-dev libxslt-dev libffi-dev libssl-dev libgflags-dev liblmdb-dev python-yaml python-numpy python-scipy 3. 下载和安装CAFFE 现在,您需要在您的系统上下载和安装CAFFE。从github上获取caffesource代码并进行安装: git clone https://github.com/weiliu89/caffe.git cd caffe git checkout ssd 4. 编译和安装CAFFE 使用以下命令编译和安装caffe: cp Makefile.config.example Makefile.config make all -j $(($(nproc) + 1)) make pycaffe 执行该命令后,您需要等待一段时间才能完成CAFFE的编译。如果出现任何编译错误,请检查您的CUDA和cuDNN版本是否正确,并重新安装依赖项。 5. 使用CAFFE-SSD-GPU 现在,您已经成功地在Ubuntu18.04操作系统上安装并编译了CAFFE-SSD-GPU,您可以开始使用该工具来执行深度学习任务了。 总结 安装CAFFE-SSD-GPU需要充分理解linux的命令行操作。需要先确认CUDA和cuDNN已经安装,并正确设置环境变量。然后需要下载和安装CAFFE, 并最后编译和安装CAFFE。在安装过程中如果存在问题,可以查看错误日志,重新检查步骤。如果对命令行操作不熟悉,则先学习linux基础操作。 ### 回答3: caffe-ssd-gpu是一种基于caffe框架的用于实现目标检测的神经网络模型,在Ubuntu18.04系统中安装caffe-ssd-gpu需要进行以下步骤: 1. 安装CUDA CUDA是NVIDIA公司推出的用于高性能计算的并行计算平台和编程模型,是使用GPU进行深度学习任务所必需的。在Ubuntu18.04上安装CUDA需要首先确认自己的显卡型号,并选择合适的CUDA版本进行安装。可以在NVIDIA官网上下载相应的CUDA安装包,也可以通过命令行方式进行安装。在安装过程中注意要按照提示完成相应的配置和设置。 2. 安装cuDNN cuDNN是用于深度神经网络的GPU加速库,也是必需的组件之一。在安装过程中同样需要确认CUDA的版本和自己的显卡型号,并下载相应的cuDNN安装包进行安装。 3. 安装依赖包 在安装caffe-ssd-gpu前需要先安装几个依赖包,包括protobuf、opencv、boost等。可以通过命令行方式进行安装,例如: ``` sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev libhdf5-serial-dev libgflags-dev libgoogle-glog-dev liblmdb-dev ``` 4. 下载caffe-ssd-gpu源码 可以在GitHub上找到caffe-ssd-gpu的源码,下载后解压到自己想要的目录下。 5. 编译和安装caffe-ssd-gpu 进入caffe-ssd-gpu源码目录下,执行以下命令: ``` cd caffe-ssd-gpu mkdir build cd build cmake .. make all -j8 make install ``` 其中,make all -j8表示使用8个线程进行编译,提高编译速度。make install表示安装编译好的caffe-ssd-gpu库文件和可执行文件。 6. 测试安装是否成功 可以尝试运行caffe-ssd-gpu自带的测试程序,检查安装是否成功。在源码目录下执行以下命令: ``` ./build/tools/caffe time --model=models/VGGNet/VOC0712/SSD_300x300_ft/deploy.prototxt --gpu=0 ``` 这条命令会测试caffe-ssd-gpu在GPU上执行推断的速度,如果没有问题,则说明安装成功。 需要注意的是,在安装过程中可能会遇到各种问题,例如依赖包的版本不兼容、CUDA和cuDNN的配置出错等等。这时候需要耐心调试错误,逐个解决问题,才能确保caffe-ssd-gpu能够正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值