def unpooling(input: Tensor, argmax: Tensor, output_shape: TensorShape, name='unpooling'): """ unpooling層 :param input: :param argmax: :param output_shape: :return: 次ノードへのTensor """ with tf.name_scope(name): # inputを直線に並べる input_stride = tf.reshape(input, [-1]) # argmaxを直線に並べる。1行1要素の2次元になる。 argmax_stride = tf.reshape(argmax, [-1, 1]) # outputの要素数 num_elem = output_shape.num_elements() # inputをargmaxに従い、num_elemの1行Tensorに再配置 output_stride = tf.scatter_nd(argmax_stride, input_stride, [num_elem]) output = tf.reshape(output_stride, output_shape) return output
def build(self, input_shape: tf.TensorShape): # Input Size B x Hi x Wi x C x 2 # Reorder to B x C x Hi x Wi x 2 self.reordered_input_shape = [input_shape[0], input_shape[3], input_shape[1], input_shape[2], input_shape[4]] presence_mask = tf.fill(self.reordered_input_shape[:-1], True) presence_indices = tf.where(presence_mask) self.presence_b = tf.expand_dims(presence_indices[:, 0], axis=-1) self.presence_chw = presence_indices[:, 1:] position_mask = tf.fill(self.reordered_input_shape, True) position_indices = tf.where(position_mask) self.position_b = tf.expand_dims(position_indices[:, 0], axis=-1) self.position_chwd = position_indices[:, 1:] # Size B x Hi x Wi x C x 2 self.input_size = tf.cast(input_shape.num_elements(), tf.int32) / 2 self.xy_offset = tf.repeat([[self.x_offset, self.y_offset]], repeats=[self.input_size], axis=0) self.presence_shape = [input_shape[0], self.length, self.width, self.num_channels, input_shape[1], input_shape[2]] self.presence_vals = tf.ones([self.input_size], dtype=tf.int32) self.position_shape = [input_shape[0], self.length, self.width, self.num_channels, input_shape[1], input_shape[2], 2]