示例#1
0
def test_concat():
    """
    Functional test for concat
    """
    g1 = empty_graph("G1")
    n1 = node('Add',
              inputs=['x1_1', 'x1_2'],
              outputs=['sum_1'],
              name="node_name")
    g1 = add_input(g1, 'x1_1', "FLOAT", [1])
    g1 = add_input(g1, 'x1_2', "FLOAT", [1])
    g1 = add_output(g1, 'sum_1', "FLOAT", [1])
    g1 = add_node(g1, n1)

    g2 = empty_graph("G2")
    n2 = node('Add',
              inputs=['x2_1', 'x2_2'],
              outputs=['sum_2'],
              name="node_name")
    g2 = add_input(g2, 'x2_2', "FLOAT", [1])
    g2 = add_output(g2, 'sum_2', "FLOAT", [1])
    g2 = add_node(g2, n2)

    g = concat(g1, g2, False, True, edge_match=[("x1_2", "x2_1")])

    data = {
        "x1_1": np.array([2]).astype(np.float32),
        "x1_2": np.array([5]).astype(np.float32),
        "x2_2": np.array([5]).astype(np.float32)
    }
    result = run(g, inputs=data, outputs=["sum_1", "sum_2"])
    assert result[
        0], "Sum of 2 and 5 should be equal to constant 7. Concat failed."
示例#2
0
def test_merge():
    """
    Functional test of merge().
    """
    # Subgraph 1
    sg1 = empty_graph("Graph 1")
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    sg1 = add_node(sg1, n1)
    sg1 = add_input(sg1, 'x1', "FLOAT", [1])
    sg1 = add_input(sg1, 'x2', "FLOAT", [1])
    sg1 = add_output(sg1, 'sum', "FLOAT", [1])

    # Subgraph 2
    sg2 = empty_graph("Graph 2")
    sg2 = add_constant(sg2, "const", np.array([7]), "FLOAT")
    n2 = node("Equal", inputs=['sum', 'const'], outputs=['equal'])
    sg2 = add_node(sg2, n2)

    sg2 = add_input(sg2, 'sum', "FLOAT", [1])
    sg2 = add_output(sg2, 'equal', "BOOL", [1])

    g = merge(sg1, sg2, outputs=["sum"], inputs=["sum"])

    data = {
        "x1": np.array([2]).astype(np.float32),
        "x2": np.array([5]).astype(np.float32)
    }
    result = run(g, inputs=data, outputs=["equal"])
    assert result[
        0], "Sum of 2 and 5 should be equal to constant 7. Merged failed."
示例#3
0
def test_clean():
    g = empty_graph()
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    g = add_input(g, 'x1', "FLOAT", [1])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    g = clean(g)
    assert type(g) == xpb2.GraphProto, "Clean failed."
示例#4
0
def test_replace_input():
    g = empty_graph()
    g = add_input(g, "test", "FLOAT", [0])
    g = replace_input(g, "test", "FLOAT", [10,10])

    type = getattr(g.input[0], "type", False)  # get the input type
    ttype = getattr(type, "tensor_type", False)
    shape = getattr(ttype, "shape", False)
    dim = getattr(shape, "dim", False)
    dim_val = getattr(dim[0], "dim_value", False)

    assert dim_val == 10, "New dimension should be 10"
