Skip to content

Commit

Permalink
Merge pull request #30 from ARM-software/add_ssd_mobilenet_v1_int8
Browse files Browse the repository at this point in the history
Added SSD MobileNet v1 INT8
  • Loading branch information
tom-arm authored Aug 24, 2021
2 parents a97add6 + 37bf60d commit 21032c1
Show file tree
Hide file tree
Showing 21 changed files with 621 additions and 12 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@
<th width="100">Mali GPU</th>
<th width="100">Ethos U</th>
</tr>
<tr>
<td><a href = "models/object_detection/ssd_mobilenet_v1/tflite_int8">SSD MobileNet v1 INT8 *</a></td>
<td align="center">INT8</td>
<td align="center">TensorFlow Lite</td>
<td align="center">:heavy_check_mark:</td>
<td align="center">:heavy_multiplication_x:</td>
<td align="center">:heavy_check_mark:</td>
<td align="center">:heavy_multiplication_x:</td>
</tr>
<tr>
<td><a href="models/object_detection/ssd_mobilenet_v1/tflite_fp32">SSD MobileNet v1 FP32 *</a></td>
<td align="center">FP32</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
git clone --depth 1 https://github.com/tensorflow/models.git ./tf_models
cp tf_models/research/object_detection/data/mscoco_label_map.pbtxt .

python scripts/export_labels.py --path mscoco_label_map.pbtxt
python scripts/export_labels.py --path mscoco_label_map.pbtxt --num_classes 90
tr -d \" < temp.txt > labelmapping.txt
rm -rf temp.txt mscoco_label_map.pbtxt
rm -rf ./tf_models
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import argparse
import collections
import sys

def read_label_map(label_map_path):
item_id = None
Expand All @@ -42,24 +41,30 @@ def read_label_map(label_map_path):

return items

def convert_dictionary_to_list(d):
def convert_dictionary_to_list(d, num_classes):
output_list = []
# order dictionary by keys
d = collections.OrderedDict(sorted(d.items()))
for k, v in d.items():
output_list.append(v)

for c in range(num_classes):
if c + 1 in d:
output_list.append(d[c + 1])
else:
output_list.append('')

return output_list


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Process ImageNet labels.")
parser.add_argument("--path", type=str, required=True)
parser.add_argument("--num_classes", type=int, required=True)

args = parser.parse_args()

items = read_label_map(args.path)
items = convert_dictionary_to_list(items)
items = convert_dictionary_to_list(items, args.num_classes)

with open("temp.txt", "w") as f:
for item in items:
f.write("%s\n" % item)
91 changes: 91 additions & 0 deletions models/object_detection/ssd_mobilenet_v1/tflite_int8/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# SSD MobileNet v1 INT8

## Description
SSD MobileNet v1 is a object detection network, that localizes and identifies objects in an input image. This is a TF Lite quantized version that takes a 300x300 input image and outputs detections for this image. This model is converted from FP32 to INT8 using post-training quantization.

## License
[Apache-2.0](https://spdx.org/licenses/Apache-2.0.html)

## Related Materials
### Class Labels
The class labels associated with this model can be downloaded by running the script `get_class_labels.sh`.

### Model Recreation Code
Code to recreate this model can be found [here](recreate_model/).


## Network Information
| Network Information | Value |
|---------------------|----------------|
| Framework | TensorFlow Lite |
| SHA-1 Hash | fef68428bd439b70eb983b57d6a342871fa0deaa |
| Size (Bytes) | 7311392 |
| Provenance | https://arxiv.org/abs/1512.02325 |
| Paper | https://arxiv.org/abs/1512.02325 |

## Performance
| Platform | Optimized |
|----------|:---------:|
| Cortex-A |:heavy_check_mark: |
| Cortex-M |:heavy_multiplication_x: |
| Mali GPU |:heavy_check_mark: |
| Ethos U |:heavy_multiplication_x: |

### Key
* :heavy_check_mark: - Will run on this platform.
* :heavy_multiplication_x: - Will not run on this platform.

## Accuracy
Dataset: COCO 2017 Validation

| Metric | Value |
|--------|-------|
| mAP | 0.234 |

## Optimizations
| Optimization | Value |
|--------------|---------|
| Quantization | INT8 |

## Network Inputs
<table>
<tr>
<th width="200">Input Node Name</th>
<th width="100">Shape</th>
<th width="300">Description</th>
</tr>
<tr>
<td>tfl.quantize</td>
<td>(1, 300, 300, 3)</td>
<td>A resized and normalized input image.</td>
</tr>
</table>

## Network Outputs
<table>
<tr>
<th width="200">Output Node Name</th>
<th width="100">Shape</th>
<th width="300">Description</th>
</tr>
<tr>
<td>TFLite_Detection_PostProcess:01</td>
<td>()</td>
<td>The y1, x1, y2, x2 coordinates of the bounding boxes for each detection</td>
</tr>
<tr>
<td>TFLite_Detection_PostProcess:02</td>
<td>()</td>
<td>The class of each detection</td>
</tr>
<tr>
<td>TFLite_Detection_PostProcess:03</td>
<td>()</td>
<td>The probability score for each classification</td>
</tr>
<tr>
<td>TFLite_Detection_PostProcess:04</td>
<td>()</td>
<td>A vector containing a number corresponding to the number of detections</td>
</tr>
</table>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
benchmark:
COCO 2017 Validation:
mAP: '0.234'
description: SSD MobileNet v1 is a object detection network, that localizes and identifies
objects in an input image. This is a TF Lite quantized version that takes a 300x300
input image and outputs detections for this image. This model is converted from
FP32 to INT8 using post-training quantization.
license:
- Apache-2.0
network:
file_size_bytes: 7311392
filename: ssd_mobilenet_v1.tflite
framework: TensorFlow Lite
hash:
algorithm: sha1
value: fef68428bd439b70eb983b57d6a342871fa0deaa
provenance: https://arxiv.org/abs/1512.02325
network_parameters:
input_nodes:
- description: A resized and normalized input image.
example_input:
path: models/object_detection/ssd_mobilenet_v1/tflite_int8/testing_input/tfl.quantize
name: tfl.quantize
shape:
- 1
- 300
- 300
- 3
output_nodes:
- description: The y1, x1, y2, x2 coordinates of the bounding boxes for each detection
name: TFLite_Detection_PostProcess:01
shape: []
test_output_path: models/object_detection/ssd_mobilenet_v1/tflite_int8/testing_output/TFLite_Detection_PostProcess:01
- description: The class of each detection
name: TFLite_Detection_PostProcess:02
shape: []
test_output_path: models/object_detection/ssd_mobilenet_v1/tflite_int8/testing_output/TFLite_Detection_PostProcess:02
- description: The probability score for each classification
name: TFLite_Detection_PostProcess:03
shape: []
test_output_path: models/object_detection/ssd_mobilenet_v1/tflite_int8/testing_output/TFLite_Detection_PostProcess:03
- description: A vector containing a number corresponding to the number of detections
name: TFLite_Detection_PostProcess:04
shape: []
test_output_path: models/object_detection/ssd_mobilenet_v1/tflite_int8/testing_output/TFLite_Detection_PostProcess:04
operators:
TensorFlow Lite:
- CONCATENATION
- CONV_2D
- CUSTOM
- DEPTHWISE_CONV_2D
- DEQUANTIZE
- LOGISTIC
- QUANTIZE
- RELU6
- RESHAPE
paper: https://arxiv.org/abs/1512.02325
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (C) 2021 Arm Limited or its affiliates. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the License); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#!/usr/bin/env bash

