Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Nano] add __call__ method for OpenVINOModel #5540

Merged
merged 10 commits into from
Sep 8, 2022
23 changes: 15 additions & 8 deletions python/nano/src/bigdl/nano/deps/openvino/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ def __init__(self, ie_network: str, device='CPU'):
def forward_step(self, *inputs):
return self._infer_request.infer(list(inputs))

def __call__(self, *inputs):
return self.forward_step(*inputs)

@property
def forward_args(self):
return self._forward_args
Expand All @@ -50,18 +53,17 @@ def ie_network(self, model):
input_names = [t.any_name for t in self._ie_network.inputs]
self._forward_args = input_names

def _save_model(self, path):
def _save(self, path):
"""
Save PytorchOpenVINOModel to local as xml and bin file
Save OpenVINOModel to local as xml and bin file

:param path: Directory to save the model.
"""
path = Path(path)
path.mkdir(exist_ok=True)
invalidInputError(self.ie_network,
"self.ie_network shouldn't be None.")
xml_path = path / self.status['xml_path']
save(self.ie_network, xml_path)
if self._model_exists_or_err("self.ie_network shouldn't be None."):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove if.

path = Path(path)
path.mkdir(exist_ok=True)
xml_path = path / 'ov_saved_model.xml'
save(self.ie_network, xml_path)

def pot(self,
dataloader,
Expand Down Expand Up @@ -148,3 +150,8 @@ def pot(self,
model = Core().read_model(model_path)
model.reshape(orig_shape)
return model

def _model_exists_or_err(self, err_msg):
if self.ie_network is None:
invalidInputError(False, err_msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if self.ie_network is None:
invalidInputError(False, err_msg)
invalidInputError(self.ie_network is not None, err_msg)

return True
39 changes: 27 additions & 12 deletions python/nano/src/bigdl/nano/deps/openvino/pytorch/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
from .utils import export
import torch
from bigdl.nano.utils.log4Error import invalidInputError
from ..core.utils import save


class PytorchOpenVINOModel(OpenVINOModel, AcceleratedLightningModule):
class PytorchOpenVINOModel(AcceleratedLightningModule):
def __init__(self, model, input_sample=None, logging=True, **export_kwargs):
"""
Create a OpenVINO model from pytorch.
Expand All @@ -43,16 +44,14 @@ def __init__(self, model, input_sample=None, logging=True, **export_kwargs):
if isinstance(model, torch.nn.Module):
export(model, input_sample, str(dir / 'tmp.xml'), logging, **export_kwargs)
ov_model_path = dir / 'tmp.xml'
OpenVINOModel.__init__(self, ov_model_path)
AcceleratedLightningModule.__init__(self, None)
self.ov_model = OpenVINOModel(ov_model_path)
super().__init__(self.ov_model)

def on_forward_start(self, inputs):
if self.ie_network is None:
invalidInputError(False,
"Please create an instance by PytorchOpenVINOModel()"
" or PytorchOpenVINOModel.load()")
inputs = self.tensors_to_numpy(inputs)
return inputs
if self.ov_model._model_exists_or_err("Please create an instance by PytorchOpenVINOModel()"
" or PytorchOpenVINOModel.load()"):
inputs = self.tensors_to_numpy(inputs)
return inputs

def on_forward_end(self, outputs):
outputs = self.numpy_to_tensors(outputs.values())
Expand All @@ -64,6 +63,10 @@ def status(self):
status.update({"xml_path": 'ov_saved_model.xml', "weight_path": 'ov_saved_model.bin'})
return status

@property
def forward_args(self):
return self.ov_model.forward_args

@staticmethod
def _load(path):
"""
Expand Down Expand Up @@ -95,7 +98,19 @@ def pot(self,
if metric:
metric = PytorchOpenVINOMetric(metric=metric, higher_better=higher_better)
dataloader = PytorchOpenVINODataLoader(dataloader, collate_fn=self.tensors_to_numpy)
model = super().pot(dataloader, metric=metric, drop_type=drop_type,
maximal_drop=maximal_drop, max_iter_num=max_iter_num,
n_requests=n_requests, sample_size=sample_size)
model = self.ov_model.pot(dataloader, metric=metric, drop_type=drop_type,
maximal_drop=maximal_drop, max_iter_num=max_iter_num,
n_requests=n_requests, sample_size=sample_size)
return PytorchOpenVINOModel(model)

def _save_model(self, path):
"""
Save PytorchOpenVINOModel to local as xml and bin file

:param path: Directory to save the model.
"""
if self.ov_model._model_exists_or_err(err_msg="model shouldn't be None"):
path = Path(path)
path.mkdir(exist_ok=True)
xml_path = path / self.status['xml_path']
save(self.ov_model.ie_network, xml_path)
32 changes: 23 additions & 9 deletions python/nano/src/bigdl/nano/deps/openvino/tf/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
from .utils import export
import tensorflow as tf
from bigdl.nano.utils.log4Error import invalidInputError
from ..core.utils import save


class KerasOpenVINOModel(OpenVINOModel, AcceleratedKerasModel):
class KerasOpenVINOModel(AcceleratedKerasModel):
def __init__(self, model):
"""
Create a OpenVINO model from Keras.
Expand All @@ -39,16 +40,17 @@ def __init__(self, model):
if isinstance(model, tf.keras.Model):
export(model, str(dir / 'tmp.xml'))
ov_model_path = dir / 'tmp.xml'
OpenVINOModel.__init__(self, ov_model_path)
AcceleratedKerasModel.__init__(self, None)
self.ov_model = OpenVINOModel(ov_model_path)
super().__init__(self.ov_model)

def forward_step(self, *inputs):
return self.ov_model.forward_step(*inputs)

def on_forward_start(self, inputs):
if self.ie_network is None:
invalidInputError(False,
"Please create an instance by KerasOpenVINOModel()"
" or KerasOpenVINOModel.load()")
inputs = self.tensors_to_numpy(inputs)
return inputs
if self.ov_model._model_exists_or_err("Please create an instance by KerasOpenVINOModel()"
" or KerasOpenVINOModel.load()"):
inputs = self.tensors_to_numpy(inputs)
return inputs

def on_forward_end(self, outputs):
outputs = tuple(outputs.values())
Expand Down Expand Up @@ -79,3 +81,15 @@ def _load(path):
invalidInputError(False, "nano_model_meta.yml must specify 'xml_path' for loading.")
xml_path = Path(path) / status['xml_path']
return KerasOpenVINOModel(xml_path)

def _save_model(self, path):
"""
Save KerasOpenVINOModel to local as xml and bin file

:param path: Directory to save the model.
"""
if self.ov_model._model_exists_or_err("model shouldn't be None"):
path = Path(path)
path.mkdir(exist_ok=True)
xml_path = path / self.status['xml_path']
save(self.ov_model.ie_network, xml_path)
2 changes: 1 addition & 1 deletion python/nano/test/openvino/basic/test_openvino.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ class TestOpenVINO(TestCase):
def test_openvino_model(self):
openvino_model = OpenVINOModel("./intel/resnet18-xnor-binary-onnx-0001/FP16-INT1/resnet18-xnor-binary-onnx-0001.xml")
x = np.random.randn(1, 3, 224, 224)
y_hat = openvino_model.forward_step(x)
y_hat = openvino_model(x)
assert tuple(next(iter(y_hat)).shape) == (1, 1000)