def call(self, inputs): inputs_shape = array_ops.shape(inputs) batch_size = inputs_shape[0] if self.data_format == 'channels_first': c_axis, h_axis, w_axis = 1, 2, 3 else: c_axis, h_axis, w_axis = 3, 1, 2 height, width = inputs_shape[h_axis], inputs_shape[w_axis] kernel_h, kernel_w = self.kernel_size stride_h, stride_w = self.strides def get_deconv_dim(dim_size, stride_size, kernel_size, padding): if isinstance(dim_size, ops.Tensor): dim_size = math_ops.mul(dim_size, stride_size) elif dim_size is not None: dim_size *= stride_size if padding == 'valid' and dim_size is not None: dim_size += max(kernel_size - stride_size, 0) return dim_size # Infer the dynamic output shape: out_height = get_deconv_dim(height, stride_h, kernel_h, self.padding) out_width = get_deconv_dim(width, stride_w, kernel_w, self.padding) if self.data_format == 'channels_first': output_shape = (batch_size, self.filters, out_height, out_width) strides = (1, 1, stride_h, stride_w) else: output_shape = (batch_size, out_height, out_width, self.filters) strides = (1, stride_h, stride_w, 1) output_shape_tensor = array_ops.stack(output_shape) outputs = nn.conv2d_transpose( inputs, self.kernel, output_shape_tensor, strides, padding=self.padding.upper(), data_format=utils.convert_data_format(self.data_format, ndim=4)) # Infer the static output shape: out_shape = inputs.get_shape().as_list() out_shape[c_axis] = self.filters out_shape[h_axis] = get_deconv_dim( out_shape[h_axis], stride_h, kernel_h, self.padding) out_shape[w_axis] = get_deconv_dim( out_shape[w_axis], stride_w, kernel_w, self.padding) outputs.set_shape(out_shape) if self.bias: outputs = nn.bias_add( outputs, self.bias, data_format=utils.convert_data_format(self.data_format, ndim=4)) if self.activation is not None: return self.activation(outputs) return outputs
def call(self, inputs, training=True): inputs_shape = array_ops.shape(inputs) batch_size = inputs_shape[0] if self.data_format == 'channels_first': c_axis, h_axis, w_axis = 1, 2, 3 else: c_axis, h_axis, w_axis = 3, 1, 2 height, width = inputs_shape[h_axis], inputs_shape[w_axis] kernel_h, kernel_w = self.kernel_size stride_h, stride_w = self.strides # Infer the dynamic output shape: out_height = utils.deconv_output_length(height, kernel_h, self.padding, stride_h) out_width = utils.deconv_output_length(width, kernel_w, self.padding, stride_w) if self.data_format == 'channels_first': output_shape = (batch_size, self.filters, out_height, out_width) strides = (1, 1, stride_h, stride_w) else: output_shape = (batch_size, out_height, out_width, self.filters) strides = (1, stride_h, stride_w, 1) output_shape_tensor = array_ops.stack(output_shape) outputs = nn.conv2d_transpose( inputs, self.compute_spectral_normal(training=training), output_shape_tensor, strides, padding=self.padding.upper(), data_format=utils.convert_data_format(self.data_format, ndim=4)) if not context.executing_eagerly(): # Infer the static output shape: out_shape = inputs.get_shape().as_list() out_shape[c_axis] = self.filters out_shape[h_axis] = utils.deconv_output_length(out_shape[h_axis], kernel_h, self.padding, stride_h) out_shape[w_axis] = utils.deconv_output_length(out_shape[w_axis], kernel_w, self.padding, stride_w) outputs.set_shape(out_shape) if self.use_bias: outputs = nn.bias_add( outputs, self.bias, data_format=utils.convert_data_format(self.data_format, ndim=4)) if self.activation is not None: return self.activation(outputs) return outputs
def conv2d_transpose(x, kernel, output_shape, strides=(1, 1), padding='VALID', data_format='NHWC', dilation_rate=(1, 1)): strides = (1,) + strides + (1,) if data_format[-1] == 'C'\ else (1, 1) + strides # deconv's output_shape can not contain "None" # if had "None", replace it with -1 if output_shape[0] is None: batch = int_shape(x)[0] output_shape = (batch if batch else -1, ) + tuple(output_shape[1:]) if dilation_rate == (1, 1): x = nn.conv2d_transpose(value=x, filter=kernel, output_shape=output_shape, strides=strides, padding=padding, data_format=data_format) else: assert dilation_rate[0] == dilation_rate[1] # atrous only support NHWC if data_format[-1] != 'C': x = transpose_to_channels_last(x) output_shape = to_channels_last(output_shape) x = nn.atrous_conv2d_transpose(value=x, filters=kernel, output_shape=output_shape, rate=dilation_rate[0], padding=padding) if data_format[-1] != 'C': x = transpose_to_channels_first(x) return x
def call(self, inputs): inputs_shape = array_ops.shape(inputs) batch_size = inputs_shape[0] if self.data_format == 'channels_first': c_axis, h_axis, w_axis = 1, 2, 3 else: c_axis, h_axis, w_axis = 3, 1, 2 height, width = inputs_shape[h_axis], inputs_shape[w_axis] kernel_h, kernel_w = self.kernel_size stride_h, stride_w = self.strides def get_deconv_dim(dim_size, stride_size, kernel_size, padding): if isinstance(dim_size, ops.Tensor): dim_size = math_ops.mul(dim_size, stride_size) elif dim_size is not None: dim_size *= stride_size if padding == 'valid' and dim_size is not None: dim_size += max(kernel_size - stride_size, 0) return dim_size # Infer the dynamic output shape: out_height = get_deconv_dim(height, stride_h, kernel_h, self.padding) out_width = get_deconv_dim(width, stride_w, kernel_w, self.padding) if self.data_format == 'channels_first': output_shape = (batch_size, self.filters, out_height, out_width) strides = (1, 1, stride_h, stride_w) else: output_shape = (batch_size, out_height, out_width, self.filters) strides = (1, stride_h, stride_w, 1) output_shape_tensor = array_ops.pack(output_shape) outputs = nn.conv2d_transpose( inputs, self.kernel, output_shape_tensor, strides, padding=self.padding.upper(), data_format=utils.convert_data_format(self.data_format, ndim=4)) # Infer the static output shape: out_shape = inputs.get_shape().as_list() out_shape[c_axis] = self.filters out_shape[h_axis] = get_deconv_dim( out_shape[h_axis], stride_h, kernel_h, self.padding) out_shape[w_axis] = get_deconv_dim( out_shape[w_axis], stride_w, kernel_w, self.padding) outputs.set_shape(out_shape) if self.bias: outputs = nn.bias_add( outputs, self.bias, data_format=utils.convert_data_format(self.data_format, ndim=4)) if self.activation is not None: return self.activation(outputs) return outputs
def call(self, inputs): inputs_shape = array_ops.shape(inputs) batch_size = inputs_shape[0] if self.data_format == 'channels_first': c_axis, h_axis, w_axis = 1, 2, 3 else: c_axis, h_axis, w_axis = 3, 1, 2 height, width = inputs_shape[h_axis], inputs_shape[w_axis] kernel_h, kernel_w = self.kernel_size stride_h, stride_w = self.strides # Infer the dynamic output shape: out_height = utils.deconv_output_length(height, kernel_h, self.padding, stride_h) out_width = utils.deconv_output_length(width, kernel_w, self.padding, stride_w) if self.data_format == 'channels_first': output_shape = (batch_size, self.filters, out_height, out_width) strides = (1, 1, stride_h, stride_w) else: output_shape = (batch_size, out_height, out_width, self.filters) strides = (1, stride_h, stride_w, 1) output_shape_tensor = array_ops.stack(output_shape) kernel_norm = nn.l2_normalize(self.kernel, [0, 1, 3]) if self.use_scale: kernel_norm = tf.reshape(self.scale, [1, 1, self.filters, 1]) * kernel_norm outputs = nn.conv2d_transpose(inputs, kernel_norm, output_shape_tensor, strides, padding=self.padding.upper(), data_format=utils.convert_data_format( self.data_format, ndim=4)) if context.in_graph_mode(): # Infer the static output shape: out_shape = inputs.get_shape().as_list() out_shape[c_axis] = self.filters out_shape[h_axis] = utils.deconv_output_length( out_shape[h_axis], kernel_h, self.padding, stride_h) out_shape[w_axis] = utils.deconv_output_length( out_shape[w_axis], kernel_w, self.padding, stride_w) outputs.set_shape(out_shape) if self.use_bias: outputs = nn.bias_add(outputs, self.bias, data_format=utils.convert_data_format( self.data_format, ndim=4)) if self.activation is not None: return self.activation(outputs) return outputs
b0 = tf.Variable(tf.zeros([32])) # Down sample conv_0 = tf.nn.relu( tf.nn.conv2d(in_data, w0, [1, 2, 2, 1], padding='SAME') + b0) print("Convolution 0:", conv_0) # Up sample 1. Upscale to 100 x 100 x 24 wt1 = tf.Variable(tf.truncated_normal([3, 3, 24, 32])) end1 = time.time() print("Checkpoint model", end1 - start) start_time = time.time() import check convt_1 = sigmoid( conv2d_transpose(conv_0, filter=wt1, output_shape=[batch_size, 100, 100, 24], strides=[1, 1, 1, 1])) print("Deconvolution 1:", convt_1) # Up sample 2. Upscale to 256 x 256 x 2 wt2 = tf.Variable(tf.truncated_normal([3, 3, 2, 24])) convt_2 = sigmoid( conv2d_transpose(convt_1, filter=wt2, output_shape=[batch_size, IMAGE_HEIGHT, IMAGE_WIDTH, 2], strides=[1, 1, 1, 1])) print("Deconvolution 2:", convt_2) # Loss computation logits = tf.reshape(convt_2, [-1, num_labels]) reshaped_labels = tf.reshape(labels, [-1])
def call(self, inputs): inputs = ops.convert_to_tensor(inputs, dtype=self.dtype) input_shape = array_ops.shape(inputs) outputs = inputs # First, perform any requested padding. if self.padding in ("same_zeros", "same_reflect"): padding = padding_ops.same_padding_for_kernel( self.kernel_support, self.corr, self.strides_up) if self.data_format == "channels_last": padding = [[0, 0]] + list(padding) + [[0, 0]] else: padding = [[0, 0], [0, 0]] + list(padding) outputs = array_ops.pad(outputs, padding, self._pad_mode) # Now, perform valid convolutions/correlations. # Not for all possible combinations of (`kernel_support`, `corr`, # `strides_up`, `strides_down`) TF ops exist. We implement some additional # combinations by manipulating the kernels and toggling `corr`. kernel = self.kernel corr = self.corr # If a convolution with no upsampling is desired, we flip the kernels and # use cross correlation to implement it, provided the kernels are odd-length # in every dimension (with even-length kernels, the boundary handling # would have to change, so we'll throw an error instead). if (not corr and all(s == 1 for s in self.strides_up) and all(s % 2 == 1 for s in self.kernel_support)): corr = True slices = self._rank * (slice(None, None, -1), ) + 2 * (slice(None), ) kernel = kernel[slices] # Similarly, we can implement a cross correlation with no downsampling using # convolutions. However, we do this only if upsampling is requested, as we # are wasting computation in the boundaries whenever we call the transpose # convolution ops. if (corr and all(s == 1 for s in self.strides_down) and any(s != 1 for s in self.strides_up) and all(s % 2 == 1 for s in self.kernel_support)): corr = False slices = self._rank * (slice(None, None, -1), ) + 2 * (slice(None), ) kernel = kernel[slices] data_format = utils.convert_data_format(self.data_format, self._rank + 2) if (corr and self.channel_separable and self._rank == 2 and all(s == 1 for s in self.strides_up) and all(s == self.strides_down[0] for s in self.strides_down)): # `nn.depthwise_conv2d_native` performs channel-separable correlations # followed by optional downsampling. outputs = nn.depthwise_conv2d_native(outputs, kernel, strides=self._pad_strides( self.strides_down), padding="VALID", data_format=data_format) elif (corr and all(s == 1 for s in self.strides_up) and not self.channel_separable): # `nn.convolution` performs correlations followed by optional # downsampling. outputs = nn.convolution(outputs, kernel, strides=self.strides_down, padding="VALID", data_format=data_format) elif (not corr and all(s == 1 for s in self.strides_down) and ((not self.channel_separable and 1 <= self._rank <= 3) or (self.channel_separable and self.filters == 1 and self._rank == 2 and all(s == self.strides_up[0] for s in self.strides_up)))): # `nn.conv?d_transpose` perform convolutions, preceded by optional # upsampling. Generally, they increase the spatial support of their # inputs, so in order to implement 'valid', we need to crop their outputs. # Transpose convolutions expect the output and input channels in reversed # order. We implement this by swapping those dimensions of the kernel. # For channel separable convolutions, we can't currently perform anything # other than one filter per channel, so the last dimension needs to be of # length one. Since this happens to be the format that the op expects it, # we can skip the transpose in that case. if not self.channel_separable: kernel = array_ops.transpose( kernel, list(range(self._rank)) + [self._rank + 1, self._rank]) # Compute shape of temporary. pad_shape = array_ops.shape(outputs) temp_shape = [pad_shape[0]] + (self._rank + 1) * [None] if self.data_format == "channels_last": spatial_axes = range(1, self._rank + 1) if self.channel_separable: temp_shape[-1] = input_shape[-1] else: temp_shape[-1] = self.filters else: spatial_axes = range(2, self._rank + 2) if self.channel_separable: temp_shape[1] = input_shape[1] else: temp_shape[1] = self.filters if self.extra_pad_end: get_length = lambda l, s, k: l * s + (k - 1) else: get_length = lambda l, s, k: l * s + (k - s) for i, a in enumerate(spatial_axes): temp_shape[a] = get_length(pad_shape[a], self.strides_up[i], self.kernel_support[i]) # Compute convolution. if self._rank == 1 and not self.channel_separable: # There's no 1D transpose convolution op, so we insert an extra # dimension and use 2D. extradim = { "channels_first": 2, "channels_last": 1 }[self.data_format] strides = self._pad_strides(self.strides_up) temp = array_ops.squeeze( nn.conv2d_transpose( array_ops.expand_dims(outputs, extradim), array_ops.expand_dims(kernel, 0), temp_shape[:extradim] + [1] + temp_shape[extradim:], strides=strides[:extradim] + (1, ) + strides[extradim:], padding="VALID", data_format=data_format.replace("W", "HW")), [extradim]) elif self._rank == 2 and self.channel_separable: temp = nn.depthwise_conv2d_native_backprop_input( temp_shape, kernel, outputs, strides=self._pad_strides(self.strides_up), padding="VALID", data_format=data_format) elif self._rank == 2 and not self.channel_separable: temp = nn.conv2d_transpose(outputs, kernel, temp_shape, strides=self._pad_strides( self.strides_up), padding="VALID", data_format=data_format) elif self._rank == 3 and not self.channel_separable: temp = nn.conv3d_transpose(outputs, kernel, temp_shape, strides=self._pad_strides( self.strides_up), padding="VALID", data_format=data_format) else: assert False # Should never reach this. # Perform crop. slices = [slice(None)] * (self._rank + 2) if self.padding == "valid": # Take `kernel_support - 1` samples away from both sides. This leaves # just samples computed without padding. for i, a in enumerate(spatial_axes): slices[a] = slice( self.kernel_support[i] - 1, None if self.kernel_support[i] == 1 else 1 - self.kernel_support[i]) else: # Take `kernel_support // 2` plus the padding away from beginning, and # crop end to input length multiplied by upsampling factor. for i, a in enumerate(spatial_axes): offset = padding[a][0] * self.strides_up[i] offset += self.kernel_support[i] // 2 length = get_length(input_shape[a], self.strides_up[i], offset + 1) slices[a] = slice(offset, length) outputs = temp[slices] else: raise NotImplementedError( "The provided combination of SignalConv arguments is not currently " "implemented (kernel_support={}, corr={}, strides_down={}, " "strides_up={}, channel_separable={}, filters={}). " "Try using odd-length kernels or turning off separability?". format(self.kernel_support, self.corr, self.strides_down, self.strides_up, self.channel_separable, self.filters)) # Now, add bias if requested. if self.bias is not None: if self.data_format == "channels_first": # As of Mar 2017, direct addition is significantly slower than # bias_add when computing gradients. if self._rank == 1: # nn.bias_add does not accept a 1D input tensor. outputs = array_ops.expand_dims(outputs, 2) outputs = nn.bias_add(outputs, self.bias, data_format="NCHW") outputs = array_ops.squeeze(outputs, [2]) elif self._rank == 2: outputs = nn.bias_add(outputs, self.bias, data_format="NCHW") elif self._rank >= 3: shape = array_ops.shape(outputs) outputs = array_ops.reshape(outputs, shape[:3] + [-1]) outputs = nn.bias_add(outputs, self.bias, data_format="NCHW") outputs = array_ops.reshape(outputs, shape) else: outputs = nn.bias_add(outputs, self.bias) # Finally, pass through activation function if requested. if self.activation is not None: outputs = self.activation(outputs) # pylint:disable=not-callable # Aid shape inference, for some reason shape info is not always available. if not context.executing_eagerly(): outputs.set_shape(self.compute_output_shape(inputs.shape)) return outputs
def convs(a, b, w1, w2): a = nn.conv2d(a, w1, 1, padding='VALID') b = nn.conv2d_transpose(b, w2, [2, 32, 32, 4], 1) return a, b