Esempio n. 1
0
def test_modelwrapper():
    lfc = get_test_model_trained("LFC", 1, 1)
    bo.export_finn_onnx(lfc, (1, 1, 28, 28), export_onnx_path)
    model = ModelWrapper(export_onnx_path)
    assert model.check_all_tensor_shapes_specified() is False
    inp_name = model.graph.input[0].name
    inp_shape = model.get_tensor_shape(inp_name)
    assert inp_shape == [1, 1, 28, 28]
    # find first matmul node
    l0_mat_tensor_name = ""
    l0_inp_tensor_name = ""
    for node in model.graph.node:
        if node.op_type == "MatMul":
            l0_inp_tensor_name = node.input[0]
            l0_mat_tensor_name = node.input[1]
            break
    assert l0_mat_tensor_name != ""
    l0_weights = model.get_initializer(l0_mat_tensor_name)
    assert l0_weights.shape == (784, 1024)
    l0_weights_hist = Counter(l0_weights.flatten())
    assert (l0_weights_hist[1.0] + l0_weights_hist[-1.0]) == 784 * 1024
    l0_weights_rand = np.random.randn(784, 1024)
    model.set_initializer(l0_mat_tensor_name, l0_weights_rand)
    assert (model.get_initializer(l0_mat_tensor_name) == l0_weights_rand).all()
    assert l0_inp_tensor_name != ""
    inp_cons = model.find_consumer(l0_inp_tensor_name)
    assert inp_cons.op_type == "MatMul"
    out_prod = model.find_producer(l0_inp_tensor_name)
    assert out_prod.op_type == "MultiThreshold"
    inp_layout = model.get_tensor_layout(inp_name)
    assert inp_layout is None
    inp_layout = DataLayout.NCHW
    model.set_tensor_layout(inp_name, inp_layout)
    assert model.get_tensor_layout(inp_name) == inp_layout
    inp_sparsity = model.get_tensor_sparsity(inp_name)
    assert inp_sparsity is None
    inp_sparsity = {"dw": {"kernel_shape": 3}}
    model.set_tensor_sparsity(inp_name, inp_sparsity)
    assert model.get_tensor_sparsity(inp_name) == inp_sparsity
    os.remove(export_onnx_path)
Esempio n. 2
0
def test_modelwrapper():
    raw_m = get_data("finn.data", "onnx/mnist-conv/model.onnx")
    model = ModelWrapper(raw_m)
    assert model.check_all_tensor_shapes_specified() is True
    inp_name = model.graph.input[0].name
    inp_shape = model.get_tensor_shape(inp_name)
    assert inp_shape == [1, 1, 28, 28]
    conv_nodes = model.get_nodes_by_op_type("Conv")
    matmul_nodes = model.get_nodes_by_op_type("MatMul")
    assert len(conv_nodes) == 2
    assert len(matmul_nodes) == 1
    first_conv = conv_nodes[0]
    first_conv_iname = first_conv.input[0]
    first_conv_wname = first_conv.input[1]
    first_conv_oname = first_conv.output[0]
    assert first_conv_iname != "" and (first_conv_iname is not None)
    assert first_conv_wname != "" and (first_conv_wname is not None)
    assert first_conv_oname != "" and (first_conv_oname is not None)
    first_conv_weights = model.get_initializer(first_conv_wname)
    assert first_conv_weights.shape == (8, 1, 5, 5)
    first_conv_weights_rand = np.random.randn(8, 1, 5, 5)
    model.set_initializer(first_conv_wname, first_conv_weights_rand)
    assert (model.get_initializer(first_conv_wname) == first_conv_weights_rand
            ).all()
    inp_cons = model.find_consumer(first_conv_iname)
    assert inp_cons == first_conv
    out_prod = model.find_producer(first_conv_oname)
    assert out_prod == first_conv
    inp_layout = model.get_tensor_layout(first_conv_iname)
    assert inp_layout is None
    inp_layout = DataLayout.NCHW
    model.set_tensor_layout(first_conv_iname, inp_layout)
    assert model.get_tensor_layout(first_conv_iname) == inp_layout
    inp_sparsity = model.get_tensor_sparsity(first_conv_iname)
    assert inp_sparsity is None
    inp_sparsity = {"dw": {"kernel_shape": [3, 3]}}
    model.set_tensor_sparsity(first_conv_iname, inp_sparsity)
    assert model.get_tensor_sparsity(first_conv_iname) == inp_sparsity
