Skip to content

Commit 7d02594

Browse files
authored
V0.6 Add Grad-CAM++ visualization for exported tf models, refactor backend base classes (#28)
* Add Grad-CAM++ visualization for exported tensorflow image classification models. * Clean comments * Batch-ify the ImageModel.visualize() function so you can pass a list of images. * Bump Pillow version to latest
1 parent d6eb4e4 commit 7d02594

19 files changed

+429
-39
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ venv.bak/
115115
.v36
116116
.v37
117117
.v38
118+
.v39
118119

119120
# Spyder project settings
120121
.spyderproject

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Lobe Python API
22
Code to run exported Lobe models in Python using the TensorFlow, TensorFlow Lite, or ONNX options.
33

4-
Works with Python 3.6, 3.7, and 3.8 untested for other versions.
4+
Works with Python 3.6, 3.7, 3.8, and 3.9 untested for other versions.
55

66
## Install
77
### Backend options with pip
@@ -94,6 +94,10 @@ print(result.prediction)
9494
for label, confidence in result.labels:
9595
print(f"{label}: {confidence*100}%")
9696

97+
# Visualize the heatmap of the prediction on the image
98+
# this shows where the model was looking to make its prediction.
99+
heatmap = model.visualize(img)
100+
heatmap.show()
97101
```
98102
Note: model predict functions should be thread-safe. If you find bugs please file an issue.
99103

RELEASE.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
# Release 0.6.0
2+
___
3+
## Breaking Changes
4+
* Refactored the ML backends into sub-folders:
5+
* `TFModel` class: `backends/backend_tf.py -> backends/tf/backend.py`
6+
* `TFLiteModel` class: `backends/backend_tflite.py -> backends/tflite/backend.py`
7+
* `ONNXModel` class: `backends/backend_onnx.py -> backends/onnx/backend.py`
8+
9+
## Bug Fixes and Other Improvements
10+
* Added `Backend` and `ImageBackend` abstract base classes in `backends/backend.py`
11+
* Added ImageBackend classes for each ML backend:
12+
* `TFImageModel` class: `backends/tf/image_backend.py`
13+
* `TFLiteImageModel` class: `backends/tflite/image_backend.py`
14+
* `ONNXImageModel` class: `backends/onnx/image_backend.py`
15+
* Added Grad-CAM++ implementation (`ImageBackend.gradcam_plusplus(image, label) -> np.ndarray`) for visualizing
16+
convolutional neural network heatmaps for explaining why the model predicted a certain label.
17+
_Note:_ Grad-CAM++ only implemented currently in `TFImageModel` for TensorFlow Lobe model exports.
18+
The visualization can be called from the top-level API of `ImageModel` -> `ImageModel.visualize(image)`
19+
20+
121
# Release 0.5.0
222
___
323
## Breaking Changes

setup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
mac_version = None
2121

2222
requirements = [
23-
"pillow~=8.3.1",
24-
"requests"
23+
"pillow~=8.4.0",
24+
"requests",
25+
"matplotlib~=3.4.3",
2526
]
2627
tf_req = "tensorflow~=2.5.0;platform_machine!='armv7l'"
2728
onnx_req = "onnxruntime~=1.8.1;platform_machine!='armv7l'"
@@ -68,7 +69,7 @@
6869

6970
setup(
7071
name="lobe",
71-
version="0.5.0",
72+
version="0.6.0",
7273
description="Lobe Python SDK",
7374
long_description=readme,
7475
long_description_content_type="text/markdown",
@@ -81,6 +82,5 @@
8182
'all': [tf_req, onnx_req],
8283
'tf': [tf_req],
8384
'onnx': [onnx_req],
84-
#'tflite': [tflite_req],
8585
}
8686
)

src/lobe/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
from .signature import Signature
2-
from .model.image_model import ImageModel
2+
from .model.image_model import ImageModel, VizEnum

src/lobe/backends/backend.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Abstract for our backend implementations.
3+
"""
4+
from abc import ABC, abstractmethod
5+
6+
from ..signature import Signature
7+
from ..results import BackendResult
8+
9+
10+
class Backend(ABC):
11+
def __init__(self, signature: Signature):
12+
self.signature = signature
13+
14+
@abstractmethod
15+
def predict(self, data: any) -> BackendResult:
16+
"""
17+
Predict the outputs by running the data through the model.
18+
19+
data: can be either a single input value (such as an image array), or a dictionary mapping the input
20+
keys from the signature to the data they should be assigned
21+
22+
Returns a dictionary in the form of the signature outputs {Name: value, ...}
23+
"""
24+
pass
25+
26+
27+
class ImageBackend(Backend):
28+
def gradcam_plusplus(self, image, label: str = None):
29+
"""
30+
Return the heatmap from Grad-CAM++
31+
https://arxiv.org/abs/1710.11063
32+
Grad-CAM++: Improved Visual Explanations for Deep Convolutional Networks
33+
Aditya Chattopadhyay, Anirban Sarkar, Prantik Howlader, Vineeth N Balasubramanian
34+
"""
35+
raise NotImplementedError(
36+
f"Image backend {self.__class__.__name__} doesn't have a Grad-CAM++ implementation yet."
37+
)

src/lobe/backends/onnx/__init__.py

Whitespace-only changes.
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
from threading import Lock
2-
from ..signature import Signature
3-
from ..signature_constants import TENSOR_NAME
4-
from ..utils import decode_dict_bytes_as_str
2+
from ...signature import Signature
3+
from ...signature_constants import TENSOR_NAME
4+
from ...utils import decode_dict_bytes_as_str
5+
6+
ONNX_IMPORT_ERROR = """
7+
ERROR: This is an ONNX model and requires onnx runtime to be installed on this device.
8+
Please install lobe-python with lobe[onnx] or lobe[all] options.
9+
If that doesn't work, please go to https://www.onnxruntime.ai/ for install instructions.
10+
"""
511

612
try:
713
import onnxruntime as rt
814

915
except ImportError:
1016
# Needs better error text
11-
raise ImportError(
12-
"ERROR: This is an ONNX model and requires onnx runtime to be installed on this device. Please install lobe-python with lobe[onnx] or lobe[all] options. If that doesn't work, please go to https://www.onnxruntime.ai/ for install instructions."
13-
)
17+
raise ImportError(ONNX_IMPORT_ERROR)
1418

1519

1620
class ONNXModel(object):
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from .backend import ONNXModel
2+
from ..backend import ImageBackend
3+
from ...signature import ImageClassificationSignature
4+
5+
6+
class ONNXImageModel(ONNXModel, ImageBackend):
7+
def __init__(self, signature: ImageClassificationSignature):
8+
super(ONNXModel, self).__init__(signature=signature)
9+
10+
def gradcam_plusplus(self, image, label=None):
11+
super(ONNXImageModel, self).gradcam_plusplus(image=image, label=label)

src/lobe/backends/tf/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)