本文主要分析caffe
中DataTransformer
这个类, 主要作用是:
将Datum
类型或者cv::Mat
, 转化为caffe
的Blob
,并按照Transformation``Parameter
参数对图像做处理,例如scale,mirro
等
推断blob
的shape
proto
定义如下:
// 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:
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:
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
}
下面看其核心的数据成员以及函数定义:
template
class DataTransformer {
public:
explicit DataTransformer(const TransformationParameter& param, Phase phase);
void Transform(const Datum& datum, Blob* transformed_blob);
void Transform(const cv::Mat& cv_img, Blob* transformed_blob);
vector InferBlobShape(const Datum& datum);
vector InferBlobShape(const cv::Mat& cv_img);
protected:
// Tranformation parameters
TransformationParameter param_;
shared_ptr rng_;
Phase phase_;
Blob data_mean_;
vector mean_values_;
};
下面仅仅给出将Datum类型转化为caffe的Blob, cv::Mat的转化同理.
template
void DataTransformer::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(static_cast(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
源码分析主要内容如下:
caffe源码分析-cmake 工程构建主要内容:
自己从头构建一遍工程,这样能让我更好的了解大型的项目的构建。当然原始的caffe的构建感觉还是比较复杂(主要是cmake),我这里仅仅使用cmake构建,而且简化点,当然最重要的是支持CLion直接运行调试(如果需要这个工程可以评论留下你的邮箱,我给你发送过去)。
SyncedMemory
, 以及类Blob
数据传输的媒介.主要内容:
caffe源码分析-SyncedMemory
caffe源码分析-Blob
其中Blob
分析给出了其直接与opencv的图片相互转化以及操作,可以使得我们更好的理解Blob
.
layer
的源码分析,包括从整体上说明了layer
类别以及其proto定义与核心函数.内容如下:
caffe源码分析-layer
caffe源码分析-ReLULayer
caffe源码分析-inner_product_layer
caffe源码分析-layer_factory
首先分析了最简单的layer
Relu
,然后在是inner_product_layer全连接层
, 最后是layer_factory
caffe中 以此工厂模式create各种Layer.
内容如下:
caffe源码分析-BlockingQueue
caffe源码分析-InternalThread
caffe源码分析-DataReader
内容如下:
caffe源码分析-DataTransformer
caffe源码分析-db, io
内容如下:
caffe c++示例(mnist 多层感知机c++训练,测试)
类似与caffe
一样按照layer、solver、loss、net
等模块构建的神经网络实现可以见下面这篇blog,相信看懂了这个python的代码理解caffe框架会更简单点.
神经网络python实现
最后如果需要cmake
+ CLion
直接运行调试caffe
的代码工程,可以评论留下你的邮箱,我给你发送过去.