def convert_onnx_chainer_convolutionnd(onnx_graph: 'ONNXGraph', node: 'nodes.NodeCall'):
    chainer_inst = node.func.owner.inst  # type: chainer.links.ConvolutionND

    nd = chainer_inst.W.ndim - 2
    ksize = oc.size_nd(chainer_inst.ksize, nd)
    stride = oc.size_nd(chainer_inst.stride, nd)
    ps = oc.size_nd(chainer_inst.pad, nd)
    pads = ps + ps

    x = oc.ONNXValue(onnx_graph, node.args.get_value('x'))
    o = oc.ONNXValue(onnx_graph, node.outputs[0])
    w = oc.ONNXValue(onnx_graph, chainer_inst.W)
    b = None

    if chainer_inst.b is not None:
        b = oc.ONNXValue(onnx_graph, chainer_inst.b)

    onnx_graph.add_node(
        'Conv',
        [x, w] + ([] if b is None else [b]),
        [o],
        str(node.lineprop),
        kernel_shape=ksize,
        pads=pads,
        strides=stride)
Beispiel #2
0
def convert_argminmax(onnx_graph, node, parser, tensor, operator, dtype):
    axis = parser.get('axis')

    if axis is None:
        (reshaped, ) = onnx_graph.add_node('Reshape', [
            parser.get(tensor),
            oc.ONNXValue(onnx_graph, np.array([-1], dtype=np.int64),
                         [node, '/Minus1'])
        ], [None], str(node.lineprop))

        (minmax, ) = onnx_graph.add_node(operator, [reshaped], [None],
                                         str(node.lineprop),
                                         axis=0)

        (squeesed, ) = onnx_graph.add_node('Squeeze', [minmax], [None],
                                           str(node.lineprop))

        onnx_graph.add_node("Cast", [squeesed],
                            node.outputs,
                            str(node.lineprop),
                            to=get_onnx_dtype(dtype))

    else:
        (minmax, ) = onnx_graph.add_node(operator, [parser.get(tensor)],
                                         [None],
                                         str(node.lineprop),
                                         keepdims=False,
                                         axis=axis)

        onnx_graph.add_node("Cast", [minmax],
                            node.outputs,
                            str(node.lineprop),
                            to=get_onnx_dtype(dtype))
def convert_broadcast_to(onnx_graph, node):
    node_ = node

    shape = oc.ONNXValue(onnx_graph, node_.args.keywords['shape'])
    onnx_graph.add_node(
        "Expand",
        [node_.inputs[0], shape.create_tensor(node.lineprop)], node_.outputs,
        str(node.lineprop))
    return
    def __call__(self, onnx_graph, node):
        parser = self.parse_args(onnx_graph, node)

        if onnx.defs.onnx_opset_version() >= 11:
            x_min = oc.ONNXValue(onnx_graph, np.array(parser.get('x_min')), [node, '/Min'], is_constant = True)
            x_max = oc.ONNXValue(onnx_graph, np.array(parser.get('x_max')), [node, '/Max'], is_constant = True)
            onnx_graph.add_node(
                "Clip",
                [parser.get('x'), x_min, x_max],
                node.outputs,
                str(node.lineprop))
        else:
            onnx_graph.add_node(
                "Clip",
                [parser.get('x')],
                node.outputs,
                str(node.lineprop),
                min=parser.get('x_min'),
                max=parser.get('x_max'))
def convert_concat(onnx_graph, node):
    xs = oc.ONNXValue(onnx_graph, node.args.keywords['xs'])
    axis = oc.try_get_attribute(node.attribute_args.keywords['axis'])

    onnx_graph.add_node(
        "ChainerSequenceConcat",
        [xs.create_sequence()],
        node.outputs,
        str(node.lineprop),
        axis=axis,
    )
def convert_dropout(onnx_graph, node):
    x = oc.ONNXValue(onnx_graph, node.args.keywords['x'])
    ratio = oc.try_get_attribute(node.attribute_args.keywords['ratio'])

    onnx_graph.add_node(
        "Dropout",
        [x],
        node.outputs,
        str(node.lineprop),
        ratio=ratio,
    )
