|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Tests for convolutions.""" |
|
|
|
import numpy as np |
|
import tensorflow as tf |
|
|
|
from deeplab2.model.layers import convolutions |
|
from deeplab2.utils import test_utils |
|
|
|
|
|
class ConvolutionsTest(tf.test.TestCase): |
|
|
|
def test_conv2dsame_logging(self): |
|
with self.assertLogs(level='WARN'): |
|
_ = convolutions.Conv2DSame( |
|
output_channels=1, |
|
kernel_size=8, |
|
strides=2, |
|
name='conv', |
|
use_bn=False, |
|
activation=None) |
|
|
|
def test_conv2dsame_conv(self): |
|
conv = convolutions.Conv2DSame( |
|
output_channels=1, |
|
kernel_size=1, |
|
name='conv', |
|
use_bn=False, |
|
activation=None) |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 5)) |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_tensor = np.dot(input_tensor.numpy(), |
|
conv._conv.get_weights()[0])[..., 0, 0] |
|
|
|
|
|
np.testing.assert_almost_equal( |
|
predicted_tensor.numpy(), expected_tensor, decimal=5) |
|
|
|
def test_conv2dsame_relu(self): |
|
conv = convolutions.Conv2DSame( |
|
output_channels=1, |
|
kernel_size=1, |
|
name='conv', |
|
activation='relu', |
|
use_bn=False) |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 5)) |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_tensor = np.dot(input_tensor.numpy(), |
|
conv._conv.get_weights()[0])[..., 0, 0] |
|
expected_tensor[expected_tensor < 0.0] = 0.0 |
|
|
|
|
|
np.testing.assert_almost_equal( |
|
predicted_tensor.numpy(), expected_tensor, decimal=5) |
|
|
|
def test_conv2dsame_relu6(self): |
|
conv = convolutions.Conv2DSame( |
|
output_channels=1, |
|
kernel_size=1, |
|
name='conv', |
|
activation='relu6', |
|
use_bn=False) |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 5)) * 10. |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_tensor = np.dot(input_tensor.numpy(), |
|
conv._conv.get_weights()[0])[..., 0, 0] |
|
expected_tensor[expected_tensor < 0.0] = 0.0 |
|
expected_tensor[expected_tensor > 6.0] = 6.0 |
|
|
|
|
|
np.testing.assert_almost_equal( |
|
predicted_tensor.numpy(), expected_tensor, decimal=5) |
|
|
|
def test_conv2dsame_shape(self): |
|
conv = convolutions.Conv2DSame( |
|
output_channels=64, |
|
kernel_size=7, |
|
strides=2, |
|
name='conv', |
|
use_bias=False, |
|
use_bn=True) |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 3)) |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_shape = [2, 90, 90, 64] |
|
|
|
self.assertListEqual(predicted_tensor.shape.as_list(), expected_shape) |
|
|
|
@test_utils.test_all_strategies |
|
def test_conv2d_sync_bn(self, strategy): |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 3)) |
|
|
|
for bn_layer in test_utils.NORMALIZATION_LAYERS: |
|
with strategy.scope(): |
|
conv = convolutions.Conv2DSame( |
|
output_channels=64, |
|
kernel_size=7, |
|
strides=2, |
|
name='conv', |
|
use_bias=False, |
|
use_bn=True, |
|
bn_layer=bn_layer) |
|
conv(input_tensor) |
|
|
|
def test_depthwise_conv(self): |
|
conv = convolutions.DepthwiseConv2DSame( |
|
kernel_size=1, use_bn=False, use_bias=True, activation=None, |
|
name='conv') |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 5)) |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_tensor = ( |
|
input_tensor.numpy() * conv._depthwise_conv.get_weights()[0][..., 0]) |
|
|
|
np.testing.assert_equal(predicted_tensor.numpy(), expected_tensor) |
|
|
|
def test_depthwise_relu(self): |
|
conv = convolutions.DepthwiseConv2DSame( |
|
kernel_size=1, use_bn=False, activation='relu', name='conv') |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 5)) |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_tensor = ( |
|
input_tensor.numpy() * conv._depthwise_conv.get_weights()[0][..., 0]) |
|
expected_tensor[expected_tensor < 0.0] = 0.0 |
|
|
|
np.testing.assert_equal(predicted_tensor.numpy(), expected_tensor) |
|
|
|
def test_depthwise_shape(self): |
|
conv = convolutions.DepthwiseConv2DSame( |
|
kernel_size=3, use_bn=True, use_bias=False, activation='relu', |
|
name='conv') |
|
input_shape = [2, 180, 180, 5] |
|
input_tensor = tf.random.uniform(shape=input_shape) |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_shape = input_shape |
|
|
|
self.assertListEqual(predicted_tensor.shape.as_list(), expected_shape) |
|
|
|
def test_depthwise_shape_with_stride2(self): |
|
conv = convolutions.DepthwiseConv2DSame( |
|
kernel_size=3, use_bn=True, use_bias=False, activation='relu', |
|
strides=2, name='conv') |
|
input_shape = [2, 181, 181, 5] |
|
input_tensor = tf.random.uniform(shape=input_shape) |
|
|
|
predicted_tensor = conv(input_tensor) |
|
expected_shape = [2, 91, 91, 5] |
|
|
|
self.assertListEqual(predicted_tensor.shape.as_list(), expected_shape) |
|
|
|
@test_utils.test_all_strategies |
|
def test_depthwise_sync_bn(self, strategy): |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 3)) |
|
|
|
for bn_layer in test_utils.NORMALIZATION_LAYERS: |
|
with strategy.scope(): |
|
conv = convolutions.DepthwiseConv2DSame( |
|
kernel_size=7, |
|
name='conv', |
|
use_bn=True, |
|
use_bias=False, |
|
bn_layer=bn_layer, |
|
activation='relu') |
|
_ = conv(input_tensor) |
|
|
|
def test_global_context(self): |
|
input_tensor = tf.random.uniform(shape=(2, 180, 180, 3)) |
|
global_context = convolutions.GlobalContext(name='global_context') |
|
output_tensor = global_context(input_tensor) |
|
|
|
np.testing.assert_array_almost_equal(input_tensor.numpy(), |
|
output_tensor.numpy()) |
|
|
|
def test_switchable_atrous_conv_class(self): |
|
|
|
input_tensor = tf.random.uniform(shape=(3, 180, 180, 32)) |
|
sac_layer = convolutions.SwitchableAtrousConvolution( |
|
64, |
|
kernel_size=3, |
|
padding='same', |
|
name='sac_conv') |
|
switch_conv = sac_layer._switch |
|
_ = switch_conv(input_tensor) |
|
switch_conv.kernel = tf.random.uniform( |
|
switch_conv.kernel.shape, |
|
minval=-1, |
|
maxval=1, |
|
dtype=switch_conv.kernel.dtype) |
|
switch_conv.bias = tf.random.uniform( |
|
switch_conv.bias.shape, |
|
minval=-1, |
|
maxval=1, |
|
dtype=switch_conv.bias.dtype) |
|
small_conv = tf.keras.layers.Conv2D( |
|
64, |
|
kernel_size=3, |
|
padding='same', |
|
dilation_rate=1, |
|
name='small_conv') |
|
large_conv = tf.keras.layers.Conv2D( |
|
64, |
|
kernel_size=3, |
|
padding='same', |
|
dilation_rate=3, |
|
name='large_conv') |
|
_ = small_conv(input_tensor) |
|
_ = large_conv(input_tensor) |
|
outputs = sac_layer(input_tensor) |
|
small_conv.kernel = sac_layer.kernel |
|
large_conv.kernel = sac_layer.kernel |
|
|
|
switch_outputs = sac_layer._switch(sac_layer._average_pool(input_tensor)) |
|
large_outputs = large_conv(input_tensor) |
|
small_outputs = small_conv(input_tensor) |
|
expected_outputs = (switch_outputs * large_outputs + |
|
(1 - switch_outputs) * small_outputs) |
|
np.testing.assert_array_almost_equal(expected_outputs.numpy(), |
|
outputs.numpy()) |
|
|
|
def test_switchable_atrous_conv_in_conv2dsame(self): |
|
|
|
input_tensor = tf.random.uniform(shape=(3, 180, 180, 32)) |
|
layer = convolutions.Conv2DSame( |
|
output_channels=64, |
|
kernel_size=7, |
|
strides=1, |
|
name='conv', |
|
use_bias=False, |
|
use_bn=True, |
|
use_switchable_atrous_conv=True, |
|
use_global_context_in_sac=True) |
|
output_tensor = layer(input_tensor) |
|
np.testing.assert_array_almost_equal(output_tensor.shape.as_list(), |
|
[3, 180, 180, 64]) |
|
|
|
def test_conv1d_shape(self): |
|
conv = convolutions.Conv1D( |
|
output_channels=64, |
|
name='conv', |
|
use_bias=False, |
|
use_bn=True) |
|
input_tensor = tf.random.uniform(shape=(2, 180, 3)) |
|
predicted_tensor = conv(input_tensor) |
|
expected_shape = [2, 180, 64] |
|
self.assertListEqual(predicted_tensor.shape.as_list(), expected_shape) |
|
|
|
def test_separable_conv2d_same_output_shape(self): |
|
conv = convolutions.SeparableConv2DSame( |
|
output_channels=64, |
|
kernel_size=3, |
|
name='conv') |
|
input_tensor = tf.random.uniform(shape=(2, 5, 5, 3)) |
|
predicted_tensor = conv(input_tensor) |
|
expected_shape = [2, 5, 5, 64] |
|
self.assertListEqual(predicted_tensor.shape.as_list(), expected_shape) |
|
|
|
def test_stacked_conv2d_same_output_shape(self): |
|
conv = convolutions.StackedConv2DSame( |
|
num_layers=2, |
|
conv_type='depthwise_separable_conv', |
|
output_channels=64, |
|
kernel_size=3, |
|
name='conv') |
|
input_tensor = tf.random.uniform(shape=(2, 5, 5, 3)) |
|
predicted_tensor = conv(input_tensor) |
|
expected_shape = [2, 5, 5, 64] |
|
self.assertListEqual(predicted_tensor.shape.as_list(), expected_shape) |
|
|
|
|
|
if __name__ == '__main__': |
|
tf.test.main() |
|
|