前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >caffe源码分析-DataTransformer

caffe源码分析-DataTransformer

作者头像
bear_fish
发布2019-02-25 11:53:25
5460
发布2019-02-25 11:53:25
举报

本文主要分析caffeDataTransformer这个类, 主要作用是:

  1. Datum类型或者cv::Mat, 转化为caffeBlob<Dtype>,并按照Transformation``Parameter参数对图像做处理,例如scale,mirro
  2. 推断blobshape

proto定义如下:

代码语言:javascript
复制
// Message that stores parameters used to apply transformation
// to the data layer's data
message TransformationParameter {

  optional float scale = 1 [default = 1];
  // Specify if we want to randomly mirror data.
  optional bool mirror = 2 [default = false];
  // Specify if we would like to randomly crop an image.
  optional uint32 crop_size = 3 [default = 0];
  // mean_file and mean_value cannot be specified at the same time
  optional string mean_file = 4;
  repeated float mean_value = 5;
  // Force the decoded image to have 3 color channels.
  optional bool force_color = 6 [default = false];
  // Force the decoded image to have 1 color channels.
  optional bool force_gray = 7 [default = false];
}

使用示例1:

代码语言:javascript
复制
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    scale: 0.00390625  # 1 / 255
  }
  data_param {
    source: "/home/xy/caffe-master/examples/mnist/mnist_test_lmdb"
    batch_size: 100
    backend: LMDB
  }
}

使用示例2:

代码语言:javascript
复制
transform_param {
  # randomly horizontally mirror the image
  mirror: 1
  crop_size: 227
  # substract mean value(RGB three channel): or use mean.binaryproto file
  # mean_file: name_of_mean_file.binaryproto
  mean_value: 104
  mean_value: 117
  mean_value: 123
}

下面看其核心的数据成员以及函数定义:

代码语言:javascript
复制
template <typename Dtype>
class DataTransformer {
public:
    explicit DataTransformer(const TransformationParameter& param, Phase phase);

    void Transform(const Datum& datum, Blob<Dtype>* transformed_blob);
    void Transform(const cv::Mat& cv_img, Blob<Dtype>* transformed_blob);

    vector<int> InferBlobShape(const Datum& datum);
    vector<int> InferBlobShape(const cv::Mat& cv_img);

protected:
    // Tranformation parameters
    TransformationParameter param_;

    shared_ptr<Caffe::RNG> rng_;
    Phase phase_;
    Blob<Dtype> data_mean_;
    vector<Dtype> mean_values_;
};

下面仅仅给出将Datum类型转化为caffe的Blob, cv::Mat的转化同理.

代码语言:javascript
复制
template<typename Dtype>
void DataTransformer<Dtype>::Transform(const Datum& datum,
                                       Dtype* transformed_data) {
    const string& data = datum.data();
    const int datum_channels = datum.channels();
    const int datum_height = datum.height();
    const int datum_width = datum.width();

    const int crop_size = param_.crop_size();
    const Dtype scale = param_.scale();
    const bool do_mirror = param_.mirror() && Rand(2);
    const bool has_mean_file = param_.has_mean_file();
    const bool has_uint8 = data.size() > 0;
    const bool has_mean_values = mean_values_.size() > 0;

    Dtype* mean = NULL;
    if (has_mean_file) {
        mean = data_mean_.mutable_cpu_data();
    }
    if (has_mean_values) {
        if (datum_channels > 1 && mean_values_.size() == 1) {
            // Replicate the mean_value for simplicity
            for (int c = 1; c < datum_channels; ++c) {
                mean_values_.push_back(mean_values_[0]);
            }
        }
    }

    int height = datum_height;
    int width = datum_width;

    int h_off = 0;
    int w_off = 0;
    if (crop_size) {
        height = crop_size;
        width = crop_size;
        // We only do random crop when we do training.
        if (phase_ == TRAIN) {
            h_off = Rand(datum_height - crop_size + 1);
            w_off = Rand(datum_width - crop_size + 1);
        } else {
            h_off = (datum_height - crop_size) / 2;
            w_off = (datum_width - crop_size) / 2;
        }
    }

    Dtype datum_element;
    int top_index, data_index;
    for (int c = 0; c < datum_channels; ++c) {
        for (int h = 0; h < height; ++h) {
            for (int w = 0; w < width; ++w) {
                data_index = (c * datum_height + h_off + h) * datum_width + w_off + w;
                if (do_mirror) {
                    top_index = (c * height + h) * width + (width - 1 - w);
                } else {
                    top_index = (c * height + h) * width + w;
                }
                if (has_uint8) {
                    datum_element =
                            static_cast<Dtype>(static_cast<uint8_t>(data[data_index]));
                } else {
                    datum_element = datum.float_data(data_index);
                }
                if (has_mean_file) {
                    transformed_data[top_index] =
                            (datum_element - mean[data_index]) * scale;
                } else {
                    if (has_mean_values) {
                        transformed_data[top_index] =
                                (datum_element - mean_values_[c]) * scale;
                    } else {
                        transformed_data[top_index] = datum_element * scale;
                    }
                }
            }
        }
    }
}

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**的代码工程,可以评论留下你的邮箱,我给你发送过去.**

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年10月07日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • caffe系列源码分析介绍
    • 1. caffe源码分析-cmake 工程构建:
      • 2. caffe的数据内存分配类SyncedMemory, 以及类Blob数据传输的媒介.
        • 3. caffe layer的源码分析,包括从整体上说明了layer类别以及其proto定义与核心函数.
          • 4. 数据输入层,主要是多线程+BlockingQueue的方式读取数据训练:
            • 5. IO处理例如读取proto文件转化为网络,以及网络参数的序列化
              • 6. 最后给出了使用纯C++结合多层感知机网络训练mnist的示例
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档