def convert_roi_average_align_2d(onnx_graph, node):
    x = oc.ONNXValue(onnx_graph, node.args.keywords['x'])
    rois = oc.ONNXValue(onnx_graph, node.args.keywords['rois'])
    roi_indices = oc.ONNXValue(onnx_graph, node.args.keywords['roi_indices'])
    outsize = oc.ONNXValue(onnx_graph, node.args.keywords['outsize'])
    spatial_scale = oc.ONNXValue(onnx_graph,
                                 node.args.keywords['spatial_scale'])
    sampling_ratio = oc.ONNXValue(onnx_graph,
                                  node.args.keywords['sampling_ratio'])

    def _pair(x):
        if isinstance(x, collections.Iterable):
            return x
        return (x, x)

    onnx_graph.add_node(
        "ChainerROIAverageAlign2D", [
            x.create_tensor(node.lineprop),
            rois.create_tensor(node.lineprop),
            roi_indices.create_tensor(node.lineprop)
        ],
        node.outputs,
        str(node.lineprop),
        output_shape=_pair(oc.try_get_attribute(outsize.value)),
        spatial_scale=oc.try_get_attribute(spatial_scale.value),
        sampling_ratio=_pair(oc.try_get_attribute(sampling_ratio.value)))
    return
def convert_split_axis(onnx_graph, node):
    force_tuple = oc.try_get_attribute(
        node.attribute_args.keywords['force_tuple'])
    assert (force_tuple is True)  # TODO(hamaji): Not supported yet.

    onnx_graph.add_node("ChainerSequenceSplitAxis", [
        node.inputs[0],
        oc.ONNXValue(onnx_graph,
                     node.args.keywords['indices_or_sections']).create_tensor(
                         node.lineprop)
    ],
                        node.outputs,
                        str(node.lineprop),
                        axis=oc.try_get_attribute(
                            node.attribute_args.keywords['axis']))
Beispiel #9
0
    def __call__(self, onnx_graph, node):
        parser = self.parse_args(onnx_graph, node)

        kwargs = {}
        assert(parser.get('stride') is None) # TODO(hamaji): Not supported yet.
        assert(parser.get('pad') == 0) # TODO(hamaji): Not supported yet.
        assert(parser.get('outsize') is None) # TODO(hamaji): Not supported yet.
        assert(parser.get('cover_all') is False) # TODO(hamaji): Not supported yet.

        scales = np.array([1, 1] + list(_pair(parser.get('ksize'))), dtype=np.float32)
        scales_ = oc.ONNXValue(onnx_graph, scales, [node, '/Scale'], is_constant = True)
        onnx_graph.add_node(
            "Upsample",
            [parser.get('x'), scales_],
            node.outputs,
            name=str(node.lineprop),
            **kwargs)
def convert_onnx_chainer_EmbedID(onnx_graph: 'ONNXGraph',
                                 node: 'nodes.NodeCall'):
    chainer_inst = node.func.owner.inst  # type: chainer.links.EmbedID

    n_vocab = chainer_inst.W.shape[0]
    n_out = chainer_inst.W.shape[1]

    w = oc.ONNXValue(onnx_graph, chainer_inst.W)

    parser = oc.NodeParse()
    parser.add_def('x', oc.ParseType.In)
    parser.parse(onnx_graph, node)

    x = parser.get('x').create_tensor(node.lineprop)

    onnx_graph.add_node('Gather', [w, x], [node.outputs[0]],
                        str(node.lineprop))
def convert_unpooling_2d(onnx_graph, node: 'nodes.NodeCall'):
    ksize = oc.try_get_attribute(node.attribute_args.keywords['ksize'])
    stride = oc.try_get_attribute(node.attribute_args.keywords['stride'])
    pad = oc.try_get_attribute(node.attribute_args.keywords['pad'])
    outsize = oc.try_get_attribute(node.attribute_args.keywords['outsize'])
    cover_all = oc.try_get_attribute(node.attribute_args.keywords['cover_all'])

    assert (stride is None)  # TODO(hamaji): Not supported yet.
    assert (pad == 0)  # TODO(hamaji): Not supported yet.
    assert (outsize is None)  # TODO(hamaji): Not supported yet.
    assert (cover_all is False)  # TODO(hamaji): Not supported yet.

    scales = np.array([1, 1] + list(_pair(ksize)), dtype=np.float32)
    scales_ = oc.ONNXValue(onnx_graph,
                           scales, [node, '/Scale'],
                           is_constant=True)
    onnx_graph.add_node("Upsample", [node.inputs[0], scales_],
                        [node.outputs[0]],
                        name=str(node.lineprop))
