Skip to content

Commit

Permalink
Crop: more tests and test tuning.
Browse files Browse the repository at this point in the history
Changes are:
  reduce test blob dims for speed
  use standard Gaussian filler,
  polish formatting and rename tests,
  test HW crop and 5D crop,
  standard gradient checks
  • Loading branch information
shelhamer authored and BlGene committed Mar 5, 2016
1 parent 2e0cf91 commit 66216cf
Showing 1 changed file with 110 additions and 73 deletions.
183 changes: 110 additions & 73 deletions src/caffe/test/test_crop_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ class CropLayerTest : public MultiDeviceTest<TypeParam> {

protected:
CropLayerTest()
: blob_bottom_0_(new Blob<Dtype>(2, 5, 6, 5)),
blob_bottom_1_(new Blob<Dtype>(2, 4, 5, 3)),
: blob_bottom_0_(new Blob<Dtype>(2, 4, 5, 4)),
blob_bottom_1_(new Blob<Dtype>(2, 3, 4, 2)),
blob_top_(new Blob<Dtype>()) {}
virtual void SetUp() {
// fill the values
for (int i = 0; i < this->blob_bottom_0_->count(); ++i) {
this->blob_bottom_0_->mutable_cpu_data()[i] = i;
}

FillerParameter filler_param;
GaussianFiller<Dtype> filler(filler_param);
filler.Fill(this->blob_bottom_0_);
filler.Fill(this->blob_bottom_1_);

blob_bottom_vec_0_.push_back(blob_bottom_0_);
blob_bottom_vec_0_.push_back(blob_bottom_1_);
blob_bottom_vec_.push_back(blob_bottom_0_);
blob_bottom_vec_.push_back(blob_bottom_1_);
blob_top_vec_.push_back(blob_top_);
}

Expand All @@ -41,7 +41,7 @@ class CropLayerTest : public MultiDeviceTest<TypeParam> {
Blob<Dtype>* const blob_bottom_0_;
Blob<Dtype>* const blob_bottom_1_;
Blob<Dtype>* const blob_top_;
vector<Blob<Dtype>*> blob_bottom_vec_0_;
vector<Blob<Dtype>*> blob_bottom_vec_;
vector<Blob<Dtype>*> blob_top_vec_;
};

Expand All @@ -51,11 +51,10 @@ TYPED_TEST_CASE(CropLayerTest, TestDtypesAndDevices);
TYPED_TEST(CropLayerTest, TestSetupShapeAll) {
typedef typename TypeParam::Dtype Dtype;
LayerParameter layer_param;

// Crop all dimensions
layer_param.mutable_crop_param()->set_axis(0);
CropLayer<Dtype> layer(layer_param);
layer.SetUp(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
for (int i = 0; i < this->blob_top_->num_axes(); ++i) {
EXPECT_EQ(this->blob_bottom_1_->shape(i), this->blob_top_->shape(i));
}
Expand All @@ -66,7 +65,7 @@ TYPED_TEST(CropLayerTest, TestSetupShapeDefault) {
LayerParameter layer_param;
// Crop last two dimensions, axis is 2 by default
CropLayer<Dtype> layer(layer_param);
layer.SetUp(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
for (int i = 0; i < this->blob_top_->num_axes(); ++i) {
if (i < 2) {
EXPECT_EQ(this->blob_bottom_0_->shape(i), this->blob_top_->shape(i));
Expand All @@ -82,7 +81,7 @@ TYPED_TEST(CropLayerTest, TestSetupShapeNegativeIndexing) {
// Crop last dimension by negative indexing
layer_param.mutable_crop_param()->set_axis(-1);
CropLayer<Dtype> layer(layer_param);
layer.SetUp(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
for (int i = 0; i < this->blob_top_->num_axes(); ++i) {
if (i < 3) {
EXPECT_EQ(this->blob_bottom_0_->shape(i), this->blob_top_->shape(i));
Expand All @@ -92,15 +91,13 @@ TYPED_TEST(CropLayerTest, TestSetupShapeNegativeIndexing) {
}
}


TYPED_TEST(CropLayerTest, TestForwardNum) {
TYPED_TEST(CropLayerTest, TestCropAll) {
typedef typename TypeParam::Dtype Dtype;
LayerParameter layer_param;
layer_param.mutable_crop_param()->set_axis(0);

CropLayer<Dtype> layer(layer_param);
layer.SetUp(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_);
for (int n = 0; n < this->blob_bottom_0_->num(); ++n) {
for (int c = 0; c < this->blob_bottom_0_->channels(); ++c) {
for (int h = 0; h < this->blob_bottom_0_->height(); ++h) {
Expand All @@ -118,7 +115,7 @@ TYPED_TEST(CropLayerTest, TestForwardNum) {
}
}

TYPED_TEST(CropLayerTest, TestForwardNumOffsets) {
TYPED_TEST(CropLayerTest, TestCropAllOffset) {
typedef typename TypeParam::Dtype Dtype;
LayerParameter layer_param;
layer_param.mutable_crop_param()->set_axis(0);
Expand All @@ -127,8 +124,8 @@ TYPED_TEST(CropLayerTest, TestForwardNumOffsets) {
layer_param.mutable_crop_param()->add_offset(1);
layer_param.mutable_crop_param()->add_offset(2);
CropLayer<Dtype> layer(layer_param);
layer.SetUp(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_);
for (int n = 0; n < this->blob_bottom_0_->num(); ++n) {
for (int c = 0; c < this->blob_bottom_0_->channels(); ++c) {
for (int h = 0; h < this->blob_bottom_0_->height(); ++h) {
Expand All @@ -138,91 +135,131 @@ TYPED_TEST(CropLayerTest, TestForwardNumOffsets) {
h < this->blob_top_->shape(2) &&
w < this->blob_top_->shape(3) ) {
EXPECT_EQ(this->blob_top_->data_at(n, c, h, w),
this->blob_bottom_0_->data_at(n+0, c+1, h+1, w+2));
this->blob_bottom_0_->data_at(n, c+1, h+1, w+2));
}
}
}
}
}
}

TYPED_TEST(CropLayerTest, TestGradientNum) {
TYPED_TEST(CropLayerTest, TestCropHW) {
typedef typename TypeParam::Dtype Dtype;
LayerParameter layer_param;
layer_param.mutable_crop_param()->set_axis(2);
layer_param.mutable_crop_param()->add_offset(1);
layer_param.mutable_crop_param()->add_offset(2);
CropLayer<Dtype> layer(layer_param);

layer.SetUp(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_0_, this->blob_top_vec_);

// Copy top data into diff
caffe_copy(this->blob_top_->count(), this->blob_top_->cpu_data(),
this->blob_top_->mutable_cpu_diff());

// Do backward pass
vector<bool> propagate_down(2, true);
layer.Backward(this->blob_top_vec_, propagate_down, this->blob_bottom_vec_0_);


// Check results
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_);
for (int n = 0; n < this->blob_bottom_0_->num(); ++n) {
for (int c = 0; c < this->blob_bottom_0_->channels(); ++c) {
for (int h = 0; h < this->blob_bottom_0_->height(); ++h) {
for (int w = 0; w < this->blob_bottom_0_->width(); ++w) {
if ( n < this->blob_top_->shape(0) &&
if (n < this->blob_top_->shape(0) &&
c < this->blob_top_->shape(1) &&
h < this->blob_top_->shape(2) &&
w < this->blob_top_->shape(3) ) {
EXPECT_EQ(this->blob_bottom_0_->diff_at(n, c, h, w),
this->blob_bottom_0_->data_at(n, c, h, w));
} else {
EXPECT_EQ(this->blob_bottom_0_->diff_at(n, c, h, w), 0);
w < this->blob_top_->shape(3)) {
EXPECT_EQ(this->blob_top_->data_at(n, c, h, w),
this->blob_bottom_0_->data_at(n, c, h+1, w+2));
}
}
}
}
}
}

TYPED_TEST(CropLayerTest, TestGradientNumOffset) {
TYPED_TEST(CropLayerTest, TestCrop5D) {
typedef typename TypeParam::Dtype Dtype;
// Add dimension to each bottom for >4D check
vector<int> bottom_0_shape = this->blob_bottom_0_->shape();
vector<int> bottom_1_shape = this->blob_bottom_1_->shape();
bottom_0_shape.push_back(2);
bottom_1_shape.push_back(1);
this->blob_bottom_0_->Reshape(bottom_0_shape);
this->blob_bottom_1_->Reshape(bottom_1_shape);
FillerParameter filler_param;
GaussianFiller<Dtype> filler(filler_param);
filler.Fill(this->blob_bottom_0_);
filler.Fill(this->blob_bottom_1_);
// Make layer
LayerParameter layer_param;
layer_param.mutable_crop_param()->set_axis(0);
layer_param.mutable_crop_param()->add_offset(0);
layer_param.mutable_crop_param()->add_offset(1);
layer_param.mutable_crop_param()->set_axis(2);
layer_param.mutable_crop_param()->add_offset(1);
layer_param.mutable_crop_param()->add_offset(2);
layer_param.mutable_crop_param()->add_offset(0);
CropLayer<Dtype> layer(layer_param);

layer.SetUp(this->blob_bottom_vec_0_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_0_, this->blob_top_vec_);

// Copy top data into diff
caffe_copy(this->blob_top_->count(), this->blob_top_->cpu_data(),
this->blob_top_->mutable_cpu_diff());

// Do backward pass
vector<bool> propagate_down(2, true);
layer.Backward(this->blob_top_vec_, propagate_down, this->blob_bottom_vec_0_);


// Check results
for (int n = 0; n < this->blob_bottom_0_->num(); ++n) {
for (int c = 0; c < this->blob_bottom_0_->channels(); ++c) {
for (int h = 0; h < this->blob_bottom_0_->height(); ++h) {
for (int w = 0; w < this->blob_bottom_0_->width(); ++w) {
if ( 0 <= n && n < 0 + this->blob_top_->shape(0) &&
1 <= c && c < 1 + this->blob_top_->shape(1) &&
1 <= h && h < 1 + this->blob_top_->shape(2) &&
2 <= w && w < 2 + this->blob_top_->shape(3) ) {
EXPECT_EQ(this->blob_bottom_0_->diff_at(n, c, h, w),
this->blob_bottom_0_->data_at(n, c, h, w));
} else {
EXPECT_EQ(this->blob_bottom_0_->diff_at(n, c, h, w), 0);
layer.SetUp(this->blob_bottom_vec_, this->blob_top_vec_);
layer.Forward(this->blob_bottom_vec_, this->blob_top_vec_);
vector<int> bottom_idx = vector<int>(5, 0);
vector<int> top_idx = vector<int>(5, 0);
for (int n = 0; n < this->blob_bottom_0_->shape(0); ++n) {
for (int c = 0; c < this->blob_bottom_0_->shape(1); ++c) {
for (int z = 0; z < this->blob_bottom_0_->shape(2); ++z) {
for (int h = 0; h < this->blob_bottom_0_->shape(3); ++h) {
for (int w = 0; w < this->blob_bottom_0_->shape(4); ++w) {
if (n < this->blob_top_->shape(0) &&
c < this->blob_top_->shape(1) &&
z < this->blob_top_->shape(2) &&
h < this->blob_top_->shape(3) &&
w < this->blob_top_->shape(4)) {
bottom_idx[0] = top_idx[0] = n;
bottom_idx[1] = top_idx[1] = c;
bottom_idx[2] = z;
bottom_idx[3] = h;
bottom_idx[4] = top_idx[4] = w;
top_idx[2] = z+1;
top_idx[3] = h+2;
EXPECT_EQ(this->blob_top_->data_at(bottom_idx),
this->blob_bottom_0_->data_at(top_idx));
}
}
}
}
}
}
}

TYPED_TEST(CropLayerTest, TestCropAllGradient) {
typedef typename TypeParam::Dtype Dtype;
LayerParameter layer_param;
layer_param.mutable_crop_param()->set_axis(0);
CropLayer<Dtype> layer(layer_param);
GradientChecker<Dtype> checker(1e-2, 1e-3);
checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_,
this->blob_top_vec_);
}

TYPED_TEST(CropLayerTest, TestCropHWGradient) {
typedef typename TypeParam::Dtype Dtype;
LayerParameter layer_param;
layer_param.mutable_crop_param()->set_axis(2);
layer_param.mutable_crop_param()->add_offset(1);
layer_param.mutable_crop_param()->add_offset(2);
CropLayer<Dtype> layer(layer_param);
GradientChecker<Dtype> checker(1e-2, 1e-3);
checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_,
this->blob_top_vec_);
}

TYPED_TEST(CropLayerTest, TestCrop5DGradient) {
typedef typename TypeParam::Dtype Dtype;
LayerParameter layer_param;
layer_param.mutable_crop_param()->set_axis(2);
layer_param.mutable_crop_param()->add_offset(1);
layer_param.mutable_crop_param()->add_offset(2);
layer_param.mutable_crop_param()->add_offset(0);
CropLayer<Dtype> layer(layer_param);
// Add dimension to each bottom for >4D check
vector<int> bottom_0_shape = this->blob_bottom_0_->shape();
vector<int> bottom_1_shape = this->blob_bottom_1_->shape();
bottom_0_shape.push_back(2);
bottom_1_shape.push_back(1);
this->blob_bottom_0_->Reshape(bottom_0_shape);
this->blob_bottom_1_->Reshape(bottom_1_shape);
GradientChecker<Dtype> checker(1e-2, 1e-3);
checker.CheckGradientExhaustive(&layer, this->blob_bottom_vec_,
this->blob_top_vec_);
}

} // namespace caffe

0 comments on commit 66216cf

Please sign in to comment.