示例#5
0
def test_check():

    # Invalid, no input/output:
    g = empty_graph()
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    assert not check(g), "Graph is not complete."

    # Valid graph
    g = add_input(g, 'x1', "FLOAT", [1])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    assert check(g), "Graph should pass checks."

    # Invalid: None operator:
    g = empty_graph()
    n1 = node('None', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    g = add_input(g, 'x1', "FLOAT", [1])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    assert not check(g), "Graph should not pass checks."

    # Invalid: Dynamic size input
    g = empty_graph()
    n1 = node('Add', inputs=['x1', 'x2'], outputs=['sum'])
    g = add_node(g, n1)
    g = add_input(g, 'x1', "FLOAT", [])
    g = add_input(g, 'x2', "FLOAT", [1])
    g = add_output(g, 'sum', "FLOAT", [1])
    assert not check(g), "Graph should not pass checks."

    check(g, _sclbl_check=False, _onnx_check=False)
    check(g, _onnx_check=False)  # Operator check.
示例#6
0
def test_split():
    """
    Functional test for split
    """
    g1 = empty_graph("G1")
    n1 = node('Add', inputs=['x1_1', 'x1_2'], outputs=['sum_1'], name="n1")
    g1 = add_input(g1, 'x1_1', "FLOAT", [1])
    g1 = add_input(g1, 'x1_2', "FLOAT", [1])
    g1 = add_output(g1, 'sum_1', "FLOAT", [1])
    g1 = add_node(g1, n1)

    g2 = empty_graph("G2")
    n2 = node('Add', inputs=['x2_1', 'x2_2'], outputs=['sum_2'], name="n2")
    g2 = add_input(g2, 'x2_1', "FLOAT", [1])
    g2 = add_input(g2, 'x2_2', "FLOAT", [1])
    g2 = add_output(g2, 'sum_2', "FLOAT", [1])
    g2 = add_node(g2, n2)

    g3 = empty_graph("G3")
    n3 = node('Add', inputs=['x3_1', 'x3_2'], outputs=['sum_3'], name="n3")
    g3 = add_input(g3, 'x3_1', "FLOAT", [1])
    g3 = add_input(g3, 'x3_2', "FLOAT", [1])
    g3 = add_output(g3, 'sum_3', "FLOAT", [1])
    g3 = add_node(g3, n3)

    g = split(g1,
              g2,
              g3,
              cg1_match=[("sum_1", "x2_2")],
              cg2_match=[("sum_1", "x3_1")])

    data = {
        "x1_1": np.array([1]).astype(np.float32),
        "x1_2": np.array([2]).astype(np.float32),
        "x2_1": np.array([3]).astype(np.float32),
        "x3_2": np.array([4]).astype(np.float32),
    }
    result = run(g, inputs=data, outputs=["sum_2", "sum_3"])
    assert result[
        0], "Sum of 1,2, and 3 should be equal to constant 6. Split failed."
示例#7
0
def test__input_details():
    g = empty_graph()
    g = add_input(g, 'sum', "FLOAT", [4, 3, 7])
    in_det = _input_details(g)
    assert in_det['sum']['data_type'] == "FLOAT", "Input details not correct."
示例#8
0
- Sum all elements of the result into a single scalar
- Compare the scalar to a threshold (another constant)
If the threshold is reached, we conclude that the container is filled.
"""

# Start with the empty graph:
g = so.empty_graph()

# Create the constant node encoding the empty image and add it to the graph:
# Note the type encoding as np.int64.
reference_image = np.array(Image.open("images/empty-average.JPG"),
                           dtype=np.int32)
g = so.add_constant(g, "c1", reference_image, "INT32")

# Add the first input (note, same shape):
g = so.add_input(g, 'in', "INT32", reference_image.shape)

# Add the Subtract, Absolute, ReduceSum, and Less nodes
# Node how the names again enforce the topology of the graph
n1 = so.node("Sub", inputs=['in', 'c1'], outputs=['sub'])
n2 = so.node("Abs", inputs=['sub'], outputs=['abs'])
n3 = so.node("ReduceSum", inputs=['abs'], outputs=['sum'],
             keepdims=0)  # Note the keepdims additional parameter.
g = so.add_nodes(g, [n1, n2, n3])

# And, we need to add the threshold (constant c2):
threshold = np.array([3000000]).astype(np.int32)
g = so.add_constant(g, "c2", threshold, "INT32")

# Add the less node. Please note that the nodes have to be added in topological order:
n4 = so.node("Less", inputs=['sum', 'c2'], outputs=['result'])
示例#9
0
This example combines two (sub) graphs into a single graph describing a longer pipeline.

The setup builds on example II (example_02.py). We create 2 separate graphs:
1. Graph that resizes an image from 600x450 to 400x300
2. The empty container graph (check_container.onnx) which takes a 400x300 image

Next, we merge the two graphs into one single ONNX file.
"""

# Let's open the large image and inspect the shape:
large_img = np.array(Image.open("images/1-BIG.JPG"), dtype=np.int32)
print(large_img.shape)  # 450x600x3

# First subgraph for resize:
sg1 = so.empty_graph("resize_graph")
sg1 = so.add_input(sg1, "large_image", "INT32", [450, 600, 3])  # Add the input

# The resize node:
e1 = so.constant("roi", np.array([]),
                 "FLOAT")  # Note the empty fields for roi and scales.
e2 = so.constant("scales", np.array([]), "FLOAT")
c1 = so.constant("size", np.array([300, 400, 3]), "INT64")
n1 = so.node("Resize",
             inputs=['large_image', 'roi', 'scales', 'size'],
             outputs=['small_image'])
sg1 = so.add_nodes(sg1, [e1, e2, c1, n1])
sg1 = so.add_output(sg1, "small_image", "INT32", [300, 400, 3])

# Check and clean
sg1 = so.clean(sg1)
so.check(sg1)
示例#10
0
scalars together.
"""

# Use the empty_graph() method to create a named xpb2.GraphProto object:
g = so.empty_graph()

# Add a node to the graph.
# Please note the list of available operators at: https://github.com/onnx/onnx/blob/master/docs/Operators.md
# Run so.list_data_types() and / or so.list_operators() so. to see all Scailable supported data types.
n1 = so.node('Add', inputs=['x1', 'x2'], outputs=['sum'])
g = so.add_node(g, n1)

# We should explicitly specify the named inputs to the graph -- note that the names determine the graph topology.
# Also, we should specify the data type and dimensions of any input.
# Use so.list_data_types() to see available data types.
g = so.add_input(g, 'x1', "FLOAT", [1])
g = so.add_input(g, 'x2', "FLOAT", [1])

# Similarly, we add the named output with its corresponding type and dimension.
# Note that types will need to "match", as do dimensions. Please see the operator docs for more info.
g = so.add_output(g, 'sum', "FLOAT", [1])

# so.check() checks the current graph to see if it matches Scailable's upload criteria for .wasm conversion.
so.check(g)

# Now, a few tricks to sanitize the graph which are always useful.
# so.clean() provides lossless reduction of the graph. If successful cleaned graph is returned.
g = so.clean(g)

# so.display() tries to open the graph using Netron to inspect it. This worsk on most systems if Netron is installed.
# Get Netron at https://github.com/onnx/onnx/blob/master/docs/Operators.md
示例#11
0
Note that merge(), join(), and split() are high level wrappers around concat(), each effectively assuming that the
resulting graph is "complete" (i.e., it is a valid onnx graph including input and output). Concat itself is more
flexible and can be used for intermediate merging/concatenation of partial graphs (i.e., graphs that are not yet
finished).

Below we provide a number of examples of each of the functions. We recommend using so.display() throughout to visualize
the resulting graphs and truly understand how the graphs are joined together. Examples are all very simple (small graphs,
scalar operations, etc.), but don't underestimate the complexities involved; with larger graphs the behavior of
the concat function can be challenging.
"""

# # Lets start by creating a few simple (and complete) graphs which we will use throughout:
# # Simple absolute value graph:
g1 = so.empty_graph("g_1")
n1 = so.node('Abs', inputs=['in_1_1'], outputs=['out_1_1'], name="node_1_1")
g1 = so.add_input(g1, 'in_1_1', "FLOAT", [1])
g1 = so.add_output(g1, 'out_1_1', "FLOAT", [1])
g1 = so.add_node(g1, n1)
# so.display(g1)
# data = {"in_1_1": np.array([2]).astype(np.float32)}
# print(so.run(g1, inputs=data, outputs=["out_1_1"]))

# # Simple max value graph:
g2 = so.empty_graph("g_2")
n2 = so.node('Max',
             inputs=['in_2_1', 'in_2_2'],
             outputs=['out_2_1'],
             name="node_2_1")
g2 = so.add_input(g2, 'in_2_1', "FLOAT", [1])
g2 = so.add_constant(g2, "in_2_2", np.array([10]), "FLOAT")
g2 = so.add_output(g2, 'out_2_1', "FLOAT", [1])
示例#12
0
def test_delete_input():
    g = empty_graph()
    g = add_input(g, "test", "FLOAT", [0])
    g = delete_input(g, "test")
    assert len(g.input) == 0, "There should not be any inputs after delete."
示例#13
0
def test_list_inputs():
    g = empty_graph()
    assert list_inputs(g), "No inputs listed."
    g = add_input(g, "test", "FLOAT", [0])
    list_inputs(g)
    assert not list_inputs(False), "List inputs should be false."
示例#14
0
def test_rename_input():
    g = empty_graph()
    g = add_input(g, "test", "FLOAT", [0])
    g = rename_input(g, "test", "new_name")
    name = getattr(g.input[0], "name", False)  # get the first input name:
    assert name == "new_name", "New name should be in list of inputs."
示例#15
0
def test_add_input():
    g = empty_graph()
    g = add_input(g, "test", "FLOAT", [0])
    name = getattr(g.input[0], "name", False)  # get the first input name:
    assert name == "test", "'test' should be in list of inputs."