def convert_onnx_chainer_batch_normalization(onnx_graph: 'ONNXGraph',
                                             node: 'nodes.NodeCall'):
    chainer_inst = node.func.owner.inst  # type: chainer.links.BatchNormalization

    assert (chainer_inst.axis is None)  # not support yet

    x = oc.ONNXValue(onnx_graph, node.args.get_value('x'))
    o = oc.ONNXValue(onnx_graph, node.outputs[0])

    gamma = oc.ONNXValue(onnx_graph, chainer_inst.gamma)
    beta = oc.ONNXValue(onnx_graph, chainer_inst.beta)
    avg_mean = oc.ONNXValue(onnx_graph, chainer_inst.avg_mean, [node, 'mean'])
    avg_var = oc.ONNXValue(onnx_graph, chainer_inst.avg_var, [node, 'var'])
    eps = chainer_inst.eps
    momentum = chainer_inst.decay

    onnx_graph.add_node('BatchNormalization',
                        [x, gamma, beta, avg_mean, avg_var], [o],
                        str(node.lineprop),
                        epsilon=eps,
                        momentum=momentum)
def convert_reshape(onnx_graph, node):
    onnx_graph.add_node("Reshape", [
        node.inputs[0],
        oc.ONNXValue(onnx_graph, node.inputs[1]).create_tensor(node.lineprop)
    ], node.outputs, str(node.lineprop))
def convert_onnx_chainer_NStepBiLSTM(onnx_graph: 'ONNXGraph',
                                     node: 'nodes.NodeCall'):
    chainer_inst = node.func.owner.inst  # type: chainer.links.NStepBiLSTM

    hd = chainer_inst.children().__next__()

    if not (hd.w0 is None):
        n_in = hd.w0.shape[1]
    else:
        n_in = None

    out_size = chainer_inst.out_size
    n_layers = chainer_inst.n_layers
    dropout = chainer_inst.dropout

    self_ws = []
    self_bs = []
    for i in range(n_layers * 2):
        ws_ = []
        bs_ = []
        for j in range(8):
            ws_.append(oc.ONNXValue(onnx_graph, chainer_inst.ws[i][j]))
            bs_.append(oc.ONNXValue(onnx_graph, chainer_inst.bs[i][j]))
        self_ws.append(ws_)
        self_bs.append(bs_)

    parser = oc.NodeParse()
    parser.add_def('hx', oc.ParseType.Att, None)
    parser.add_def('cx', oc.ParseType.Att, None)
    parser.add_def('xs', oc.ParseType.In)
    parser.parse(onnx_graph, node)

    xs = parser.get('xs').create_sequence()

    # disolve nstep into 1step

    (ilens, ) = onnx_graph.add_node('ChainerSequenceLengths', [xs], [None],
                                    str(node.lineprop))

    (tilens, ) = onnx_graph.add_node('ChainerSequenceStack', [ilens], [None],
                                     str(node.lineprop))

    v = xs

    def lstm_param(ps):
        (p, ) = onnx_graph.add_node("Concat", [v_ for v_ in ps], [None],
                                    str(node.lineprop),
                                    axis=0)

        return onnx_graph.add_node("Unsqueeze", [p], [None],
                                   str(node.lineprop),
                                   axes=[0])[0]

    wst = []
    rst = []
    bst = []
    for w in self_ws:
        wst.append(lstm_param([w[0], w[3], w[1], w[2]]))
        rst.append(lstm_param([w[4], w[7], w[5], w[6]]))

    for b in self_bs:
        bst.append(lstm_param([b[0], b[3], b[1], b[2], b[4], b[7], b[5],
                               b[6]]))

    ws = []
    rs = []
    bs = []
    for i in range(n_layers):
        for s, t in [(ws, wst), (rs, rst), (bs, bst)]:
            (temp, ) = onnx_graph.add_node("Concat", [t[i * 2], t[i * 2 + 1]],
                                           [None],
                                           str(node.lineprop),
                                           axis=0)

            s.append(temp)

    hs = []
    cs = []

    (v, ) = onnx_graph.add_node("ChainerSequencePad", [v], [None],
                                str(node.lineprop))

    (v, ) = onnx_graph.add_node(
        "Transpose",
        [v],
        [None],
        str(node.lineprop),
        perm=(1, 0, 2),
    )

    (sequence_length, ) = onnx_graph.add_node(
        "ChainerGenericLen",
        [v],
        [None],
        str(node.lineprop),
    )

    minus1 = oc.ONNXValue(onnx_graph, np.array(-1), [node, '/Minus1'])
    out_size2 = oc.ONNXValue(onnx_graph, np.array(out_size * 2),
                             [node, '/Outputs'])

    (sout_shape, ) = onnx_graph.add_node(
        "ChainerSequenceCreate",
        [sequence_length, minus1, out_size2],
        [None],
        str(node.lineprop),
    )
    sout_shape.onnx_type = oc.ONNXValueType.Sequence

    out_shape = sout_shape.create_tensor(node.lineprop)

    for i in range(n_layers):
        h = oc.ONNXValue(onnx_graph, np.float32, [node, '/h'])
        c = oc.ONNXValue(onnx_graph, np.float32, [node, '/c'])
        ys = oc.ONNXValue(onnx_graph, np.float32, [node, '/ys'])

        onnx_graph.add_node(
            "LSTM",
            [v, ws[i], rs[i], bs[i], tilens],
            [ys, h, c],
            str(node.lineprop),
            direction='bidirectional',
            hidden_size=out_size,
            # sequence_lens=[ilens.name]
        )

        hs.append(h)
        cs.append(c)

        # ys :: [seqlen x 2 x batchsize x hiddensize]
        (v, ) = onnx_graph.add_node("Transpose", [ys], [None],
                                    str(node.lineprop),
                                    perm=(0, 2, 1, 3))
        (v, ) = onnx_graph.add_node("Reshape", [v, out_shape], [None],
                                    str(node.lineprop))

    (v, ) = onnx_graph.add_node("Transpose", [v.name], [None],
                                str(node.lineprop),
                                perm=(1, 0, 2))

    (v, ) = onnx_graph.add_node("ChainerSequenceUnpad", [v.name, ilens.name],
                                [None], str(node.lineprop))
    v.onnx_type = oc.ONNXValueType.Sequence

    v = v.create_sequence()

    onnx_graph.add_node(
        "Concat",
        hs,
        [node.outputs[0]],
        str(node.lineprop),
        axis=0,
    )

    onnx_graph.add_node(
        "Concat",
        cs,
        [node.outputs[1]],
        str(node.lineprop),
        axis=0,
    )

    onnx_graph.add_node('Identity', [v], [node.outputs[2]], str(node.lineprop))
