提交 d1d70ec8 编写于 作者: W wanghaoshuang

Refine configure option of crop layer

1. change configure content to 'axis, offset, shape'
2. add an optional input to crop layer as cropping reference
上级 e10040ca
7 合并请求!11636[IMPORTANT] MKLDNN layout: Support for sum operator,!8482Release/0.11.0,!8190Release/0.11.0,!8189Release/0.11.0,!6633给线性回归的get-started代码加上了预测的示例~~,!4615Feature/tensor array add python binding,!2490Add crop layers for supporting FCN model
......@@ -17,28 +17,27 @@ limitations under the License. */
#include "paddle/function/TensorShape.h"
namespace paddle {
static inline CropConf castToCropConf(const FuncConfig& conf) {
return {conf.get<std::vector<uint32_t>>("crop_corner"),
conf.get<std::vector<uint32_t>>("crop_shape")};
}
template <>
void Crop<DEVICE_TYPE_CPU>(real* outputs,
const real* inputs,
const TensorShape inShape,
const CropConf& crop) {
int cCrop = crop.corner[0];
int hCrop = crop.corner[1];
int wCrop = crop.corner[2];
const FuncConfig& conf) {
std::vector<uint32_t> crop_corner =
conf.get<std::vector<uint32_t>>("crop_corner");
std::vector<uint32_t> crop_shape =
conf.get<std::vector<uint32_t>>("crop_shape");
int cCrop = crop_corner[1];
int hCrop = crop_corner[2];
int wCrop = crop_corner[3];
int num = inShape[0];
int inC = inShape[1];
int inH = inShape[2];
int inW = inShape[3];
int outC = crop.shape[0];
int outH = crop.shape[1];
int outW = crop.shape[2];
int outC = crop_shape[1];
int outH = crop_shape[2];
int outW = crop_shape[3];
for (int n = 0; n < num; n++) {
for (int c = 0; c < outC; c++) {
......@@ -55,19 +54,23 @@ template <>
void CropGrad<DEVICE_TYPE_CPU>(const real* inGrad,
real* outGrad,
const TensorShape outShape,
const CropConf& crop) {
int cCrop = crop.corner[0];
int hCrop = crop.corner[1];
int wCrop = crop.corner[2];
const FuncConfig& conf) {
std::vector<uint32_t> crop_corner =
conf.get<std::vector<uint32_t>>("crop_corner");
std::vector<uint32_t> crop_shape =
conf.get<std::vector<uint32_t>>("crop_shape");
int cCrop = crop_corner[1];
int hCrop = crop_corner[2];
int wCrop = crop_corner[3];
int num = outShape[0];
int outC = outShape[1];
int outH = outShape[2];
int outW = outShape[3];
int inC = crop.shape[0];
int inH = crop.shape[1];
int inW = crop.shape[2];
int inC = crop_shape[1];
int inH = crop_shape[2];
int inW = crop_shape[3];
for (int n = 0; n < num; n++) {
for (int c = 0; c < inC; c++) {
......@@ -111,26 +114,21 @@ void CropGrad<DEVICE_TYPE_CPU>(const real* inGrad,
template <DeviceType Device>
class CropFunc : public FunctionBase {
public:
void init(const FuncConfig& config) override {
crop_ = castToCropConf(config);
}
void init(const FuncConfig& config) override { conf_ = config; }
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(1UL, inputs.size());
CHECK_EQ(1UL, outputs.size());
CHECK_EQ(outputs[0].shape()[1], crop_.shape[0]);
CHECK_EQ(outputs[0].shape()[2], crop_.shape[1]);
CHECK_EQ(outputs[0].shape()[3], crop_.shape[2]);
CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO);
TensorShape inShape = inputs[0].shape();
Crop<Device>(
outputs[0].data<real>(), inputs[0].data<real>(), inShape, crop_);
outputs[0].data<real>(), inputs[0].data<real>(), inShape, conf_);
}
private:
CropConf crop_;
FuncConfig conf_;
};
/**
......@@ -145,26 +143,21 @@ private:
template <DeviceType Device>
class CropGradFunc : public FunctionBase {
public:
void init(const FuncConfig& config) override {
crop_ = castToCropConf(config);
}
void init(const FuncConfig& config) override { conf_ = config; }
void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
CHECK_EQ(1UL, inputs.size());
CHECK_EQ(1UL, outputs.size());
CHECK_EQ(inputs[0].shape()[1], crop_.shape[0]);
CHECK_EQ(inputs[0].shape()[2], crop_.shape[1]);
CHECK_EQ(inputs[0].shape()[3], crop_.shape[2]);
CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO);
TensorShape outShape = outputs[0].shape();
CropGrad<Device>(
inputs[0].data<real>(), outputs[0].data<real>(), outShape, crop_);
inputs[0].data<real>(), outputs[0].data<real>(), outShape, conf_);
}
private:
CropConf crop_;
FuncConfig conf_;
};
REGISTER_TYPED_FUNC(Crop, CPU, CropFunc);
......
......@@ -18,13 +18,6 @@ limitations under the License. */
namespace paddle {
struct CropConf {
/// The upper left corner of croped result
std::vector<uint32_t> corner;
/// The shape of croped result
std::vector<uint32_t> shape;
};
/**
* \brief This funtion crops inputs according to the specify start point and
*shape.
......@@ -32,13 +25,13 @@ struct CropConf {
* \param[out] outputs save results.
* \param[in] inputs input data.
* \param[in] inShape the shape of input tensor.
* \param[in] crop the cropping config
* \param[in] conf the cropping config
*/
template <DeviceType Device>
void Crop(real* outputs,
const real* inputs,
const TensorShape inShape,
const CropConf& crop);
const FuncConfig& conf);
/**
* \brief Cropping operation backward.
......@@ -46,11 +39,11 @@ void Crop(real* outputs,
* \param[out] inGrad gradients of previous layer
* \param[in] outGrad output gradient
* \param[in] inShape the shape of input tensor.
* \param[in] crop the cropping config
* \param[in] conf the cropping config
*/
template <DeviceType Device>
void CropGrad(const real* inGrad,
real* outGrad,
const TensorShape inShape,
const CropConf& crop);
const FuncConfig& conf);
} // namespace paddle
......@@ -37,19 +37,21 @@ template <>
void Crop<DEVICE_TYPE_GPU>(real* outputs,
const real* inputs,
const TensorShape inShape,
const CropConf& crop) {
int cropC = crop.corner[0];
int cropH = crop.corner[1];
int cropW = crop.corner[2];
const FuncConfig& conf) {
std::vector<uint32_t> crop_corner = conf.get<std::vector<uint32_t>>("crop_corner");
std::vector<uint32_t> crop_shape = conf.get<std::vector<uint32_t>>("crop_shape");
int cropC = crop_corner[1];
int cropH = crop_corner[2];
int cropW = crop_corner[3];
int num = inShape[0];
int inC = inShape[1];
int inH = inShape[2];
int inW = inShape[3];
int outC = crop.shape[0];
int outH = crop.shape[1];
int outW = crop.shape[2];
int outC = crop_shape[1];
int outH = crop_shape[2];
int outW = crop_shape[3];
size_t nth = num * outC * outH * outW;
int blockSize = 1024;
......@@ -82,19 +84,21 @@ template <>
void CropGrad<DEVICE_TYPE_GPU>(const real* inGrad,
real* outGrad,
const TensorShape outShape,
const CropConf& crop) {
int cropC = crop.corner[0];
int cropH = crop.corner[1];
int cropW = crop.corner[2];
const FuncConfig& conf) {
std::vector<uint32_t> crop_corner = conf.get<std::vector<uint32_t>>("crop_corner");
std::vector<uint32_t> crop_shape = conf.get<std::vector<uint32_t>>("crop_shape");
int cropC = crop_corner[1];
int cropH = crop_corner[2];
int cropW = crop_corner[3];
int num = outShape[0];
int outC = outShape[1];
int outH = outShape[2];
int outW = outShape[3];
int inC = crop.shape[0];
int inH = crop.shape[1];
int inW = crop.shape[2];
int inC = crop_shape[1];
int inH = crop_shape[2];
int inW = crop_shape[3];
size_t nth = num * inC * inH * inW;
int blockSize = 1024;
......
......@@ -28,8 +28,8 @@ TEST(Crop, real) {
FunctionCompare compare(
test_grad ? "CropGrad" : "Crop",
FuncConfig()
.set<std::vector<uint32_t>>("crop_corner", {1, 1, 1})
.set<std::vector<uint32_t>>("crop_shape", {2, 3, 3}));
.set<std::vector<uint32_t>>("crop_corner", {0, 1, 1, 1})
.set<std::vector<uint32_t>>("crop_shape", {0, 2, 3, 3}));
TensorShape inDims{numSamples, channels, imgSizeH, imgSizeW};
TensorShape outDims{numSamples, 2, 3, 3};
compare.addInputs(
......
......@@ -25,20 +25,57 @@ bool CropLayer::init(const LayerMap& layerMap,
Layer::init(layerMap, parameterMap);
auto& crop_conf = config_.inputs(0).crop_conf();
auto& img_conf = crop_conf.image_conf();
CHECK_EQ(config_.inputs_size(), 1);
inDims_ = TensorShape(
{0,
img_conf.channels(),
img_conf.has_img_size_y() ? img_conf.img_size_y() : img_conf.img_size(),
img_conf.img_size()});
crop_corner_ = {crop_conf.crop_corner(0),
crop_conf.crop_corner(1),
crop_conf.crop_corner(2)};
crop_shape_ = {crop_conf.crop_shape(0),
crop_conf.crop_shape(1),
crop_conf.crop_shape(2)};
crop_axis_ = crop_conf.axis();
for (int i = 0; i < crop_conf.offset_size(); i++) {
crop_offsets_[i] = crop_conf.offset(i);
}
// 1. get input_0 shape
auto& input0_img_conf = config_.inputs(0).image_conf();
inDims_ = TensorShape({0,
input0_img_conf.channels(),
input0_img_conf.has_img_size_y()
? input0_img_conf.img_size_y()
: input0_img_conf.img_size(),
input0_img_conf.img_size()});
// 2. get output shape from input_1 or crop shap conf
if (config_.inputs_size() == 2) {
auto& input1_img_conf = config_.inputs(1).image_conf();
targetDims_ = TensorShape({0,
input1_img_conf.channels(),
input1_img_conf.has_img_size_y()
? input1_img_conf.img_size_y()
: input1_img_conf.img_size(),
input1_img_conf.img_size()});
} else {
targetDims_ = TensorShape({crop_conf.shape(0),
crop_conf.shape(1),
crop_conf.shape(2),
crop_conf.shape(3)});
}
// 3. get final crop shape
int dimSize = 4;
for (int i = 0; i < dimSize; i++) {
if (i >= crop_axis_) {
crop_shape_[i] = targetDims_[i];
} else {
crop_shape_[i] = inDims_[i];
}
}
// 4. get final crop corner
crop_corner_ = {0, 0, 0, 0};
for (int i = 0; i < dimSize; i++) {
if (i >= crop_axis_) {
if (crop_offsets_.size() > 1) {
crop_corner_[i] = crop_offsets_[i - crop_axis_];
} else {
crop_corner_[i] = crop_offsets_[0];
}
}
}
outDims_ = TensorShape(4);
setOutDims(0);
......@@ -58,7 +95,7 @@ bool CropLayer::init(const LayerMap& layerMap,
}
void CropLayer::setOutDims(const size_t batchSize) {
outDims_.reshape({batchSize, crop_shape_[0], crop_shape_[1], crop_shape_[2]});
outDims_.reshape({batchSize, crop_shape_[1], crop_shape_[2], crop_shape_[3]});
}
void CropLayer::setTensorDim(const size_t batchSize) {
......
......@@ -19,9 +19,13 @@ limitations under the License. */
namespace paddle {
/**
* \brief This layer crop inputs according to the specify corner and shape.
* The input and output is a 4D tensor. Cropping from the 2nd to
* the 4th dimenstion.
* \brief This layer crop input according to the specify conf.
* input_0: input to be cropped
* input_1: optional reference input
* axis: start dimension to be croped
* offset: offset of cropping in each dimension
* shape: if reference input layer was not setted,
* crop input as this shape conf
*/
class CropLayer : public Layer {
public:
......@@ -38,9 +42,12 @@ protected:
void setOutDims(const size_t batchSize);
void setTensorDim(const size_t batchSize);
int32_t crop_axis_;
std::vector<uint32_t> crop_offsets_;
std::vector<uint32_t> crop_corner_;
std::vector<uint32_t> crop_shape_;
TensorShape inDims_;
TensorShape targetDims_;
TensorShape outDims_;
};
} // namespace paddle
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部