Spaces:
Runtime error
Runtime error
# coding=utf-8 | |
# Copyright 2021 The Deeplab2 Authors. | |
# | |
# 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 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] | |
# Compare only up to 5 decimal digits to account for numerical accuracy. | |
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 | |
# Compare only up to 5 decimal digits to account for numerical accuracy. | |
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 | |
# Compare only up to 5 decimal digits to account for numerical accuracy. | |
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) | |
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) | |
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) | |
# global_context is supposed to not change any values before training. | |
np.testing.assert_array_almost_equal(input_tensor.numpy(), | |
output_tensor.numpy()) | |
def test_switchable_atrous_conv_class(self): | |
# Tests Switchable Atrous Convolution by equations. | |
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 | |
# Compute the expected outputs. | |
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): | |
# Tests Switchable Atrous Convolution in Conv2DSame. | |
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() | |