def test_conv_kernel_mask_wrong_dims(self, *input_shape): kernel_shape = 1 strides = 1 conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, 'valid') ndims = len(input_shape) kernel_shape = (2, ) * (ndims + 1) self.assertRaises(ValueError, conv_utils.conv_kernel_mask, input_shape, kernel_shape, strides, 'same') strides = (1, ) * ndims self.assertRaises(ValueError, conv_utils.conv_kernel_mask, input_shape, kernel_shape, strides, 'valid') kernel_shape = (1, ) * ndims strides = (2, ) * (ndims - 1) self.assertRaises(ValueError, conv_utils.conv_kernel_mask, input_shape, kernel_shape, strides, 'valid') strides = (2, ) * ndims conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, 'valid')
def test_conv_kernel_mask_wrong_padding(self, *input_shape): ndims = len(input_shape) kernel_shape = (1, ) * ndims strides = (1, ) * ndims conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, 'valid') conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, 'same') self.assertRaises(NotImplementedError, conv_utils.conv_kernel_mask, input_shape, kernel_shape, strides, 'full')
def test_conv_kernel_mask_rect_kernel(self, *input_shape): padding = 'valid' ndims = len(input_shape) strides = (1, ) * ndims for d in range(ndims): kernel_shape = [1] * ndims kernel_shape[d] = input_shape[d] output_shape = list(input_shape) output_shape[d] = min(1, input_shape[d]) mask = np.identity(int(np.prod(input_shape)), np.bool) mask = np.reshape(mask, input_shape * 2) for p in itertools.product( *[range(input_shape[dim]) for dim in range(ndims)]): p = list(p) p[d] = slice(None) mask[p * 2] = True mask = np.take(mask, range(0, min(1, input_shape[d])), ndims + d) self.assertAllEqual( mask, conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, padding))
def get_locallyconnected_mask(input_shape, kernel_shape, strides, padding, data_format): """Return a mask representing connectivity of a locally-connected operation. This method returns a masking numpy array of 0s and 1s (of type `np.float32`) that, when element-wise multiplied with a fully-connected weight tensor, masks out the weights between disconnected input-output pairs and thus implements local connectivity through a sparse fully-connected weight tensor. Assume an unshared convolution with given parameters is applied to an input having N spatial dimensions with `input_shape = (d_in1, ..., d_inN)` to produce an output with spatial shape `(d_out1, ..., d_outN)` (determined by layer parameters such as `strides`). This method returns a mask which can be broadcast-multiplied (element-wise) with a 2*(N+1)-D weight matrix (equivalent to a fully-connected layer between (N+1)-D activations (N spatial + 1 channel dimensions for input and output) to make it perform an unshared convolution with given `kernel_shape`, `strides`, `padding` and `data_format`. Args: input_shape: tuple of size N: `(d_in1, ..., d_inN)` spatial shape of the input. kernel_shape: tuple of size N, spatial shape of the convolutional kernel / receptive field. strides: tuple of size N, strides along each spatial dimension. padding: type of padding, string `"same"` or `"valid"`. data_format: a string, `"channels_first"` or `"channels_last"`. Returns: a `np.float32`-type `np.ndarray` of shape `(1, d_in1, ..., d_inN, 1, d_out1, ..., d_outN)` if `data_format == `"channels_first"`, or `(d_in1, ..., d_inN, 1, d_out1, ..., d_outN, 1)` if `data_format == "channels_last"`. Raises: ValueError: if `data_format` is neither `"channels_first"` nor `"channels_last"`. """ mask = conv_utils.conv_kernel_mask( input_shape=input_shape, kernel_shape=kernel_shape, strides=strides, padding=padding) ndims = int(mask.ndim / 2) if data_format == 'channels_first': mask = np.expand_dims(mask, 0) mask = np.expand_dims(mask, -ndims - 1) elif data_format == 'channels_last': mask = np.expand_dims(mask, ndims) mask = np.expand_dims(mask, -1) else: raise ValueError('Unrecognized data_format: ' + str(data_format)) return mask
def test_conv_kernel_mask_fc(self, *input_shape): padding = 'valid' kernel_shape = input_shape ndims = len(input_shape) strides = (1, ) * ndims output_shape = _get_const_output_shape(input_shape, dim=1) mask = np.ones(input_shape + output_shape, np.bool) self.assertAllEqual( mask, conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, padding))
def test_conv_kernel_mask_diag(self, *input_shape): ndims = len(input_shape) kernel_shape = (1, ) * ndims strides = (1, ) * ndims for padding in ['valid', 'same']: mask = np.identity(int(np.prod(input_shape)), np.bool) mask = np.reshape(mask, input_shape * 2) self.assertAllEqual( mask, conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, padding))
def test_conv_kernel_mask_full_stride(self, *input_shape): padding = 'valid' ndims = len(input_shape) kernel_shape = (1, ) * ndims strides = tuple([max(d, 1) for d in input_shape]) output_shape = _get_const_output_shape(input_shape, dim=1) mask = np.zeros(input_shape + output_shape, np.bool) if all(d > 0 for d in mask.shape): mask[(0, ) * len(output_shape)] = True self.assertAllEqual( mask, conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, padding))
def test_conv_kernel_mask_almost_full_stride(self, *input_shape): padding = 'valid' ndims = len(input_shape) kernel_shape = (1, ) * ndims strides = tuple([max(d - 1, 1) for d in input_shape]) output_shape = _get_const_output_shape(input_shape, dim=2) mask = np.zeros(input_shape + output_shape, np.bool) if all(d > 0 for d in mask.shape): for in_position in itertools.product(*[[0, d - 1] for d in input_shape]): out_position = tuple([min(p, 1) for p in in_position]) mask[in_position + out_position] = True self.assertAllEqual( mask, conv_utils.conv_kernel_mask(input_shape, kernel_shape, strides, padding))