def convert_onnx_chainer_linear(onnx_graph: 'ONNXGraph',
                                node: 'nodes.NodeCall'):
    chainer_inst = node.func.owner.inst  # type: chainer.links.Linear
    onnx_name = oc.node2onnx_parameter[node].onnx_name

    x = oc.ONNXValue(onnx_graph, node.args.get_value('x'))
    axes = oc.try_get_attribute(node.args.get_value('n_batch_axes'), node)
    o = oc.ONNXValue(onnx_graph, node.outputs[0])

    if chainer_inst.W.data is None:
        print("W is unknown. Please infer this model.")

    w = oc.ONNXValue(onnx_graph, chainer_inst.W)

    if axes != 1:
        inputs = [x, w]

        if chainer_inst.b is not None:
            b = oc.ONNXValue(onnx_graph, chainer_inst.b)
            inputs.append(b)

        onnx_graph.add_node('ChainerLinear',
                            inputs, [o],
                            str(node.lineprop),
                            n_batch_axes=axes)
        return

    (x_shape, ) = onnx_graph.add_node('Shape', [x], [None], str(node.lineprop))

    (batch_size_1, ) = onnx_graph.add_node('Gather', [
        x_shape,
        oc.ONNXValue(onnx_graph, np.array(0, dtype=np.int64),
                     [onnx_name, '/Zero'])
    ], [None], str(node.lineprop))

    (batch_size_2, ) = onnx_graph.add_node('Unsqueeze', [batch_size_1], [None],
                                           str(node.lineprop),
                                           axes=[0])

    (mat_shape, ) = onnx_graph.add_node('Concat', [
        batch_size_2,
        oc.ONNXValue(onnx_graph, np.array([-1], dtype=np.int64),
                     [onnx_name, '/Minus1'])
    ], [None],
                                        str(node.lineprop),
                                        axis=0)

    (x_reshape, ) = onnx_graph.add_node('Reshape', [x, mat_shape], [None],
                                        str(node.lineprop))

    if chainer_inst.b is not None:
        b = oc.ONNXValue(onnx_graph, chainer_inst.b)

        onnx_graph.add_node('Gemm', [x_reshape, w, b], [o],
                            str(node.lineprop),
                            transA=0,
                            transB=1)
    else:
        temp = oc.ONNXValue(onnx_graph, np.float32, [onnx_name, '/Temp'])

        onnx_graph.add_node('Transpose', [w], [temp],
                            str(node.lineprop),
                            perm=[1, 0])

        onnx_graph.add_node('MatMul', [x_reshape, temp], [o],
                            str(node.lineprop))
