1# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Tests for tf.layers.convolutional."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20
21import numpy as np
22
23from tensorflow.python.framework import dtypes
24from tensorflow.python.framework import ops
25from tensorflow.python.framework import test_util
26from tensorflow.python.layers import convolutional as conv_layers
27from tensorflow.python.ops import array_ops
28from tensorflow.python.ops import init_ops
29from tensorflow.python.ops import math_ops
30from tensorflow.python.ops import nn_ops
31from tensorflow.python.ops import random_ops
32from tensorflow.python.ops import variable_scope
33from tensorflow.python.ops import variables
34from tensorflow.python.platform import test
35
36
37@test_util.with_c_api
38class ConvTest(test.TestCase):
39
40  def testInvalidDataFormat(self):
41    height, width = 7, 9
42    images = random_ops.random_uniform((5, height, width, 3), seed=1)
43    with self.assertRaisesRegexp(ValueError, 'data_format'):
44      conv_layers.conv2d(images, 32, 3, data_format='invalid')
45
46  def testInvalidStrides(self):
47    height, width = 7, 9
48    images = random_ops.random_uniform((5, height, width, 3), seed=1)
49    with self.assertRaisesRegexp(ValueError, 'strides'):
50      conv_layers.conv2d(images, 32, 3, strides=(1, 2, 3))
51
52    with self.assertRaisesRegexp(ValueError, 'strides'):
53      conv_layers.conv2d(images, 32, 3, strides=None)
54
55  def testInvalidKernelSize(self):
56    height, width = 7, 9
57    images = random_ops.random_uniform((5, height, width, 3), seed=1)
58    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
59      conv_layers.conv2d(images, 32, (1, 2, 3))
60
61    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
62      conv_layers.conv2d(images, 32, None)
63
64  def testCreateConv2D(self):
65    height, width = 7, 9
66    images = random_ops.random_uniform((5, height, width, 4))
67    layer = conv_layers.Conv2D(32, [3, 3], activation=nn_ops.relu)
68    output = layer.apply(images)
69    self.assertEqual(output.op.name, 'conv2d/Relu')
70    self.assertListEqual(output.get_shape().as_list(),
71                         [5, height - 2, width - 2, 32])
72    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 4, 32])
73    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
74
75  def testConv2DFloat16(self):
76    height, width = 7, 9
77    images = random_ops.random_uniform((5, height, width, 4), dtype='float16')
78    output = conv_layers.conv2d(images, 32, [3, 3], activation=nn_ops.relu)
79    self.assertListEqual(output.get_shape().as_list(),
80                         [5, height - 2, width - 2, 32])
81
82  def testCreateConv2DIntegerKernelSize(self):
83    height, width = 7, 9
84    images = random_ops.random_uniform((5, height, width, 4))
85    layer = conv_layers.Conv2D(32, 3)
86    output = layer.apply(images)
87    self.assertListEqual(output.get_shape().as_list(),
88                         [5, height - 2, width - 2, 32])
89    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 4, 32])
90    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
91
92  def testCreateConv2DChannelsFirst(self):
93    height, width = 7, 9
94    images = random_ops.random_uniform((5, 4, height, width))
95    layer = conv_layers.Conv2D(32, [3, 3], data_format='channels_first')
96    output = layer.apply(images)
97    self.assertListEqual(output.get_shape().as_list(),
98                         [5, 32, height - 2, width - 2])
99    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 4, 32])
100    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
101
102  def testUnknownInputChannels(self):
103    images = array_ops.placeholder(dtypes.float32, (5, 7, 9, None))
104    layer = conv_layers.Conv2D(32, [3, 3], activation=nn_ops.relu)
105    with self.assertRaisesRegexp(ValueError,
106                                 'The channel dimension of the inputs '
107                                 'should be defined. Found `None`.'):
108      _ = layer.apply(images)
109
110    images = array_ops.placeholder(dtypes.float32, (5, None, 7, 9))
111    layer = conv_layers.Conv2D(32, [3, 3], data_format='channels_first')
112    with self.assertRaisesRegexp(ValueError,
113                                 'The channel dimension of the inputs '
114                                 'should be defined. Found `None`.'):
115      _ = layer.apply(images)
116
117  def testConv2DPaddingSame(self):
118    height, width = 7, 9
119    images = random_ops.random_uniform((5, height, width, 32), seed=1)
120    layer = conv_layers.Conv2D(64, images.get_shape()[1:3], padding='same')
121    output = layer.apply(images)
122    self.assertListEqual(output.get_shape().as_list(), [5, height, width, 64])
123
124  def testCreateConvWithStrides(self):
125    height, width = 6, 8
126    # Test strides tuple
127    images = random_ops.random_uniform((5, height, width, 3), seed=1)
128    layer = conv_layers.Conv2D(32, [3, 3], strides=(2, 2), padding='same')
129    output = layer.apply(images)
130    self.assertListEqual(output.get_shape().as_list(),
131                         [5, height / 2, width / 2, 32])
132
133    # Test strides integer
134    layer = conv_layers.Conv2D(32, [3, 3], strides=2, padding='same')
135    output = layer.apply(images)
136    self.assertListEqual(output.get_shape().as_list(),
137                         [5, height / 2, width / 2, 32])
138
139    # Test unequal strides
140    layer = conv_layers.Conv2D(32, [3, 3], strides=(2, 1), padding='same')
141    output = layer.apply(images)
142    self.assertListEqual(output.get_shape().as_list(),
143                         [5, height / 2, width, 32])
144
145  def testCreateConv1D(self):
146    width = 7
147    data = random_ops.random_uniform((5, width, 4))
148    layer = conv_layers.Conv1D(32, 3, activation=nn_ops.relu)
149    output = layer.apply(data)
150    self.assertEqual(output.op.name, 'conv1d/Relu')
151    self.assertListEqual(output.get_shape().as_list(), [5, width - 2, 32])
152    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 4, 32])
153    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
154
155  def testConv1DFloat16(self):
156    width = 7
157    data = random_ops.random_uniform((5, width, 4), dtype='float16')
158    output = conv_layers.conv1d(data, 32, 3, activation=nn_ops.relu)
159    self.assertListEqual(output.get_shape().as_list(), [5, width - 2, 32])
160
161  def testCreateConv1DChannelsFirst(self):
162    width = 7
163    data = random_ops.random_uniform((5, 4, width))
164    layer = conv_layers.Conv1D(32, 3, data_format='channels_first')
165    output = layer.apply(data)
166    self.assertListEqual(output.get_shape().as_list(), [5, 32, width - 2])
167    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 4, 32])
168    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
169
170  def testUnknownInputChannelsConv1D(self):
171    data = array_ops.placeholder(dtypes.float32, (5, 4, None))
172    layer = conv_layers.Conv1D(32, 3, activation=nn_ops.relu)
173    with self.assertRaisesRegexp(ValueError,
174                                 'The channel dimension of the inputs '
175                                 'should be defined. Found `None`.'):
176      _ = layer.apply(data)
177
178    data = array_ops.placeholder(dtypes.float32, (5, None, 4))
179    layer = conv_layers.Conv1D(32, 3, data_format='channels_first')
180    with self.assertRaisesRegexp(ValueError,
181                                 'The channel dimension of the inputs '
182                                 'should be defined. Found `None`.'):
183      _ = layer.apply(data)
184
185  def testCreateConv3D(self):
186    depth, height, width = 6, 7, 9
187    volumes = random_ops.random_uniform((5, depth, height, width, 4))
188    layer = conv_layers.Conv3D(32, [3, 3, 3], activation=nn_ops.relu)
189    output = layer.apply(volumes)
190    self.assertEqual(output.op.name, 'conv3d/Relu')
191    self.assertListEqual(output.get_shape().as_list(),
192                         [5, depth - 2, height - 2, width - 2, 32])
193    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32])
194    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
195
196  def testUnknownInputChannelsConv3D(self):
197    volumes = array_ops.placeholder(dtypes.float32, (5, 6, 7, 9, None))
198    layer = conv_layers.Conv3D(32, [3, 3, 3], activation=nn_ops.relu)
199    with self.assertRaisesRegexp(ValueError,
200                                 'The channel dimension of the inputs '
201                                 'should be defined. Found `None`.'):
202      _ = layer.apply(volumes)
203
204  def testConv2DKernelRegularizer(self):
205    height, width = 7, 9
206    images = random_ops.random_uniform((5, height, width, 4))
207    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
208    layer = conv_layers.Conv2D(32, [3, 3], kernel_regularizer=reg)
209    layer.apply(images)
210    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
211    self.assertEqual(len(loss_keys), 1)
212    self.assertListEqual(layer.losses, loss_keys)
213
214  def testConv2DBiasRegularizer(self):
215    height, width = 7, 9
216    images = random_ops.random_uniform((5, height, width, 4))
217    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
218    layer = conv_layers.Conv2D(32, [3, 3], bias_regularizer=reg)
219    layer.apply(images)
220    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
221    self.assertEqual(len(loss_keys), 1)
222    self.assertListEqual(layer.losses, loss_keys)
223
224  def testConv2DNoBias(self):
225    height, width = 7, 9
226    images = random_ops.random_uniform((5, height, width, 4))
227    layer = conv_layers.Conv2D(
228        32, [3, 3], activation=nn_ops.relu, use_bias=False)
229    output = layer.apply(images)
230    self.assertEqual(output.op.name, 'conv2d/Relu')
231    self.assertListEqual(output.get_shape().as_list(),
232                         [5, height - 2, width - 2, 32])
233    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 4, 32])
234    self.assertEqual(layer.bias, None)
235
236  def testDilatedConv2D(self):
237    height, width = 7, 9
238    images = random_ops.random_uniform((5, height, width, 4))
239    layer = conv_layers.Conv2D(32, [3, 3], dilation_rate=3)
240    output = layer.apply(images)
241    self.assertListEqual(output.get_shape().as_list(), [5, 1, 3, 32])
242    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 4, 32])
243    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
244
245    # Test tuple dilation rate
246    layer = conv_layers.Conv2D(32, [3, 3], dilation_rate=(1, 3))
247    output = layer.apply(images)
248    self.assertListEqual(output.get_shape().as_list(), [5, height - 2, 3, 32])
249
250  def testFunctionalConv2DReuse(self):
251    height, width = 7, 9
252    images = random_ops.random_uniform((5, height, width, 3), seed=1)
253    conv_layers.conv2d(images, 32, [3, 3], name='conv1')
254    self.assertEqual(len(variables.trainable_variables()), 2)
255    conv_layers.conv2d(images, 32, [3, 3], name='conv1', reuse=True)
256    self.assertEqual(len(variables.trainable_variables()), 2)
257
258  def testFunctionalConv2DReuseFromScope(self):
259    with variable_scope.variable_scope('scope'):
260      height, width = 7, 9
261      images = random_ops.random_uniform((5, height, width, 3), seed=1)
262      conv_layers.conv2d(images, 32, [3, 3], name='conv1')
263      self.assertEqual(len(variables.trainable_variables()), 2)
264    with variable_scope.variable_scope('scope', reuse=True):
265      conv_layers.conv2d(images, 32, [3, 3], name='conv1')
266      self.assertEqual(len(variables.trainable_variables()), 2)
267
268  def testFunctionalConv2DInitializerFromScope(self):
269    with self.test_session() as sess:
270      with variable_scope.variable_scope(
271          'scope', initializer=init_ops.ones_initializer()):
272        height, width = 7, 9
273        images = random_ops.random_uniform((5, height, width, 3), seed=1)
274        conv_layers.conv2d(images, 32, [3, 3], name='conv1')
275        weights = variables.trainable_variables()
276        # Check the names of weights in order.
277        self.assertTrue('kernel' in weights[0].name)
278        self.assertTrue('bias' in weights[1].name)
279        sess.run(variables.global_variables_initializer())
280        weights = sess.run(weights)
281        # Check that the kernel weights got initialized to ones (from scope)
282        self.assertAllClose(weights[0], np.ones((3, 3, 3, 32)))
283        # Check that the bias still got initialized to zeros.
284        self.assertAllClose(weights[1], np.zeros((32)))
285
286  def testFunctionalConv2DNoReuse(self):
287    height, width = 7, 9
288    images = random_ops.random_uniform((5, height, width, 3), seed=1)
289    conv_layers.conv2d(images, 32, [3, 3])
290    self.assertEqual(len(variables.trainable_variables()), 2)
291    conv_layers.conv2d(images, 32, [3, 3])
292    self.assertEqual(len(variables.trainable_variables()), 4)
293
294  def testConstraints(self):
295    # Conv1D
296    k_constraint = lambda x: x / math_ops.reduce_sum(x)
297    b_constraint = lambda x: x / math_ops.reduce_max(x)
298    conv1d = conv_layers.Conv1D(2, 3,
299                                kernel_constraint=k_constraint,
300                                bias_constraint=b_constraint)
301    inputs = random_ops.random_uniform((5, 3, 5), seed=1)
302    conv1d(inputs)
303    self.assertEqual(conv1d.kernel_constraint, k_constraint)
304    self.assertEqual(conv1d.bias_constraint, b_constraint)
305
306    # Conv2D
307    k_constraint = lambda x: x / math_ops.reduce_sum(x)
308    b_constraint = lambda x: x / math_ops.reduce_max(x)
309    conv2d = conv_layers.Conv2D(2, 3,
310                                kernel_constraint=k_constraint,
311                                bias_constraint=b_constraint)
312    inputs = random_ops.random_uniform((5, 3, 3, 5), seed=1)
313    conv2d(inputs)
314    self.assertEqual(conv2d.kernel_constraint, k_constraint)
315    self.assertEqual(conv2d.bias_constraint, b_constraint)
316
317    # Conv3D
318    k_constraint = lambda x: x / math_ops.reduce_sum(x)
319    b_constraint = lambda x: x / math_ops.reduce_max(x)
320    conv3d = conv_layers.Conv3D(2, 3,
321                                kernel_constraint=k_constraint,
322                                bias_constraint=b_constraint)
323    inputs = random_ops.random_uniform((5, 3, 3, 3, 5), seed=1)
324    conv3d(inputs)
325    self.assertEqual(conv3d.kernel_constraint, k_constraint)
326    self.assertEqual(conv3d.bias_constraint, b_constraint)
327
328
329@test_util.with_c_api
330class SeparableConv1DTest(test.TestCase):
331
332  def testInvalidDataFormat(self):
333    length = 9
334    data = random_ops.random_uniform((5, length, 3), seed=1)
335    with self.assertRaisesRegexp(ValueError, 'data_format'):
336      conv_layers.separable_conv1d(data, 32, 3, data_format='invalid')
337
338  def testInvalidStrides(self):
339    length = 9
340    data = random_ops.random_uniform((5, length, 3), seed=1)
341    with self.assertRaisesRegexp(ValueError, 'strides'):
342      conv_layers.separable_conv1d(data, 32, 3, strides=(1, 2))
343
344    with self.assertRaisesRegexp(ValueError, 'strides'):
345      conv_layers.separable_conv1d(data, 32, 3, strides=None)
346
347  def testInvalidKernelSize(self):
348    length = 9
349    data = random_ops.random_uniform((5, length, 3), seed=1)
350    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
351      conv_layers.separable_conv1d(data, 32, (1, 2))
352
353    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
354      conv_layers.separable_conv1d(data, 32, None)
355
356  def testCreateSeparableConv1D(self):
357    length = 9
358    data = random_ops.random_uniform((5, length, 4))
359    layer = conv_layers.SeparableConv1D(32, 3, activation=nn_ops.relu)
360    output = layer.apply(data)
361    self.assertEqual(output.op.name, 'separable_conv1d/Relu')
362    self.assertEqual(output.get_shape().as_list(), [5, length - 2, 32])
363    self.assertEqual(layer.depthwise_kernel.get_shape().as_list(), [3, 4, 1])
364    self.assertEqual(layer.pointwise_kernel.get_shape().as_list(), [1, 4, 32])
365    self.assertEqual(layer.bias.get_shape().as_list(), [32])
366
367  def testCreateSeparableConv1DDepthMultiplier(self):
368    length = 9
369    data = random_ops.random_uniform((5, length, 4))
370    layer = conv_layers.SeparableConv1D(32, 3, depth_multiplier=2)
371    output = layer.apply(data)
372    self.assertEqual(output.get_shape().as_list(), [5, length - 2, 32])
373    self.assertEqual(layer.depthwise_kernel.get_shape().as_list(), [3, 4, 2])
374    self.assertEqual(layer.pointwise_kernel.get_shape().as_list(), [1, 8, 32])
375    self.assertEqual(layer.bias.get_shape().as_list(), [32])
376
377  def testCreateSeparableConv1DChannelsFirst(self):
378    length = 9
379    data = random_ops.random_uniform((5, 4, length))
380    layer = conv_layers.SeparableConv1D(32, 3, data_format='channels_first')
381    output = layer.apply(data)
382    self.assertEqual(output.get_shape().as_list(), [5, 32, length - 2])
383    self.assertEqual(layer.depthwise_kernel.get_shape().as_list(), [3, 4, 1])
384    self.assertEqual(layer.pointwise_kernel.get_shape().as_list(), [1, 4, 32])
385    self.assertEqual(layer.bias.get_shape().as_list(), [32])
386
387  def testSeparableConv1DPaddingSame(self):
388    length = 9
389    data = random_ops.random_uniform((5, length, 32), seed=1)
390    layer = conv_layers.SeparableConv1D(
391        64, length, padding='same')
392    output = layer.apply(data)
393    self.assertEqual(output.get_shape().as_list(), [5, length, 64])
394
395  def testCreateSeparableConv1DWithStrides(self):
396    length = 10
397    data = random_ops.random_uniform((5, length, 3), seed=1)
398    layer = conv_layers.SeparableConv1D(32, 3, strides=2, padding='same')
399    output = layer.apply(data)
400    self.assertEqual(output.get_shape().as_list(), [5, length // 2, 32])
401
402  def testCreateSeparableConv1DWithStridesChannelsFirst(self):
403    data_format = 'channels_first'
404    length = 10
405    data = random_ops.random_uniform((5, 3, length), seed=1)
406    layer = conv_layers.SeparableConv1D(
407        32, 3, strides=2, padding='same', data_format=data_format)
408    output = layer.apply(data)
409    self.assertEqual(output.get_shape().as_list(), [5, 32, length // 2])
410
411  def testFunctionalConv1DReuse(self):
412    length = 10
413    data = random_ops.random_uniform((5, length, 3), seed=1)
414    conv_layers.separable_conv1d(data, 32, 3, name='sepconv1')
415    self.assertEqual(len(variables.trainable_variables()), 3)
416    conv_layers.separable_conv1d(data, 32, 3, name='sepconv1', reuse=True)
417    self.assertEqual(len(variables.trainable_variables()), 3)
418
419  def testFunctionalConv1DReuseFromScope(self):
420    with variable_scope.variable_scope('scope'):
421      length = 10
422      data = random_ops.random_uniform((5, length, 3), seed=1)
423      conv_layers.separable_conv1d(data, 32, 3, name='sepconv1')
424      self.assertEqual(len(variables.trainable_variables()), 3)
425    with variable_scope.variable_scope('scope', reuse=True):
426      conv_layers.separable_conv1d(data, 32, 3, name='sepconv1')
427      self.assertEqual(len(variables.trainable_variables()), 3)
428
429  def testFunctionalConv1DNoReuse(self):
430    length = 10
431    data = random_ops.random_uniform((5, length, 3), seed=1)
432    conv_layers.separable_conv1d(data, 32, 3)
433    self.assertEqual(len(variables.trainable_variables()), 3)
434    conv_layers.separable_conv1d(data, 32, 3)
435    self.assertEqual(len(variables.trainable_variables()), 6)
436
437  def testSeparableConv1DDepthwiseRegularizer(self):
438    length = 9
439    data = random_ops.random_uniform((5, length, 4))
440    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
441    layer = conv_layers.SeparableConv1D(32, 3, depthwise_regularizer=reg)
442    layer.apply(data)
443    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
444    self.assertEqual(len(loss_keys), 1)
445    self.assertEqual(layer.losses, loss_keys)
446
447  def testSeparableConv1DPointwiseRegularizer(self):
448    length = 9
449    data = random_ops.random_uniform((5, length, 4))
450    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
451    layer = conv_layers.SeparableConv1D(32, 3, pointwise_regularizer=reg)
452    layer.apply(data)
453    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
454    self.assertEqual(len(loss_keys), 1)
455    self.assertEqual(layer.losses, loss_keys)
456
457  def testSeparableConv1DBiasRegularizer(self):
458    length = 9
459    data = random_ops.random_uniform((5, length, 4))
460    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
461    layer = conv_layers.SeparableConv1D(32, 3, bias_regularizer=reg)
462    layer.apply(data)
463    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
464    self.assertEqual(len(loss_keys), 1)
465    self.assertEqual(layer.losses, loss_keys)
466
467  def testSeparableConv1DNoBias(self):
468    length = 9
469    data = random_ops.random_uniform((5, length, 4))
470    layer = conv_layers.SeparableConv1D(
471        32, 3, activation=nn_ops.relu, use_bias=False)
472    output = layer.apply(data)
473    self.assertEqual(output.op.name, 'separable_conv1d/Relu')
474    self.assertEqual(layer.bias, None)
475
476  def testConstraints(self):
477    d_constraint = lambda x: x / math_ops.reduce_sum(x)
478    p_constraint = lambda x: x / math_ops.reduce_sum(x)
479    b_constraint = lambda x: x / math_ops.reduce_max(x)
480    layer = conv_layers.SeparableConv1D(2, 3,
481                                        depthwise_constraint=d_constraint,
482                                        pointwise_constraint=p_constraint,
483                                        bias_constraint=b_constraint)
484    inputs = random_ops.random_uniform((5, 3, 5), seed=1)
485    layer(inputs)
486    self.assertEqual(layer.depthwise_constraint, d_constraint)
487    self.assertEqual(layer.pointwise_constraint, p_constraint)
488    self.assertEqual(layer.bias_constraint, b_constraint)
489
490
491@test_util.with_c_api
492class SeparableConv2DTest(test.TestCase):
493
494  def testInvalidDataFormat(self):
495    height, width = 7, 9
496    images = random_ops.random_uniform((5, height, width, 3), seed=1)
497    with self.assertRaisesRegexp(ValueError, 'data_format'):
498      conv_layers.separable_conv2d(images, 32, 3, data_format='invalid')
499
500  def testInvalidStrides(self):
501    height, width = 7, 9
502    images = random_ops.random_uniform((5, height, width, 3), seed=1)
503    with self.assertRaisesRegexp(ValueError, 'strides'):
504      conv_layers.separable_conv2d(images, 32, 3, strides=(1, 2, 3))
505
506    with self.assertRaisesRegexp(ValueError, 'strides'):
507      conv_layers.separable_conv2d(images, 32, 3, strides=None)
508
509  def testInvalidKernelSize(self):
510    height, width = 7, 9
511    images = random_ops.random_uniform((5, height, width, 3), seed=1)
512    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
513      conv_layers.separable_conv2d(images, 32, (1, 2, 3))
514
515    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
516      conv_layers.separable_conv2d(images, 32, None)
517
518  def testCreateSeparableConv2D(self):
519    height, width = 7, 9
520    images = random_ops.random_uniform((5, height, width, 4))
521    layer = conv_layers.SeparableConv2D(32, [3, 3], activation=nn_ops.relu)
522    output = layer.apply(images)
523    self.assertEqual(output.op.name, 'separable_conv2d/Relu')
524    self.assertListEqual(output.get_shape().as_list(),
525                         [5, height - 2, width - 2, 32])
526    self.assertListEqual(layer.depthwise_kernel.get_shape().as_list(),
527                         [3, 3, 4, 1])
528    self.assertListEqual(layer.pointwise_kernel.get_shape().as_list(),
529                         [1, 1, 4, 32])
530    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
531
532  def testCreateSeparableConv2DDepthMultiplier(self):
533    height, width = 7, 9
534    images = random_ops.random_uniform((5, height, width, 4))
535    layer = conv_layers.SeparableConv2D(32, [3, 3], depth_multiplier=2)
536    output = layer.apply(images)
537    self.assertListEqual(output.get_shape().as_list(),
538                         [5, height - 2, width - 2, 32])
539    self.assertListEqual(layer.depthwise_kernel.get_shape().as_list(),
540                         [3, 3, 4, 2])
541    self.assertListEqual(layer.pointwise_kernel.get_shape().as_list(),
542                         [1, 1, 8, 32])
543    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
544
545  def testCreateSeparableConv2DIntegerKernelSize(self):
546    height, width = 7, 9
547    images = random_ops.random_uniform((5, height, width, 4))
548    layer = conv_layers.SeparableConv2D(32, 3)
549    output = layer.apply(images)
550    self.assertListEqual(output.get_shape().as_list(),
551                         [5, height - 2, width - 2, 32])
552    self.assertListEqual(layer.depthwise_kernel.get_shape().as_list(),
553                         [3, 3, 4, 1])
554    self.assertListEqual(layer.pointwise_kernel.get_shape().as_list(),
555                         [1, 1, 4, 32])
556    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
557
558  def testCreateSeparableConv2DChannelsFirst(self):
559    height, width = 7, 9
560    images = random_ops.random_uniform((5, 4, height, width))
561    layer = conv_layers.SeparableConv2D(
562        32, [3, 3], data_format='channels_first')
563    output = layer.apply(images)
564    self.assertListEqual(output.get_shape().as_list(),
565                         [5, 32, height - 2, width - 2])
566    self.assertListEqual(layer.depthwise_kernel.get_shape().as_list(),
567                         [3, 3, 4, 1])
568    self.assertListEqual(layer.pointwise_kernel.get_shape().as_list(),
569                         [1, 1, 4, 32])
570    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
571
572  def testSeparableConv2DPaddingSame(self):
573    height, width = 7, 9
574    images = random_ops.random_uniform((5, height, width, 32), seed=1)
575    layer = conv_layers.SeparableConv2D(
576        64, images.get_shape()[1:3], padding='same')
577    output = layer.apply(images)
578    self.assertListEqual(output.get_shape().as_list(), [5, height, width, 64])
579
580  def testCreateSeparableConvWithStrides(self):
581    height, width = 6, 8
582    # Test strides tuple
583    images = random_ops.random_uniform((5, height, width, 3), seed=1)
584    layer = conv_layers.SeparableConv2D(
585        32, [3, 3], strides=(2, 2), padding='same')
586    output = layer.apply(images)
587    self.assertListEqual(output.get_shape().as_list(),
588                         [5, height / 2, width / 2, 32])
589
590    # Test strides integer
591    layer = conv_layers.SeparableConv2D(32, [3, 3], strides=2, padding='same')
592    output = layer.apply(images)
593    self.assertListEqual(output.get_shape().as_list(),
594                         [5, height / 2, width / 2, 32])
595
596    # Test unequal strides
597    layer = conv_layers.SeparableConv2D(
598        32, [3, 3], strides=(2, 1), padding='same')
599    output = layer.apply(images)
600    self.assertListEqual(output.get_shape().as_list(),
601                         [5, height / 2, width, 32])
602
603  def testCreateSeparableConvWithStridesChannelsFirst(self):
604    data_format = 'channels_first'
605    height, width = 6, 8
606    # Test strides tuple
607    images = random_ops.random_uniform((5, 3, height, width), seed=1)
608    layer = conv_layers.SeparableConv2D(
609        32, [3, 3], strides=(2, 2), padding='same', data_format=data_format)
610    output = layer.apply(images)
611    self.assertListEqual(output.get_shape().as_list(),
612                         [5, 32, height / 2, width / 2])
613
614    # Test strides integer
615    layer = conv_layers.SeparableConv2D(32, [3, 3], strides=2, padding='same',
616                                        data_format=data_format)
617    output = layer.apply(images)
618    self.assertListEqual(output.get_shape().as_list(),
619                         [5, 32, height / 2, width / 2])
620
621    # Test unequal strides
622    layer = conv_layers.SeparableConv2D(
623        32, [3, 3], strides=(2, 1), padding='same', data_format=data_format)
624    output = layer.apply(images)
625    self.assertListEqual(output.get_shape().as_list(),
626                         [5, 32, height / 2, width])
627
628  def testFunctionalConv2DReuse(self):
629    height, width = 7, 9
630    images = random_ops.random_uniform((5, height, width, 3), seed=1)
631    conv_layers.separable_conv2d(images, 32, [3, 3], name='sepconv1')
632    self.assertEqual(len(variables.trainable_variables()), 3)
633    conv_layers.separable_conv2d(
634        images, 32, [3, 3], name='sepconv1', reuse=True)
635    self.assertEqual(len(variables.trainable_variables()), 3)
636
637  def testFunctionalConv2DReuseFromScope(self):
638    with variable_scope.variable_scope('scope'):
639      height, width = 7, 9
640      images = random_ops.random_uniform((5, height, width, 3), seed=1)
641      conv_layers.separable_conv2d(images, 32, [3, 3], name='sepconv1')
642      self.assertEqual(len(variables.trainable_variables()), 3)
643    with variable_scope.variable_scope('scope', reuse=True):
644      conv_layers.separable_conv2d(images, 32, [3, 3], name='sepconv1')
645      self.assertEqual(len(variables.trainable_variables()), 3)
646
647  def testFunctionalConv2DInitializerFromScope(self):
648    with self.test_session() as sess:
649      with variable_scope.variable_scope(
650          'scope', initializer=init_ops.ones_initializer()):
651        height, width = 7, 9
652        images = random_ops.random_uniform((5, height, width, 3), seed=1)
653        conv_layers.separable_conv2d(images, 32, [3, 3], name='sepconv1')
654        weights = variables.trainable_variables()
655        # Check the names of weights in order.
656        self.assertTrue('depthwise_kernel' in weights[0].name)
657        self.assertTrue('pointwise_kernel' in weights[1].name)
658        self.assertTrue('bias' in weights[2].name)
659        sess.run(variables.global_variables_initializer())
660        weights = sess.run(weights)
661        # Check that the kernel weights got initialized to ones (from scope)
662        self.assertAllClose(weights[0], np.ones((3, 3, 3, 1)))
663        self.assertAllClose(weights[1], np.ones((1, 1, 3, 32)))
664        # Check that the bias still got initialized to zeros.
665        self.assertAllClose(weights[2], np.zeros((32)))
666
667  def testFunctionalConv2DNoReuse(self):
668    height, width = 7, 9
669    images = random_ops.random_uniform((5, height, width, 3), seed=1)
670    conv_layers.separable_conv2d(images, 32, [3, 3])
671    self.assertEqual(len(variables.trainable_variables()), 3)
672    conv_layers.separable_conv2d(images, 32, [3, 3])
673    self.assertEqual(len(variables.trainable_variables()), 6)
674
675  def testSeparableConv2DDepthwiseRegularizer(self):
676    height, width = 7, 9
677    images = random_ops.random_uniform((5, height, width, 4))
678    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
679    layer = conv_layers.SeparableConv2D(32, [3, 3], depthwise_regularizer=reg)
680    layer.apply(images)
681    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
682    self.assertEqual(len(loss_keys), 1)
683    self.assertListEqual(layer.losses, loss_keys)
684
685  def testSeparableConv2DPointwiseRegularizer(self):
686    height, width = 7, 9
687    images = random_ops.random_uniform((5, height, width, 4))
688    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
689    layer = conv_layers.SeparableConv2D(32, [3, 3], pointwise_regularizer=reg)
690    layer.apply(images)
691    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
692    self.assertEqual(len(loss_keys), 1)
693    self.assertListEqual(layer.losses, loss_keys)
694
695  def testSeparableConv2DBiasRegularizer(self):
696    height, width = 7, 9
697    images = random_ops.random_uniform((5, height, width, 4))
698    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
699    layer = conv_layers.SeparableConv2D(32, [3, 3], bias_regularizer=reg)
700    layer.apply(images)
701    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
702    self.assertEqual(len(loss_keys), 1)
703    self.assertListEqual(layer.losses, loss_keys)
704
705  def testSeparableConv2DNoBias(self):
706    height, width = 7, 9
707    images = random_ops.random_uniform((5, height, width, 4))
708    layer = conv_layers.SeparableConv2D(
709        32, [3, 3], activation=nn_ops.relu, use_bias=False)
710    output = layer.apply(images)
711    self.assertEqual(output.op.name, 'separable_conv2d/Relu')
712    self.assertListEqual(output.get_shape().as_list(),
713                         [5, height - 2, width - 2, 32])
714    self.assertListEqual(layer.depthwise_kernel.get_shape().as_list(),
715                         [3, 3, 4, 1])
716    self.assertListEqual(layer.pointwise_kernel.get_shape().as_list(),
717                         [1, 1, 4, 32])
718    self.assertEqual(layer.bias, None)
719
720  def testConstraints(self):
721    d_constraint = lambda x: x / math_ops.reduce_sum(x)
722    p_constraint = lambda x: x / math_ops.reduce_sum(x)
723    b_constraint = lambda x: x / math_ops.reduce_max(x)
724    layer = conv_layers.SeparableConv2D(2, 3,
725                                        depthwise_constraint=d_constraint,
726                                        pointwise_constraint=p_constraint,
727                                        bias_constraint=b_constraint)
728    inputs = random_ops.random_uniform((5, 3, 3, 5), seed=1)
729    layer(inputs)
730    self.assertEqual(layer.depthwise_constraint, d_constraint)
731    self.assertEqual(layer.pointwise_constraint, p_constraint)
732    self.assertEqual(layer.bias_constraint, b_constraint)
733
734
735@test_util.with_c_api
736class Conv2DTransposeTest(test.TestCase):
737
738  def testInvalidDataFormat(self):
739    height, width = 7, 9
740    images = random_ops.random_uniform((5, height, width, 3), seed=1)
741    with self.assertRaisesRegexp(ValueError, 'data_format'):
742      conv_layers.conv2d_transpose(images, 32, 3, data_format='invalid')
743
744  def testInvalidStrides(self):
745    height, width = 7, 9
746    images = random_ops.random_uniform((5, height, width, 3), seed=1)
747    with self.assertRaisesRegexp(ValueError, 'strides'):
748      conv_layers.conv2d_transpose(images, 32, 3, strides=(1, 2, 3))
749
750    with self.assertRaisesRegexp(ValueError, 'strides'):
751      conv_layers.conv2d_transpose(images, 32, 3, strides=None)
752
753  def testInvalidKernelSize(self):
754    height, width = 7, 9
755    images = random_ops.random_uniform((5, height, width, 3), seed=1)
756    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
757      conv_layers.conv2d_transpose(images, 32, (1, 2, 3))
758
759    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
760      conv_layers.conv2d_transpose(images, 32, None)
761
762  def testCreateConv2DTranspose(self):
763    height, width = 7, 9
764    images = random_ops.random_uniform((5, height, width, 4))
765    layer = conv_layers.Conv2DTranspose(32, [3, 3], activation=nn_ops.relu)
766    output = layer.apply(images)
767    self.assertEqual(output.op.name, 'conv2d_transpose/Relu')
768    self.assertListEqual(output.get_shape().as_list(),
769                         [5, height + 2, width + 2, 32])
770    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 32, 4])
771    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
772
773  def testConv2DTransposeFloat16(self):
774    height, width = 7, 9
775    images = random_ops.random_uniform((5, height, width, 4), dtype='float16')
776    output = conv_layers.conv2d_transpose(images, 32, [3, 3],
777                                          activation=nn_ops.relu)
778    self.assertListEqual(output.get_shape().as_list(),
779                         [5, height + 2, width + 2, 32])
780
781  def testCreateConv2DTransposeIntegerKernelSize(self):
782    height, width = 7, 9
783    images = random_ops.random_uniform((5, height, width, 4))
784    layer = conv_layers.Conv2DTranspose(32, 3)
785    output = layer.apply(images)
786    self.assertListEqual(output.get_shape().as_list(),
787                         [5, height + 2, width + 2, 32])
788    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 32, 4])
789    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
790
791  def testCreateConv2DTransposeChannelsFirst(self):
792    height, width = 7, 9
793    images = random_ops.random_uniform((5, 4, height, width))
794    layer = conv_layers.Conv2DTranspose(
795        32, [3, 3], data_format='channels_first')
796    output = layer.apply(images)
797    self.assertListEqual(output.get_shape().as_list(),
798                         [5, 32, height + 2, width + 2])
799    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 32, 4])
800    self.assertListEqual(layer.bias.get_shape().as_list(), [32])
801
802  def testConv2DTransposePaddingSame(self):
803    height, width = 7, 9
804    images = random_ops.random_uniform((5, height, width, 32), seed=1)
805    layer = conv_layers.Conv2DTranspose(
806        64, images.get_shape()[1:3], padding='same')
807    output = layer.apply(images)
808    self.assertListEqual(output.get_shape().as_list(), [5, height, width, 64])
809
810  def testCreateConv2DTransposeWithStrides(self):
811    height, width = 6, 8
812    # Test strides tuple
813    images = random_ops.random_uniform((5, height, width, 3), seed=1)
814    layer = conv_layers.Conv2DTranspose(
815        32, [3, 3], strides=(2, 2), padding='same')
816    output = layer.apply(images)
817    self.assertListEqual(output.get_shape().as_list(),
818                         [5, height * 2, width * 2, 32])
819
820    # Test strides integer
821    layer = conv_layers.Conv2DTranspose(32, [3, 3], strides=2, padding='same')
822    output = layer.apply(images)
823    self.assertListEqual(output.get_shape().as_list(),
824                         [5, height * 2, width * 2, 32])
825
826    # Test unequal strides
827    layer = conv_layers.Conv2DTranspose(
828        32, [3, 3], strides=(2, 1), padding='same')
829    output = layer.apply(images)
830    self.assertListEqual(output.get_shape().as_list(),
831                         [5, height * 2, width, 32])
832
833  def testConv2DTransposeKernelRegularizer(self):
834    height, width = 7, 9
835    images = random_ops.random_uniform((5, height, width, 4))
836    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
837    layer = conv_layers.Conv2DTranspose(32, [3, 3], kernel_regularizer=reg)
838    layer.apply(images)
839    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
840    self.assertEqual(len(loss_keys), 1)
841    self.assertListEqual(layer.losses, loss_keys)
842
843  def testConv2DTransposeBiasRegularizer(self):
844    height, width = 7, 9
845    images = random_ops.random_uniform((5, height, width, 4))
846    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
847    layer = conv_layers.Conv2DTranspose(32, [3, 3], bias_regularizer=reg)
848    layer.apply(images)
849    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
850    self.assertEqual(len(loss_keys), 1)
851    self.assertListEqual(layer.losses, loss_keys)
852
853  def testConv2DTransposeNoBias(self):
854    height, width = 7, 9
855    images = random_ops.random_uniform((5, height, width, 4))
856    layer = conv_layers.Conv2DTranspose(
857        32, [3, 3], activation=nn_ops.relu, use_bias=False)
858    output = layer.apply(images)
859    self.assertEqual(output.op.name, 'conv2d_transpose/Relu')
860    self.assertListEqual(output.get_shape().as_list(),
861                         [5, height + 2, width + 2, 32])
862    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 32, 4])
863    self.assertEqual(layer.bias, None)
864
865  def testFunctionalConv2DTransposeReuse(self):
866    height, width = 7, 9
867    images = random_ops.random_uniform((5, height, width, 3), seed=1)
868    conv_layers.conv2d_transpose(images, 32, [3, 3], name='deconv1')
869    self.assertEqual(len(variables.trainable_variables()), 2)
870    conv_layers.conv2d_transpose(images, 32, [3, 3], name='deconv1', reuse=True)
871    self.assertEqual(len(variables.trainable_variables()), 2)
872
873  def testFunctionalConv2DTransposeReuseFromScope(self):
874    with variable_scope.variable_scope('scope'):
875      height, width = 7, 9
876      images = random_ops.random_uniform((5, height, width, 3), seed=1)
877      conv_layers.conv2d_transpose(images, 32, [3, 3], name='deconv1')
878      self.assertEqual(len(variables.trainable_variables()), 2)
879    with variable_scope.variable_scope('scope', reuse=True):
880      conv_layers.conv2d_transpose(images, 32, [3, 3], name='deconv1')
881      self.assertEqual(len(variables.trainable_variables()), 2)
882
883  def testFunctionalConv2DTransposeInitializerFromScope(self):
884    with self.test_session() as sess:
885      with variable_scope.variable_scope(
886          'scope', initializer=init_ops.ones_initializer()):
887        height, width = 7, 9
888        images = random_ops.random_uniform((5, height, width, 3), seed=1)
889        conv_layers.conv2d_transpose(images, 32, [3, 3], name='deconv1')
890        weights = variables.trainable_variables()
891        # Check the names of weights in order.
892        self.assertTrue('kernel' in weights[0].name)
893        self.assertTrue('bias' in weights[1].name)
894        sess.run(variables.global_variables_initializer())
895        weights = sess.run(weights)
896        # Check that the kernel weights got initialized to ones (from scope)
897        self.assertAllClose(weights[0], np.ones((3, 3, 32, 3)))
898        # Check that the bias still got initialized to zeros.
899        self.assertAllClose(weights[1], np.zeros((32)))
900
901  def testFunctionalConv2DTransposeNoReuse(self):
902    height, width = 7, 9
903    images = random_ops.random_uniform((5, height, width, 3), seed=1)
904    conv_layers.conv2d_transpose(images, 32, [3, 3])
905    self.assertEqual(len(variables.trainable_variables()), 2)
906    conv_layers.conv2d_transpose(images, 32, [3, 3])
907    self.assertEqual(len(variables.trainable_variables()), 4)
908
909  def testConstraints(self):
910    k_constraint = lambda x: x / math_ops.reduce_sum(x)
911    b_constraint = lambda x: x / math_ops.reduce_max(x)
912    layer = conv_layers.Conv2DTranspose(2, 3,
913                                        kernel_constraint=k_constraint,
914                                        bias_constraint=b_constraint)
915    inputs = random_ops.random_uniform((5, 3, 3, 5), seed=1)
916    layer(inputs)
917    self.assertEqual(layer.kernel_constraint, k_constraint)
918    self.assertEqual(layer.bias_constraint, b_constraint)
919
920
921@test_util.with_c_api
922class Conv3DTransposeTest(test.TestCase):
923
924  def testInvalidDataFormat(self):
925    depth, height, width = 5, 7, 9
926    volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1)
927    with self.assertRaisesRegexp(ValueError, 'data_format'):
928      conv_layers.conv3d_transpose(volumes, 4, 3, data_format='invalid')
929
930  def testInvalidStrides(self):
931    depth, height, width = 5, 7, 9
932    volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1)
933    with self.assertRaisesRegexp(ValueError, 'strides'):
934      conv_layers.conv3d_transpose(volumes, 4, 3, strides=(1, 2))
935
936    with self.assertRaisesRegexp(ValueError, 'strides'):
937      conv_layers.conv3d_transpose(volumes, 4, 3, strides=None)
938
939  def testInvalidKernelSize(self):
940    depth, height, width = 5, 7, 9
941    volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1)
942    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
943      conv_layers.conv3d_transpose(volumes, 4, (1, 2))
944
945    with self.assertRaisesRegexp(ValueError, 'kernel_size'):
946      conv_layers.conv3d_transpose(volumes, 4, None)
947
948  def testCreateConv3DTranspose(self):
949    depth, height, width = 5, 7, 9
950    volumes = random_ops.random_uniform((5, depth, height, width, 32))
951    layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], activation=nn_ops.relu)
952    output = layer.apply(volumes)
953    self.assertEqual(output.op.name, 'conv3d_transpose/Relu')
954    self.assertListEqual(output.get_shape().as_list(),
955                         [5, depth + 2, height + 2, width + 2, 4])
956    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32])
957    self.assertListEqual(layer.bias.get_shape().as_list(), [4])
958
959  def testCreateConv3DTransposeIntegerKernelSize(self):
960    depth, height, width = 5, 7, 9
961    volumes = random_ops.random_uniform((5, depth, height, width, 32))
962    layer = conv_layers.Conv3DTranspose(4, 3)
963    output = layer.apply(volumes)
964    self.assertListEqual(output.get_shape().as_list(),
965                         [5, depth + 2, height + 2, width + 2, 4])
966    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32])
967    self.assertListEqual(layer.bias.get_shape().as_list(), [4])
968
969  def testCreateConv3DTransposeChannelsFirst(self):
970    depth, height, width = 5, 7, 9
971    volumes = random_ops.random_uniform((5, 32, depth, height, width))
972    layer = conv_layers.Conv3DTranspose(
973        4, [3, 3, 3], data_format='channels_first')
974    output = layer.apply(volumes)
975    self.assertListEqual(output.get_shape().as_list(),
976                         [5, 4, depth + 2, height + 2, width + 2])
977    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32])
978    self.assertListEqual(layer.bias.get_shape().as_list(), [4])
979
980  def testConv3DTransposePaddingSame(self):
981    depth, height, width = 5, 7, 9
982    volumes = random_ops.random_uniform((5, depth, height, width, 64), seed=1)
983    layer = conv_layers.Conv3DTranspose(
984        32, volumes.get_shape()[1:4], padding='same')
985    output = layer.apply(volumes)
986    self.assertListEqual(output.get_shape().as_list(),
987                         [5, depth, height, width, 32])
988
989  def testCreateConv3DTransposeWithStrides(self):
990    depth, height, width = 4, 6, 8
991    # Test strides tuple.
992    volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1)
993    layer = conv_layers.Conv3DTranspose(
994        4, [3, 3, 3], strides=(2, 2, 2), padding='same')
995    output = layer.apply(volumes)
996    self.assertListEqual(output.get_shape().as_list(),
997                         [5, depth * 2, height * 2, width * 2, 4])
998
999    # Test strides integer.
1000    layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], strides=2, padding='same')
1001    output = layer.apply(volumes)
1002    self.assertListEqual(output.get_shape().as_list(),
1003                         [5, depth * 2, height * 2, width * 2, 4])
1004
1005    # Test unequal strides.
1006    layer = conv_layers.Conv3DTranspose(
1007        4, [3, 3, 3], strides=(2, 1, 1), padding='same')
1008    output = layer.apply(volumes)
1009    self.assertListEqual(output.get_shape().as_list(),
1010                         [5, depth * 2, height, width, 4])
1011
1012  def testConv3DTransposeKernelRegularizer(self):
1013    depth, height, width = 5, 7, 9
1014    volumes = random_ops.random_uniform((5, depth, height, width, 32))
1015    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
1016    layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], kernel_regularizer=reg)
1017    layer.apply(volumes)
1018    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
1019    self.assertEqual(len(loss_keys), 1)
1020    self.assertListEqual(layer.losses, loss_keys)
1021
1022  def testConv3DTransposeBiasRegularizer(self):
1023    depth, height, width = 5, 7, 9
1024    volumes = random_ops.random_uniform((5, depth, height, width, 32))
1025    reg = lambda x: 0.1 * math_ops.reduce_sum(x)
1026    layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], bias_regularizer=reg)
1027    layer.apply(volumes)
1028    loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)
1029    self.assertEqual(len(loss_keys), 1)
1030    self.assertListEqual(layer.losses, loss_keys)
1031
1032  def testConv3DTransposeNoBias(self):
1033    depth, height, width = 5, 7, 9
1034    volumes = random_ops.random_uniform((5, depth, height, width, 32))
1035    layer = conv_layers.Conv3DTranspose(
1036        4, [3, 3, 3], activation=nn_ops.relu, use_bias=False)
1037    output = layer.apply(volumes)
1038    self.assertEqual(output.op.name, 'conv3d_transpose/Relu')
1039    self.assertListEqual(output.get_shape().as_list(),
1040                         [5, depth + 2, height + 2, width + 2, 4])
1041    self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32])
1042    self.assertEqual(layer.bias, None)
1043
1044  def testFunctionalConv3DTransposeReuse(self):
1045    depth, height, width = 5, 7, 9
1046    volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1)
1047    conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1')
1048    self.assertEqual(len(variables.trainable_variables()), 2)
1049    conv_layers.conv3d_transpose(
1050        volumes, 4, [3, 3, 3], name='deconv1', reuse=True)
1051    self.assertEqual(len(variables.trainable_variables()), 2)
1052
1053  def testFunctionalConv3DTransposeReuseFromScope(self):
1054    with variable_scope.variable_scope('scope'):
1055      depth, height, width = 5, 7, 9
1056      volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1)
1057      conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1')
1058      self.assertEqual(len(variables.trainable_variables()), 2)
1059    with variable_scope.variable_scope('scope', reuse=True):
1060      conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1')
1061      self.assertEqual(len(variables.trainable_variables()), 2)
1062
1063  def testFunctionalConv3DTransposeInitializerFromScope(self):
1064    with self.test_session() as sess:
1065      with variable_scope.variable_scope(
1066          'scope', initializer=init_ops.ones_initializer()):
1067        depth, height, width = 5, 7, 9
1068        volumes = random_ops.random_uniform(
1069            (5, depth, height, width, 32), seed=1)
1070        conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1')
1071        weights = variables.trainable_variables()
1072        # Check the names of weights in order.
1073        self.assertTrue('kernel' in weights[0].name)
1074        self.assertTrue('bias' in weights[1].name)
1075        sess.run(variables.global_variables_initializer())
1076        weights = sess.run(weights)
1077        # Check that the kernel weights got initialized to ones (from scope)
1078        self.assertAllClose(weights[0], np.ones((3, 3, 3, 4, 32)))
1079        # Check that the bias still got initialized to zeros.
1080        self.assertAllClose(weights[1], np.zeros((4)))
1081
1082  def testFunctionalConv3DTransposeNoReuse(self):
1083    depth, height, width = 5, 7, 9
1084    volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1)
1085    conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3])
1086    self.assertEqual(len(variables.trainable_variables()), 2)
1087    conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3])
1088    self.assertEqual(len(variables.trainable_variables()), 4)
1089
1090  def testConstraints(self):
1091    k_constraint = lambda x: x / math_ops.reduce_sum(x)
1092    b_constraint = lambda x: x / math_ops.reduce_max(x)
1093    layer = conv_layers.Conv3DTranspose(2, 3,
1094                                        kernel_constraint=k_constraint,
1095                                        bias_constraint=b_constraint)
1096    inputs = random_ops.random_uniform((5, 3, 3, 3, 5), seed=1)
1097    layer(inputs)
1098    self.assertEqual(layer.kernel_constraint, k_constraint)
1099    self.assertEqual(layer.bias_constraint, b_constraint)
1100
1101
1102if __name__ == '__main__':
1103  test.main()
1104