Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit d9f10aa

Browse files
author
DEKHTIARJonathan
committed
[Benchmarking Py] Addition of NVIDIA Example Model: EfficientDet
1 parent 1458d08 commit d9f10aa

File tree

3 files changed

+415
-0
lines changed

3 files changed

+415
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:
2+
3+
signature_def['__saved_model_init_op']:
4+
The given SavedModel SignatureDef contains the following input(s):
5+
The given SavedModel SignatureDef contains the following output(s):
6+
outputs['__saved_model_init_op'] tensor_info:
7+
dtype: DT_INVALID
8+
shape: unknown_rank
9+
name: NoOp
10+
Method name is:
11+
12+
signature_def['serving_default']:
13+
The given SavedModel SignatureDef contains the following input(s):
14+
inputs['input_1'] tensor_info:
15+
dtype: DT_HALF
16+
shape: (-1, 512, 512, 3)
17+
name: serving_default_input_1:0
18+
The given SavedModel SignatureDef contains the following output(s):
19+
outputs['output_1_1'] tensor_info:
20+
dtype: DT_HALF
21+
shape: (-1, 64, 64, 819)
22+
name: StatefulPartitionedCall:0
23+
outputs['output_1_2'] tensor_info:
24+
dtype: DT_HALF
25+
shape: (-1, 32, 32, 819)
26+
name: StatefulPartitionedCall:1
27+
outputs['output_1_3'] tensor_info:
28+
dtype: DT_HALF
29+
shape: (-1, 16, 16, 819)
30+
name: StatefulPartitionedCall:2
31+
outputs['output_1_4'] tensor_info:
32+
dtype: DT_HALF
33+
shape: (-1, 8, 8, 819)
34+
name: StatefulPartitionedCall:3
35+
outputs['output_1_5'] tensor_info:
36+
dtype: DT_HALF
37+
shape: (-1, 4, 4, 819)
38+
name: StatefulPartitionedCall:4
39+
outputs['output_2_1'] tensor_info:
40+
dtype: DT_HALF
41+
shape: (-1, 64, 64, 36)
42+
name: StatefulPartitionedCall:5
43+
outputs['output_2_2'] tensor_info:
44+
dtype: DT_HALF
45+
shape: (-1, 32, 32, 36)
46+
name: StatefulPartitionedCall:6
47+
outputs['output_2_3'] tensor_info:
48+
dtype: DT_HALF
49+
shape: (-1, 16, 16, 36)
50+
name: StatefulPartitionedCall:7
51+
outputs['output_2_4'] tensor_info:
52+
dtype: DT_HALF
53+
shape: (-1, 8, 8, 36)
54+
name: StatefulPartitionedCall:8
55+
outputs['output_2_5'] tensor_info:
56+
dtype: DT_HALF
57+
shape: (-1, 4, 4, 36)
58+
name: StatefulPartitionedCall:9
59+
Method name is: tensorflow/serving/predict
60+
61+
Concrete Functions:
62+
Function Name: '__call__'
63+
Option #1
64+
Callable with:
65+
Argument #1
66+
inputs: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='inputs')
67+
Argument #2
68+
DType: bool
69+
Value: False
70+
Option #2
71+
Callable with:
72+
Argument #1
73+
input_1: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='input_1')
74+
Argument #2
75+
DType: bool
76+
Value: False
77+
Option #3
78+
Callable with:
79+
Argument #1
80+
input_1: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='input_1')
81+
Argument #2
82+
DType: bool
83+
Value: True
84+
Option #4
85+
Callable with:
86+
Argument #1
87+
inputs: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='inputs')
88+
Argument #2
89+
DType: bool
90+
Value: True
91+
92+
Function Name: '_default_save_signature'
93+
Option #1
94+
Callable with:
95+
Argument #1
96+
input_1: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='input_1')
97+
98+
Function Name: 'call_and_return_all_conditional_losses'
99+
Option #1
100+
Callable with:
101+
Argument #1
102+
input_1: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='input_1')
103+
Argument #2
104+
DType: bool
105+
Value: False
106+
Option #2
107+
Callable with:
108+
Argument #1
109+
inputs: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='inputs')
110+
Argument #2
111+
DType: bool
112+
Value: False
113+
Option #3
114+
Callable with:
115+
Argument #1
116+
input_1: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='input_1')
117+
Argument #2
118+
DType: bool
119+
Value: True
120+
Option #4
121+
Callable with:
122+
Argument #1
123+
inputs: TensorSpec(shape=(None, 512, 512, 3), dtype=tf.float16, name='inputs')
124+
Argument #2
125+
DType: bool
126+
Value: True
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
2+
#
3+
# Copyright 2021 The TensorFlow Authors. All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
# =============================================================================
17+
18+
import os
19+
import sys
20+
21+
import numpy as np
22+
23+
import tensorflow as tf
24+
25+
# Allow import of top level python files
26+
import inspect
27+
28+
currentdir = os.path.dirname(
29+
os.path.abspath(inspect.getfile(inspect.currentframe()))
30+
)
31+
32+
benchmark_base_dir = os.path.dirname(os.path.dirname(currentdir))
33+
sys.path.insert(0, benchmark_base_dir)
34+
35+
from benchmark_args import BaseCommandLineAPI
36+
from benchmark_runner import BaseBenchmarkRunner
37+
38+
39+
class CommandLineAPI(BaseCommandLineAPI):
40+
41+
def __init__(self):
42+
super(CommandLineAPI, self).__init__()
43+
44+
self._parser.add_argument(
45+
"--input_size",
46+
type=int,
47+
default=None,
48+
required=True,
49+
help="Size of input images expected by the model"
50+
)
51+
52+
def _validate_args(self, args):
53+
super(CommandLineAPI, self)._validate_args(args)
54+
55+
# TODO: Remove when proper dataloading is implemented
56+
if not args.use_synthetic_data:
57+
raise ValueError(
58+
"This benchmark does not currently support non-synthetic data "
59+
"--use_synthetic_data"
60+
)
61+
62+
63+
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #
64+
# %%%%%%%%%%%%%%%%% IMPLEMENT MODEL-SPECIFIC FUNCTIONS HERE %%%%%%%%%%%%%%%%%% #
65+
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #
66+
67+
68+
class BenchmarkRunner(BaseBenchmarkRunner):
69+
70+
def get_dataset_batches(self):
71+
"""Returns a list of batches of input samples.
72+
73+
Each batch should be in the form [x, y], where
74+
x is a numpy array of the input samples for the batch, and
75+
y is a numpy array of the expected model outputs for the batch
76+
77+
Returns:
78+
- dataset: a TF Dataset object
79+
- bypass_data_to_eval: any object type that will be passed unmodified to
80+
`evaluate_result()`. If not necessary: `None`
81+
82+
Note: script arguments can be accessed using `self._args.attr`
83+
"""
84+
85+
def decode_and_center_crop(
86+
image_bytes: tf.Tensor, image_size, crop_padding=32
87+
) -> tf.Tensor:
88+
"""Crops to center of image with padding then scales image_size.
89+
90+
Args:
91+
image_bytes: `Tensor` representing an image binary of arbitrary size.
92+
image_size: image height/width dimension.
93+
crop_padding: the padding size to use when centering the crop.
94+
95+
Returns:
96+
A decoded and cropped image `Tensor`.
97+
"""
98+
decoded = image_bytes.dtype != tf.string
99+
shape = (
100+
tf.shape(image_bytes)
101+
if decoded else tf.image.extract_jpeg_shape(image_bytes)
102+
)
103+
image_height = shape[0]
104+
image_width = shape[1]
105+
106+
padded_center_crop_size = tf.cast(
107+
((image_size / (image_size+crop_padding)) *
108+
tf.cast(tf.minimum(image_height, image_width), tf.float32)),
109+
tf.int32
110+
)
111+
112+
offset_height = ((image_height-padded_center_crop_size) + 1) // 2
113+
offset_width = ((image_width-padded_center_crop_size) + 1) // 2
114+
crop_window = tf.stack([
115+
offset_height, offset_width, padded_center_crop_size,
116+
padded_center_crop_size
117+
])
118+
if decoded:
119+
image = tf.image.crop_to_bounding_box(
120+
image_bytes,
121+
offset_height=offset_height,
122+
offset_width=offset_width,
123+
target_height=padded_center_crop_size,
124+
target_width=padded_center_crop_size
125+
)
126+
else:
127+
image = tf.image.decode_and_crop_jpeg(
128+
image_bytes, crop_window, channels=3
129+
)
130+
131+
image = tf.compat.v1.image.resize(
132+
image, [image_size, image_size],
133+
method=tf.image.ResizeMethod.BILINEAR,
134+
align_corners=False
135+
)
136+
137+
return image
138+
139+
def preprocess(
140+
image_bytes,
141+
label,
142+
image_size,
143+
num_channels=3,
144+
num_classes=1000,
145+
dtype=tf.float32,
146+
) -> tf.Tensor:
147+
"""Preprocesses the given image for evaluation.
148+
149+
Args:
150+
image_bytes: `Tensor` representing an image binary of arbitrary size.
151+
image_size: image height/width dimension.
152+
num_channels: number of image input channels.
153+
mean_subtract: whether or not to apply mean subtraction.
154+
standardize: whether or not to apply standardization.
155+
dtype: the dtype to convert the images to. Set to `None` to skip conversion.
156+
157+
Returns:
158+
A preprocessed and normalized image `Tensor`.
159+
"""
160+
images = decode_and_center_crop(
161+
image_bytes, image_size=image_size, crop_padding=32
162+
)
163+
images = tf.reshape(images, [image_size, image_size, num_channels])
164+
165+
if dtype is not None:
166+
images = tf.image.convert_image_dtype(images, dtype=dtype)
167+
label = tf.one_hot(label, num_classes)
168+
label = tf.reshape(label, [num_classes])
169+
return images, label
170+
171+
def parse_record(record, image_size):
172+
"""Parse an ImageNet record from a serialized string Tensor."""
173+
keys_to_features = {
174+
'image/encoded': tf.io.FixedLenFeature((), tf.string, ''),
175+
'image/format': tf.io.FixedLenFeature((), tf.string, 'jpeg'),
176+
'image/class/label': tf.io.FixedLenFeature([], tf.int64, -1),
177+
'image/class/text': tf.io.FixedLenFeature([], tf.string, ''),
178+
'image/object/bbox/xmin': tf.io.VarLenFeature(dtype=tf.float32),
179+
'image/object/bbox/ymin': tf.io.VarLenFeature(dtype=tf.float32),
180+
'image/object/bbox/xmax': tf.io.VarLenFeature(dtype=tf.float32),
181+
'image/object/bbox/ymax': tf.io.VarLenFeature(dtype=tf.float32),
182+
'image/object/class/label': tf.io.VarLenFeature(dtype=tf.int64),
183+
}
184+
185+
parsed = tf.io.parse_single_example(record, keys_to_features)
186+
187+
label = tf.reshape(parsed['image/class/label'], shape=[1])
188+
label = tf.cast(label, dtype=tf.int32)
189+
190+
# Subtract one so that labels are in [0, 1000)
191+
label -= 1
192+
193+
image_bytes = tf.reshape(parsed['image/encoded'], shape=[])
194+
image, label = preprocess(image_bytes, label, image_size)
195+
196+
# populate features and labels dict
197+
features = dict()
198+
features['input_1'] = tf.cast(image, dtype=tf.float16)
199+
# features['is_tr_split'] = [False]
200+
# features['cutmix_mask'] = tf.zeros((image_size, image_size, 1))
201+
# features['mixup_weight'] = tf.ones((1, 1, 1))
202+
return features, label
203+
204+
file_pattern = os.path.join(self._args.data_dir, 'validation*')
205+
dataset = tf.data.Dataset.list_files(file_pattern, shuffle=False)
206+
207+
dataset = dataset.interleave(
208+
tf.data.TFRecordDataset,
209+
cycle_length=10,
210+
block_length=1,
211+
num_parallel_calls=tf.data.AUTOTUNE
212+
)
213+
214+
parse_record_fn = lambda record: parse_record(
215+
record=record, image_size=self._args.input_size
216+
)
217+
dataset = dataset.map(
218+
parse_record_fn, num_parallel_calls=tf.data.AUTOTUNE
219+
)
220+
dataset = dataset.batch(self._args.batch_size, drop_remainder=False)
221+
dataset = dataset.prefetch(buffer_size=tf.data.AUTOTUNE)
222+
223+
return dataset, None
224+
225+
def preprocess_model_inputs(self, data_batch):
226+
"""This function prepare the `data_batch` generated from the dataset.
227+
Returns:
228+
x: input of the model
229+
y: data to be used for model evaluation
230+
231+
Note: script arguments can be accessed using `self._args.attr`
232+
"""
233+
234+
x, y = data_batch
235+
236+
return x, y
237+
238+
def postprocess_model_outputs(self, predictions, expected):
239+
"""Post process if needed the predictions and expected tensors. At the
240+
minimum, this function transforms all TF Tensors into a numpy arrays.
241+
Most models will not need to modify this function.
242+
243+
Note: script arguments can be accessed using `self._args.attr`
244+
"""
245+
246+
predictions_np = {k: v.numpy() for k, v in predictions.items()}
247+
expected_np = expected.numpy()
248+
249+
return predictions_np, expected_np
250+
251+
def evaluate_model(self, predictions, expected, bypass_data_to_eval):
252+
"""Evaluate result predictions for entire dataset.
253+
254+
This computes overall accuracy, mAP, etc. Returns the
255+
metric value and a metric_units string naming the metric.
256+
257+
Note: script arguments can be accessed using `self._args.attr`
258+
"""
259+
260+
return None, "Top-1 Accuracy %"
261+
262+
263+
if __name__ == '__main__':
264+
265+
cmdline_api = CommandLineAPI()
266+
args = cmdline_api.parse_args()
267+
268+
runner = BenchmarkRunner(args)
269+
270+
runner.execute_benchmark()

0 commit comments

Comments
 (0)