Esempio n. 3
0
def test_merge_onnx_models():
    # load pre model
    raw_m = get_data("finn", "data/onnx/mnist-conv/model.onnx")
    model1 = ModelWrapper(raw_m)
    # the input for model1 comes from a uint8 vector so we set the finn datatype
    # of the input tensor to DataType.UINT8 to verify that the datatypes are correctly
    # preserved in the transformed model
    model1.set_tensor_datatype(model1.graph.input[0].name, DataType.UINT8)
    model1 = model1.transform(InferShapes())
    model1 = model1.transform(GiveUniqueNodeNames())
    model1 = model1.transform(GiveReadableTensorNames())

    # set up post model
    shape = [1, 10]
    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, shape)
    a0 = helper.make_tensor_value_info("a0", TensorProto.FLOAT, [])
    a1 = helper.make_tensor_value_info("a1", TensorProto.FLOAT, [])
    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, shape)

    mul_node = helper.make_node("Mul", ["inp", "a0"], ["mul_out"])
    div_node = helper.make_node("Div", ["mul_out", "a1"], ["outp"])

    graph = helper.make_graph(
        nodes=[mul_node, div_node],
        name="model2-graph",
        inputs=[inp],
        outputs=[outp],
        value_info=[a0, a1],
    )

    model2 = helper.make_model(graph, producer_name="model2")
    model2 = ModelWrapper(model2)
    # initialize model2
    a0_value = np.random.uniform(low=0, high=1, size=(1)).astype(np.float32)
    model2.set_initializer("a0", a0_value)
    a1_value = np.random.uniform(low=0.1, high=1, size=(1)).astype(np.float32)
    model2.set_initializer("a1", a1_value)
    # set a dummy sparsity annotation to check if it gets correctly transferred
    # to the merged model
    sparsity = {"dw": {"kernel_shape": 0}}
    model2.set_tensor_sparsity("a1", sparsity)
    model2 = model2.transform(InferShapes())
    model2 = model2.transform(InferDataTypes())
    model2 = model2.transform(InferDataLayouts())
    model2 = model2.transform(GiveUniqueNodeNames())
    model2 = model2.transform(GiveReadableTensorNames())

    # simulate the models before the merging and pass the output of model1 to model2
    # load one of the test vectors
    raw_i = get_data("finn", "data/onnx/mnist-conv/test_data_set_0/input_0.pb")
    inp_values = onnx.load_tensor_from_string(raw_i)
    inp_values = np_helper.to_array(inp_values)
    idict = {model1.graph.input[0].name: inp_values}
    odict = oxe.execute_onnx(model1, idict)
    temp = odict[model1.graph.output[0].name]

    idict = {model2.graph.input[0].name: temp}
    odict = oxe.execute_onnx(model2, idict)
    outp = odict[model2.graph.output[0].name]
    # merge models
    model_transformed = model2.transform(MergeONNXModels(model1))

    idict = {model_transformed.graph.input[0].name: inp_values}
    odict = oxe.execute_onnx(model_transformed, idict)
    outp_transformed = odict[model_transformed.graph.output[0].name]

    assert (outp == outp_transformed).all()
    assert len(model_transformed.graph.node) == len(model1.graph.node) + len(
        model2.graph.node
    )
    # to test if the value is preserved we set the sparsity annotation of input[1]
    # of the division block to a dummy value, we can now look for the division block
    # and check if the sparsity annotation is still the same
    for n in model_transformed.graph.node:
        if n.op_type == "Div":
            tensor_name = n.input[1]
            set_sparsity = model_transformed.get_tensor_sparsity(tensor_name)
            assert sparsity == set_sparsity

    # check if finn datatype of graph.input[0] is still set to UINT8
    assert model_transformed.get_tensor_datatype("global_in") == DataType.UINT8
