def _convert_conv2d_transpose(converter: KerasConverter, k_op: "keras.layers.Conv2DTranspose"): x = converter.get_variable(converter.get_input_tensor(k_op)[0]) check_data_format(x, k_op.data_format) w = converter.convert_to_constant_variable( k_op.kernel, Order([Axis.KH, Axis.KW, Axis.N, Axis.C])) if tuple(k_op.dilation_rate) != (1, 1): raise NotImplementedError( "[KerasConverter] keras.layers.Convolution2DTranspose with large dilation_rate is not supported" ) padding = (parse_padding(k_op.padding, k_op.kernel_size[0], k_op.dilation_rate[0]), parse_padding(k_op.padding, k_op.kernel_size[1], k_op.dilation_rate[1])) if any(p[0] != p[1] for p in padding): pad_col2im = tuple(p[0] if p[0] == p[1] else 0 for p in padding) pad_extra = tuple((0, 0) if p[0] == p[1] else p for p in padding) y, = Deconvolution2D(None, ksize=k_op.kernel_size, stride=k_op.strides, padding=pad_col2im)(x, w) if k_op.data_format == "channels_first": y = y[:, :, pad_extra[0][0]:-pad_extra[0][1], pad_extra[1][0]:-pad_extra[1][1]] elif k_op.data_format == "channels_last": y = y[:, pad_extra[0][0]:-pad_extra[0][1], pad_extra[1][0]:-pad_extra[1][1], :] else: raise NotImplementedError( f"Unknown data format: {k_op.data_format}") else: y, = Deconvolution2D(None, ksize=k_op.kernel_size, stride=k_op.strides, padding=tuple(p[0] for p in padding))(x, w) if k_op.use_bias: b = converter.convert_to_constant_variable(k_op.bias, OrderC) y = y + b y = do_activation(k_op.activation, y) converter.set_variable(converter.get_output_tensor(k_op)[0], y)
def _convert_conv2d_transpose(converter: KerasConverter, k_op: "keras.layers.Conv2DTranspose"): x = converter.get_variable(converter.get_input_tensor(k_op)[0]) check_data_format(x, k_op.data_format) w = converter.convert_to_constant_variable( k_op.kernel, Order([Axis.KH, Axis.KW, Axis.N, Axis.C])) ksize = tuple(k_op.kernel_size) stride = tuple(k_op.strides) dilation_rate = tuple(k_op.dilation_rate) if dilation_rate != (1, 1): raise NotImplementedError( "[KerasConverter] keras.layers.Convolution2DTranspose with large dilation_rate is not supported" ) padding = (parse_padding(k_op.padding, ksize[0], dilation_rate[0]), parse_padding(k_op.padding, ksize[1], dilation_rate[1])) y, = Deconvolution2D(None, ksize=ksize, stride=stride, padding=padding)(x, w) if k_op.use_bias: b = converter.convert_to_constant_variable(k_op.bias, OrderC) y = y + b y = do_activation(k_op.activation, y) converter.set_variable(converter.get_output_tensor(k_op)[0], y)
def conv2_d_backprop_input_handler(converter: TensorFlowConverter, tf_op: "tf.Operation"): input_sizes = converter.get_variable(tf_op.inputs[0]) # input_sizes is not needed assert input_sizes.size == 4 and isinstance(input_sizes, ConstantVariable) x_shape = input_sizes.data.flatten().astype(int).tolist() # type: List[int] w = converter.get_variable(tf_op.inputs[1]) # HWNC gy = converter.get_variable(tf_op.inputs[2]) # NHWC assert tf_op.get_attr("data_format") == b"NHWC" w.order.unify(Order([Axis.KH, Axis.KW, Axis.N, Axis.C])) gy.order.unify(OrderNHWC) ksize_hw = (w.shape_dict[Axis.KH], w.shape_dict[Axis.KW]) stride_nhwc = tf_op.get_attr("strides") # type: List[int] assert stride_nhwc[0] == 1 assert stride_nhwc[3] == 1 stride_hw = stride_nhwc[1:3] padding_name = tf_op.get_attr("padding") # type: str if padding_name == b"SAME": padding = (padding_same(x_shape[gy.order.axes_dict[Axis.H]], ksize_hw[0], stride_hw[0]), padding_same(x_shape[gy.order.axes_dict[Axis.W]], ksize_hw[1], stride_hw[1])) elif padding_name == b"VALID": padding = (0, 0) else: raise NotImplementedError(f"[TensorFlowConverter] Conv2D: padding '{padding_name}' is not supported yet.") x, = Deconvolution2D(None, ksize=ksize_hw, stride=stride_hw, padding=padding)(gy, w) converter.set_variable(tf_op.outputs[0], x)
def _convert_conv2d_transpose(converter: KerasConverter, k_op: "keras.layers.Conv2DTranspose"): x = converter.get_variable(converter.get_input_tensor(k_op)[0]) if k_op.data_format == "channels_first": assert x.order == OrderNCHW elif k_op.data_format == "channels_last": assert x.order == OrderNHWC else: raise ValueError( f"[KerasConverter] Unknown data format is detected: {k_op.data_format}" ) w = converter.convert_to_constant_variable(k_op.kernel, OrderHWNC) ksize = tuple(k_op.kernel_size) stride = tuple(k_op.strides) if k_op.padding == "valid": padding = (0, 0) elif k_op.padding == "same": # @see https://github.com/tensorflow/tensorflow/blob/e5cf6f0c13b6053e4c58af6a951b204fde263172/tensorflow/python/ops/nn_ops.py#L507-L519 pad_extra_shape = [k - 1 for k in ksize] if any(p % 2 != 0 for p in pad_extra_shape): raise NotImplementedError( f"[KerasConverter] Currently WebDNN doesn't supports different size padding: " f" (pad_extra_shape)=f{pad_extra_shape}") padding = tuple(p // 2 for p in pad_extra_shape) w = converter.convert_to_constant_variable(k_op.kernel, OrderHWNC) ksize = tuple(k_op.kernel_size) stride = tuple(k_op.strides) if k_op.padding == "valid": padding = (0, 0) elif k_op.padding == "same": padding = (ksize[0] // 2, ksize[1] // 2) else: raise ValueError(f"[KerasConverter] Unknown padding: {k_op.padding}") y, = Deconvolution2D(None, ksize=ksize, stride=stride, padding=padding)(x, w) if k_op.use_bias: b = converter.convert_to_constant_variable(k_op.bias, OrderC) y = y + b y = do_activation(k_op.activation, y) converter.set_variable(converter.get_output_tensor(k_op)[0], y)
def main(k, s, p, n, h1, w1, c1, c2, expected_shape_dict: AxisKeyDict[int]): op = Deconvolution2D(None, ksize=k, stride=s, padding=p) x = Variable((n, h1, w1, c1), Order([Axis.N, Axis.H, Axis.W, Axis.C])) w = Variable((c1, op.ksize[0], op.ksize[1], c2), Order([Axis.C, Axis.KH, Axis.KW, Axis.N])) y, = op(x, w) for axis in y.order.axes: assert y.shape_dict[axis] == expected_shape_dict[axis]
def main(k, s, p, n, h1, w1, c1, c2, expected_shape_dict: Dict[Axis, int]): orders = [OrderNHWC, OrderHWNC, OrderHWCN, OrderNCHW, OrderCNHW, OrderCHWN] for order_x, order_w in itertools.product(orders, orders): op = Deconvolution2D(None, ksize=k, stride=s, padding=p) x = Variable((n, h1, w1, c1), OrderNHWC) x.change_order(order_x) w = Variable((c1, op.ksize[0], op.ksize[1], c2), OrderCHWN) w.change_order(order_w) y, = op(x, w) for axis in y.order.axes: assert y.shape_dict[axis] == expected_shape_dict[axis]
def _convert_conv2d_transpose(converter: KerasConverter, k_op: "keras.layers.Conv2DTranspose"): x = converter.get_variable(converter.get_input_tensor(k_op)[0]) if k_op.data_format == "channels_first": assert x.order == OrderNCHW elif k_op.data_format == "channels_last": assert x.order == OrderNHWC else: raise ValueError( f"[KerasConverter] Unknown data format is detected: {k_op.data_format}" ) w = converter.convert_to_constant_variable(k_op.kernel, OrderHWNC) ksize = tuple(k_op.kernel_size) stride = tuple(k_op.strides) if k_op.padding == "valid": padding = (0, 0) elif k_op.padding == "same": padding = (ksize[0] // 2, ksize[1] // 2) w = converter.convert_to_constant_variable(k_op.kernel, OrderHWNC) ksize = tuple(k_op.kernel_size) stride = tuple(k_op.strides) if k_op.padding == "valid": padding = (0, 0) elif k_op.padding == "same": padding = (ksize[0] // 2, ksize[1] // 2) else: raise ValueError(f"[KerasConverter] Unknown padding: {k_op.padding}") y, = Deconvolution2D(None, ksize=ksize, stride=stride, padding=padding)(x, w) if k_op.use_bias: b = converter.convert_to_constant_variable(k_op.bias, OrderC) y = y + b y = do_activation(k_op.activation, y) converter.set_variable(converter.get_output_tensor(k_op)[0], y)
def __call__(self, inputs: List[Variable]) -> Tuple[Variable]: w = inputs[1] w_shape_dict = w.shape_dict conv_opr = Deconvolution2D(generate_unique_name(self.cfunc.label), ksize=(w_shape_dict[Axis.H], w_shape_dict[Axis.W]), stride=(self.cfunc.sy, self.cfunc.sx), padding=(self.cfunc.ph, self.cfunc.pw)) opr_out, = conv_opr(inputs[0], inputs[1]) opr_out.change_order(OrderNCHW) if len(inputs) == 3: # biasあり bias_opr = AxiswiseBias(generate_unique_name(self.cfunc.label), axis=Axis.C) self.hidden_vars.append(opr_out) opr_out, = bias_opr(opr_out, inputs[2]) return opr_out,
def _convert_deconvolution_2d(converter: ChainerConverter, c_op: "chainer.functions.connection.deconvolution_2d.Deconvolution2DFunction"): x = converter.get_variable(c_op.inputs[0]) w = converter.get_variable(c_op.inputs[1]) deconv_opr = Deconvolution2D(None, ksize=(w.shape_dict[Axis.H], w.shape_dict[Axis.W]), stride=(c_op.sy, c_op.sx), padding=(c_op.ph, c_op.pw)) y, = deconv_opr(x, w) if len(c_op.inputs) == 3: # with bias bias = converter.get_variable(c_op.inputs[2]) y = y + bias converter.set_variable(c_op.outputs[0](), y)
def _convert_deconvolution_2d( converter: ChainerConverter, c_op: "chainer.functions.connection.deconvolution_2d.Deconvolution2DFunction"): x = converter.get_variable(c_op.inputs[0]) w = converter.get_variable(c_op.inputs[1]) x.order.unify(OrderNCHW) w.order.unify(Order([Axis.C, Axis.N, Axis.KH, Axis.KW])) deconv_opr = Deconvolution2D(None, ksize=(w.shape_dict[Axis.KH], w.shape_dict[Axis.KW]), stride=(c_op.sy, c_op.sx), padding=(c_op.ph, c_op.pw)) y, = deconv_opr(x, w) if len(c_op.inputs) == 3: # with bias b = converter.get_variable(c_op.inputs[2]) b.order.unify(OrderC) y = y + b converter.set_variable(c_op.outputs[0](), y)
def conv2_d_backprop_input_handler(converter: TensorFlowConverter, tf_op: "tf.Operation"): input_sizes = converter.get_variable(tf_op.inputs[0]) if not isinstance(input_sizes, ConstantVariable): raise NotImplementedError( "[TensorFlowConverter] Conv2DBackpropInput with dynamic shape of output (input of convolution) variable is not supported." ) input_sizes = tuple(input_sizes.data.astype(np.int32).tolist()) w = converter.get_variable(tf_op.inputs[1]) # HWNC w.order.unify(Order([Axis.KH, Axis.KW, Axis.N, Axis.C])) gy = converter.get_variable(tf_op.inputs[2]) # NHWC data_format = tf_op.get_attr("data_format") check_data_format(gy, data_format) input_size = np.array([ input_sizes[gy.order.axes_dict[Axis.H]], input_sizes[gy.order.axes_dict[Axis.W]] ]) ksize = np.array([w.shape_dict[Axis.KH], w.shape_dict[Axis.KW]]) stride = np.array(tf_op.get_attr("strides")) assert stride[gy.order.axes_dict[Axis.N]] == 1 assert stride[gy.order.axes_dict[Axis.C]] == 1 stride = stride[[gy.order.axes_dict[Axis.H], gy.order.axes_dict[Axis.W]]] padding = np.array([ parse_padding(tf_op.get_attr("padding"), ksize[0], 1), parse_padding(tf_op.get_attr("padding"), ksize[1], 1) ]) x, = Deconvolution2D(None, ksize=ksize.tolist(), stride=stride.tolist(), padding=0)(gy, w) # Actual padding size is depend on 2 factors # 1. padding mode # 2. extra apron size (= (input size of convolution) - (size of the tensor expanded by deconvolution)) expanded_size = np.array([x.shape_dict[Axis.H], x.shape_dict[Axis.W]]) apron_size = input_size - (expanded_size - padding.sum(axis=1)) # cancel padding by apron if possible for i in (0, 1): if padding[i, 0] > apron_size[i]: padding[i, 0] -= apron_size[i] apron_size[i] = 0 else: apron_size[i] -= padding[i, 0] padding[i, 0] = 0 if padding[i, 1] > apron_size[i]: padding[i, 1] -= apron_size[i] apron_size[i] = 0 else: apron_size[i] -= padding[i, 1] padding[i, 1] = 0 # append extra apron for i, axis in enumerate((Axis.H, Axis.W)): if apron_size[i] == 0: continue data = np.zeros([ apron_size[i] if a == axis else x.shape_dict[a] for a in x.order.axes ]) x, = Concat(None, axis=axis)(x, ConstantVariable(data, x.order)) # crop without padding padding = padding.tolist() # type: List[List[int]] slice_h = slice(None) if padding[0] == [0, 0] else slice( padding[0][0], -padding[0][1]) slice_w = slice(None) if padding[1] == [0, 0] else slice( padding[1][0], -padding[1][1]) if data_format == b"NCHW": x = x[:, :, slice_h, slice_w] elif data_format == b"NHWC": x = x[:, slice_h, slice_w, :] else: raise NotImplementedError(f"Unknown data format: {data_format}") converter.set_variable(tf_op.outputs[0], x)