git clone --depth 1 https://github.com/tensorflow/models.git ./tf_models
cp tf_models/research/object_detection/data/mscoco_label_map.pbtxt .

python scripts/export_labels.py --path mscoco_label_map.pbtxt --num_classes 90
tr -d \" < temp.txt > labelmapping.txt
rm -rf temp.txt mscoco_label_map.pbtxt
rm -rf ./tf_models
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SSD MobileNet v1 INT8 Re-Creation
This folder contains scripts that allow you to re-create the model and benchmark it's performance.

## Requirements
The scripts in this folder requires that the following must be installed:
- Python 3.7
- protoc

## Running The Script
### Recreate The Model
Run the following command in a terminal: `./quantize_ssd_mobilenet_v1.sh`

### Benchmarking The Model
Run the following command in a terminal: `./benchmark_ssd_mobilenet_v1.sh`
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Copyright (C) 2021 Arm Limited or its affiliates. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the License); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse

import numpy as np
import tensorflow_datasets as tfds
import tensorflow as tf

from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval

detections = []

# Yields the image pre-processed with it's class
def coco_generator(coco_dataset, input_size=(300, 300)):
for item in coco_dataset:
image = item['image']
image = tf.image.resize(image, input_size)
image = tf.expand_dims(image, 0)

# MobileNet pre-processing
image = (image / 255. - 0.5) * 2

yield image, item['image/id'], item['image'].shape


def __convert_to_coco_bbox(b, input_size):
# For COCO it is [x, y, width, height]
# The bounding box b is of type: [ymin, xmin, ymax, xmax]
x = b[1] * input_size[1]
y = b[0] * input_size[0]
width = (b[3] - b[1]) * input_size[1]
height = (b[2] - b[0]) * input_size[0]

return [x, y, width, height]


def process_output(output, image_id, image_size):
detection_boxes, detection_classes, detection_scores, num_detections = output

detections_in_image = []
for i in range(int(num_detections[0])):
detections_in_image.append(
{
'image_id': image_id.numpy(),
'category_id': int(detection_classes[0, i]) + 1,
'bbox': __convert_to_coco_bbox(detection_boxes[0, i], image_size),
'score': detection_scores[0, i]
}
)

return detections_in_image


if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Benchmark SSD MobileNet v1.')
parser.add_argument('--path', type=str, help='Path to the model.')

args = parser.parse_args()

# Get the COCO 2017 validation set
coco_dataset = tfds.load('coco/2017', split='validation')

# Setup the TensorFlow Lite interpreter
interpreter = tf.lite.Interpreter(model_path=args.path)
interpreter.allocate_tensors()

input_node = interpreter.get_input_details()[0]
input_t = input_node['index']
output_t = [details['index'] for details in interpreter.get_output_details()]

for data, data_id, image_shape in coco_generator(coco_dataset):
# Quantize the input data
scale = input_node["quantization_parameters"]["scales"]
zero_point = input_node["quantization_parameters"]["zero_points"]

data = data / scale
data += zero_point

numpy_data = tf.cast(data, tf.int8).numpy()
interpreter.set_tensor(input_t, numpy_data)
interpreter.invoke()

output = [ interpreter.get_tensor(o) for o in output_t ]

detection_outputs = process_output(output, data_id, (image_shape[0], image_shape[1]))
detections += detection_outputs

# Use the COCO API to measure the accuracy on the annotations
coco_ground_truth = COCO('./annotations/instances_val2017.json')
coco_results = coco_ground_truth.loadRes(detections)

coco_eval = COCOeval(coco_ground_truth, coco_results, 'bbox')

image_ids = [d['image_id'] for d in detections]
coco_eval.params.imgIds = image_ids

coco_eval.evaluate()
coco_eval.accumulate()
coco_eval.summarize()
Loading

0 comments on commit 21032c1

Please sign in to comment.