Esempio n. 4
0
def set_up_reference_model(act, idt, wdt, k, ifm_dim, ifm_ch, stride, padding):

    # set up reference model consisting of Im2Col + MatMul (+ MultiThreshold)
    ofm_ch = ifm_ch
    ofm_dim = compute_conv_output_dim(ifm_dim, k, stride, pad=padding)

    if act is None:
        odt = DataType.INT32
    else:
        odt = act
        out_act = oh.make_tensor_value_info("out_act", TensorProto.FLOAT,
                                            [1, ofm_dim, ofm_dim, ofm_ch])
        T = oh.make_tensor_value_info("T", TensorProto.FLOAT, [ofm_ch, 15])
        tdt = DataType.INT32
        thresh_node = oh.make_node(
            "MultiThreshold",
            domain="finn.custom_op.general",
            inputs=["outp", "T"],
            outputs=["out_act"],
            data_layout="NHWC",
            out_dtype=odt.name,
            out_scale=1.0,
            out_bias=0.0,
        )

    # set up onnx model
    inp = oh.make_tensor_value_info("inp", TensorProto.FLOAT,
                                    [1, ifm_dim, ifm_dim, ifm_ch])
    outp = oh.make_tensor_value_info("outp", TensorProto.FLOAT,
                                     [1, ofm_dim, ofm_dim, ofm_ch])

    W_sparse = oh.make_tensor_value_info("W_sparse", TensorProto.FLOAT,
                                         [ifm_ch * k * k, ofm_ch])

    im2col_node = oh.make_node(
        "Im2Col",
        domain="finn.custom_op.general",
        inputs=["inp"],
        outputs=["im2col_out"],
        kernel_size=k,
        stride=stride,
        pad_amount=padding,
        input_shape="(1, {}, {}, {})".format(ifm_dim, ifm_dim, ifm_ch),
        depthwise=1,
    )

    matmul_node = oh.make_node("MatMul",
                               inputs=["im2col_out", "W_sparse"],
                               outputs=["outp"])

    if act is None:
        node_list = [im2col_node, matmul_node]
        global_out = outp
        value_info = [W_sparse]
    else:
        node_list = [im2col_node, matmul_node, thresh_node]
        global_out = out_act
        value_info = [W_sparse, T]

    graph = oh.make_graph(
        nodes=node_list,
        name="lowered_dw_cnv_graph",
        inputs=[inp],
        outputs=[global_out],
        value_info=value_info,
    )
    model = oh.make_model(graph, producer_name="lowered_dw_cnv-model")
    model = ModelWrapper(model)

    # initialize model
    model.set_tensor_datatype("inp", idt)
    model.set_tensor_datatype(model.graph.output[0].name, odt)
    model.set_tensor_datatype("W_sparse", wdt)

    w_tensor = gen_finn_dt_tensor(wdt, [ofm_ch, 1, k, k])
    # create sparse matrix
    W_matrix = np.zeros((ofm_ch, ifm_ch, k, k))
    for ch in range(ifm_ch):
        W_matrix[ch][ch] = w_tensor[ch][0]
    W_matrix = W_matrix.astype(np.float32)
    W_matrix = W_matrix.transpose(0, 2, 3, 1)
    W_matrix = W_matrix.reshape(ofm_ch, ifm_ch * k * k)

    model.set_initializer("W_sparse", W_matrix.T)
    sparsity = {"dw": {"kernel_shape": k}}
    model.set_tensor_sparsity("W_sparse", sparsity)

    if act is not None:
        (min, max) = calculate_signed_dot_prod_range(idt, wdt, ifm_ch * k * k)
        n_steps = odt.get_num_possible_values() - 1
        T_values = np.random.randint(min, max - 1,
                                     (ofm_ch, n_steps)).astype(np.float32)
        # provide non-decreasing thresholds
        T_values = np.sort(T_values, axis=1)
        model.set_initializer("T", T_values)
        model.set_tensor_datatype("T", tdt)

    model = model.transform(InferShapes())

    return model