-
Notifications
You must be signed in to change notification settings - Fork 835
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #430 from dtrawins/openvino_demo
updated ensemble pipeline with OpenVINO component
- Loading branch information
Showing
24 changed files
with
692 additions
and
579 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
dog.jpeg 248 | ||
zebra.jpeg 340 | ||
pelican.jpeg 144 |
559 changes: 48 additions & 511 deletions
559
examples/models/openvino_imagenet_ensemble/openvino_imagenet_ensemble.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file was deleted.
Oops, something went wrong.
5 changes: 3 additions & 2 deletions
5
examples/models/openvino_imagenet_ensemble/resources/combiner/ImageNetCombiner.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,11 @@ | ||
import logging | ||
import numpy as np | ||
logger = logging.getLogger(__name__) | ||
|
||
class ImageNetCombiner(object): | ||
|
||
def aggregate(self, Xs, features_names): | ||
print("ImageNet Combiner aggregate called") | ||
logger.info(Xs) | ||
return (Xs[0]+Xs[1])/2.0 | ||
logger.debug(Xs) | ||
return (np.reshape(Xs[0],(1,-1)) + np.reshape(Xs[1], (1,-1)))/2.0 | ||
|
2 changes: 1 addition & 1 deletion
2
examples/models/openvino_imagenet_ensemble/resources/combiner/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
|
||
build: | ||
s2i build -E environment_grpc . seldonio/seldon-core-s2i-python36:0.4-SNAPSHOT seldonio/imagenet_combiner:0.1 | ||
s2i build -E environment_grpc . seldon_openvino_base:latest seldonio/imagenet_combiner:0.1 | ||
|
8 changes: 8 additions & 0 deletions
8
examples/models/openvino_imagenet_ensemble/resources/combiner/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Combiner components for two models' results | ||
|
||
|
||
### Building | ||
```bash | ||
s2i build -E environment_grpc . seldon_openvino_base:latest seldonio/imagenet_combiner:0.1 | ||
|
||
``` |
100 changes: 100 additions & 0 deletions
100
examples/models/openvino_imagenet_ensemble/resources/model/Prediction.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import numpy as np | ||
import logging | ||
import datetime | ||
import os | ||
import sys | ||
from urllib.parse import urlparse | ||
from google.cloud import storage | ||
from openvino.inference_engine import IENetwork, IEPlugin | ||
|
||
|
||
def get_logger(name): | ||
logger = logging.getLogger(name) | ||
log_formatter = logging.Formatter("%(asctime)s - %(name)s - " | ||
"%(levelname)s - %(message)s") | ||
logger.setLevel('DEBUG') | ||
|
||
console_handler = logging.StreamHandler() | ||
console_handler.setFormatter(log_formatter) | ||
logger.addHandler(console_handler) | ||
|
||
return logger | ||
|
||
logger = get_logger(__name__) | ||
|
||
|
||
def gs_download_file(path): | ||
if path is None: | ||
return None | ||
parsed_path = urlparse(path) | ||
bucket_name = parsed_path.netloc | ||
file_path = parsed_path.path[1:] | ||
gs_client = storage.Client() | ||
bucket = gs_client.get_bucket(bucket_name) | ||
blob = bucket.blob(file_path) | ||
tmp_path = os.path.join('/tmp', file_path.split(os.sep)[-1]) | ||
blob.download_to_filename(tmp_path) | ||
return tmp_path | ||
|
||
|
||
def s3_download_file(path): | ||
if path is None: | ||
return None | ||
s3_endpoint = os.getenv('S3_ENDPOINT') | ||
s3_client = boto3.client('s3', endpoint_url=s3_endpoint) | ||
parsed_path = urlparse(path) | ||
bucket_name = parsed_path.netloc | ||
file_path = parsed_path.path[1:] | ||
tmp_path = os.path.join('/tmp', file_path.split(os.sep)[-1]) | ||
s3_transfer = boto3.s3.transfer.S3Transfer(s3_client) | ||
s3_transfer.download_file(bucket_name, file_path, tmp_path) | ||
return tmp_path | ||
|
||
|
||
def GetLocalPath(requested_path): | ||
parsed_path = urlparse(requested_path) | ||
if parsed_path.scheme == '': | ||
return requested_path | ||
elif parsed_path.scheme == 'gs': | ||
return gs_download_file(path=requested_path) | ||
elif parsed_path.scheme == 's3': | ||
return s3_download_file(path=requested_path) | ||
|
||
|
||
class Prediction(object): | ||
def __init__(self): | ||
try: | ||
xml_path = os.environ["XML_PATH"] | ||
bin_path = os.environ["BIN_PATH"] | ||
|
||
except KeyError: | ||
print("Please set the environment variables XML_PATH, BIN_PATH") | ||
sys.exit(1) | ||
|
||
xml_local_path = GetLocalPath(xml_path) | ||
bin_local_path = GetLocalPath(bin_path) | ||
print('path object', xml_local_path) | ||
|
||
CPU_EXTENSION = os.getenv('CPU_EXTENSION', "/usr/local/lib/libcpu_extension.so") | ||
|
||
plugin = IEPlugin(device='CPU', plugin_dirs=None) | ||
if CPU_EXTENSION: | ||
plugin.add_cpu_extension(CPU_EXTENSION) | ||
net = IENetwork(model=xml_local_path, weights=bin_local_path) | ||
self.input_blob = next(iter(net.inputs)) | ||
self.out_blob = next(iter(net.outputs)) | ||
self.batch_size = net.inputs[self.input_blob].shape[0] | ||
self.inputs = net.inputs | ||
self.outputs = net.outputs | ||
self.exec_net = plugin.load(network=net, num_requests=self.batch_size) | ||
|
||
|
||
def predict(self,X,feature_names): | ||
start_time = datetime.datetime.now() | ||
results = self.exec_net.infer(inputs={self.input_blob: X}) | ||
predictions = results[self.out_blob] | ||
end_time = datetime.datetime.now() | ||
duration = (end_time - start_time).total_seconds() * 1000 | ||
logger.debug("Processing time: {:.2f} ms".format(duration)) | ||
return predictions.astype(np.float64) | ||
|
41 changes: 41 additions & 0 deletions
41
examples/models/openvino_imagenet_ensemble/resources/model/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# OpenVINO prediction component | ||
|
||
Model configuration is implemented using environment variables: | ||
|
||
`XML_PATH` - s3, gs or local path to xml file in OpenVINO model server | ||
|
||
`BIN_PATH` - s3, gs or local path to bin file in OpenVINO model server | ||
|
||
When using GCS make sure you added also GOOGLE_APPLICATION_CREDENTIALS variable and mounted correspondent token file. | ||
|
||
In case is S3 or Minio storage add appropriate environment variables with the credentials. | ||
|
||
Component is executing inference operation. Processing time is included in the components debug logs. | ||
|
||
Model input and output tensors are determined automatically. There is assumed only one input tensor and output tensor. | ||
|
||
### Building example: | ||
|
||
```bash | ||
s2i build -E environment_grpc . seldon_openvino_base:latest seldon-openvino-prediction:0.1 | ||
``` | ||
The base image `seldon_openvino_base:latest` should be created according to this [procedure](../../../../../wrappers/s2i/python_openvino) | ||
|
||
|
||
### Local testing example: | ||
|
||
```bash | ||
docker run -it -v $GOOGLE_APPLICATION_CREDENTIALS:/etc/gcp.json -e GOOGLE_APPLICATION_CREDENTIALS=/etc/gcp.json \ | ||
-e XML_PATH=gs://inference-eu/models_zoo/resnet_V1_50/resnet_V1_50.xml \ | ||
-e BIN_PATH=gs://inference-eu/models_zoo/resnet_V1_50/resnet_V1_50.bin | ||
starting microservice | ||
2019-02-05 11:13:32,045 - seldon_core.microservice:main:261 - INFO: Starting microservice.py:main | ||
2019-02-05 11:13:32,047 - seldon_core.microservice:main:292 - INFO: Annotations: {} | ||
path object /tmp/resnet_V1_50.xml | ||
net = IENetwork(model=xml_local_path, weights=bin_local_path) | ||
2019-02-05 11:14:19,870 - seldon_core.microservice:main:354 - INFO: Starting servers | ||
2019-02-05 11:14:19,906 - seldon_core.microservice:grpc_prediction_server:333 - INFO: GRPC microservice Running on port 5000 | ||
``` | ||
|
||
|
||
|
5 changes: 5 additions & 0 deletions
5
examples/models/openvino_imagenet_ensemble/resources/model/environment_grpc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
MODEL_NAME=Prediction | ||
API_TYPE=GRPC | ||
SERVICE_TYPE=MODEL | ||
PERSISTENCE=0 | ||
|
2 changes: 2 additions & 0 deletions
2
examples/models/openvino_imagenet_ensemble/resources/model/requirements.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
google-cloud-storage==1.13.0 | ||
boto3==1.9.34 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
examples/models/openvino_imagenet_ensemble/resources/transformer/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
|
||
build: | ||
s2i build -E environment_grpc . seldonio/seldon-core-s2i-python36:0.5-SNAPSHOT seldonio/imagenet_transformer:0.1 | ||
s2i build -E environment_grpc . seldon_openvino_base:latest seldonio/imagenet_transformer:0.1 |
24 changes: 24 additions & 0 deletions
24
examples/models/openvino_imagenet_ensemble/resources/transformer/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
## Transformer component | ||
|
||
Exemplary implementation of data transformation tasks. | ||
|
||
Input transformation function accepts as input the binary representation of jpeg content. | ||
It performs the following operations: | ||
- convert compressed jpeg content to numpy array (BGR format) | ||
- crop/resize the image to the square shape set in the environment variable `SIZE` (by default 224) | ||
- transpose the data to NCWH | ||
|
||
|
||
Output transformation function is consuming the imagenet classification models. | ||
It is converting the array including probability for each imagenet classes into the class name. | ||
It is returning 'human readable' string with most likely class name. | ||
The function is using `CLASSES` environment variable to define the expected number of classes in the output. | ||
Depending on the model it could be 1000 (the default value) or 1001. | ||
|
||
|
||
### Building example: | ||
```bash | ||
s2i build -E environment_grpc . seldon_openvino_base:latest seldonio/imagenet_transformer:0.1 | ||
``` | ||
|
||
The base image `seldon_openvino_base:latest` should be created according to this [procedure](../../../../../wrappers/s2i/python_openvino) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ MODEL_NAME=ImageNetTransformer | |
API_TYPE=GRPC | ||
SERVICE_TYPE=TRANSFORMER | ||
PERSISTENCE=0 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +0,0 @@ | ||
numpy>=1.8.2 | ||
keras | ||
pillow | ||
Oops, something went wrong.