array_grad_test.cc revision ccb22083570219884f871d30a7124d93c151ef70
1/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7    http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#include "tensorflow/cc/framework/grad_op_registry.h"
17#include "tensorflow/cc/framework/gradient_checker.h"
18#include "tensorflow/cc/framework/testutil.h"
19#include "tensorflow/cc/gradients/grad_testutil.h"
20#include "tensorflow/cc/ops/standard_ops.h"
21#include "tensorflow/core/framework/tensor_testutil.h"
22#include "tensorflow/core/lib/core/status_test_util.h"
23
24namespace tensorflow {
25using namespace ops;  // NOLINT(build/namespaces)
26
27namespace {
28
29class ArrayGradTest : public ::testing::Test {
30 protected:
31  ArrayGradTest() : scope_(Scope::NewRootScope()) {}
32
33  void RunTest(const Output& x, const TensorShape& x_shape, const Output& y,
34               const TensorShape& y_shape) {
35    TF_ASSERT_OK(scope_.status());
36    float max_error;
37    TF_ASSERT_OK(ComputeGradientError(scope_, {x}, {x_shape}, {y}, {y_shape},
38                                      &max_error));
39    EXPECT_LT(max_error, 1e-4);
40  }
41
42  void RunTest(const OutputList& xs, const std::vector<TensorShape>& x_shapes,
43               const OutputList& ys, const std::vector<TensorShape>& y_shapes) {
44    TF_ASSERT_OK(scope_.status());
45    float max_error;
46    TF_ASSERT_OK(
47        ComputeGradientError(scope_, xs, x_shapes, ys, y_shapes, &max_error));
48    EXPECT_LT(max_error, 1e-4);
49  }
50
51  Scope scope_;
52};
53
54TEST_F(ArrayGradTest, PackGrad_Axis0) {
55  TensorShape x_shape({1, 2, 3});
56  std::vector<Output> xs;
57  xs.push_back(Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape)));
58  xs.push_back(Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape)));
59  auto y = Pack(scope_, xs, Pack::Axis(0));
60  TensorShape y_shape({2, 1, 2, 3});
61  RunTest(xs, {x_shape, x_shape}, {y}, {y_shape});
62}
63
64TEST_F(ArrayGradTest, PackGrad_Axis1) {
65  TensorShape x_shape({1, 2, 3});
66  std::vector<Output> xs;
67  xs.push_back(Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape)));
68  xs.push_back(Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape)));
69  auto y = Pack(scope_, xs, Pack::Axis(1));
70  TensorShape y_shape({1, 2, 2, 3});
71  RunTest(xs, {x_shape, x_shape}, {y}, {y_shape});
72}
73
74TEST_F(ArrayGradTest, UnpackGrad_Axis0) {
75  TensorShape x_shape({4, 2, 3});
76  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
77  // Unpacking the first dimension results in 4 outputs.
78  std::vector<TensorShape> y_shapes(4, TensorShape({2, 3}));
79  auto y = Unpack(scope_, x, 4, Unpack::Axis(0));
80  RunTest({x}, {x_shape}, y.output, y_shapes);
81}
82
83TEST_F(ArrayGradTest, UnpackGrad_Axis1) {
84  TensorShape x_shape({4, 2, 3});
85  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
86  // Unpacking the second dimension results in 2 outputs.
87  std::vector<TensorShape> y_shapes(2, TensorShape({4, 3}));
88  auto y = Unpack(scope_, x, 2, Unpack::Axis(1));
89  RunTest({x}, {x_shape}, y.output, y_shapes);
90}
91
92TEST_F(ArrayGradTest, IdentityGrad) {
93  TensorShape shape({5, 2});
94  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(shape));
95  auto y = Identity(scope_, x);
96  RunTest(x, shape, y, shape);
97}
98
99TEST_F(ArrayGradTest, SplitGrad) {
100  TensorShape x_shape({5, 2});
101  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
102  // Split along the second dimension.
103  auto split_dim = Const(scope_, 1, {});
104  auto y = Split(scope_, split_dim, x, /* num_split */ 2);
105  TensorShape y_shape = TensorShape({5, 1});
106  RunTest({x}, {x_shape}, y.output, {y_shape, y_shape});
107}
108
109TEST_F(ArrayGradTest, DiagGrad) {
110  TensorShape x_shape({5, 2});
111  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
112  auto y = Diag(scope_, x);
113  TensorShape y_shape({5, 2, 5, 2});
114  RunTest(x, x_shape, y, y_shape);
115}
116
117TEST_F(ArrayGradTest, DiagPartGrad) {
118  TensorShape x_shape({5, 2, 5, 2});
119  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
120  auto y = DiagPart(scope_, x);
121  TensorShape y_shape({5, 2});
122  RunTest(x, x_shape, y, y_shape);
123}
124
125TEST_F(ArrayGradTest, MatrixDiagGrad) {
126  TensorShape x_shape({5, 2});
127  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
128  auto y = MatrixDiag(scope_, x);
129  TensorShape y_shape({5, 2, 2});
130  RunTest(x, x_shape, y, y_shape);
131}
132
133TEST_F(ArrayGradTest, MatrixBandPartGrad) {
134  TensorShape shape({5, 5});
135  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(shape));
136  const int64 num_lower = 1;
137  const int64 num_upper = 2;
138  auto y = MatrixBandPart(scope_, x, num_lower, num_upper);
139  RunTest(x, shape, y, shape);
140}
141
142TEST_F(ArrayGradTest, GatherNdGrad_SimpleIndexing) {
143  TensorShape x_shape({2, 2});
144  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
145  auto indices = Const(scope_, {{0, 0}, {1, 1}});
146  TensorShape y_shape({2});
147  auto y = GatherNd(scope_, x, indices);
148  RunTest(x, x_shape, y, y_shape);
149}
150
151TEST_F(ArrayGradTest, GatherNdGrad_SliceIndexing) {
152  TensorShape shape({2, 2});
153  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(shape));
154  auto indices = Const(scope_, {{1}, {0}});
155  auto y = GatherNd(scope_, x, indices);
156  RunTest(x, shape, y, shape);
157}
158
159TEST_F(ArrayGradTest, CheckNumericsGrad) {
160  TensorShape shape({5, 2});
161  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(shape));
162  auto y = CheckNumerics(scope_, x, "CheckNumerics failed");
163  RunTest(x, shape, y, shape);
164}
165
166TEST_F(ArrayGradTest, ReshapeGrad) {
167  TensorShape x_shape({5, 2});
168  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
169  TensorShape y_shape({2, 5});
170  auto y = Reshape(scope_, x, {2, 5});
171  RunTest(x, x_shape, y, y_shape);
172}
173
174TEST_F(ArrayGradTest, ExpandDimsGrad) {
175  TensorShape x_shape({5, 2});
176  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
177  TensorShape y_shape({1, 5, 2});
178  auto y = ExpandDims(scope_, x, 0);
179  RunTest(x, x_shape, y, y_shape);
180}
181
182TEST_F(ArrayGradTest, SqueezeGrad) {
183  TensorShape x_shape({1, 5, 1, 2});
184  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
185  TensorShape y_shape({5, 2});
186  auto y = Squeeze(scope_, x);
187  RunTest(x, x_shape, y, y_shape);
188}
189
190TEST_F(ArrayGradTest, TransposeGrad) {
191  TensorShape x_shape({5, 2});
192  auto x = Placeholder(scope_, DT_FLOAT, Placeholder::Shape(x_shape));
193  TensorShape y_shape({2, 5});
194  auto y = Transpose(scope_, x, {1, 0});
195  RunTest(x, x_shape, y, y_shape);
196}
197
198}  // namespace
199}  // namespace tensorflow
200