示例#1
0
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)
示例#2
0
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)
示例#3
0
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)
示例#4
0
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)
示例#5
0
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]
示例#6
0
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]
示例#7
0
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)
示例#8
0
    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,
示例#9
0
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)
示例#10
0
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)
示例#11
0
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)