SequenceMap#
SequenceMap - 17#
Version
name: SequenceMap (GitHub)
domain: main
since_version: 17
function: False
support_level: SupportType.COMMON
shape inference: True
This version of the operator has been available since version 17.
Summary
Applies a sub-graph to each sample in the input sequence(s).
Inputs can be either tensors or sequences, with the exception of the first input which must be a sequence. The length of the first input sequence will determine the number of samples in the outputs. Any other sequence inputs should have the same number of samples. The number of inputs and outputs, should match the one of the subgraph.
For each i-th element in the output, a sample will be extracted from the input sequence(s) at the i-th position and the sub-graph will be applied to it. The outputs will contain the outputs of the sub-graph for each sample, in the same order as in the input.
This operator assumes that processing each sample is independent and could executed in parallel or in any order. Users cannot expect any specific ordering in which each subgraph is computed.
Attributes
body (required): The graph to be run for each sample in the sequence(s). It should have as many inputs and outputs as inputs and outputs to the SequenceMap function.
Inputs
Between 1 and 2147483647 inputs.
input_sequence (heterogeneous) - S: Input sequence.
additional_inputs (variadic) - V: Additional inputs to the graph
Outputs
Between 1 and 2147483647 outputs.
out_sequence (variadic) - S: Output sequence(s)
Type Constraints
S in ( seq(tensor(bool)), seq(tensor(complex128)), seq(tensor(complex64)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)) ): Constrain input types to any sequence type.
V in ( seq(tensor(bool)), seq(tensor(complex128)), seq(tensor(complex64)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) ): Constrain to any tensor or sequence type.
Examples
_sequence_map_identity_1_sequence
import numpy as np
import onnx
body = onnx.helper.make_graph(
[onnx.helper.make_node("Identity", ["in0"], ["out0"])],
"seq_map_body",
[onnx.helper.make_tensor_value_info("in0", onnx.TensorProto.FLOAT, ["N"])],
[onnx.helper.make_tensor_value_info("out0", onnx.TensorProto.FLOAT, ["M"])],
)
node = onnx.helper.make_node(
"SequenceMap", inputs=["x"], outputs=["y"], body=body
)
x = [np.random.uniform(0.0, 1.0, 10).astype(np.float32) for _ in range(3)]
y = x
input_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
]
output_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
]
expect(
node,
inputs=[x],
outputs=[y],
input_type_protos=input_type_protos,
output_type_protos=output_type_protos,
name="test_sequence_map_identity_1_sequence",
)
_sequence_map_identity_2_sequences
import numpy as np
import onnx
body = onnx.helper.make_graph(
[
onnx.helper.make_node("Identity", ["in0"], ["out0"]),
onnx.helper.make_node("Identity", ["in1"], ["out1"]),
],
"seq_map_body",
[
onnx.helper.make_tensor_value_info(
"in0", onnx.TensorProto.FLOAT, ["N"]
),
onnx.helper.make_tensor_value_info(
"in1", onnx.TensorProto.FLOAT, ["M"]
),
],
[
onnx.helper.make_tensor_value_info(
"out0", onnx.TensorProto.FLOAT, ["N"]
),
onnx.helper.make_tensor_value_info(
"out1", onnx.TensorProto.FLOAT, ["M"]
),
],
)
node = onnx.helper.make_node(
"SequenceMap", inputs=["x0", "x1"], outputs=["y0", "y1"], body=body
)
x0 = [
np.random.uniform(0.0, 1.0, np.random.randint(1, 10)).astype(np.float32)
for _ in range(3)
]
x1 = [
np.random.uniform(0.0, 1.0, np.random.randint(1, 10)).astype(np.float32)
for _ in range(3)
]
y0 = x0
y1 = x1
input_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["M"])
),
]
output_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["M"])
),
]
expect(
node,
inputs=[x0, x1],
outputs=[y0, y1],
input_type_protos=input_type_protos,
output_type_protos=output_type_protos,
name="test_sequence_map_identity_2_sequences",
)
_sequence_map_identity_1_sequence_1_tensor
import numpy as np
import onnx
body = onnx.helper.make_graph(
[
onnx.helper.make_node("Identity", ["in0"], ["out0"]),
onnx.helper.make_node("Identity", ["in1"], ["out1"]),
],
"seq_map_body",
[
onnx.helper.make_tensor_value_info(
"in0", onnx.TensorProto.FLOAT, ["N"]
),
onnx.helper.make_tensor_value_info(
"in1", onnx.TensorProto.FLOAT, ["M"]
),
],
[
onnx.helper.make_tensor_value_info(
"out0", onnx.TensorProto.FLOAT, ["N"]
),
onnx.helper.make_tensor_value_info(
"out1", onnx.TensorProto.FLOAT, ["M"]
),
],
)
node = onnx.helper.make_node(
"SequenceMap", inputs=["x0", "x1"], outputs=["y0", "y1"], body=body
)
x0 = [
np.random.uniform(0.0, 1.0, np.random.randint(1, 10)).astype(np.float32)
for _ in range(3)
]
x1 = np.random.uniform(0.0, 1.0, np.random.randint(1, 10)).astype(np.float32)
y0 = x0
y1 = [x1 for _ in range(3)]
input_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["M"]),
]
output_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["M"])
),
]
expect(
node,
inputs=[x0, x1],
outputs=[y0, y1],
input_type_protos=input_type_protos,
output_type_protos=output_type_protos,
name="test_sequence_map_identity_1_sequence_1_tensor",
)
_sequence_map_add_2_sequences
import numpy as np
import onnx
body = onnx.helper.make_graph(
[onnx.helper.make_node("Add", ["in0", "in1"], ["out0"])],
"seq_map_body",
[
onnx.helper.make_tensor_value_info(
"in0", onnx.TensorProto.FLOAT, ["N"]
),
onnx.helper.make_tensor_value_info(
"in1", onnx.TensorProto.FLOAT, ["N"]
),
],
[onnx.helper.make_tensor_value_info("out0", onnx.TensorProto.FLOAT, ["N"])],
)
node = onnx.helper.make_node(
"SequenceMap", inputs=["x0", "x1"], outputs=["y0"], body=body
)
N = [np.random.randint(1, 10) for _ in range(3)]
x0 = [np.random.uniform(0.0, 1.0, N[k]).astype(np.float32) for k in range(3)]
x1 = [np.random.uniform(0.0, 1.0, N[k]).astype(np.float32) for k in range(3)]
y0 = [x0[k] + x1[k] for k in range(3)]
input_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
]
output_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
]
expect(
node,
inputs=[x0, x1],
outputs=[y0],
input_type_protos=input_type_protos,
output_type_protos=output_type_protos,
name="test_sequence_map_add_2_sequences",
)
_sequence_map_add_1_sequence_1_tensor
import numpy as np
import onnx
body = onnx.helper.make_graph(
[onnx.helper.make_node("Add", ["in0", "in1"], ["out0"])],
"seq_map_body",
[
onnx.helper.make_tensor_value_info(
"in0", onnx.TensorProto.FLOAT, ["N"]
),
onnx.helper.make_tensor_value_info(
"in1", onnx.TensorProto.FLOAT, ["N"]
),
],
[onnx.helper.make_tensor_value_info("out0", onnx.TensorProto.FLOAT, ["N"])],
)
node = onnx.helper.make_node(
"SequenceMap", inputs=["x0", "x1"], outputs=["y0"], body=body
)
x0 = [np.random.uniform(0.0, 1.0, 10).astype(np.float32) for k in range(3)]
x1 = np.random.uniform(0.0, 1.0, 10).astype(np.float32)
y0 = [x0[i] + x1 for i in range(3)]
input_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"]),
]
output_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.FLOAT, ["N"])
),
]
expect(
node,
inputs=[x0, x1],
outputs=[y0],
input_type_protos=input_type_protos,
output_type_protos=output_type_protos,
name="test_sequence_map_add_1_sequence_1_tensor",
)
_sequence_map_extract_shapes
import numpy as np
import onnx
body = onnx.helper.make_graph(
[onnx.helper.make_node("Shape", ["x"], ["shape"])],
"seq_map_body",
[
onnx.helper.make_tensor_value_info(
"x", onnx.TensorProto.FLOAT, ["H", "W", "C"]
)
],
[onnx.helper.make_tensor_value_info("shape", onnx.TensorProto.INT64, [3])],
)
node = onnx.helper.make_node(
"SequenceMap", inputs=["in_seq"], outputs=["shapes"], body=body
)
shapes = [
np.array([40, 30, 3], dtype=np.int64),
np.array([20, 10, 3], dtype=np.int64),
np.array([10, 5, 3], dtype=np.int64),
]
x0 = [np.zeros(shape, dtype=np.float32) for shape in shapes]
input_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(
onnx.TensorProto.FLOAT, ["H", "W", "C"]
)
),
]
output_type_protos = [
onnx.helper.make_sequence_type_proto(
onnx.helper.make_tensor_type_proto(onnx.TensorProto.INT64, [3])
),
]
expect(
node,
inputs=[x0],
outputs=[shapes],
input_type_protos=input_type_protos,
output_type_protos=output_type_protos,
name="test_sequence_map_extract_shapes",
)