Skip to content

Commit 80973df

Browse files
Sachin Joglekartensorflower-gardener
Sachin Joglekar
authored andcommitted
Fix evaluation tooling issues with the MessageLite proto change. Also rectify documentation accordingly.
PiperOrigin-RevId: 307060347 Change-Id: I08cf9887d9960965aee7b60af5287d077a4cafc5
1 parent 8a70938 commit 80973df

File tree

11 files changed

+206
-208
lines changed

11 files changed

+206
-208
lines changed

tensorflow/lite/tools/evaluation/stages/BUILD

-1
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,5 @@ cc_library(
232232
"//tensorflow/lite/tools/evaluation/proto:evaluation_config_cc_proto",
233233
"//tensorflow/lite/tools/evaluation/proto:evaluation_stages_cc_proto",
234234
"@com_google_absl//absl/container:flat_hash_map",
235-
"@com_google_protobuf//:protobuf_headers",
236235
],
237236
)

tensorflow/lite/tools/evaluation/stages/object_detection_stage.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ limitations under the License.
1616

1717
#include <fstream>
1818

19-
#include "google/protobuf/text_format.h"
2019
#include "tensorflow/core/platform/logging.h"
2120
#include "tensorflow/lite/c/common.h"
2221
#include "tensorflow/lite/tools/evaluation/proto/evaluation_config.pb.h"
@@ -171,7 +170,7 @@ TfLiteStatus PopulateGroundTruth(
171170
std::string proto_str((std::istreambuf_iterator<char>(t)),
172171
std::istreambuf_iterator<char>());
173172
ObjectDetectionGroundTruth ground_truth_proto;
174-
google::protobuf::TextFormat::ParseFromString(proto_str, &ground_truth_proto);
173+
ground_truth_proto.ParseFromString(proto_str);
175174

176175
for (const auto& image_ground_truth :
177176
ground_truth_proto.detection_results()) {

tensorflow/lite/tools/evaluation/tasks/coco_object_detection/BUILD

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ cc_binary(
2929
"//conditions:default": [],
3030
}),
3131
deps = [
32-
"//tensorflow/core:tflite_portable_logging",
3332
"//tensorflow/lite/c:common",
3433
"//tensorflow/lite/tools:command_line_flags",
34+
"//tensorflow/lite/tools:logging",
3535
"//tensorflow/lite/tools/evaluation:evaluation_delegate_provider",
3636
"//tensorflow/lite/tools/evaluation:evaluation_stage",
3737
"//tensorflow/lite/tools/evaluation:utils",

tensorflow/lite/tools/evaluation/tasks/coco_object_detection/README.md

+54-74
Original file line numberDiff line numberDiff line change
@@ -11,75 +11,23 @@ This binary evaluates the following parameters of TFLite models trained for the
1111

1212
The binary takes the path to validation images and a ground truth proto file as
1313
inputs, along with the model and inference-specific parameters such as delegate
14-
and number of threads. It outputs the metrics as a text proto to a file, similar
15-
to the following:
14+
and number of threads. It outputs the metrics to std-out as follows:
1615

1716
```
18-
num_runs: 8059
19-
process_metrics {
20-
object_detection_metrics {
21-
pre_processing_latency {
22-
last_us: 27197
23-
max_us: 61372
24-
min_us: 6166
25-
sum_us: 189403170
26-
avg_us: 23502.068494850479
27-
}
28-
inference_latency {
29-
last_us: 386378
30-
max_us: 412804
31-
min_us: 378841
32-
sum_us: 3122849071
33-
avg_us: 387498.33366422635 # Average Inference Latency.
34-
}
35-
inference_metrics {
36-
num_inferences: 8059 # Number of images evaluated.
37-
}
38-
average_precision_metrics {
39-
individual_average_precisions {
40-
iou_threshold: 0.5
41-
average_precision: 0.26113987
42-
}
43-
individual_average_precisions {
44-
iou_threshold: 0.55
45-
average_precision: 0.2456704
46-
}
47-
individual_average_precisions {
48-
iou_threshold: 0.6
49-
average_precision: 0.22885525
50-
}
51-
individual_average_precisions {
52-
iou_threshold: 0.65
53-
average_precision: 0.20678344
54-
}
55-
individual_average_precisions {
56-
iou_threshold: 0.7
57-
average_precision: 0.18185228
58-
}
59-
individual_average_precisions {
60-
iou_threshold: 0.75
61-
average_precision: 0.14681709 # AP at IoU threshold of 0.75.
62-
}
63-
individual_average_precisions {
64-
iou_threshold: 0.8
65-
average_precision: 0.107850626
66-
}
67-
individual_average_precisions {
68-
iou_threshold: 0.85
69-
average_precision: 0.061735578
70-
}
71-
individual_average_precisions {
72-
iou_threshold: 0.9
73-
average_precision: 0.017980274
74-
}
75-
individual_average_precisions {
76-
iou_threshold: 0.95
77-
average_precision: 0.0010084915
78-
}
79-
overall_mean_average_precision: 0.14596924 # Overall mAP average.
80-
}
81-
}
82-
}
17+
Num evaluation runs: 8059
18+
Preprocessing latency: avg=16589.9(us), std_dev=0(us)
19+
Inference latency: avg=85169.7(us), std_dev=505(us)
20+
Average Precision [IOU Threshold=0.5]: 0.349581
21+
Average Precision [IOU Threshold=0.55]: 0.330213
22+
Average Precision [IOU Threshold=0.6]: 0.307694
23+
Average Precision [IOU Threshold=0.65]: 0.281025
24+
Average Precision [IOU Threshold=0.7]: 0.248507
25+
Average Precision [IOU Threshold=0.75]: 0.210295
26+
Average Precision [IOU Threshold=0.8]: 0.165011
27+
Average Precision [IOU Threshold=0.85]: 0.116215
28+
Average Precision [IOU Threshold=0.9]: 0.0507883
29+
Average Precision [IOU Threshold=0.95]: 0.0064338
30+
Overall mAP: 0.206576
8331
```
8432

8533
To run the binary, please follow the
@@ -135,15 +83,47 @@ The following optional parameters can be used to modify the inference runtime:
13583
assumes that `libhexagon_interface.so` and Qualcomm libraries lie in
13684
`/data/local/tmp`.
13785

86+
This script also supports all applicable runtime/delegate arguments supported on
87+
the `benchmark_model` tool. If there is any conflict (for example, `num_threads`
88+
in `benchmark_model` vs `num_interpreter_threads` here), the parameters of this
89+
script are given precedence.
90+
13891
### Debug Mode
13992

14093
The script also supports a debug mode with the following parameter:
14194

14295
* `debug_mode`: `boolean` \
143-
Whether to enable debug mode. Per-image predictions are written to the
144-
output file along with metrics. NOTE: Its not possible to parse the output
145-
file as a proto in this mode, since it contains demarcations between
146-
per-file outputs for readability.
96+
Whether to enable debug mode. Per-image predictions are written to std-out
97+
along with metrics.
98+
99+
Image-wise predictions are output as follows:
100+
101+
```
102+
======================================================
103+
104+
Image: image_1.jpg
105+
106+
Object [0]
107+
Score: 0.585938
108+
Class-ID: 5
109+
Bounding Box:
110+
Normalized Top: 0.23103
111+
Normalized Bottom: 0.388524
112+
Normalized Left: 0.559144
113+
Normalized Right: 0.763928
114+
Object [1]
115+
Score: 0.574219
116+
Class-ID: 5
117+
Bounding Box:
118+
Normalized Top: 0.269571
119+
Normalized Bottom: 0.373971
120+
Normalized Left: 0.613175
121+
Normalized Right: 0.760507
122+
======================================================
123+
124+
Image: image_2.jpg
125+
...
126+
```
147127

148128
This mode lets you debug the output of an object detection model that isn't
149129
necessarily trained on the COCO dataset (by leaving `ground_truth_proto` empty).
@@ -187,7 +167,7 @@ The script generates the following within the output folder:
187167

188168
* `images/`: the resulting subset of the 2014 COCO Validation images.
189169

190-
* `ground_truth.pbtxt`: a `.pbtxt` (text proto) file holding
170+
* `ground_truth.pb`: a `.pb` (binary-format proto) file holding
191171
`tflite::evaluation::ObjectDetectionGroundTruth` corresponding to image
192172
subset.
193173

@@ -248,7 +228,7 @@ adb push /path/to/output/folder /data/local/tmp/coco_validation
248228
adb shell /data/local/tmp/run_eval \
249229
--model_file=/data/local/tmp/ssd_mobilenet_v1_float.tflite \
250230
--ground_truth_images_path=/data/local/tmp/coco_validation/images \
251-
--ground_truth_proto=/data/local/tmp/coco_validation/ground_truth.pbtxt \
231+
--ground_truth_proto=/data/local/tmp/coco_validation/ground_truth.pb \
252232
--model_output_labels=/data/local/tmp/labelmap.txt \
253233
--output_file_path=/data/local/tmp/coco_output.txt
254234
```
@@ -266,7 +246,7 @@ bazel run -c opt \
266246
//tensorflow/lite/tools/evaluation/tasks/coco_object_detection:run_eval \
267247
--model_file=/path/to/ssd_mobilenet_v1_float.tflite \
268248
--ground_truth_images_path=/path/to/images \
269-
--ground_truth_proto=/path/to/ground_truth.pbtxt \
249+
--ground_truth_proto=/path/to/ground_truth.pb \
270250
--model_output_labels=/path/to/labelmap.txt \
271251
--output_file_path=/path/to/coco_output.txt
272252
```

tensorflow/lite/tools/evaluation/tasks/coco_object_detection/preprocess_coco_minival.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ def _dump_data(ground_truth_detections, images_folder_path, output_folder_path):
134134
135135
The following are created in output_folder_path:
136136
images/: sub-folder for whitelisted validation images.
137-
ground_truth.pbtxt: A text proto file containing all ground-truth
137+
ground_truth.pb: A binary proto file containing all ground-truth
138138
object-sets.
139139
140140
Args:
@@ -149,7 +149,7 @@ def _dump_data(ground_truth_detections, images_folder_path, output_folder_path):
149149
output_images_folder = os.path.join(output_folder_path, 'images')
150150
if not os.path.exists(output_images_folder):
151151
os.makedirs(output_images_folder)
152-
output_proto_file = os.path.join(output_folder_path, 'ground_truth.pbtxt')
152+
output_proto_file = os.path.join(output_folder_path, 'ground_truth.pb')
153153

154154
ground_truth_data = evaluation_stages_pb2.ObjectDetectionGroundTruth()
155155
for image_dict in ground_truth_detections.values():
@@ -170,8 +170,8 @@ def _dump_data(ground_truth_detections, images_folder_path, output_folder_path):
170170
output_images_folder)
171171

172172
# Dump proto.
173-
with open(output_proto_file, 'w') as proto_file:
174-
proto_file.write(str(ground_truth_data))
173+
with open(output_proto_file, 'wb') as proto_file:
174+
proto_file.write(ground_truth_data.SerializeToString())
175175

176176

177177
def _parse_args():

tensorflow/lite/tools/evaluation/tasks/coco_object_detection/run_eval.cc

+55-16
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ limitations under the License.
1818
#include <vector>
1919

2020
#include "absl/container/flat_hash_map.h"
21-
#include "tensorflow/core/platform/logging.h"
2221
#include "tensorflow/lite/c/common.h"
2322
#include "tensorflow/lite/tools/command_line_flags.h"
2423
#include "tensorflow/lite/tools/evaluation/evaluation_delegate_provider.h"
2524
#include "tensorflow/lite/tools/evaluation/proto/evaluation_config.pb.h"
2625
#include "tensorflow/lite/tools/evaluation/proto/evaluation_stages.pb.h"
2726
#include "tensorflow/lite/tools/evaluation/stages/object_detection_stage.h"
2827
#include "tensorflow/lite/tools/evaluation/utils.h"
28+
#include "tensorflow/lite/tools/logging.h"
2929

3030
namespace tflite {
3131
namespace evaluation {
@@ -62,7 +62,7 @@ bool EvaluateModel(const std::string& model_file_path,
6262
inference_params->set_delegate(ParseStringToDelegateType(delegate));
6363
if (!delegate.empty() &&
6464
inference_params->delegate() == TfliteInferenceParams::NONE) {
65-
LOG(WARNING) << "Unsupported TFLite delegate: " << delegate;
65+
TFLITE_LOG(WARN) << "Unsupported TFLite delegate: " << delegate;
6666
return false;
6767
}
6868

@@ -77,14 +77,10 @@ bool EvaluateModel(const std::string& model_file_path,
7777
eval.SetAllLabels(model_labels);
7878
if (eval.Init(&delegate_providers) != kTfLiteOk) return false;
7979

80-
// Open output file for writing.
81-
std::ofstream ofile;
82-
ofile.open(output_file_path, std::ios::out);
83-
8480
const int step = image_paths.size() / 100;
8581
for (int i = 0; i < image_paths.size(); ++i) {
8682
if (step > 1 && i % step == 0) {
87-
LOG(INFO) << "Finished: " << i / step << "%";
83+
TFLITE_LOG(INFO) << "Finished: " << i / step << "%";
8884
}
8985

9086
const std::string image_name = GetNameFromPath(image_paths[i]);
@@ -93,22 +89,65 @@ bool EvaluateModel(const std::string& model_file_path,
9389

9490
if (debug_mode) {
9591
ObjectDetectionResult prediction = *eval.GetLatestPrediction();
96-
prediction.set_image_name(image_name);
97-
ofile << prediction.DebugString();
98-
ofile << "======================================================\n";
92+
TFLITE_LOG(INFO) << "Image: " << image_name << "\n";
93+
for (int i = 0; i < prediction.objects_size(); ++i) {
94+
const auto& object = prediction.objects(i);
95+
TFLITE_LOG(INFO) << "Object [" << i << "]";
96+
TFLITE_LOG(INFO) << " Score: " << object.score();
97+
TFLITE_LOG(INFO) << " Class-ID: " << object.class_id();
98+
TFLITE_LOG(INFO) << " Bounding Box:";
99+
const auto& bounding_box = object.bounding_box();
100+
TFLITE_LOG(INFO) << " Normalized Top: "
101+
<< bounding_box.normalized_top();
102+
TFLITE_LOG(INFO) << " Normalized Bottom: "
103+
<< bounding_box.normalized_bottom();
104+
TFLITE_LOG(INFO) << " Normalized Left: "
105+
<< bounding_box.normalized_left();
106+
TFLITE_LOG(INFO) << " Normalized Right: "
107+
<< bounding_box.normalized_right();
108+
}
109+
TFLITE_LOG(INFO)
110+
<< "======================================================\n";
99111
}
100112
}
101113

102114
// Write metrics to file.
103-
EvaluationStageMetrics metrics = eval.LatestMetrics();
115+
EvaluationStageMetrics latest_metrics = eval.LatestMetrics();
104116
if (ground_truth_proto_file.empty()) {
105117
// mAP metrics are meaningless for no ground truth.
106-
metrics.mutable_process_metrics()
118+
latest_metrics.mutable_process_metrics()
107119
->mutable_object_detection_metrics()
108120
->clear_average_precision_metrics();
109121
}
110-
ofile << metrics.DebugString();
111-
ofile.close();
122+
if (!output_file_path.empty()) {
123+
std::ofstream metrics_ofile;
124+
metrics_ofile.open(output_file_path, std::ios::out);
125+
metrics_ofile << latest_metrics.SerializeAsString();
126+
metrics_ofile.close();
127+
}
128+
TFLITE_LOG(INFO) << "Num evaluation runs: " << latest_metrics.num_runs();
129+
const auto object_detection_metrics =
130+
latest_metrics.process_metrics().object_detection_metrics();
131+
const auto& preprocessing_latency =
132+
object_detection_metrics.pre_processing_latency();
133+
TFLITE_LOG(INFO) << "Preprocessing latency: avg="
134+
<< preprocessing_latency.avg_us() << "(us), std_dev="
135+
<< preprocessing_latency.std_deviation_us() << "(us)";
136+
const auto& inference_latency = object_detection_metrics.inference_latency();
137+
TFLITE_LOG(INFO) << "Inference latency: avg=" << inference_latency.avg_us()
138+
<< "(us), std_dev=" << inference_latency.std_deviation_us()
139+
<< "(us)";
140+
const auto& precision_metrics =
141+
object_detection_metrics.average_precision_metrics();
142+
for (int i = 0; i < precision_metrics.individual_average_precisions_size();
143+
++i) {
144+
const auto ap_metric = precision_metrics.individual_average_precisions(i);
145+
TFLITE_LOG(INFO) << "Average Precision [IOU Threshold="
146+
<< ap_metric.iou_threshold()
147+
<< "]: " << ap_metric.average_precision();
148+
}
149+
TFLITE_LOG(INFO) << "Overall mAP: "
150+
<< precision_metrics.overall_mean_average_precision();
112151

113152
return true;
114153
}
@@ -167,14 +206,14 @@ int Main(int argc, char* argv[]) {
167206

168207
std::vector<std::string> model_labels;
169208
if (!ReadFileLines(model_output_labels_path, &model_labels)) {
170-
LOG(ERROR) << "Could not read model output labels file";
209+
TFLITE_LOG(ERROR) << "Could not read model output labels file";
171210
return EXIT_FAILURE;
172211
}
173212

174213
if (!EvaluateModel(model_file_path, model_labels, image_paths,
175214
ground_truth_proto_file, delegate, output_file_path,
176215
num_interpreter_threads, debug_mode, delegate_providers)) {
177-
LOG(ERROR) << "Could not evaluate model";
216+
TFLITE_LOG(ERROR) << "Could not evaluate model";
178217
return EXIT_FAILURE;
179218
}
180219

tensorflow/lite/tools/evaluation/tasks/imagenet_image_classification/BUILD

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ cc_binary(
2222
copts = tflite_copts(),
2323
linkopts = common_linkopts,
2424
deps = [
25-
"//tensorflow/core:tflite_portable_logging",
2625
"//tensorflow/lite/c:common",
2726
"//tensorflow/lite/tools:command_line_flags",
27+
"//tensorflow/lite/tools:logging",
2828
"//tensorflow/lite/tools/evaluation:evaluation_delegate_provider",
2929
"//tensorflow/lite/tools/evaluation:evaluation_stage",
3030
"//tensorflow/lite/tools/evaluation:utils",

0 commit comments

Comments
 (0)