2021-04-14 13:24:32 +03:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
# -*- coding: utf-8 -*-
|
2022-01-19 01:07:49 +03:00
|
|
|
# Copyright (C) 2018-2022 Intel Corporation
|
2021-03-26 17:54:28 +03:00
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
2021-04-14 13:24:32 +03:00
|
|
|
import logging as log
|
2021-04-08 20:07:25 +03:00
|
|
|
import sys
|
2021-04-22 11:03:49 +03:00
|
|
|
import typing
|
2021-04-14 13:24:32 +03:00
|
|
|
from functools import reduce
|
|
|
|
|
|
2020-10-09 13:05:55 +03:00
|
|
|
import numpy as np
|
2021-12-27 09:19:18 +03:00
|
|
|
from openvino.preprocess import PrePostProcessor
|
2022-02-14 19:03:45 +03:00
|
|
|
from openvino.runtime import (Core, Layout, Model, Shape, Type, op, opset1,
|
|
|
|
|
opset8, set_batch)
|
|
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
from data import digits
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_ngraph_function(model_path: str) -> Model:
|
2022-03-30 20:26:36 +03:00
|
|
|
"""Create a model on the fly from the source code using ngraph."""
|
2020-10-09 13:05:55 +03:00
|
|
|
|
2021-04-22 11:03:49 +03:00
|
|
|
def shape_and_length(shape: list) -> typing.Tuple[list, int]:
|
2021-04-14 13:24:32 +03:00
|
|
|
length = reduce(lambda x, y: x * y, shape)
|
|
|
|
|
return shape, length
|
2020-10-09 13:05:55 +03:00
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
weights = np.fromfile(model_path, dtype=np.float32)
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset = 0
|
2021-04-14 13:24:32 +03:00
|
|
|
padding_begin = padding_end = [0, 0]
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# input
|
|
|
|
|
input_shape = [64, 1, 28, 28]
|
2022-02-14 19:03:45 +03:00
|
|
|
param_node = op.Parameter(Type.f32, Shape(input_shape))
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# convolution 1
|
|
|
|
|
conv_1_kernel_shape, conv_1_kernel_length = shape_and_length([20, 1, 5, 5])
|
2022-02-14 19:03:45 +03:00
|
|
|
conv_1_kernel = op.Constant(Type.f32, Shape(conv_1_kernel_shape), weights[0:conv_1_kernel_length].tolist())
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += conv_1_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
conv_1_node = opset8.convolution(param_node, conv_1_kernel, [1, 1], padding_begin, padding_end, [1, 1])
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# add 1
|
|
|
|
|
add_1_kernel_shape, add_1_kernel_length = shape_and_length([1, 20, 1, 1])
|
2022-02-14 19:03:45 +03:00
|
|
|
add_1_kernel = op.Constant(Type.f32, Shape(add_1_kernel_shape),
|
|
|
|
|
weights[weights_offset : weights_offset + add_1_kernel_length])
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += add_1_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
add_1_node = opset8.add(conv_1_node, add_1_kernel)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# maxpool 1
|
2022-02-14 19:03:45 +03:00
|
|
|
maxpool_1_node = opset1.max_pool(add_1_node, [2, 2], padding_begin, padding_end, [2, 2], 'ceil')
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# convolution 2
|
|
|
|
|
conv_2_kernel_shape, conv_2_kernel_length = shape_and_length([50, 20, 5, 5])
|
2022-02-14 19:03:45 +03:00
|
|
|
conv_2_kernel = op.Constant(Type.f32, Shape(conv_2_kernel_shape),
|
|
|
|
|
weights[weights_offset : weights_offset + conv_2_kernel_length],
|
|
|
|
|
)
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += conv_2_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
conv_2_node = opset8.convolution(maxpool_1_node, conv_2_kernel, [1, 1], padding_begin, padding_end, [1, 1])
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# add 2
|
|
|
|
|
add_2_kernel_shape, add_2_kernel_length = shape_and_length([1, 50, 1, 1])
|
2022-02-14 19:03:45 +03:00
|
|
|
add_2_kernel = op.Constant(Type.f32, Shape(add_2_kernel_shape),
|
|
|
|
|
weights[weights_offset : weights_offset + add_2_kernel_length],
|
|
|
|
|
)
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += add_2_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
add_2_node = opset8.add(conv_2_node, add_2_kernel)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# maxpool 2
|
2022-02-14 19:03:45 +03:00
|
|
|
maxpool_2_node = opset1.max_pool(add_2_node, [2, 2], padding_begin, padding_end, [2, 2], 'ceil')
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# reshape 1
|
|
|
|
|
reshape_1_dims, reshape_1_length = shape_and_length([2])
|
|
|
|
|
# workaround to get int64 weights from float32 ndarray w/o unnecessary copying
|
|
|
|
|
dtype_weights = np.frombuffer(
|
2021-04-28 13:52:03 +03:00
|
|
|
weights[weights_offset : weights_offset + 2 * reshape_1_length],
|
|
|
|
|
dtype=np.int64,
|
2020-10-09 13:05:55 +03:00
|
|
|
)
|
2022-02-14 19:03:45 +03:00
|
|
|
reshape_1_kernel = op.Constant(Type.i64, Shape(list(dtype_weights.shape)), dtype_weights)
|
2021-04-14 13:24:32 +03:00
|
|
|
weights_offset += 2 * reshape_1_length
|
2022-02-14 19:03:45 +03:00
|
|
|
reshape_1_node = opset8.reshape(maxpool_2_node, reshape_1_kernel, True)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# matmul 1
|
|
|
|
|
matmul_1_kernel_shape, matmul_1_kernel_length = shape_and_length([500, 800])
|
2022-02-14 19:03:45 +03:00
|
|
|
matmul_1_kernel = op.Constant(Type.f32, Shape(matmul_1_kernel_shape),
|
|
|
|
|
weights[weights_offset : weights_offset + matmul_1_kernel_length],
|
|
|
|
|
)
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += matmul_1_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
matmul_1_node = opset8.matmul(reshape_1_node, matmul_1_kernel, False, True)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# add 3
|
|
|
|
|
add_3_kernel_shape, add_3_kernel_length = shape_and_length([1, 500])
|
2022-02-14 19:03:45 +03:00
|
|
|
add_3_kernel = op.Constant(Type.f32, Shape(add_3_kernel_shape),
|
|
|
|
|
weights[weights_offset : weights_offset + add_3_kernel_length],
|
|
|
|
|
)
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += add_3_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
add_3_node = opset8.add(matmul_1_node, add_3_kernel)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# ReLU
|
2022-02-14 19:03:45 +03:00
|
|
|
relu_node = opset8.relu(add_3_node)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# reshape 2
|
2022-02-14 19:03:45 +03:00
|
|
|
reshape_2_kernel = op.Constant(Type.i64, Shape(list(dtype_weights.shape)), dtype_weights)
|
|
|
|
|
reshape_2_node = opset8.reshape(relu_node, reshape_2_kernel, True)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# matmul 2
|
|
|
|
|
matmul_2_kernel_shape, matmul_2_kernel_length = shape_and_length([10, 500])
|
2022-02-14 19:03:45 +03:00
|
|
|
matmul_2_kernel = op.Constant(Type.f32, Shape(matmul_2_kernel_shape),
|
|
|
|
|
weights[weights_offset : weights_offset + matmul_2_kernel_length],
|
|
|
|
|
)
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += matmul_2_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
matmul_2_node = opset8.matmul(reshape_2_node, matmul_2_kernel, False, True)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# add 4
|
|
|
|
|
add_4_kernel_shape, add_4_kernel_length = shape_and_length([1, 10])
|
2022-02-14 19:03:45 +03:00
|
|
|
add_4_kernel = op.Constant(Type.f32, Shape(add_4_kernel_shape),
|
|
|
|
|
weights[weights_offset : weights_offset + add_4_kernel_length],
|
|
|
|
|
)
|
2020-10-09 13:05:55 +03:00
|
|
|
weights_offset += add_4_kernel_length
|
2022-02-14 19:03:45 +03:00
|
|
|
add_4_node = opset8.add(matmul_2_node, add_4_kernel)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
# softmax
|
|
|
|
|
softmax_axis = 1
|
2022-02-14 19:03:45 +03:00
|
|
|
softmax_node = opset8.softmax(add_4_node, softmax_axis)
|
2020-10-09 13:05:55 +03:00
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
return Model(softmax_node, [param_node], 'lenet')
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
log.basicConfig(format='[ %(levelname)s ] %(message)s', level=log.INFO, stream=sys.stdout)
|
2021-12-27 09:19:18 +03:00
|
|
|
# Parsing and validation of input arguments
|
|
|
|
|
if len(sys.argv) != 3:
|
2022-02-14 19:03:45 +03:00
|
|
|
log.info(f'Usage: {sys.argv[0]} <path_to_model> <device_name>')
|
2021-12-27 09:19:18 +03:00
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
model_path = sys.argv[1]
|
|
|
|
|
device_name = sys.argv[2]
|
|
|
|
|
labels = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
|
|
|
|
number_top = 1
|
2022-03-24 22:27:29 +03:00
|
|
|
# ---------------------------Step 1. Initialize OpenVINO Runtime Core--------------------------------------------------
|
2021-12-27 09:19:18 +03:00
|
|
|
log.info('Creating OpenVINO Runtime Core')
|
|
|
|
|
core = Core()
|
2020-10-09 13:05:55 +03:00
|
|
|
|
2021-04-28 13:52:03 +03:00
|
|
|
# ---------------------------Step 2. Read a model in OpenVINO Intermediate Representation------------------------------
|
2022-02-14 19:03:45 +03:00
|
|
|
log.info(f'Loading the model using ngraph function with weights from {model_path}')
|
2021-12-27 09:19:18 +03:00
|
|
|
model = create_ngraph_function(model_path)
|
|
|
|
|
# ---------------------------Step 3. Apply preprocessing----------------------------------------------------------
|
2021-04-14 13:24:32 +03:00
|
|
|
# Get names of input and output blobs
|
2021-12-27 09:19:18 +03:00
|
|
|
ppp = PrePostProcessor(model)
|
|
|
|
|
# 1) Set input tensor information:
|
|
|
|
|
# - input() provides information about a single model input
|
|
|
|
|
# - precision of tensor is supposed to be 'u8'
|
|
|
|
|
# - layout of data is 'NHWC'
|
|
|
|
|
ppp.input().tensor() \
|
|
|
|
|
.set_element_type(Type.u8) \
|
|
|
|
|
.set_layout(Layout('NHWC')) # noqa: N400
|
|
|
|
|
|
|
|
|
|
# 2) Here we suppose model has 'NCHW' layout for input
|
|
|
|
|
ppp.input().model().set_layout(Layout('NCHW'))
|
|
|
|
|
# 3) Set output tensor information:
|
|
|
|
|
# - precision of tensor is supposed to be 'f32'
|
|
|
|
|
ppp.output().tensor().set_element_type(Type.f32)
|
|
|
|
|
|
|
|
|
|
# 4) Apply preprocessing modifing the original 'model'
|
|
|
|
|
model = ppp.build()
|
|
|
|
|
|
|
|
|
|
# Set a batch size equal to number of input images
|
2022-02-14 19:03:45 +03:00
|
|
|
set_batch(model, digits.shape[0])
|
2021-04-28 13:52:03 +03:00
|
|
|
# ---------------------------Step 4. Loading model to the device-------------------------------------------------------
|
2021-04-14 13:24:32 +03:00
|
|
|
log.info('Loading the model to the plugin')
|
2021-12-27 09:19:18 +03:00
|
|
|
compiled_model = core.compile_model(model, device_name)
|
2021-04-14 13:24:32 +03:00
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
# ---------------------------Step 5. Prepare input---------------------------------------------------------------------
|
|
|
|
|
n, c, h, w = model.input().shape
|
2021-04-14 13:24:32 +03:00
|
|
|
input_data = np.ndarray(shape=(n, c, h, w))
|
2020-10-09 13:05:55 +03:00
|
|
|
for i in range(n):
|
2021-12-27 09:19:18 +03:00
|
|
|
image = digits[i].reshape(28, 28)
|
|
|
|
|
image = image[:, :, np.newaxis]
|
2021-04-14 13:24:32 +03:00
|
|
|
input_data[i] = image
|
2020-10-09 13:05:55 +03:00
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
# ---------------------------Step 6. Do inference----------------------------------------------------------------------
|
2021-04-14 13:24:32 +03:00
|
|
|
log.info('Starting inference in synchronous mode')
|
2021-12-27 09:19:18 +03:00
|
|
|
results = compiled_model.infer_new_request({0: input_data})
|
2021-04-14 13:24:32 +03:00
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
# ---------------------------Step 7. Process output--------------------------------------------------------------------
|
|
|
|
|
predictions = next(iter(results.values()))
|
2021-04-14 13:24:32 +03:00
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
log.info(f'Top {number_top} results: ')
|
2021-04-14 13:24:32 +03:00
|
|
|
for i in range(n):
|
2021-12-27 09:19:18 +03:00
|
|
|
probs = predictions[i]
|
|
|
|
|
# Get an array of number_top class IDs in descending order of probability
|
|
|
|
|
top_n_idexes = np.argsort(probs)[-number_top :][::-1]
|
2021-04-14 13:24:32 +03:00
|
|
|
|
|
|
|
|
header = 'classid probability'
|
2021-12-27 09:19:18 +03:00
|
|
|
header = header + ' label' if labels else header
|
2021-04-14 13:24:32 +03:00
|
|
|
|
2021-12-27 09:19:18 +03:00
|
|
|
log.info(f'Image {i}')
|
|
|
|
|
log.info('')
|
2021-04-14 13:24:32 +03:00
|
|
|
log.info(header)
|
|
|
|
|
log.info('-' * len(header))
|
|
|
|
|
|
|
|
|
|
for class_id in top_n_idexes:
|
|
|
|
|
probability_indent = ' ' * (len('classid') - len(str(class_id)) + 1)
|
2021-12-27 09:19:18 +03:00
|
|
|
label_indent = ' ' * (len('probability') - 8) if labels else ''
|
|
|
|
|
label = labels[class_id] if labels else ''
|
2021-04-14 13:24:32 +03:00
|
|
|
log.info(f'{class_id}{probability_indent}{probs[class_id]:.7f}{label_indent}{label}')
|
|
|
|
|
log.info('')
|
|
|
|
|
|
2021-04-28 13:52:03 +03:00
|
|
|
# ----------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
log.info('This sample is an API example, for any performance measurements please use the dedicated benchmark_app tool\n')
|
2021-04-14 13:24:32 +03:00
|
|
|
return 0
|
2020-10-09 13:05:55 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2021-04-14 13:24:32 +03:00
|
|
|
sys.exit(main())
|