def convert_onnx_chainer_NStepLSTM(onnx_graph: 'ONNXGraph',
                                   node: 'nodes.NodeCall'):
    chainer_inst = node.func.owner.inst  # type: chainer.links.NStepLSTM

    hd = chainer_inst.children().__next__()

    if not (hd.w0 is None):
        n_in = hd.w0.shape[1]
    else:
        n_in = None

    out_size = chainer_inst.out_size
    n_layers = chainer_inst.n_layers
    dropout = chainer_inst.dropout

    self_ws = []
    self_bs = []
    for i in range(n_layers):
        ws_ = []
        bs_ = []
        for j in range(8):
            ws_.append(oc.ONNXValue(onnx_graph, chainer_inst.ws[i][j]))
            bs_.append(oc.ONNXValue(onnx_graph, chainer_inst.bs[i][j]))
        self_ws.append(ws_)
        self_bs.append(bs_)

    parser = oc.NodeParse()
    parser.add_def('hx', oc.ParseType.Att, None)
    parser.add_def('cx', oc.ParseType.Att, None)
    parser.add_def('xs', oc.ParseType.In)
    parser.parse(onnx_graph, node)

    xs = parser.get('xs').create_sequence()

    # disolve nstep into 1step

    (ilens, ) = onnx_graph.add_node('ChainerSequenceLengths', [xs], [None],
                                    str(node.lineprop))

    (tilens, ) = onnx_graph.add_node('ChainerSequenceStack', [ilens], [None],
                                     str(node.lineprop))

    (v, ) = onnx_graph.add_node("ChainerSequencePad", [xs], [None],
                                str(node.lineprop))

    (v, ) = onnx_graph.add_node(
        "Transpose",
        [v],
        [None],
        str(node.lineprop),
        perm=(1, 0, 2),
    )

    def lstm_param(ps):
        (p, ) = onnx_graph.add_node("Concat", [v_ for v_ in ps], [None],
                                    str(node.lineprop),
                                    axis=0)

        return onnx_graph.add_node("Unsqueeze", [p], [None],
                                   str(node.lineprop),
                                   axes=[0])[0]

    ws = []
    rs = []
    bs = []
    for w in self_ws:
        ws.append(lstm_param([w[0], w[3], w[1], w[2]]))
        rs.append(lstm_param([w[4], w[7], w[5], w[6]]))

    for b in self_bs:
        bs.append(lstm_param([b[0], b[3], b[1], b[2], b[4], b[7], b[5], b[6]]))

    hs = []
    cs = []
    for i in range(n_layers):
        h = oc.ONNXValue(onnx_graph, np.float32, [node, '/h'])
        c = oc.ONNXValue(onnx_graph, np.float32, [node, '/c'])
        ys = oc.ONNXValue(onnx_graph, np.float32, [node, '/ys'])

        onnx_graph.add_node(
            "LSTM",
            [v, ws[i], rs[i], bs[i], tilens],
            [ys, h, c],
            str(node.lineprop),
            direction='forward',
            hidden_size=out_size,
            # sequence_lens=[ilens.name]
        )

        hs.append(h)
        cs.append(c)
        (yys, ) = onnx_graph.add_node("Squeeze", [ys], [None],
                                      str(node.lineprop),
                                      axes=[1])

        v = yys

    onnx_graph.add_node(
        "Concat",
        hs,
        [node.outputs[0]],
        str(node.lineprop),
        axis=0,
    )

    onnx_graph.add_node(
        "Concat",
        cs,
        [node.outputs[1]],
        str(node.lineprop),
        axis=0,
    )

    (tv, ) = onnx_graph.add_node(
        "Transpose",
        [v],
        [None],
        str(node.lineprop),
        perm=(1, 0, 2),
    )
    v = tv

    onnx_graph.add_node(
        "ChainerSequenceUnpad",
        [v, ilens],
        [node.outputs[2]],
        str(node.lineprop),
    )