.. _l-onnx-doc-SequenceMap: =========== SequenceMap =========== .. contents:: :local: .. _l-onnx-op-sequencemap-17: 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** :: 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** :: 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** :: 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** :: 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** :: 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** :: 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", )