NCTC / models /research /deeplab /core /xception_test.py
NCTCMumbai's picture
Upload 2571 files
0b8359d
# Lint as: python2, python3
# Copyright 2018 The TensorFlow Authors All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for xception.py."""
import numpy as np
import six
import tensorflow as tf
from tensorflow.contrib import slim as contrib_slim
from deeplab.core import xception
from tensorflow.contrib.slim.nets import resnet_utils
slim = contrib_slim
def create_test_input(batch, height, width, channels):
"""Create test input tensor."""
if None in [batch, height, width, channels]:
return tf.placeholder(tf.float32, (batch, height, width, channels))
else:
return tf.cast(
np.tile(
np.reshape(
np.reshape(np.arange(height), [height, 1]) +
np.reshape(np.arange(width), [1, width]),
[1, height, width, 1]),
[batch, 1, 1, channels]),
tf.float32)
class UtilityFunctionTest(tf.test.TestCase):
def testSeparableConv2DSameWithInputEvenSize(self):
n, n2 = 4, 2
# Input image.
x = create_test_input(1, n, n, 1)
# Convolution kernel.
dw = create_test_input(1, 3, 3, 1)
dw = tf.reshape(dw, [3, 3, 1, 1])
tf.get_variable('Conv/depthwise_weights', initializer=dw)
tf.get_variable('Conv/pointwise_weights',
initializer=tf.ones([1, 1, 1, 1]))
tf.get_variable('Conv/biases', initializer=tf.zeros([1]))
tf.get_variable_scope().reuse_variables()
y1 = slim.separable_conv2d(x, 1, [3, 3], depth_multiplier=1,
stride=1, scope='Conv')
y1_expected = tf.cast([[14, 28, 43, 26],
[28, 48, 66, 37],
[43, 66, 84, 46],
[26, 37, 46, 22]], tf.float32)
y1_expected = tf.reshape(y1_expected, [1, n, n, 1])
y2 = resnet_utils.subsample(y1, 2)
y2_expected = tf.cast([[14, 43],
[43, 84]], tf.float32)
y2_expected = tf.reshape(y2_expected, [1, n2, n2, 1])
y3 = xception.separable_conv2d_same(x, 1, 3, depth_multiplier=1,
regularize_depthwise=True,
stride=2, scope='Conv')
y3_expected = y2_expected
y4 = slim.separable_conv2d(x, 1, [3, 3], depth_multiplier=1,
stride=2, scope='Conv')
y4_expected = tf.cast([[48, 37],
[37, 22]], tf.float32)
y4_expected = tf.reshape(y4_expected, [1, n2, n2, 1])
with self.test_session() as sess:
sess.run(tf.global_variables_initializer())
self.assertAllClose(y1.eval(), y1_expected.eval())
self.assertAllClose(y2.eval(), y2_expected.eval())
self.assertAllClose(y3.eval(), y3_expected.eval())
self.assertAllClose(y4.eval(), y4_expected.eval())
def testSeparableConv2DSameWithInputOddSize(self):
n, n2 = 5, 3
# Input image.
x = create_test_input(1, n, n, 1)
# Convolution kernel.
dw = create_test_input(1, 3, 3, 1)
dw = tf.reshape(dw, [3, 3, 1, 1])
tf.get_variable('Conv/depthwise_weights', initializer=dw)
tf.get_variable('Conv/pointwise_weights',
initializer=tf.ones([1, 1, 1, 1]))
tf.get_variable('Conv/biases', initializer=tf.zeros([1]))
tf.get_variable_scope().reuse_variables()
y1 = slim.separable_conv2d(x, 1, [3, 3], depth_multiplier=1,
stride=1, scope='Conv')
y1_expected = tf.cast([[14, 28, 43, 58, 34],
[28, 48, 66, 84, 46],
[43, 66, 84, 102, 55],
[58, 84, 102, 120, 64],
[34, 46, 55, 64, 30]], tf.float32)
y1_expected = tf.reshape(y1_expected, [1, n, n, 1])
y2 = resnet_utils.subsample(y1, 2)
y2_expected = tf.cast([[14, 43, 34],
[43, 84, 55],
[34, 55, 30]], tf.float32)
y2_expected = tf.reshape(y2_expected, [1, n2, n2, 1])
y3 = xception.separable_conv2d_same(x, 1, 3, depth_multiplier=1,
regularize_depthwise=True,
stride=2, scope='Conv')
y3_expected = y2_expected
y4 = slim.separable_conv2d(x, 1, [3, 3], depth_multiplier=1,
stride=2, scope='Conv')
y4_expected = y2_expected
with self.test_session() as sess:
sess.run(tf.global_variables_initializer())
self.assertAllClose(y1.eval(), y1_expected.eval())
self.assertAllClose(y2.eval(), y2_expected.eval())
self.assertAllClose(y3.eval(), y3_expected.eval())
self.assertAllClose(y4.eval(), y4_expected.eval())
class XceptionNetworkTest(tf.test.TestCase):
"""Tests with small Xception network."""
def _xception_small(self,
inputs,
num_classes=None,
is_training=True,
global_pool=True,
output_stride=None,
regularize_depthwise=True,
reuse=None,
scope='xception_small'):
"""A shallow and thin Xception for faster tests."""
block = xception.xception_block
blocks = [
block('entry_flow/block1',
depth_list=[1, 1, 1],
skip_connection_type='conv',
activation_fn_in_separable_conv=False,
regularize_depthwise=regularize_depthwise,
num_units=1,
stride=2),
block('entry_flow/block2',
depth_list=[2, 2, 2],
skip_connection_type='conv',
activation_fn_in_separable_conv=False,
regularize_depthwise=regularize_depthwise,
num_units=1,
stride=2),
block('entry_flow/block3',
depth_list=[4, 4, 4],
skip_connection_type='conv',
activation_fn_in_separable_conv=False,
regularize_depthwise=regularize_depthwise,
num_units=1,
stride=1),
block('entry_flow/block4',
depth_list=[4, 4, 4],
skip_connection_type='conv',
activation_fn_in_separable_conv=False,
regularize_depthwise=regularize_depthwise,
num_units=1,
stride=2),
block('middle_flow/block1',
depth_list=[4, 4, 4],
skip_connection_type='sum',
activation_fn_in_separable_conv=False,
regularize_depthwise=regularize_depthwise,
num_units=2,
stride=1),
block('exit_flow/block1',
depth_list=[8, 8, 8],
skip_connection_type='conv',
activation_fn_in_separable_conv=False,
regularize_depthwise=regularize_depthwise,
num_units=1,
stride=2),
block('exit_flow/block2',
depth_list=[16, 16, 16],
skip_connection_type='none',
activation_fn_in_separable_conv=True,
regularize_depthwise=regularize_depthwise,
num_units=1,
stride=1),
]
return xception.xception(inputs,
blocks=blocks,
num_classes=num_classes,
is_training=is_training,
global_pool=global_pool,
output_stride=output_stride,
reuse=reuse,
scope=scope)
def testClassificationEndPoints(self):
global_pool = True
num_classes = 3
inputs = create_test_input(2, 32, 32, 3)
with slim.arg_scope(xception.xception_arg_scope()):
logits, end_points = self._xception_small(
inputs,
num_classes=num_classes,
global_pool=global_pool,
scope='xception')
self.assertTrue(
logits.op.name.startswith('xception/logits'))
self.assertListEqual(logits.get_shape().as_list(), [2, 1, 1, num_classes])
self.assertTrue('predictions' in end_points)
self.assertListEqual(end_points['predictions'].get_shape().as_list(),
[2, 1, 1, num_classes])
self.assertTrue('global_pool' in end_points)
self.assertListEqual(end_points['global_pool'].get_shape().as_list(),
[2, 1, 1, 16])
def testEndpointNames(self):
global_pool = True
num_classes = 3
inputs = create_test_input(2, 32, 32, 3)
with slim.arg_scope(xception.xception_arg_scope()):
_, end_points = self._xception_small(
inputs,
num_classes=num_classes,
global_pool=global_pool,
scope='xception')
expected = [
'xception/entry_flow/conv1_1',
'xception/entry_flow/conv1_2',
'xception/entry_flow/block1/unit_1/xception_module/separable_conv1',
'xception/entry_flow/block1/unit_1/xception_module/separable_conv2',
'xception/entry_flow/block1/unit_1/xception_module/separable_conv3',
'xception/entry_flow/block1/unit_1/xception_module/shortcut',
'xception/entry_flow/block1/unit_1/xception_module',
'xception/entry_flow/block1',
'xception/entry_flow/block2/unit_1/xception_module/separable_conv1',
'xception/entry_flow/block2/unit_1/xception_module/separable_conv2',
'xception/entry_flow/block2/unit_1/xception_module/separable_conv3',
'xception/entry_flow/block2/unit_1/xception_module/shortcut',
'xception/entry_flow/block2/unit_1/xception_module',
'xception/entry_flow/block2',
'xception/entry_flow/block3/unit_1/xception_module/separable_conv1',
'xception/entry_flow/block3/unit_1/xception_module/separable_conv2',
'xception/entry_flow/block3/unit_1/xception_module/separable_conv3',
'xception/entry_flow/block3/unit_1/xception_module/shortcut',
'xception/entry_flow/block3/unit_1/xception_module',
'xception/entry_flow/block3',
'xception/entry_flow/block4/unit_1/xception_module/separable_conv1',
'xception/entry_flow/block4/unit_1/xception_module/separable_conv2',
'xception/entry_flow/block4/unit_1/xception_module/separable_conv3',
'xception/entry_flow/block4/unit_1/xception_module/shortcut',
'xception/entry_flow/block4/unit_1/xception_module',
'xception/entry_flow/block4',
'xception/middle_flow/block1/unit_1/xception_module/separable_conv1',
'xception/middle_flow/block1/unit_1/xception_module/separable_conv2',
'xception/middle_flow/block1/unit_1/xception_module/separable_conv3',
'xception/middle_flow/block1/unit_1/xception_module',
'xception/middle_flow/block1/unit_2/xception_module/separable_conv1',
'xception/middle_flow/block1/unit_2/xception_module/separable_conv2',
'xception/middle_flow/block1/unit_2/xception_module/separable_conv3',
'xception/middle_flow/block1/unit_2/xception_module',
'xception/middle_flow/block1',
'xception/exit_flow/block1/unit_1/xception_module/separable_conv1',
'xception/exit_flow/block1/unit_1/xception_module/separable_conv2',
'xception/exit_flow/block1/unit_1/xception_module/separable_conv3',
'xception/exit_flow/block1/unit_1/xception_module/shortcut',
'xception/exit_flow/block1/unit_1/xception_module',
'xception/exit_flow/block1',
'xception/exit_flow/block2/unit_1/xception_module/separable_conv1',
'xception/exit_flow/block2/unit_1/xception_module/separable_conv2',
'xception/exit_flow/block2/unit_1/xception_module/separable_conv3',
'xception/exit_flow/block2/unit_1/xception_module',
'xception/exit_flow/block2',
'global_pool',
'xception/logits',
'predictions',
]
self.assertItemsEqual(list(end_points.keys()), expected)
def testClassificationShapes(self):
global_pool = True
num_classes = 3
inputs = create_test_input(2, 64, 64, 3)
with slim.arg_scope(xception.xception_arg_scope()):
_, end_points = self._xception_small(
inputs,
num_classes,
global_pool=global_pool,
scope='xception')
endpoint_to_shape = {
'xception/entry_flow/conv1_1': [2, 32, 32, 32],
'xception/entry_flow/block1': [2, 16, 16, 1],
'xception/entry_flow/block2': [2, 8, 8, 2],
'xception/entry_flow/block4': [2, 4, 4, 4],
'xception/middle_flow/block1': [2, 4, 4, 4],
'xception/exit_flow/block1': [2, 2, 2, 8],
'xception/exit_flow/block2': [2, 2, 2, 16]}
for endpoint, shape in six.iteritems(endpoint_to_shape):
self.assertListEqual(end_points[endpoint].get_shape().as_list(), shape)
def testFullyConvolutionalEndpointShapes(self):
global_pool = False
num_classes = 3
inputs = create_test_input(2, 65, 65, 3)
with slim.arg_scope(xception.xception_arg_scope()):
_, end_points = self._xception_small(
inputs,
num_classes,
global_pool=global_pool,
scope='xception')
endpoint_to_shape = {
'xception/entry_flow/conv1_1': [2, 33, 33, 32],
'xception/entry_flow/block1': [2, 17, 17, 1],
'xception/entry_flow/block2': [2, 9, 9, 2],
'xception/entry_flow/block4': [2, 5, 5, 4],
'xception/middle_flow/block1': [2, 5, 5, 4],
'xception/exit_flow/block1': [2, 3, 3, 8],
'xception/exit_flow/block2': [2, 3, 3, 16]}
for endpoint, shape in six.iteritems(endpoint_to_shape):
self.assertListEqual(end_points[endpoint].get_shape().as_list(), shape)
def testAtrousFullyConvolutionalEndpointShapes(self):
global_pool = False
num_classes = 3
output_stride = 8
inputs = create_test_input(2, 65, 65, 3)
with slim.arg_scope(xception.xception_arg_scope()):
_, end_points = self._xception_small(
inputs,
num_classes,
global_pool=global_pool,
output_stride=output_stride,
scope='xception')
endpoint_to_shape = {
'xception/entry_flow/block1': [2, 17, 17, 1],
'xception/entry_flow/block2': [2, 9, 9, 2],
'xception/entry_flow/block4': [2, 9, 9, 4],
'xception/middle_flow/block1': [2, 9, 9, 4],
'xception/exit_flow/block1': [2, 9, 9, 8],
'xception/exit_flow/block2': [2, 9, 9, 16]}
for endpoint, shape in six.iteritems(endpoint_to_shape):
self.assertListEqual(end_points[endpoint].get_shape().as_list(), shape)
def testAtrousFullyConvolutionalValues(self):
"""Verify dense feature extraction with atrous convolution."""
nominal_stride = 32
for output_stride in [4, 8, 16, 32, None]:
with slim.arg_scope(xception.xception_arg_scope()):
with tf.Graph().as_default():
with self.test_session() as sess:
tf.set_random_seed(0)
inputs = create_test_input(2, 96, 97, 3)
# Dense feature extraction followed by subsampling.
output, _ = self._xception_small(
inputs,
None,
is_training=False,
global_pool=False,
output_stride=output_stride)
if output_stride is None:
factor = 1
else:
factor = nominal_stride // output_stride
output = resnet_utils.subsample(output, factor)
# Make the two networks use the same weights.
tf.get_variable_scope().reuse_variables()
# Feature extraction at the nominal network rate.
expected, _ = self._xception_small(
inputs,
None,
is_training=False,
global_pool=False)
sess.run(tf.global_variables_initializer())
self.assertAllClose(output.eval(), expected.eval(),
atol=1e-5, rtol=1e-5)
def testUnknownBatchSize(self):
batch = 2
height, width = 65, 65
global_pool = True
num_classes = 10
inputs = create_test_input(None, height, width, 3)
with slim.arg_scope(xception.xception_arg_scope()):
logits, _ = self._xception_small(
inputs,
num_classes,
global_pool=global_pool,
scope='xception')
self.assertTrue(logits.op.name.startswith('xception/logits'))
self.assertListEqual(logits.get_shape().as_list(),
[None, 1, 1, num_classes])
images = create_test_input(batch, height, width, 3)
with self.test_session() as sess:
sess.run(tf.global_variables_initializer())
output = sess.run(logits, {inputs: images.eval()})
self.assertEquals(output.shape, (batch, 1, 1, num_classes))
def testFullyConvolutionalUnknownHeightWidth(self):
batch = 2
height, width = 65, 65
global_pool = False
inputs = create_test_input(batch, None, None, 3)
with slim.arg_scope(xception.xception_arg_scope()):
output, _ = self._xception_small(
inputs,
None,
global_pool=global_pool)
self.assertListEqual(output.get_shape().as_list(),
[batch, None, None, 16])
images = create_test_input(batch, height, width, 3)
with self.test_session() as sess:
sess.run(tf.global_variables_initializer())
output = sess.run(output, {inputs: images.eval()})
self.assertEquals(output.shape, (batch, 3, 3, 16))
def testAtrousFullyConvolutionalUnknownHeightWidth(self):
batch = 2
height, width = 65, 65
global_pool = False
output_stride = 8
inputs = create_test_input(batch, None, None, 3)
with slim.arg_scope(xception.xception_arg_scope()):
output, _ = self._xception_small(
inputs,
None,
global_pool=global_pool,
output_stride=output_stride)
self.assertListEqual(output.get_shape().as_list(),
[batch, None, None, 16])
images = create_test_input(batch, height, width, 3)
with self.test_session() as sess:
sess.run(tf.global_variables_initializer())
output = sess.run(output, {inputs: images.eval()})
self.assertEquals(output.shape, (batch, 9, 9, 16))
def testEndpointsReuse(self):
inputs = create_test_input(2, 32, 32, 3)
with slim.arg_scope(xception.xception_arg_scope()):
_, end_points0 = xception.xception_65(
inputs,
num_classes=10,
reuse=False)
with slim.arg_scope(xception.xception_arg_scope()):
_, end_points1 = xception.xception_65(
inputs,
num_classes=10,
reuse=True)
self.assertItemsEqual(list(end_points0.keys()), list(end_points1.keys()))
def testUseBoundedAcitvation(self):
global_pool = False
num_classes = 3
output_stride = 16
for use_bounded_activation in (True, False):
tf.reset_default_graph()
inputs = create_test_input(2, 65, 65, 3)
with slim.arg_scope(xception.xception_arg_scope(
use_bounded_activation=use_bounded_activation)):
_, _ = self._xception_small(
inputs,
num_classes,
global_pool=global_pool,
output_stride=output_stride,
scope='xception')
for node in tf.get_default_graph().as_graph_def().node:
if node.op.startswith('Relu'):
self.assertEqual(node.op == 'Relu6', use_bounded_activation)
if __name__ == '__main__':
tf.test.main()