Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ModelZoo
ResNet50_tensorflow
Commits
83a9a239
Unverified
Commit
83a9a239
authored
Aug 10, 2018
by
Taylor Robie
Committed by
GitHub
Aug 10, 2018
Browse files
remove fork of object_detection created for MLPerf. (#4840)
parent
ad3526a9
Changes
172
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
0 additions
and
4524 deletions
+0
-4524
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder.py
...ion/Mask_RCNN/object_detection/builders/losses_builder.py
+0
-222
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder_test.py
...ask_RCNN/object_detection/builders/losses_builder_test.py
+0
-488
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder.py
...on/Mask_RCNN/object_detection/builders/matcher_builder.py
+0
-53
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder_test.py
...sk_RCNN/object_detection/builders/matcher_builder_test.py
+0
-99
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder.py
...tion/Mask_RCNN/object_detection/builders/model_builder.py
+0
-377
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder_test.py
...Mask_RCNN/object_detection/builders/model_builder_test.py
+0
-1056
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder.py
.../Mask_RCNN/object_detection/builders/optimizer_builder.py
+0
-124
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder_test.py
..._RCNN/object_detection/builders/optimizer_builder_test.py
+0
-208
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder.py
...RCNN/object_detection/builders/post_processing_builder.py
+0
-123
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder_test.py
...object_detection/builders/post_processing_builder_test.py
+0
-107
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder.py
...sk_RCNN/object_detection/builders/preprocessor_builder.py
+0
-322
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder_test.py
...NN/object_detection/builders/preprocessor_builder_test.py
+0
-566
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder.py
...etection/builders/region_similarity_calculator_builder.py
+0
-56
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder_test.py
...ion/builders/region_similarity_calculator_builder_test.py
+0
-67
research/mlperf_object_detection/Mask_RCNN/object_detection/core/__init__.py
...ect_detection/Mask_RCNN/object_detection/core/__init__.py
+0
-1
research/mlperf_object_detection/Mask_RCNN/object_detection/core/anchor_generator.py
...ction/Mask_RCNN/object_detection/core/anchor_generator.py
+0
-150
research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler.py
...ject_detection/core/balanced_positive_negative_sampler.py
+0
-105
research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler_test.py
...detection/core/balanced_positive_negative_sampler_test.py
+0
-106
research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher.py
...ject_detection/Mask_RCNN/object_detection/core/batcher.py
+0
-136
research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher_test.py
...detection/Mask_RCNN/object_detection/core/batcher_test.py
+0
-158
No files found.
Too many changes to show.
To preserve performance only
172 of 172+
files are displayed.
Plain diff
Email patch
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""A function to build localization and classification losses from config."""
from
object_detection.core
import
balanced_positive_negative_sampler
as
sampler
from
object_detection.core
import
losses
from
object_detection.protos
import
losses_pb2
def
build
(
loss_config
):
"""Build losses based on the config.
Builds classification, localization losses and optionally a hard example miner
based on the config.
Args:
loss_config: A losses_pb2.Loss object.
Returns:
classification_loss: Classification loss object.
localization_loss: Localization loss object.
classification_weight: Classification loss weight.
localization_weight: Localization loss weight.
hard_example_miner: Hard example miner object.
random_example_sampler: BalancedPositiveNegativeSampler object.
Raises:
ValueError: If hard_example_miner is used with sigmoid_focal_loss.
ValueError: If random_example_sampler is getting non-positive value as
desired positive example fraction.
"""
classification_loss
=
_build_classification_loss
(
loss_config
.
classification_loss
)
localization_loss
=
_build_localization_loss
(
loss_config
.
localization_loss
)
classification_weight
=
loss_config
.
classification_weight
localization_weight
=
loss_config
.
localization_weight
hard_example_miner
=
None
if
loss_config
.
HasField
(
'hard_example_miner'
):
if
(
loss_config
.
classification_loss
.
WhichOneof
(
'classification_loss'
)
==
'weighted_sigmoid_focal'
):
raise
ValueError
(
'HardExampleMiner should not be used with sigmoid focal '
'loss'
)
hard_example_miner
=
build_hard_example_miner
(
loss_config
.
hard_example_miner
,
classification_weight
,
localization_weight
)
random_example_sampler
=
None
if
loss_config
.
HasField
(
'random_example_sampler'
):
if
loss_config
.
random_example_sampler
.
positive_sample_fraction
<=
0
:
raise
ValueError
(
'RandomExampleSampler should not use non-positive'
'value as positive sample fraction.'
)
random_example_sampler
=
sampler
.
BalancedPositiveNegativeSampler
(
positive_fraction
=
loss_config
.
random_example_sampler
.
positive_sample_fraction
)
return
(
classification_loss
,
localization_loss
,
classification_weight
,
localization_weight
,
hard_example_miner
,
random_example_sampler
)
def
build_hard_example_miner
(
config
,
classification_weight
,
localization_weight
):
"""Builds hard example miner based on the config.
Args:
config: A losses_pb2.HardExampleMiner object.
classification_weight: Classification loss weight.
localization_weight: Localization loss weight.
Returns:
Hard example miner.
"""
loss_type
=
None
if
config
.
loss_type
==
losses_pb2
.
HardExampleMiner
.
BOTH
:
loss_type
=
'both'
if
config
.
loss_type
==
losses_pb2
.
HardExampleMiner
.
CLASSIFICATION
:
loss_type
=
'cls'
if
config
.
loss_type
==
losses_pb2
.
HardExampleMiner
.
LOCALIZATION
:
loss_type
=
'loc'
max_negatives_per_positive
=
None
num_hard_examples
=
None
if
config
.
max_negatives_per_positive
>
0
:
max_negatives_per_positive
=
config
.
max_negatives_per_positive
if
config
.
num_hard_examples
>
0
:
num_hard_examples
=
config
.
num_hard_examples
hard_example_miner
=
losses
.
HardExampleMiner
(
num_hard_examples
=
num_hard_examples
,
iou_threshold
=
config
.
iou_threshold
,
loss_type
=
loss_type
,
cls_loss_weight
=
classification_weight
,
loc_loss_weight
=
localization_weight
,
max_negatives_per_positive
=
max_negatives_per_positive
,
min_negatives_per_image
=
config
.
min_negatives_per_image
)
return
hard_example_miner
def
build_faster_rcnn_classification_loss
(
loss_config
):
"""Builds a classification loss for Faster RCNN based on the loss config.
Args:
loss_config: A losses_pb2.ClassificationLoss object.
Returns:
Loss based on the config.
Raises:
ValueError: On invalid loss_config.
"""
if
not
isinstance
(
loss_config
,
losses_pb2
.
ClassificationLoss
):
raise
ValueError
(
'loss_config not of type losses_pb2.ClassificationLoss.'
)
loss_type
=
loss_config
.
WhichOneof
(
'classification_loss'
)
if
loss_type
==
'weighted_sigmoid'
:
return
losses
.
WeightedSigmoidClassificationLoss
()
if
loss_type
==
'weighted_softmax'
:
config
=
loss_config
.
weighted_softmax
return
losses
.
WeightedSoftmaxClassificationLoss
(
logit_scale
=
config
.
logit_scale
)
if
loss_type
==
'weighted_logits_softmax'
:
config
=
loss_config
.
weighted_logits_softmax
return
losses
.
WeightedSoftmaxClassificationAgainstLogitsLoss
(
logit_scale
=
config
.
logit_scale
)
# By default, Faster RCNN second stage classifier uses Softmax loss
# with anchor-wise outputs.
config
=
loss_config
.
weighted_softmax
return
losses
.
WeightedSoftmaxClassificationLoss
(
logit_scale
=
config
.
logit_scale
)
def
_build_localization_loss
(
loss_config
):
"""Builds a localization loss based on the loss config.
Args:
loss_config: A losses_pb2.LocalizationLoss object.
Returns:
Loss based on the config.
Raises:
ValueError: On invalid loss_config.
"""
if
not
isinstance
(
loss_config
,
losses_pb2
.
LocalizationLoss
):
raise
ValueError
(
'loss_config not of type losses_pb2.LocalizationLoss.'
)
loss_type
=
loss_config
.
WhichOneof
(
'localization_loss'
)
if
loss_type
==
'weighted_l2'
:
return
losses
.
WeightedL2LocalizationLoss
()
if
loss_type
==
'weighted_smooth_l1'
:
return
losses
.
WeightedSmoothL1LocalizationLoss
(
loss_config
.
weighted_smooth_l1
.
delta
)
if
loss_type
==
'weighted_iou'
:
return
losses
.
WeightedIOULocalizationLoss
()
raise
ValueError
(
'Empty loss config.'
)
def
_build_classification_loss
(
loss_config
):
"""Builds a classification loss based on the loss config.
Args:
loss_config: A losses_pb2.ClassificationLoss object.
Returns:
Loss based on the config.
Raises:
ValueError: On invalid loss_config.
"""
if
not
isinstance
(
loss_config
,
losses_pb2
.
ClassificationLoss
):
raise
ValueError
(
'loss_config not of type losses_pb2.ClassificationLoss.'
)
loss_type
=
loss_config
.
WhichOneof
(
'classification_loss'
)
if
loss_type
==
'weighted_sigmoid'
:
return
losses
.
WeightedSigmoidClassificationLoss
()
if
loss_type
==
'weighted_sigmoid_focal'
:
config
=
loss_config
.
weighted_sigmoid_focal
alpha
=
None
if
config
.
HasField
(
'alpha'
):
alpha
=
config
.
alpha
return
losses
.
SigmoidFocalClassificationLoss
(
gamma
=
config
.
gamma
,
alpha
=
alpha
)
if
loss_type
==
'weighted_softmax'
:
config
=
loss_config
.
weighted_softmax
return
losses
.
WeightedSoftmaxClassificationLoss
(
logit_scale
=
config
.
logit_scale
)
if
loss_type
==
'weighted_logits_softmax'
:
config
=
loss_config
.
weighted_logits_softmax
return
losses
.
WeightedSoftmaxClassificationAgainstLogitsLoss
(
logit_scale
=
config
.
logit_scale
)
if
loss_type
==
'bootstrapped_sigmoid'
:
config
=
loss_config
.
bootstrapped_sigmoid
return
losses
.
BootstrappedSigmoidClassificationLoss
(
alpha
=
config
.
alpha
,
bootstrap_type
=
(
'hard'
if
config
.
hard_bootstrap
else
'soft'
))
raise
ValueError
(
'Empty loss config.'
)
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/losses_builder_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for losses_builder."""
import
tensorflow
as
tf
from
google.protobuf
import
text_format
from
object_detection.builders
import
losses_builder
from
object_detection.core
import
losses
from
object_detection.protos
import
losses_pb2
class
LocalizationLossBuilderTest
(
tf
.
test
.
TestCase
):
def
test_build_weighted_l2_localization_loss
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
classification_loss {
weighted_softmax {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
localization_loss
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
localization_loss
,
losses
.
WeightedL2LocalizationLoss
))
def
test_build_weighted_smooth_l1_localization_loss_default_delta
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_smooth_l1 {
}
}
classification_loss {
weighted_softmax {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
localization_loss
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
localization_loss
,
losses
.
WeightedSmoothL1LocalizationLoss
))
self
.
assertAlmostEqual
(
localization_loss
.
_delta
,
1.0
)
def
test_build_weighted_smooth_l1_localization_loss_non_default_delta
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_smooth_l1 {
delta: 0.1
}
}
classification_loss {
weighted_softmax {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
localization_loss
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
localization_loss
,
losses
.
WeightedSmoothL1LocalizationLoss
))
self
.
assertAlmostEqual
(
localization_loss
.
_delta
,
0.1
)
def
test_build_weighted_iou_localization_loss
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_iou {
}
}
classification_loss {
weighted_softmax {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
localization_loss
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
localization_loss
,
losses
.
WeightedIOULocalizationLoss
))
def
test_anchorwise_output
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_smooth_l1 {
}
}
classification_loss {
weighted_softmax {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
localization_loss
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
localization_loss
,
losses
.
WeightedSmoothL1LocalizationLoss
))
predictions
=
tf
.
constant
([[[
0.0
,
0.0
,
1.0
,
1.0
],
[
0.0
,
0.0
,
1.0
,
1.0
]]])
targets
=
tf
.
constant
([[[
0.0
,
0.0
,
1.0
,
1.0
],
[
0.0
,
0.0
,
1.0
,
1.0
]]])
weights
=
tf
.
constant
([[
1.0
,
1.0
]])
loss
=
localization_loss
(
predictions
,
targets
,
weights
=
weights
)
self
.
assertEqual
(
loss
.
shape
,
[
1
,
2
])
def
test_raise_error_on_empty_localization_config
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_softmax {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
with
self
.
assertRaises
(
ValueError
):
losses_builder
.
_build_localization_loss
(
losses_proto
)
class
ClassificationLossBuilderTest
(
tf
.
test
.
TestCase
):
def
test_build_weighted_sigmoid_classification_loss
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_sigmoid {
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSigmoidClassificationLoss
))
def
test_build_weighted_sigmoid_focal_classification_loss
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_sigmoid_focal {
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
SigmoidFocalClassificationLoss
))
self
.
assertAlmostEqual
(
classification_loss
.
_alpha
,
None
)
self
.
assertAlmostEqual
(
classification_loss
.
_gamma
,
2.0
)
def
test_build_weighted_sigmoid_focal_loss_non_default
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_sigmoid_focal {
alpha: 0.25
gamma: 3.0
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
SigmoidFocalClassificationLoss
))
self
.
assertAlmostEqual
(
classification_loss
.
_alpha
,
0.25
)
self
.
assertAlmostEqual
(
classification_loss
.
_gamma
,
3.0
)
def
test_build_weighted_softmax_classification_loss
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_softmax {
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSoftmaxClassificationLoss
))
def
test_build_weighted_logits_softmax_classification_loss
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_logits_softmax {
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSoftmaxClassificationAgainstLogitsLoss
))
def
test_build_weighted_softmax_classification_loss_with_logit_scale
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_softmax {
logit_scale: 2.0
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSoftmaxClassificationLoss
))
def
test_build_bootstrapped_sigmoid_classification_loss
(
self
):
losses_text_proto
=
"""
classification_loss {
bootstrapped_sigmoid {
alpha: 0.5
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
BootstrappedSigmoidClassificationLoss
))
def
test_anchorwise_output
(
self
):
losses_text_proto
=
"""
classification_loss {
weighted_sigmoid {
anchorwise_output: true
}
}
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
,
_
,
_
,
_
,
_
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSigmoidClassificationLoss
))
predictions
=
tf
.
constant
([[[
0.0
,
1.0
,
0.0
],
[
0.0
,
0.5
,
0.5
]]])
targets
=
tf
.
constant
([[[
0.0
,
1.0
,
0.0
],
[
0.0
,
0.0
,
1.0
]]])
weights
=
tf
.
constant
([[
1.0
,
1.0
]])
loss
=
classification_loss
(
predictions
,
targets
,
weights
=
weights
)
self
.
assertEqual
(
loss
.
shape
,
[
1
,
2
,
3
])
def
test_raise_error_on_empty_config
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
with
self
.
assertRaises
(
ValueError
):
losses_builder
.
build
(
losses_proto
)
class
HardExampleMinerBuilderTest
(
tf
.
test
.
TestCase
):
def
test_do_not_build_hard_example_miner_by_default
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
classification_loss {
weighted_softmax {
}
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
_
,
_
,
_
,
hard_example_miner
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertEqual
(
hard_example_miner
,
None
)
def
test_build_hard_example_miner_for_classification_loss
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
classification_loss {
weighted_softmax {
}
}
hard_example_miner {
loss_type: CLASSIFICATION
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
_
,
_
,
_
,
hard_example_miner
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
hard_example_miner
,
losses
.
HardExampleMiner
))
self
.
assertEqual
(
hard_example_miner
.
_loss_type
,
'cls'
)
def
test_build_hard_example_miner_for_localization_loss
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
classification_loss {
weighted_softmax {
}
}
hard_example_miner {
loss_type: LOCALIZATION
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
_
,
_
,
_
,
hard_example_miner
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
hard_example_miner
,
losses
.
HardExampleMiner
))
self
.
assertEqual
(
hard_example_miner
.
_loss_type
,
'loc'
)
def
test_build_hard_example_miner_with_non_default_values
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
classification_loss {
weighted_softmax {
}
}
hard_example_miner {
num_hard_examples: 32
iou_threshold: 0.5
loss_type: LOCALIZATION
max_negatives_per_positive: 10
min_negatives_per_image: 3
}
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
_
,
_
,
_
,
_
,
hard_example_miner
,
_
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
hard_example_miner
,
losses
.
HardExampleMiner
))
self
.
assertEqual
(
hard_example_miner
.
_num_hard_examples
,
32
)
self
.
assertAlmostEqual
(
hard_example_miner
.
_iou_threshold
,
0.5
)
self
.
assertEqual
(
hard_example_miner
.
_max_negatives_per_positive
,
10
)
self
.
assertEqual
(
hard_example_miner
.
_min_negatives_per_image
,
3
)
class
LossBuilderTest
(
tf
.
test
.
TestCase
):
def
test_build_all_loss_parameters
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
classification_loss {
weighted_softmax {
}
}
hard_example_miner {
}
classification_weight: 0.8
localization_weight: 0.2
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
(
classification_loss
,
localization_loss
,
classification_weight
,
localization_weight
,
hard_example_miner
,
_
)
=
losses_builder
.
build
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
hard_example_miner
,
losses
.
HardExampleMiner
))
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSoftmaxClassificationLoss
))
self
.
assertTrue
(
isinstance
(
localization_loss
,
losses
.
WeightedL2LocalizationLoss
))
self
.
assertAlmostEqual
(
classification_weight
,
0.8
)
self
.
assertAlmostEqual
(
localization_weight
,
0.2
)
def
test_raise_error_when_both_focal_loss_and_hard_example_miner
(
self
):
losses_text_proto
=
"""
localization_loss {
weighted_l2 {
}
}
classification_loss {
weighted_sigmoid_focal {
}
}
hard_example_miner {
}
classification_weight: 0.8
localization_weight: 0.2
"""
losses_proto
=
losses_pb2
.
Loss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
with
self
.
assertRaises
(
ValueError
):
losses_builder
.
build
(
losses_proto
)
class
FasterRcnnClassificationLossBuilderTest
(
tf
.
test
.
TestCase
):
def
test_build_sigmoid_loss
(
self
):
losses_text_proto
=
"""
weighted_sigmoid {
}
"""
losses_proto
=
losses_pb2
.
ClassificationLoss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
=
losses_builder
.
build_faster_rcnn_classification_loss
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSigmoidClassificationLoss
))
def
test_build_softmax_loss
(
self
):
losses_text_proto
=
"""
weighted_softmax {
}
"""
losses_proto
=
losses_pb2
.
ClassificationLoss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
=
losses_builder
.
build_faster_rcnn_classification_loss
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSoftmaxClassificationLoss
))
def
test_build_logits_softmax_loss
(
self
):
losses_text_proto
=
"""
weighted_logits_softmax {
}
"""
losses_proto
=
losses_pb2
.
ClassificationLoss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
=
losses_builder
.
build_faster_rcnn_classification_loss
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSoftmaxClassificationAgainstLogitsLoss
))
def
test_build_softmax_loss_by_default
(
self
):
losses_text_proto
=
"""
"""
losses_proto
=
losses_pb2
.
ClassificationLoss
()
text_format
.
Merge
(
losses_text_proto
,
losses_proto
)
classification_loss
=
losses_builder
.
build_faster_rcnn_classification_loss
(
losses_proto
)
self
.
assertTrue
(
isinstance
(
classification_loss
,
losses
.
WeightedSoftmaxClassificationLoss
))
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""A function to build an object detection matcher from configuration."""
from
object_detection.matchers
import
argmax_matcher
from
object_detection.matchers
import
bipartite_matcher
from
object_detection.protos
import
matcher_pb2
def
build
(
matcher_config
):
"""Builds a matcher object based on the matcher config.
Args:
matcher_config: A matcher.proto object containing the config for the desired
Matcher.
Returns:
Matcher based on the config.
Raises:
ValueError: On empty matcher proto.
"""
if
not
isinstance
(
matcher_config
,
matcher_pb2
.
Matcher
):
raise
ValueError
(
'matcher_config not of type matcher_pb2.Matcher.'
)
if
matcher_config
.
WhichOneof
(
'matcher_oneof'
)
==
'argmax_matcher'
:
matcher
=
matcher_config
.
argmax_matcher
matched_threshold
=
unmatched_threshold
=
None
if
not
matcher
.
ignore_thresholds
:
matched_threshold
=
matcher
.
matched_threshold
unmatched_threshold
=
matcher
.
unmatched_threshold
return
argmax_matcher
.
ArgMaxMatcher
(
matched_threshold
=
matched_threshold
,
unmatched_threshold
=
unmatched_threshold
,
negatives_lower_than_unmatched
=
matcher
.
negatives_lower_than_unmatched
,
force_match_for_each_row
=
matcher
.
force_match_for_each_row
,
use_matmul_gather
=
matcher
.
use_matmul_gather
)
if
matcher_config
.
WhichOneof
(
'matcher_oneof'
)
==
'bipartite_matcher'
:
matcher
=
matcher_config
.
bipartite_matcher
return
bipartite_matcher
.
GreedyBipartiteMatcher
(
matcher
.
use_matmul_gather
)
raise
ValueError
(
'Empty matcher.'
)
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/matcher_builder_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for matcher_builder."""
import
tensorflow
as
tf
from
google.protobuf
import
text_format
from
object_detection.builders
import
matcher_builder
from
object_detection.matchers
import
argmax_matcher
from
object_detection.matchers
import
bipartite_matcher
from
object_detection.protos
import
matcher_pb2
class
MatcherBuilderTest
(
tf
.
test
.
TestCase
):
def
test_build_arg_max_matcher_with_defaults
(
self
):
matcher_text_proto
=
"""
argmax_matcher {
}
"""
matcher_proto
=
matcher_pb2
.
Matcher
()
text_format
.
Merge
(
matcher_text_proto
,
matcher_proto
)
matcher_object
=
matcher_builder
.
build
(
matcher_proto
)
self
.
assertTrue
(
isinstance
(
matcher_object
,
argmax_matcher
.
ArgMaxMatcher
))
self
.
assertAlmostEqual
(
matcher_object
.
_matched_threshold
,
0.5
)
self
.
assertAlmostEqual
(
matcher_object
.
_unmatched_threshold
,
0.5
)
self
.
assertTrue
(
matcher_object
.
_negatives_lower_than_unmatched
)
self
.
assertFalse
(
matcher_object
.
_force_match_for_each_row
)
def
test_build_arg_max_matcher_without_thresholds
(
self
):
matcher_text_proto
=
"""
argmax_matcher {
ignore_thresholds: true
}
"""
matcher_proto
=
matcher_pb2
.
Matcher
()
text_format
.
Merge
(
matcher_text_proto
,
matcher_proto
)
matcher_object
=
matcher_builder
.
build
(
matcher_proto
)
self
.
assertTrue
(
isinstance
(
matcher_object
,
argmax_matcher
.
ArgMaxMatcher
))
self
.
assertEqual
(
matcher_object
.
_matched_threshold
,
None
)
self
.
assertEqual
(
matcher_object
.
_unmatched_threshold
,
None
)
self
.
assertTrue
(
matcher_object
.
_negatives_lower_than_unmatched
)
self
.
assertFalse
(
matcher_object
.
_force_match_for_each_row
)
def
test_build_arg_max_matcher_with_non_default_parameters
(
self
):
matcher_text_proto
=
"""
argmax_matcher {
matched_threshold: 0.7
unmatched_threshold: 0.3
negatives_lower_than_unmatched: false
force_match_for_each_row: true
use_matmul_gather: true
}
"""
matcher_proto
=
matcher_pb2
.
Matcher
()
text_format
.
Merge
(
matcher_text_proto
,
matcher_proto
)
matcher_object
=
matcher_builder
.
build
(
matcher_proto
)
self
.
assertTrue
(
isinstance
(
matcher_object
,
argmax_matcher
.
ArgMaxMatcher
))
self
.
assertAlmostEqual
(
matcher_object
.
_matched_threshold
,
0.7
)
self
.
assertAlmostEqual
(
matcher_object
.
_unmatched_threshold
,
0.3
)
self
.
assertFalse
(
matcher_object
.
_negatives_lower_than_unmatched
)
self
.
assertTrue
(
matcher_object
.
_force_match_for_each_row
)
self
.
assertTrue
(
matcher_object
.
_use_matmul_gather
)
def
test_build_bipartite_matcher
(
self
):
matcher_text_proto
=
"""
bipartite_matcher {
}
"""
matcher_proto
=
matcher_pb2
.
Matcher
()
text_format
.
Merge
(
matcher_text_proto
,
matcher_proto
)
matcher_object
=
matcher_builder
.
build
(
matcher_proto
)
self
.
assertTrue
(
isinstance
(
matcher_object
,
bipartite_matcher
.
GreedyBipartiteMatcher
))
def
test_raise_error_on_empty_matcher
(
self
):
matcher_text_proto
=
"""
"""
matcher_proto
=
matcher_pb2
.
Matcher
()
text_format
.
Merge
(
matcher_text_proto
,
matcher_proto
)
with
self
.
assertRaises
(
ValueError
):
matcher_builder
.
build
(
matcher_proto
)
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""A function to build a DetectionModel from configuration."""
from
object_detection.builders
import
anchor_generator_builder
from
object_detection.builders
import
box_coder_builder
from
object_detection.builders
import
box_predictor_builder
from
object_detection.builders
import
hyperparams_builder
from
object_detection.builders
import
image_resizer_builder
from
object_detection.builders
import
losses_builder
from
object_detection.builders
import
matcher_builder
from
object_detection.builders
import
post_processing_builder
from
object_detection.builders
import
region_similarity_calculator_builder
as
sim_calc
from
object_detection.core
import
box_predictor
from
object_detection.meta_architectures
import
faster_rcnn_meta_arch
from
object_detection.meta_architectures
import
rfcn_meta_arch
from
object_detection.meta_architectures
import
ssd_meta_arch
from
object_detection.models
import
faster_rcnn_inception_resnet_v2_feature_extractor
as
frcnn_inc_res
from
object_detection.models
import
faster_rcnn_inception_v2_feature_extractor
as
frcnn_inc_v2
from
object_detection.models
import
faster_rcnn_nas_feature_extractor
as
frcnn_nas
from
object_detection.models
import
faster_rcnn_pnas_feature_extractor
as
frcnn_pnas
from
object_detection.models
import
faster_rcnn_resnet_v1_feature_extractor
as
frcnn_resnet_v1
from
object_detection.models
import
ssd_resnet_v1_fpn_feature_extractor
as
ssd_resnet_v1_fpn
from
object_detection.models.embedded_ssd_mobilenet_v1_feature_extractor
import
EmbeddedSSDMobileNetV1FeatureExtractor
from
object_detection.models.ssd_inception_v2_feature_extractor
import
SSDInceptionV2FeatureExtractor
from
object_detection.models.ssd_inception_v3_feature_extractor
import
SSDInceptionV3FeatureExtractor
from
object_detection.models.ssd_mobilenet_v1_feature_extractor
import
SSDMobileNetV1FeatureExtractor
from
object_detection.models.ssd_mobilenet_v2_feature_extractor
import
SSDMobileNetV2FeatureExtractor
from
object_detection.protos
import
model_pb2
# A map of names to SSD feature extractors.
SSD_FEATURE_EXTRACTOR_CLASS_MAP
=
{
'ssd_inception_v2'
:
SSDInceptionV2FeatureExtractor
,
'ssd_inception_v3'
:
SSDInceptionV3FeatureExtractor
,
'ssd_mobilenet_v1'
:
SSDMobileNetV1FeatureExtractor
,
'ssd_mobilenet_v2'
:
SSDMobileNetV2FeatureExtractor
,
'ssd_resnet50_v1_fpn'
:
ssd_resnet_v1_fpn
.
SSDResnet50V1FpnFeatureExtractor
,
'ssd_resnet101_v1_fpn'
:
ssd_resnet_v1_fpn
.
SSDResnet101V1FpnFeatureExtractor
,
'ssd_resnet152_v1_fpn'
:
ssd_resnet_v1_fpn
.
SSDResnet152V1FpnFeatureExtractor
,
'embedded_ssd_mobilenet_v1'
:
EmbeddedSSDMobileNetV1FeatureExtractor
,
}
# A map of names to Faster R-CNN feature extractors.
FASTER_RCNN_FEATURE_EXTRACTOR_CLASS_MAP
=
{
'faster_rcnn_nas'
:
frcnn_nas
.
FasterRCNNNASFeatureExtractor
,
'faster_rcnn_pnas'
:
frcnn_pnas
.
FasterRCNNPNASFeatureExtractor
,
'faster_rcnn_inception_resnet_v2'
:
frcnn_inc_res
.
FasterRCNNInceptionResnetV2FeatureExtractor
,
'faster_rcnn_inception_v2'
:
frcnn_inc_v2
.
FasterRCNNInceptionV2FeatureExtractor
,
'faster_rcnn_resnet50'
:
frcnn_resnet_v1
.
FasterRCNNResnet50FeatureExtractor
,
'faster_rcnn_resnet101'
:
frcnn_resnet_v1
.
FasterRCNNResnet101FeatureExtractor
,
'faster_rcnn_resnet152'
:
frcnn_resnet_v1
.
FasterRCNNResnet152FeatureExtractor
,
}
def
build
(
model_config
,
is_training
,
add_summaries
=
True
,
add_background_class
=
True
):
"""Builds a DetectionModel based on the model config.
Args:
model_config: A model.proto object containing the config for the desired
DetectionModel.
is_training: True if this model is being built for training purposes.
add_summaries: Whether to add tensorflow summaries in the model graph.
add_background_class: Whether to add an implicit background class to one-hot
encodings of groundtruth labels. Set to false if using groundtruth labels
with an explicit background class or using multiclass scores instead of
truth in the case of distillation. Ignored in the case of faster_rcnn.
Returns:
DetectionModel based on the config.
Raises:
ValueError: On invalid meta architecture or model.
"""
if
not
isinstance
(
model_config
,
model_pb2
.
DetectionModel
):
raise
ValueError
(
'model_config not of type model_pb2.DetectionModel.'
)
meta_architecture
=
model_config
.
WhichOneof
(
'model'
)
if
meta_architecture
==
'ssd'
:
return
_build_ssd_model
(
model_config
.
ssd
,
is_training
,
add_summaries
,
add_background_class
)
if
meta_architecture
==
'faster_rcnn'
:
return
_build_faster_rcnn_model
(
model_config
.
faster_rcnn
,
is_training
,
add_summaries
)
raise
ValueError
(
'Unknown meta architecture: {}'
.
format
(
meta_architecture
))
def
_build_ssd_feature_extractor
(
feature_extractor_config
,
is_training
,
reuse_weights
=
None
):
"""Builds a ssd_meta_arch.SSDFeatureExtractor based on config.
Args:
feature_extractor_config: A SSDFeatureExtractor proto config from ssd.proto.
is_training: True if this feature extractor is being built for training.
reuse_weights: if the feature extractor should reuse weights.
Returns:
ssd_meta_arch.SSDFeatureExtractor based on config.
Raises:
ValueError: On invalid feature extractor type.
"""
feature_type
=
feature_extractor_config
.
type
depth_multiplier
=
feature_extractor_config
.
depth_multiplier
min_depth
=
feature_extractor_config
.
min_depth
pad_to_multiple
=
feature_extractor_config
.
pad_to_multiple
use_explicit_padding
=
feature_extractor_config
.
use_explicit_padding
use_depthwise
=
feature_extractor_config
.
use_depthwise
conv_hyperparams
=
hyperparams_builder
.
build
(
feature_extractor_config
.
conv_hyperparams
,
is_training
)
override_base_feature_extractor_hyperparams
=
(
feature_extractor_config
.
override_base_feature_extractor_hyperparams
)
if
feature_type
not
in
SSD_FEATURE_EXTRACTOR_CLASS_MAP
:
raise
ValueError
(
'Unknown ssd feature_extractor: {}'
.
format
(
feature_type
))
feature_extractor_class
=
SSD_FEATURE_EXTRACTOR_CLASS_MAP
[
feature_type
]
return
feature_extractor_class
(
is_training
,
depth_multiplier
,
min_depth
,
pad_to_multiple
,
conv_hyperparams
,
reuse_weights
,
use_explicit_padding
,
use_depthwise
,
override_base_feature_extractor_hyperparams
)
def
_build_ssd_model
(
ssd_config
,
is_training
,
add_summaries
,
add_background_class
=
True
):
"""Builds an SSD detection model based on the model config.
Args:
ssd_config: A ssd.proto object containing the config for the desired
SSDMetaArch.
is_training: True if this model is being built for training purposes.
add_summaries: Whether to add tf summaries in the model.
add_background_class: Whether to add an implicit background class to one-hot
encodings of groundtruth labels. Set to false if using groundtruth labels
with an explicit background class or using multiclass scores instead of
truth in the case of distillation.
Returns:
SSDMetaArch based on the config.
Raises:
ValueError: If ssd_config.type is not recognized (i.e. not registered in
model_class_map).
"""
num_classes
=
ssd_config
.
num_classes
# Feature extractor
feature_extractor
=
_build_ssd_feature_extractor
(
feature_extractor_config
=
ssd_config
.
feature_extractor
,
is_training
=
is_training
)
box_coder
=
box_coder_builder
.
build
(
ssd_config
.
box_coder
)
matcher
=
matcher_builder
.
build
(
ssd_config
.
matcher
)
region_similarity_calculator
=
sim_calc
.
build
(
ssd_config
.
similarity_calculator
)
encode_background_as_zeros
=
ssd_config
.
encode_background_as_zeros
negative_class_weight
=
ssd_config
.
negative_class_weight
ssd_box_predictor
=
box_predictor_builder
.
build
(
hyperparams_builder
.
build
,
ssd_config
.
box_predictor
,
is_training
,
num_classes
)
anchor_generator
=
anchor_generator_builder
.
build
(
ssd_config
.
anchor_generator
)
image_resizer_fn
=
image_resizer_builder
.
build
(
ssd_config
.
image_resizer
)
non_max_suppression_fn
,
score_conversion_fn
=
post_processing_builder
.
build
(
ssd_config
.
post_processing
)
(
classification_loss
,
localization_loss
,
classification_weight
,
localization_weight
,
hard_example_miner
,
random_example_sampler
)
=
losses_builder
.
build
(
ssd_config
.
loss
)
normalize_loss_by_num_matches
=
ssd_config
.
normalize_loss_by_num_matches
normalize_loc_loss_by_codesize
=
ssd_config
.
normalize_loc_loss_by_codesize
return
ssd_meta_arch
.
SSDMetaArch
(
is_training
,
anchor_generator
,
ssd_box_predictor
,
box_coder
,
feature_extractor
,
matcher
,
region_similarity_calculator
,
encode_background_as_zeros
,
negative_class_weight
,
image_resizer_fn
,
non_max_suppression_fn
,
score_conversion_fn
,
classification_loss
,
localization_loss
,
classification_weight
,
localization_weight
,
normalize_loss_by_num_matches
,
hard_example_miner
,
add_summaries
=
add_summaries
,
normalize_loc_loss_by_codesize
=
normalize_loc_loss_by_codesize
,
freeze_batchnorm
=
ssd_config
.
freeze_batchnorm
,
inplace_batchnorm_update
=
ssd_config
.
inplace_batchnorm_update
,
add_background_class
=
add_background_class
,
random_example_sampler
=
random_example_sampler
)
def
_build_faster_rcnn_feature_extractor
(
feature_extractor_config
,
is_training
,
reuse_weights
=
None
,
inplace_batchnorm_update
=
False
):
"""Builds a faster_rcnn_meta_arch.FasterRCNNFeatureExtractor based on config.
Args:
feature_extractor_config: A FasterRcnnFeatureExtractor proto config from
faster_rcnn.proto.
is_training: True if this feature extractor is being built for training.
reuse_weights: if the feature extractor should reuse weights.
inplace_batchnorm_update: Whether to update batch_norm inplace during
training. This is required for batch norm to work correctly on TPUs. When
this is false, user must add a control dependency on
tf.GraphKeys.UPDATE_OPS for train/loss op in order to update the batch
norm moving average parameters.
Returns:
faster_rcnn_meta_arch.FasterRCNNFeatureExtractor based on config.
Raises:
ValueError: On invalid feature extractor type.
"""
if
inplace_batchnorm_update
:
raise
ValueError
(
'inplace batchnorm updates not supported.'
)
feature_type
=
feature_extractor_config
.
type
first_stage_features_stride
=
(
feature_extractor_config
.
first_stage_features_stride
)
batch_norm_trainable
=
feature_extractor_config
.
batch_norm_trainable
if
feature_type
not
in
FASTER_RCNN_FEATURE_EXTRACTOR_CLASS_MAP
:
raise
ValueError
(
'Unknown Faster R-CNN feature_extractor: {}'
.
format
(
feature_type
))
feature_extractor_class
=
FASTER_RCNN_FEATURE_EXTRACTOR_CLASS_MAP
[
feature_type
]
return
feature_extractor_class
(
is_training
,
first_stage_features_stride
,
batch_norm_trainable
,
reuse_weights
)
def
_build_faster_rcnn_model
(
frcnn_config
,
is_training
,
add_summaries
):
"""Builds a Faster R-CNN or R-FCN detection model based on the model config.
Builds R-FCN model if the second_stage_box_predictor in the config is of type
`rfcn_box_predictor` else builds a Faster R-CNN model.
Args:
frcnn_config: A faster_rcnn.proto object containing the config for the
desired FasterRCNNMetaArch or RFCNMetaArch.
is_training: True if this model is being built for training purposes.
add_summaries: Whether to add tf summaries in the model.
Returns:
FasterRCNNMetaArch based on the config.
Raises:
ValueError: If frcnn_config.type is not recognized (i.e. not registered in
model_class_map).
"""
num_classes
=
frcnn_config
.
num_classes
image_resizer_fn
=
image_resizer_builder
.
build
(
frcnn_config
.
image_resizer
)
feature_extractor
=
_build_faster_rcnn_feature_extractor
(
frcnn_config
.
feature_extractor
,
is_training
,
frcnn_config
.
inplace_batchnorm_update
)
number_of_stages
=
frcnn_config
.
number_of_stages
first_stage_anchor_generator
=
anchor_generator_builder
.
build
(
frcnn_config
.
first_stage_anchor_generator
)
first_stage_atrous_rate
=
frcnn_config
.
first_stage_atrous_rate
first_stage_box_predictor_arg_scope_fn
=
hyperparams_builder
.
build
(
frcnn_config
.
first_stage_box_predictor_conv_hyperparams
,
is_training
)
first_stage_box_predictor_kernel_size
=
(
frcnn_config
.
first_stage_box_predictor_kernel_size
)
first_stage_box_predictor_depth
=
frcnn_config
.
first_stage_box_predictor_depth
first_stage_minibatch_size
=
frcnn_config
.
first_stage_minibatch_size
first_stage_positive_balance_fraction
=
(
frcnn_config
.
first_stage_positive_balance_fraction
)
first_stage_nms_score_threshold
=
frcnn_config
.
first_stage_nms_score_threshold
first_stage_nms_iou_threshold
=
frcnn_config
.
first_stage_nms_iou_threshold
first_stage_max_proposals
=
frcnn_config
.
first_stage_max_proposals
first_stage_loc_loss_weight
=
(
frcnn_config
.
first_stage_localization_loss_weight
)
first_stage_obj_loss_weight
=
frcnn_config
.
first_stage_objectness_loss_weight
initial_crop_size
=
frcnn_config
.
initial_crop_size
maxpool_kernel_size
=
frcnn_config
.
maxpool_kernel_size
maxpool_stride
=
frcnn_config
.
maxpool_stride
second_stage_box_predictor
=
box_predictor_builder
.
build
(
hyperparams_builder
.
build
,
frcnn_config
.
second_stage_box_predictor
,
is_training
=
is_training
,
num_classes
=
num_classes
)
second_stage_batch_size
=
frcnn_config
.
second_stage_batch_size
second_stage_balance_fraction
=
frcnn_config
.
second_stage_balance_fraction
(
second_stage_non_max_suppression_fn
,
second_stage_score_conversion_fn
)
=
post_processing_builder
.
build
(
frcnn_config
.
second_stage_post_processing
)
second_stage_localization_loss_weight
=
(
frcnn_config
.
second_stage_localization_loss_weight
)
second_stage_classification_loss
=
(
losses_builder
.
build_faster_rcnn_classification_loss
(
frcnn_config
.
second_stage_classification_loss
))
second_stage_classification_loss_weight
=
(
frcnn_config
.
second_stage_classification_loss_weight
)
second_stage_mask_prediction_loss_weight
=
(
frcnn_config
.
second_stage_mask_prediction_loss_weight
)
hard_example_miner
=
None
if
frcnn_config
.
HasField
(
'hard_example_miner'
):
hard_example_miner
=
losses_builder
.
build_hard_example_miner
(
frcnn_config
.
hard_example_miner
,
second_stage_classification_loss_weight
,
second_stage_localization_loss_weight
)
common_kwargs
=
{
'is_training'
:
is_training
,
'num_classes'
:
num_classes
,
'image_resizer_fn'
:
image_resizer_fn
,
'feature_extractor'
:
feature_extractor
,
'number_of_stages'
:
number_of_stages
,
'first_stage_anchor_generator'
:
first_stage_anchor_generator
,
'first_stage_atrous_rate'
:
first_stage_atrous_rate
,
'first_stage_box_predictor_arg_scope_fn'
:
first_stage_box_predictor_arg_scope_fn
,
'first_stage_box_predictor_kernel_size'
:
first_stage_box_predictor_kernel_size
,
'first_stage_box_predictor_depth'
:
first_stage_box_predictor_depth
,
'first_stage_minibatch_size'
:
first_stage_minibatch_size
,
'first_stage_positive_balance_fraction'
:
first_stage_positive_balance_fraction
,
'first_stage_nms_score_threshold'
:
first_stage_nms_score_threshold
,
'first_stage_nms_iou_threshold'
:
first_stage_nms_iou_threshold
,
'first_stage_max_proposals'
:
first_stage_max_proposals
,
'first_stage_localization_loss_weight'
:
first_stage_loc_loss_weight
,
'first_stage_objectness_loss_weight'
:
first_stage_obj_loss_weight
,
'second_stage_batch_size'
:
second_stage_batch_size
,
'second_stage_balance_fraction'
:
second_stage_balance_fraction
,
'second_stage_non_max_suppression_fn'
:
second_stage_non_max_suppression_fn
,
'second_stage_score_conversion_fn'
:
second_stage_score_conversion_fn
,
'second_stage_localization_loss_weight'
:
second_stage_localization_loss_weight
,
'second_stage_classification_loss'
:
second_stage_classification_loss
,
'second_stage_classification_loss_weight'
:
second_stage_classification_loss_weight
,
'hard_example_miner'
:
hard_example_miner
,
'add_summaries'
:
add_summaries
}
if
isinstance
(
second_stage_box_predictor
,
box_predictor
.
RfcnBoxPredictor
):
return
rfcn_meta_arch
.
RFCNMetaArch
(
second_stage_rfcn_box_predictor
=
second_stage_box_predictor
,
**
common_kwargs
)
else
:
return
faster_rcnn_meta_arch
.
FasterRCNNMetaArch
(
initial_crop_size
=
initial_crop_size
,
maxpool_kernel_size
=
maxpool_kernel_size
,
maxpool_stride
=
maxpool_stride
,
second_stage_mask_rcnn_box_predictor
=
second_stage_box_predictor
,
second_stage_mask_prediction_loss_weight
=
(
second_stage_mask_prediction_loss_weight
),
**
common_kwargs
)
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/model_builder_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for object_detection.models.model_builder."""
import
tensorflow
as
tf
from
google.protobuf
import
text_format
from
object_detection.builders
import
model_builder
from
object_detection.meta_architectures
import
faster_rcnn_meta_arch
from
object_detection.meta_architectures
import
rfcn_meta_arch
from
object_detection.meta_architectures
import
ssd_meta_arch
from
object_detection.models
import
faster_rcnn_inception_resnet_v2_feature_extractor
as
frcnn_inc_res
from
object_detection.models
import
faster_rcnn_inception_v2_feature_extractor
as
frcnn_inc_v2
from
object_detection.models
import
faster_rcnn_nas_feature_extractor
as
frcnn_nas
from
object_detection.models
import
faster_rcnn_pnas_feature_extractor
as
frcnn_pnas
from
object_detection.models
import
faster_rcnn_resnet_v1_feature_extractor
as
frcnn_resnet_v1
from
object_detection.models
import
ssd_resnet_v1_fpn_feature_extractor
as
ssd_resnet_v1_fpn
from
object_detection.models.embedded_ssd_mobilenet_v1_feature_extractor
import
EmbeddedSSDMobileNetV1FeatureExtractor
from
object_detection.models.ssd_inception_v2_feature_extractor
import
SSDInceptionV2FeatureExtractor
from
object_detection.models.ssd_inception_v3_feature_extractor
import
SSDInceptionV3FeatureExtractor
from
object_detection.models.ssd_mobilenet_v1_feature_extractor
import
SSDMobileNetV1FeatureExtractor
from
object_detection.models.ssd_mobilenet_v2_feature_extractor
import
SSDMobileNetV2FeatureExtractor
from
object_detection.protos
import
model_pb2
FRCNN_RESNET_FEAT_MAPS
=
{
'faster_rcnn_resnet50'
:
frcnn_resnet_v1
.
FasterRCNNResnet50FeatureExtractor
,
'faster_rcnn_resnet101'
:
frcnn_resnet_v1
.
FasterRCNNResnet101FeatureExtractor
,
'faster_rcnn_resnet152'
:
frcnn_resnet_v1
.
FasterRCNNResnet152FeatureExtractor
}
SSD_RESNET_V1_FPN_FEAT_MAPS
=
{
'ssd_resnet50_v1_fpn'
:
ssd_resnet_v1_fpn
.
SSDResnet50V1FpnFeatureExtractor
,
'ssd_resnet101_v1_fpn'
:
ssd_resnet_v1_fpn
.
SSDResnet101V1FpnFeatureExtractor
,
'ssd_resnet152_v1_fpn'
:
ssd_resnet_v1_fpn
.
SSDResnet152V1FpnFeatureExtractor
}
class
ModelBuilderTest
(
tf
.
test
.
TestCase
):
def
create_model
(
self
,
model_config
):
"""Builds a DetectionModel based on the model config.
Args:
model_config: A model.proto object containing the config for the desired
DetectionModel.
Returns:
DetectionModel based on the config.
"""
return
model_builder
.
build
(
model_config
,
is_training
=
True
)
def
test_create_ssd_inception_v2_model_from_config
(
self
):
model_text_proto
=
"""
ssd {
feature_extractor {
type: 'ssd_inception_v2'
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
override_base_feature_extractor_hyperparams: true
}
box_coder {
faster_rcnn_box_coder {
}
}
matcher {
argmax_matcher {
}
}
similarity_calculator {
iou_similarity {
}
}
anchor_generator {
ssd_anchor_generator {
aspect_ratios: 1.0
}
}
image_resizer {
fixed_shape_resizer {
height: 320
width: 320
}
}
box_predictor {
convolutional_box_predictor {
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
loss {
classification_loss {
weighted_softmax {
}
}
localization_loss {
weighted_smooth_l1 {
}
}
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
self
.
create_model
(
model_proto
)
self
.
assertIsInstance
(
model
,
ssd_meta_arch
.
SSDMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
SSDInceptionV2FeatureExtractor
)
def
test_create_ssd_inception_v3_model_from_config
(
self
):
model_text_proto
=
"""
ssd {
feature_extractor {
type: 'ssd_inception_v3'
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
override_base_feature_extractor_hyperparams: true
}
box_coder {
faster_rcnn_box_coder {
}
}
matcher {
argmax_matcher {
}
}
similarity_calculator {
iou_similarity {
}
}
anchor_generator {
ssd_anchor_generator {
aspect_ratios: 1.0
}
}
image_resizer {
fixed_shape_resizer {
height: 320
width: 320
}
}
box_predictor {
convolutional_box_predictor {
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
loss {
classification_loss {
weighted_softmax {
}
}
localization_loss {
weighted_smooth_l1 {
}
}
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
self
.
create_model
(
model_proto
)
self
.
assertIsInstance
(
model
,
ssd_meta_arch
.
SSDMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
SSDInceptionV3FeatureExtractor
)
def
test_create_ssd_resnet_v1_fpn_model_from_config
(
self
):
model_text_proto
=
"""
ssd {
feature_extractor {
type: 'ssd_resnet50_v1_fpn'
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
box_coder {
faster_rcnn_box_coder {
}
}
matcher {
argmax_matcher {
}
}
similarity_calculator {
iou_similarity {
}
}
encode_background_as_zeros: true
anchor_generator {
multiscale_anchor_generator {
aspect_ratios: [1.0, 2.0, 0.5]
scales_per_octave: 2
}
}
image_resizer {
fixed_shape_resizer {
height: 320
width: 320
}
}
box_predictor {
weight_shared_convolutional_box_predictor {
depth: 32
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
random_normal_initializer {
}
}
}
num_layers_before_predictor: 1
}
}
normalize_loss_by_num_matches: true
normalize_loc_loss_by_codesize: true
loss {
classification_loss {
weighted_sigmoid_focal {
alpha: 0.25
gamma: 2.0
}
}
localization_loss {
weighted_smooth_l1 {
delta: 0.1
}
}
classification_weight: 1.0
localization_weight: 1.0
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
for
extractor_type
,
extractor_class
in
SSD_RESNET_V1_FPN_FEAT_MAPS
.
items
():
model_proto
.
ssd
.
feature_extractor
.
type
=
extractor_type
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsInstance
(
model
,
ssd_meta_arch
.
SSDMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
extractor_class
)
def
test_create_ssd_mobilenet_v1_model_from_config
(
self
):
model_text_proto
=
"""
ssd {
freeze_batchnorm: true
inplace_batchnorm_update: true
feature_extractor {
type: 'ssd_mobilenet_v1'
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
box_coder {
faster_rcnn_box_coder {
}
}
matcher {
argmax_matcher {
}
}
similarity_calculator {
iou_similarity {
}
}
anchor_generator {
ssd_anchor_generator {
aspect_ratios: 1.0
}
}
image_resizer {
fixed_shape_resizer {
height: 320
width: 320
}
}
box_predictor {
convolutional_box_predictor {
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
normalize_loc_loss_by_codesize: true
loss {
classification_loss {
weighted_softmax {
}
}
localization_loss {
weighted_smooth_l1 {
}
}
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
self
.
create_model
(
model_proto
)
self
.
assertIsInstance
(
model
,
ssd_meta_arch
.
SSDMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
SSDMobileNetV1FeatureExtractor
)
self
.
assertTrue
(
model
.
_normalize_loc_loss_by_codesize
)
self
.
assertTrue
(
model
.
_freeze_batchnorm
)
self
.
assertTrue
(
model
.
_inplace_batchnorm_update
)
def
test_create_ssd_mobilenet_v2_model_from_config
(
self
):
model_text_proto
=
"""
ssd {
feature_extractor {
type: 'ssd_mobilenet_v2'
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
box_coder {
faster_rcnn_box_coder {
}
}
matcher {
argmax_matcher {
}
}
similarity_calculator {
iou_similarity {
}
}
anchor_generator {
ssd_anchor_generator {
aspect_ratios: 1.0
}
}
image_resizer {
fixed_shape_resizer {
height: 320
width: 320
}
}
box_predictor {
convolutional_box_predictor {
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
normalize_loc_loss_by_codesize: true
loss {
classification_loss {
weighted_softmax {
}
}
localization_loss {
weighted_smooth_l1 {
}
}
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
self
.
create_model
(
model_proto
)
self
.
assertIsInstance
(
model
,
ssd_meta_arch
.
SSDMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
SSDMobileNetV2FeatureExtractor
)
self
.
assertTrue
(
model
.
_normalize_loc_loss_by_codesize
)
def
test_create_embedded_ssd_mobilenet_v1_model_from_config
(
self
):
model_text_proto
=
"""
ssd {
feature_extractor {
type: 'embedded_ssd_mobilenet_v1'
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
box_coder {
faster_rcnn_box_coder {
}
}
matcher {
argmax_matcher {
}
}
similarity_calculator {
iou_similarity {
}
}
anchor_generator {
ssd_anchor_generator {
aspect_ratios: 1.0
}
}
image_resizer {
fixed_shape_resizer {
height: 256
width: 256
}
}
box_predictor {
convolutional_box_predictor {
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
loss {
classification_loss {
weighted_softmax {
}
}
localization_loss {
weighted_smooth_l1 {
}
}
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
self
.
create_model
(
model_proto
)
self
.
assertIsInstance
(
model
,
ssd_meta_arch
.
SSDMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
EmbeddedSSDMobileNetV1FeatureExtractor
)
def
test_create_faster_rcnn_resnet_v1_models_from_config
(
self
):
model_text_proto
=
"""
faster_rcnn {
inplace_batchnorm_update: true
num_classes: 3
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
feature_extractor {
type: 'faster_rcnn_resnet101'
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
initial_crop_size: 14
maxpool_kernel_size: 2
maxpool_stride: 2
second_stage_box_predictor {
mask_rcnn_box_predictor {
fc_hyperparams {
op: FC
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
second_stage_post_processing {
batch_non_max_suppression {
score_threshold: 0.01
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
score_converter: SOFTMAX
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
for
extractor_type
,
extractor_class
in
FRCNN_RESNET_FEAT_MAPS
.
items
():
model_proto
.
faster_rcnn
.
feature_extractor
.
type
=
extractor_type
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsInstance
(
model
,
faster_rcnn_meta_arch
.
FasterRCNNMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
extractor_class
)
def
test_create_faster_rcnn_resnet101_with_mask_prediction_enabled
(
self
):
model_text_proto
=
"""
faster_rcnn {
num_classes: 3
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
feature_extractor {
type: 'faster_rcnn_resnet101'
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
initial_crop_size: 14
maxpool_kernel_size: 2
maxpool_stride: 2
second_stage_box_predictor {
mask_rcnn_box_predictor {
fc_hyperparams {
op: FC
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
predict_instance_masks: true
}
}
second_stage_mask_prediction_loss_weight: 3.0
second_stage_post_processing {
batch_non_max_suppression {
score_threshold: 0.01
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
score_converter: SOFTMAX
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertAlmostEqual
(
model
.
_second_stage_mask_loss_weight
,
3.0
)
def
test_create_faster_rcnn_nas_model_from_config
(
self
):
model_text_proto
=
"""
faster_rcnn {
num_classes: 3
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
feature_extractor {
type: 'faster_rcnn_nas'
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
initial_crop_size: 17
maxpool_kernel_size: 1
maxpool_stride: 1
second_stage_box_predictor {
mask_rcnn_box_predictor {
fc_hyperparams {
op: FC
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
second_stage_post_processing {
batch_non_max_suppression {
score_threshold: 0.01
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
score_converter: SOFTMAX
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsInstance
(
model
,
faster_rcnn_meta_arch
.
FasterRCNNMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
frcnn_nas
.
FasterRCNNNASFeatureExtractor
)
def
test_create_faster_rcnn_pnas_model_from_config
(
self
):
model_text_proto
=
"""
faster_rcnn {
num_classes: 3
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
feature_extractor {
type: 'faster_rcnn_pnas'
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
initial_crop_size: 17
maxpool_kernel_size: 1
maxpool_stride: 1
second_stage_box_predictor {
mask_rcnn_box_predictor {
fc_hyperparams {
op: FC
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
second_stage_post_processing {
batch_non_max_suppression {
score_threshold: 0.01
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
score_converter: SOFTMAX
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsInstance
(
model
,
faster_rcnn_meta_arch
.
FasterRCNNMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
frcnn_pnas
.
FasterRCNNPNASFeatureExtractor
)
def
test_create_faster_rcnn_inception_resnet_v2_model_from_config
(
self
):
model_text_proto
=
"""
faster_rcnn {
num_classes: 3
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
feature_extractor {
type: 'faster_rcnn_inception_resnet_v2'
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
initial_crop_size: 17
maxpool_kernel_size: 1
maxpool_stride: 1
second_stage_box_predictor {
mask_rcnn_box_predictor {
fc_hyperparams {
op: FC
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
second_stage_post_processing {
batch_non_max_suppression {
score_threshold: 0.01
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
score_converter: SOFTMAX
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsInstance
(
model
,
faster_rcnn_meta_arch
.
FasterRCNNMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
frcnn_inc_res
.
FasterRCNNInceptionResnetV2FeatureExtractor
)
def
test_create_faster_rcnn_inception_v2_model_from_config
(
self
):
model_text_proto
=
"""
faster_rcnn {
num_classes: 3
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
feature_extractor {
type: 'faster_rcnn_inception_v2'
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
initial_crop_size: 14
maxpool_kernel_size: 2
maxpool_stride: 2
second_stage_box_predictor {
mask_rcnn_box_predictor {
fc_hyperparams {
op: FC
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
second_stage_post_processing {
batch_non_max_suppression {
score_threshold: 0.01
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
score_converter: SOFTMAX
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsInstance
(
model
,
faster_rcnn_meta_arch
.
FasterRCNNMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
frcnn_inc_v2
.
FasterRCNNInceptionV2FeatureExtractor
)
def
test_create_faster_rcnn_model_from_config_with_example_miner
(
self
):
model_text_proto
=
"""
faster_rcnn {
num_classes: 3
feature_extractor {
type: 'faster_rcnn_inception_resnet_v2'
}
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
second_stage_box_predictor {
mask_rcnn_box_predictor {
fc_hyperparams {
op: FC
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
hard_example_miner {
num_hard_examples: 10
iou_threshold: 0.99
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsNotNone
(
model
.
_hard_example_miner
)
def
test_create_rfcn_resnet_v1_model_from_config
(
self
):
model_text_proto
=
"""
faster_rcnn {
num_classes: 3
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 600
max_dimension: 1024
}
}
feature_extractor {
type: 'faster_rcnn_resnet101'
}
first_stage_anchor_generator {
grid_anchor_generator {
scales: [0.25, 0.5, 1.0, 2.0]
aspect_ratios: [0.5, 1.0, 2.0]
height_stride: 16
width_stride: 16
}
}
first_stage_box_predictor_conv_hyperparams {
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
initial_crop_size: 14
maxpool_kernel_size: 2
maxpool_stride: 2
second_stage_box_predictor {
rfcn_box_predictor {
conv_hyperparams {
op: CONV
regularizer {
l2_regularizer {
}
}
initializer {
truncated_normal_initializer {
}
}
}
}
}
second_stage_post_processing {
batch_non_max_suppression {
score_threshold: 0.01
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
score_converter: SOFTMAX
}
}"""
model_proto
=
model_pb2
.
DetectionModel
()
text_format
.
Merge
(
model_text_proto
,
model_proto
)
for
extractor_type
,
extractor_class
in
FRCNN_RESNET_FEAT_MAPS
.
items
():
model_proto
.
faster_rcnn
.
feature_extractor
.
type
=
extractor_type
model
=
model_builder
.
build
(
model_proto
,
is_training
=
True
)
self
.
assertIsInstance
(
model
,
rfcn_meta_arch
.
RFCNMetaArch
)
self
.
assertIsInstance
(
model
.
_feature_extractor
,
extractor_class
)
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Functions to build DetectionModel training optimizers."""
import
tensorflow
as
tf
from
object_detection.utils
import
learning_schedules
def
build
(
optimizer_config
):
"""Create optimizer based on config.
Args:
optimizer_config: A Optimizer proto message.
Returns:
An optimizer and a list of variables for summary.
Raises:
ValueError: when using an unsupported input data type.
"""
optimizer_type
=
optimizer_config
.
WhichOneof
(
'optimizer'
)
optimizer
=
None
summary_vars
=
[]
if
optimizer_type
==
'rms_prop_optimizer'
:
config
=
optimizer_config
.
rms_prop_optimizer
learning_rate
=
_create_learning_rate
(
config
.
learning_rate
)
summary_vars
.
append
(
learning_rate
)
optimizer
=
tf
.
train
.
RMSPropOptimizer
(
learning_rate
,
decay
=
config
.
decay
,
momentum
=
config
.
momentum_optimizer_value
,
epsilon
=
config
.
epsilon
)
if
optimizer_type
==
'momentum_optimizer'
:
config
=
optimizer_config
.
momentum_optimizer
learning_rate
=
_create_learning_rate
(
config
.
learning_rate
)
summary_vars
.
append
(
learning_rate
)
optimizer
=
tf
.
train
.
MomentumOptimizer
(
learning_rate
,
momentum
=
config
.
momentum_optimizer_value
)
if
optimizer_type
==
'adam_optimizer'
:
config
=
optimizer_config
.
adam_optimizer
learning_rate
=
_create_learning_rate
(
config
.
learning_rate
)
summary_vars
.
append
(
learning_rate
)
optimizer
=
tf
.
train
.
AdamOptimizer
(
learning_rate
)
if
optimizer
is
None
:
raise
ValueError
(
'Optimizer %s not supported.'
%
optimizer_type
)
if
optimizer_config
.
use_moving_average
:
optimizer
=
tf
.
contrib
.
opt
.
MovingAverageOptimizer
(
optimizer
,
average_decay
=
optimizer_config
.
moving_average_decay
)
return
optimizer
,
summary_vars
def
_create_learning_rate
(
learning_rate_config
):
"""Create optimizer learning rate based on config.
Args:
learning_rate_config: A LearningRate proto message.
Returns:
A learning rate.
Raises:
ValueError: when using an unsupported input data type.
"""
learning_rate
=
None
learning_rate_type
=
learning_rate_config
.
WhichOneof
(
'learning_rate'
)
if
learning_rate_type
==
'constant_learning_rate'
:
config
=
learning_rate_config
.
constant_learning_rate
learning_rate
=
tf
.
constant
(
config
.
learning_rate
,
dtype
=
tf
.
float32
,
name
=
'learning_rate'
)
if
learning_rate_type
==
'exponential_decay_learning_rate'
:
config
=
learning_rate_config
.
exponential_decay_learning_rate
learning_rate
=
tf
.
train
.
exponential_decay
(
config
.
initial_learning_rate
,
tf
.
train
.
get_or_create_global_step
(),
config
.
decay_steps
,
config
.
decay_factor
,
staircase
=
config
.
staircase
,
name
=
'learning_rate'
)
if
learning_rate_type
==
'manual_step_learning_rate'
:
config
=
learning_rate_config
.
manual_step_learning_rate
if
not
config
.
schedule
:
raise
ValueError
(
'Empty learning rate schedule.'
)
learning_rate_step_boundaries
=
[
x
.
step
for
x
in
config
.
schedule
]
learning_rate_sequence
=
[
config
.
initial_learning_rate
]
learning_rate_sequence
+=
[
x
.
learning_rate
for
x
in
config
.
schedule
]
learning_rate
=
learning_schedules
.
manual_stepping
(
tf
.
train
.
get_or_create_global_step
(),
learning_rate_step_boundaries
,
learning_rate_sequence
,
config
.
warmup
)
if
learning_rate_type
==
'cosine_decay_learning_rate'
:
config
=
learning_rate_config
.
cosine_decay_learning_rate
learning_rate
=
learning_schedules
.
cosine_decay_with_warmup
(
tf
.
train
.
get_or_create_global_step
(),
config
.
learning_rate_base
,
config
.
total_steps
,
config
.
warmup_learning_rate
,
config
.
warmup_steps
,
config
.
hold_base_rate_steps
)
if
learning_rate
is
None
:
raise
ValueError
(
'Learning_rate %s not supported.'
%
learning_rate_type
)
return
learning_rate
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/optimizer_builder_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for optimizer_builder."""
import
tensorflow
as
tf
from
google.protobuf
import
text_format
from
object_detection.builders
import
optimizer_builder
from
object_detection.protos
import
optimizer_pb2
class
LearningRateBuilderTest
(
tf
.
test
.
TestCase
):
def
testBuildConstantLearningRate
(
self
):
learning_rate_text_proto
=
"""
constant_learning_rate {
learning_rate: 0.004
}
"""
learning_rate_proto
=
optimizer_pb2
.
LearningRate
()
text_format
.
Merge
(
learning_rate_text_proto
,
learning_rate_proto
)
learning_rate
=
optimizer_builder
.
_create_learning_rate
(
learning_rate_proto
)
self
.
assertTrue
(
learning_rate
.
op
.
name
.
endswith
(
'learning_rate'
))
with
self
.
test_session
():
learning_rate_out
=
learning_rate
.
eval
()
self
.
assertAlmostEqual
(
learning_rate_out
,
0.004
)
def
testBuildExponentialDecayLearningRate
(
self
):
learning_rate_text_proto
=
"""
exponential_decay_learning_rate {
initial_learning_rate: 0.004
decay_steps: 99999
decay_factor: 0.85
staircase: false
}
"""
learning_rate_proto
=
optimizer_pb2
.
LearningRate
()
text_format
.
Merge
(
learning_rate_text_proto
,
learning_rate_proto
)
learning_rate
=
optimizer_builder
.
_create_learning_rate
(
learning_rate_proto
)
self
.
assertTrue
(
learning_rate
.
op
.
name
.
endswith
(
'learning_rate'
))
self
.
assertTrue
(
isinstance
(
learning_rate
,
tf
.
Tensor
))
def
testBuildManualStepLearningRate
(
self
):
learning_rate_text_proto
=
"""
manual_step_learning_rate {
initial_learning_rate: 0.002
schedule {
step: 100
learning_rate: 0.006
}
schedule {
step: 90000
learning_rate: 0.00006
}
warmup: true
}
"""
learning_rate_proto
=
optimizer_pb2
.
LearningRate
()
text_format
.
Merge
(
learning_rate_text_proto
,
learning_rate_proto
)
learning_rate
=
optimizer_builder
.
_create_learning_rate
(
learning_rate_proto
)
self
.
assertTrue
(
isinstance
(
learning_rate
,
tf
.
Tensor
))
def
testBuildCosineDecayLearningRate
(
self
):
learning_rate_text_proto
=
"""
cosine_decay_learning_rate {
learning_rate_base: 0.002
total_steps: 20000
warmup_learning_rate: 0.0001
warmup_steps: 1000
hold_base_rate_steps: 20000
}
"""
learning_rate_proto
=
optimizer_pb2
.
LearningRate
()
text_format
.
Merge
(
learning_rate_text_proto
,
learning_rate_proto
)
learning_rate
=
optimizer_builder
.
_create_learning_rate
(
learning_rate_proto
)
self
.
assertTrue
(
isinstance
(
learning_rate
,
tf
.
Tensor
))
def
testRaiseErrorOnEmptyLearningRate
(
self
):
learning_rate_text_proto
=
"""
"""
learning_rate_proto
=
optimizer_pb2
.
LearningRate
()
text_format
.
Merge
(
learning_rate_text_proto
,
learning_rate_proto
)
with
self
.
assertRaises
(
ValueError
):
optimizer_builder
.
_create_learning_rate
(
learning_rate_proto
)
class
OptimizerBuilderTest
(
tf
.
test
.
TestCase
):
def
testBuildRMSPropOptimizer
(
self
):
optimizer_text_proto
=
"""
rms_prop_optimizer: {
learning_rate: {
exponential_decay_learning_rate {
initial_learning_rate: 0.004
decay_steps: 800720
decay_factor: 0.95
}
}
momentum_optimizer_value: 0.9
decay: 0.9
epsilon: 1.0
}
use_moving_average: false
"""
optimizer_proto
=
optimizer_pb2
.
Optimizer
()
text_format
.
Merge
(
optimizer_text_proto
,
optimizer_proto
)
optimizer
,
_
=
optimizer_builder
.
build
(
optimizer_proto
)
self
.
assertTrue
(
isinstance
(
optimizer
,
tf
.
train
.
RMSPropOptimizer
))
def
testBuildMomentumOptimizer
(
self
):
optimizer_text_proto
=
"""
momentum_optimizer: {
learning_rate: {
constant_learning_rate {
learning_rate: 0.001
}
}
momentum_optimizer_value: 0.99
}
use_moving_average: false
"""
optimizer_proto
=
optimizer_pb2
.
Optimizer
()
text_format
.
Merge
(
optimizer_text_proto
,
optimizer_proto
)
optimizer
,
_
=
optimizer_builder
.
build
(
optimizer_proto
)
self
.
assertTrue
(
isinstance
(
optimizer
,
tf
.
train
.
MomentumOptimizer
))
def
testBuildAdamOptimizer
(
self
):
optimizer_text_proto
=
"""
adam_optimizer: {
learning_rate: {
constant_learning_rate {
learning_rate: 0.002
}
}
}
use_moving_average: false
"""
optimizer_proto
=
optimizer_pb2
.
Optimizer
()
text_format
.
Merge
(
optimizer_text_proto
,
optimizer_proto
)
optimizer
,
_
=
optimizer_builder
.
build
(
optimizer_proto
)
self
.
assertTrue
(
isinstance
(
optimizer
,
tf
.
train
.
AdamOptimizer
))
def
testBuildMovingAverageOptimizer
(
self
):
optimizer_text_proto
=
"""
adam_optimizer: {
learning_rate: {
constant_learning_rate {
learning_rate: 0.002
}
}
}
use_moving_average: True
"""
optimizer_proto
=
optimizer_pb2
.
Optimizer
()
text_format
.
Merge
(
optimizer_text_proto
,
optimizer_proto
)
optimizer
,
_
=
optimizer_builder
.
build
(
optimizer_proto
)
self
.
assertTrue
(
isinstance
(
optimizer
,
tf
.
contrib
.
opt
.
MovingAverageOptimizer
))
def
testBuildMovingAverageOptimizerWithNonDefaultDecay
(
self
):
optimizer_text_proto
=
"""
adam_optimizer: {
learning_rate: {
constant_learning_rate {
learning_rate: 0.002
}
}
}
use_moving_average: True
moving_average_decay: 0.2
"""
optimizer_proto
=
optimizer_pb2
.
Optimizer
()
text_format
.
Merge
(
optimizer_text_proto
,
optimizer_proto
)
optimizer
,
_
=
optimizer_builder
.
build
(
optimizer_proto
)
self
.
assertTrue
(
isinstance
(
optimizer
,
tf
.
contrib
.
opt
.
MovingAverageOptimizer
))
# TODO(rathodv): Find a way to not depend on the private members.
self
.
assertAlmostEqual
(
optimizer
.
_ema
.
_decay
,
0.2
)
def
testBuildEmptyOptimizer
(
self
):
optimizer_text_proto
=
"""
"""
optimizer_proto
=
optimizer_pb2
.
Optimizer
()
text_format
.
Merge
(
optimizer_text_proto
,
optimizer_proto
)
with
self
.
assertRaises
(
ValueError
):
optimizer_builder
.
build
(
optimizer_proto
)
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Builder function for post processing operations."""
import
functools
import
tensorflow
as
tf
from
object_detection.core
import
post_processing
from
object_detection.protos
import
post_processing_pb2
def
build
(
post_processing_config
):
"""Builds callables for post-processing operations.
Builds callables for non-max suppression and score conversion based on the
configuration.
Non-max suppression callable takes `boxes`, `scores`, and optionally
`clip_window`, `parallel_iterations` `masks, and `scope` as inputs. It returns
`nms_boxes`, `nms_scores`, `nms_classes` `nms_masks` and `num_detections`. See
post_processing.batch_multiclass_non_max_suppression for the type and shape
of these tensors.
Score converter callable should be called with `input` tensor. The callable
returns the output from one of 3 tf operations based on the configuration -
tf.identity, tf.sigmoid or tf.nn.softmax. See tensorflow documentation for
argument and return value descriptions.
Args:
post_processing_config: post_processing.proto object containing the
parameters for the post-processing operations.
Returns:
non_max_suppressor_fn: Callable for non-max suppression.
score_converter_fn: Callable for score conversion.
Raises:
ValueError: if the post_processing_config is of incorrect type.
"""
if
not
isinstance
(
post_processing_config
,
post_processing_pb2
.
PostProcessing
):
raise
ValueError
(
'post_processing_config not of type '
'post_processing_pb2.Postprocessing.'
)
non_max_suppressor_fn
=
_build_non_max_suppressor
(
post_processing_config
.
batch_non_max_suppression
)
score_converter_fn
=
_build_score_converter
(
post_processing_config
.
score_converter
,
post_processing_config
.
logit_scale
)
return
non_max_suppressor_fn
,
score_converter_fn
def
_build_non_max_suppressor
(
nms_config
):
"""Builds non-max suppresson based on the nms config.
Args:
nms_config: post_processing_pb2.PostProcessing.BatchNonMaxSuppression proto.
Returns:
non_max_suppressor_fn: Callable non-max suppressor.
Raises:
ValueError: On incorrect iou_threshold or on incompatible values of
max_total_detections and max_detections_per_class.
"""
if
nms_config
.
iou_threshold
<
0
or
nms_config
.
iou_threshold
>
1.0
:
raise
ValueError
(
'iou_threshold not in [0, 1.0].'
)
if
nms_config
.
max_detections_per_class
>
nms_config
.
max_total_detections
:
raise
ValueError
(
'max_detections_per_class should be no greater than '
'max_total_detections.'
)
non_max_suppressor_fn
=
functools
.
partial
(
post_processing
.
batch_multiclass_non_max_suppression
,
score_thresh
=
nms_config
.
score_threshold
,
iou_thresh
=
nms_config
.
iou_threshold
,
max_size_per_class
=
nms_config
.
max_detections_per_class
,
max_total_size
=
nms_config
.
max_total_detections
)
return
non_max_suppressor_fn
def
_score_converter_fn_with_logit_scale
(
tf_score_converter_fn
,
logit_scale
):
"""Create a function to scale logits then apply a Tensorflow function."""
def
score_converter_fn
(
logits
):
scaled_logits
=
tf
.
divide
(
logits
,
logit_scale
,
name
=
'scale_logits'
)
return
tf_score_converter_fn
(
scaled_logits
,
name
=
'convert_scores'
)
score_converter_fn
.
__name__
=
'%s_with_logit_scale'
%
(
tf_score_converter_fn
.
__name__
)
return
score_converter_fn
def
_build_score_converter
(
score_converter_config
,
logit_scale
):
"""Builds score converter based on the config.
Builds one of [tf.identity, tf.sigmoid, tf.softmax] score converters based on
the config.
Args:
score_converter_config: post_processing_pb2.PostProcessing.score_converter.
logit_scale: temperature to use for SOFTMAX score_converter.
Returns:
Callable score converter op.
Raises:
ValueError: On unknown score converter.
"""
if
score_converter_config
==
post_processing_pb2
.
PostProcessing
.
IDENTITY
:
return
_score_converter_fn_with_logit_scale
(
tf
.
identity
,
logit_scale
)
if
score_converter_config
==
post_processing_pb2
.
PostProcessing
.
SIGMOID
:
return
_score_converter_fn_with_logit_scale
(
tf
.
sigmoid
,
logit_scale
)
if
score_converter_config
==
post_processing_pb2
.
PostProcessing
.
SOFTMAX
:
return
_score_converter_fn_with_logit_scale
(
tf
.
nn
.
softmax
,
logit_scale
)
raise
ValueError
(
'Unknown score converter.'
)
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/post_processing_builder_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for post_processing_builder."""
import
tensorflow
as
tf
from
google.protobuf
import
text_format
from
object_detection.builders
import
post_processing_builder
from
object_detection.protos
import
post_processing_pb2
class
PostProcessingBuilderTest
(
tf
.
test
.
TestCase
):
def
test_build_non_max_suppressor_with_correct_parameters
(
self
):
post_processing_text_proto
=
"""
batch_non_max_suppression {
score_threshold: 0.7
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 300
}
"""
post_processing_config
=
post_processing_pb2
.
PostProcessing
()
text_format
.
Merge
(
post_processing_text_proto
,
post_processing_config
)
non_max_suppressor
,
_
=
post_processing_builder
.
build
(
post_processing_config
)
self
.
assertEqual
(
non_max_suppressor
.
keywords
[
'max_size_per_class'
],
100
)
self
.
assertEqual
(
non_max_suppressor
.
keywords
[
'max_total_size'
],
300
)
self
.
assertAlmostEqual
(
non_max_suppressor
.
keywords
[
'score_thresh'
],
0.7
)
self
.
assertAlmostEqual
(
non_max_suppressor
.
keywords
[
'iou_thresh'
],
0.6
)
def
test_build_identity_score_converter
(
self
):
post_processing_text_proto
=
"""
score_converter: IDENTITY
"""
post_processing_config
=
post_processing_pb2
.
PostProcessing
()
text_format
.
Merge
(
post_processing_text_proto
,
post_processing_config
)
_
,
score_converter
=
post_processing_builder
.
build
(
post_processing_config
)
self
.
assertEqual
(
score_converter
.
__name__
,
'identity_with_logit_scale'
)
inputs
=
tf
.
constant
([
1
,
1
],
tf
.
float32
)
outputs
=
score_converter
(
inputs
)
with
self
.
test_session
()
as
sess
:
converted_scores
=
sess
.
run
(
outputs
)
expected_converted_scores
=
sess
.
run
(
inputs
)
self
.
assertAllClose
(
converted_scores
,
expected_converted_scores
)
def
test_build_identity_score_converter_with_logit_scale
(
self
):
post_processing_text_proto
=
"""
score_converter: IDENTITY
logit_scale: 2.0
"""
post_processing_config
=
post_processing_pb2
.
PostProcessing
()
text_format
.
Merge
(
post_processing_text_proto
,
post_processing_config
)
_
,
score_converter
=
post_processing_builder
.
build
(
post_processing_config
)
self
.
assertEqual
(
score_converter
.
__name__
,
'identity_with_logit_scale'
)
inputs
=
tf
.
constant
([
1
,
1
],
tf
.
float32
)
outputs
=
score_converter
(
inputs
)
with
self
.
test_session
()
as
sess
:
converted_scores
=
sess
.
run
(
outputs
)
expected_converted_scores
=
sess
.
run
(
tf
.
constant
([.
5
,
.
5
],
tf
.
float32
))
self
.
assertAllClose
(
converted_scores
,
expected_converted_scores
)
def
test_build_sigmoid_score_converter
(
self
):
post_processing_text_proto
=
"""
score_converter: SIGMOID
"""
post_processing_config
=
post_processing_pb2
.
PostProcessing
()
text_format
.
Merge
(
post_processing_text_proto
,
post_processing_config
)
_
,
score_converter
=
post_processing_builder
.
build
(
post_processing_config
)
self
.
assertEqual
(
score_converter
.
__name__
,
'sigmoid_with_logit_scale'
)
def
test_build_softmax_score_converter
(
self
):
post_processing_text_proto
=
"""
score_converter: SOFTMAX
"""
post_processing_config
=
post_processing_pb2
.
PostProcessing
()
text_format
.
Merge
(
post_processing_text_proto
,
post_processing_config
)
_
,
score_converter
=
post_processing_builder
.
build
(
post_processing_config
)
self
.
assertEqual
(
score_converter
.
__name__
,
'softmax_with_logit_scale'
)
def
test_build_softmax_score_converter_with_temperature
(
self
):
post_processing_text_proto
=
"""
score_converter: SOFTMAX
logit_scale: 2.0
"""
post_processing_config
=
post_processing_pb2
.
PostProcessing
()
text_format
.
Merge
(
post_processing_text_proto
,
post_processing_config
)
_
,
score_converter
=
post_processing_builder
.
build
(
post_processing_config
)
self
.
assertEqual
(
score_converter
.
__name__
,
'softmax_with_logit_scale'
)
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Builder for preprocessing steps."""
import
tensorflow
as
tf
from
object_detection.core
import
preprocessor
from
object_detection.protos
import
preprocessor_pb2
def
_get_step_config_from_proto
(
preprocessor_step_config
,
step_name
):
"""Returns the value of a field named step_name from proto.
Args:
preprocessor_step_config: A preprocessor_pb2.PreprocessingStep object.
step_name: Name of the field to get value from.
Returns:
result_dict: a sub proto message from preprocessor_step_config which will be
later converted to a dictionary.
Raises:
ValueError: If field does not exist in proto.
"""
for
field
,
value
in
preprocessor_step_config
.
ListFields
():
if
field
.
name
==
step_name
:
return
value
raise
ValueError
(
'Could not get field %s from proto!'
,
step_name
)
def
_get_dict_from_proto
(
config
):
"""Helper function to put all proto fields into a dictionary.
For many preprocessing steps, there's an trivial 1-1 mapping from proto fields
to function arguments. This function automatically populates a dictionary with
the arguments from the proto.
Protos that CANNOT be trivially populated include:
* nested messages.
* steps that check if an optional field is set (ie. where None != 0).
* protos that don't map 1-1 to arguments (ie. list should be reshaped).
* fields requiring additional validation (ie. repeated field has n elements).
Args:
config: A protobuf object that does not violate the conditions above.
Returns:
result_dict: |config| converted into a python dictionary.
"""
result_dict
=
{}
for
field
,
value
in
config
.
ListFields
():
result_dict
[
field
.
name
]
=
value
return
result_dict
# A map from a PreprocessingStep proto config field name to the preprocessing
# function that should be used. The PreprocessingStep proto should be parsable
# with _get_dict_from_proto.
PREPROCESSING_FUNCTION_MAP
=
{
'normalize_image'
:
preprocessor
.
normalize_image
,
'random_pixel_value_scale'
:
preprocessor
.
random_pixel_value_scale
,
'random_image_scale'
:
preprocessor
.
random_image_scale
,
'random_rgb_to_gray'
:
preprocessor
.
random_rgb_to_gray
,
'random_adjust_brightness'
:
preprocessor
.
random_adjust_brightness
,
'random_adjust_contrast'
:
preprocessor
.
random_adjust_contrast
,
'random_adjust_hue'
:
preprocessor
.
random_adjust_hue
,
'random_adjust_saturation'
:
preprocessor
.
random_adjust_saturation
,
'random_distort_color'
:
preprocessor
.
random_distort_color
,
'random_jitter_boxes'
:
preprocessor
.
random_jitter_boxes
,
'random_crop_to_aspect_ratio'
:
preprocessor
.
random_crop_to_aspect_ratio
,
'random_black_patches'
:
preprocessor
.
random_black_patches
,
'rgb_to_gray'
:
preprocessor
.
rgb_to_gray
,
'scale_boxes_to_pixel_coordinates'
:
(
preprocessor
.
scale_boxes_to_pixel_coordinates
),
'subtract_channel_mean'
:
preprocessor
.
subtract_channel_mean
,
}
# A map to convert from preprocessor_pb2.ResizeImage.Method enum to
# tf.image.ResizeMethod.
RESIZE_METHOD_MAP
=
{
preprocessor_pb2
.
ResizeImage
.
AREA
:
tf
.
image
.
ResizeMethod
.
AREA
,
preprocessor_pb2
.
ResizeImage
.
BICUBIC
:
tf
.
image
.
ResizeMethod
.
BICUBIC
,
preprocessor_pb2
.
ResizeImage
.
BILINEAR
:
tf
.
image
.
ResizeMethod
.
BILINEAR
,
preprocessor_pb2
.
ResizeImage
.
NEAREST_NEIGHBOR
:
(
tf
.
image
.
ResizeMethod
.
NEAREST_NEIGHBOR
),
}
def
build
(
preprocessor_step_config
):
"""Builds preprocessing step based on the configuration.
Args:
preprocessor_step_config: PreprocessingStep configuration proto.
Returns:
function, argmap: A callable function and an argument map to call function
with.
Raises:
ValueError: On invalid configuration.
"""
step_type
=
preprocessor_step_config
.
WhichOneof
(
'preprocessing_step'
)
if
step_type
in
PREPROCESSING_FUNCTION_MAP
:
preprocessing_function
=
PREPROCESSING_FUNCTION_MAP
[
step_type
]
step_config
=
_get_step_config_from_proto
(
preprocessor_step_config
,
step_type
)
function_args
=
_get_dict_from_proto
(
step_config
)
return
(
preprocessing_function
,
function_args
)
if
step_type
==
'random_horizontal_flip'
:
config
=
preprocessor_step_config
.
random_horizontal_flip
return
(
preprocessor
.
random_horizontal_flip
,
{
'keypoint_flip_permutation'
:
tuple
(
config
.
keypoint_flip_permutation
),
})
if
step_type
==
'random_vertical_flip'
:
config
=
preprocessor_step_config
.
random_vertical_flip
return
(
preprocessor
.
random_vertical_flip
,
{
'keypoint_flip_permutation'
:
tuple
(
config
.
keypoint_flip_permutation
),
})
if
step_type
==
'random_rotation90'
:
return
(
preprocessor
.
random_rotation90
,
{})
if
step_type
==
'random_crop_image'
:
config
=
preprocessor_step_config
.
random_crop_image
return
(
preprocessor
.
random_crop_image
,
{
'min_object_covered'
:
config
.
min_object_covered
,
'aspect_ratio_range'
:
(
config
.
min_aspect_ratio
,
config
.
max_aspect_ratio
),
'area_range'
:
(
config
.
min_area
,
config
.
max_area
),
'overlap_thresh'
:
config
.
overlap_thresh
,
'random_coef'
:
config
.
random_coef
,
})
if
step_type
==
'random_pad_image'
:
config
=
preprocessor_step_config
.
random_pad_image
min_image_size
=
None
if
(
config
.
HasField
(
'min_image_height'
)
!=
config
.
HasField
(
'min_image_width'
)):
raise
ValueError
(
'min_image_height and min_image_width should be either '
'both set or both unset.'
)
if
config
.
HasField
(
'min_image_height'
):
min_image_size
=
(
config
.
min_image_height
,
config
.
min_image_width
)
max_image_size
=
None
if
(
config
.
HasField
(
'max_image_height'
)
!=
config
.
HasField
(
'max_image_width'
)):
raise
ValueError
(
'max_image_height and max_image_width should be either '
'both set or both unset.'
)
if
config
.
HasField
(
'max_image_height'
):
max_image_size
=
(
config
.
max_image_height
,
config
.
max_image_width
)
pad_color
=
config
.
pad_color
if
pad_color
and
len
(
pad_color
)
!=
3
:
raise
ValueError
(
'pad_color should have 3 elements (RGB) if set!'
)
if
not
pad_color
:
pad_color
=
None
return
(
preprocessor
.
random_pad_image
,
{
'min_image_size'
:
min_image_size
,
'max_image_size'
:
max_image_size
,
'pad_color'
:
pad_color
,
})
if
step_type
==
'random_crop_pad_image'
:
config
=
preprocessor_step_config
.
random_crop_pad_image
min_padded_size_ratio
=
config
.
min_padded_size_ratio
if
min_padded_size_ratio
and
len
(
min_padded_size_ratio
)
!=
2
:
raise
ValueError
(
'min_padded_size_ratio should have 2 elements if set!'
)
max_padded_size_ratio
=
config
.
max_padded_size_ratio
if
max_padded_size_ratio
and
len
(
max_padded_size_ratio
)
!=
2
:
raise
ValueError
(
'max_padded_size_ratio should have 2 elements if set!'
)
pad_color
=
config
.
pad_color
if
pad_color
and
len
(
pad_color
)
!=
3
:
raise
ValueError
(
'pad_color should have 3 elements if set!'
)
kwargs
=
{
'min_object_covered'
:
config
.
min_object_covered
,
'aspect_ratio_range'
:
(
config
.
min_aspect_ratio
,
config
.
max_aspect_ratio
),
'area_range'
:
(
config
.
min_area
,
config
.
max_area
),
'overlap_thresh'
:
config
.
overlap_thresh
,
'random_coef'
:
config
.
random_coef
,
}
if
min_padded_size_ratio
:
kwargs
[
'min_padded_size_ratio'
]
=
tuple
(
min_padded_size_ratio
)
if
max_padded_size_ratio
:
kwargs
[
'max_padded_size_ratio'
]
=
tuple
(
max_padded_size_ratio
)
if
pad_color
:
kwargs
[
'pad_color'
]
=
tuple
(
pad_color
)
return
(
preprocessor
.
random_crop_pad_image
,
kwargs
)
if
step_type
==
'random_resize_method'
:
config
=
preprocessor_step_config
.
random_resize_method
return
(
preprocessor
.
random_resize_method
,
{
'target_size'
:
[
config
.
target_height
,
config
.
target_width
],
})
if
step_type
==
'resize_image'
:
config
=
preprocessor_step_config
.
resize_image
method
=
RESIZE_METHOD_MAP
[
config
.
method
]
return
(
preprocessor
.
resize_image
,
{
'new_height'
:
config
.
new_height
,
'new_width'
:
config
.
new_width
,
'method'
:
method
})
if
step_type
==
'ssd_random_crop'
:
config
=
preprocessor_step_config
.
ssd_random_crop
if
config
.
operations
:
min_object_covered
=
[
op
.
min_object_covered
for
op
in
config
.
operations
]
aspect_ratio_range
=
[(
op
.
min_aspect_ratio
,
op
.
max_aspect_ratio
)
for
op
in
config
.
operations
]
area_range
=
[(
op
.
min_area
,
op
.
max_area
)
for
op
in
config
.
operations
]
overlap_thresh
=
[
op
.
overlap_thresh
for
op
in
config
.
operations
]
random_coef
=
[
op
.
random_coef
for
op
in
config
.
operations
]
return
(
preprocessor
.
ssd_random_crop
,
{
'min_object_covered'
:
min_object_covered
,
'aspect_ratio_range'
:
aspect_ratio_range
,
'area_range'
:
area_range
,
'overlap_thresh'
:
overlap_thresh
,
'random_coef'
:
random_coef
,
})
return
(
preprocessor
.
ssd_random_crop
,
{})
if
step_type
==
'ssd_random_crop_pad'
:
config
=
preprocessor_step_config
.
ssd_random_crop_pad
if
config
.
operations
:
min_object_covered
=
[
op
.
min_object_covered
for
op
in
config
.
operations
]
aspect_ratio_range
=
[(
op
.
min_aspect_ratio
,
op
.
max_aspect_ratio
)
for
op
in
config
.
operations
]
area_range
=
[(
op
.
min_area
,
op
.
max_area
)
for
op
in
config
.
operations
]
overlap_thresh
=
[
op
.
overlap_thresh
for
op
in
config
.
operations
]
random_coef
=
[
op
.
random_coef
for
op
in
config
.
operations
]
min_padded_size_ratio
=
[
tuple
(
op
.
min_padded_size_ratio
)
for
op
in
config
.
operations
]
max_padded_size_ratio
=
[
tuple
(
op
.
max_padded_size_ratio
)
for
op
in
config
.
operations
]
pad_color
=
[(
op
.
pad_color_r
,
op
.
pad_color_g
,
op
.
pad_color_b
)
for
op
in
config
.
operations
]
return
(
preprocessor
.
ssd_random_crop_pad
,
{
'min_object_covered'
:
min_object_covered
,
'aspect_ratio_range'
:
aspect_ratio_range
,
'area_range'
:
area_range
,
'overlap_thresh'
:
overlap_thresh
,
'random_coef'
:
random_coef
,
'min_padded_size_ratio'
:
min_padded_size_ratio
,
'max_padded_size_ratio'
:
max_padded_size_ratio
,
'pad_color'
:
pad_color
,
})
return
(
preprocessor
.
ssd_random_crop_pad
,
{})
if
step_type
==
'ssd_random_crop_fixed_aspect_ratio'
:
config
=
preprocessor_step_config
.
ssd_random_crop_fixed_aspect_ratio
if
config
.
operations
:
min_object_covered
=
[
op
.
min_object_covered
for
op
in
config
.
operations
]
area_range
=
[(
op
.
min_area
,
op
.
max_area
)
for
op
in
config
.
operations
]
overlap_thresh
=
[
op
.
overlap_thresh
for
op
in
config
.
operations
]
random_coef
=
[
op
.
random_coef
for
op
in
config
.
operations
]
return
(
preprocessor
.
ssd_random_crop_fixed_aspect_ratio
,
{
'min_object_covered'
:
min_object_covered
,
'aspect_ratio'
:
config
.
aspect_ratio
,
'area_range'
:
area_range
,
'overlap_thresh'
:
overlap_thresh
,
'random_coef'
:
random_coef
,
})
return
(
preprocessor
.
ssd_random_crop_fixed_aspect_ratio
,
{})
if
step_type
==
'ssd_random_crop_pad_fixed_aspect_ratio'
:
config
=
preprocessor_step_config
.
ssd_random_crop_pad_fixed_aspect_ratio
kwargs
=
{}
aspect_ratio
=
config
.
aspect_ratio
if
aspect_ratio
:
kwargs
[
'aspect_ratio'
]
=
aspect_ratio
min_padded_size_ratio
=
config
.
min_padded_size_ratio
if
min_padded_size_ratio
:
if
len
(
min_padded_size_ratio
)
!=
2
:
raise
ValueError
(
'min_padded_size_ratio should have 2 elements if set!'
)
kwargs
[
'min_padded_size_ratio'
]
=
tuple
(
min_padded_size_ratio
)
max_padded_size_ratio
=
config
.
max_padded_size_ratio
if
max_padded_size_ratio
:
if
len
(
max_padded_size_ratio
)
!=
2
:
raise
ValueError
(
'max_padded_size_ratio should have 2 elements if set!'
)
kwargs
[
'max_padded_size_ratio'
]
=
tuple
(
max_padded_size_ratio
)
if
config
.
operations
:
kwargs
[
'min_object_covered'
]
=
[
op
.
min_object_covered
for
op
in
config
.
operations
]
kwargs
[
'aspect_ratio_range'
]
=
[(
op
.
min_aspect_ratio
,
op
.
max_aspect_ratio
)
for
op
in
config
.
operations
]
kwargs
[
'area_range'
]
=
[(
op
.
min_area
,
op
.
max_area
)
for
op
in
config
.
operations
]
kwargs
[
'overlap_thresh'
]
=
[
op
.
overlap_thresh
for
op
in
config
.
operations
]
kwargs
[
'random_coef'
]
=
[
op
.
random_coef
for
op
in
config
.
operations
]
return
(
preprocessor
.
ssd_random_crop_pad_fixed_aspect_ratio
,
kwargs
)
raise
ValueError
(
'Unknown preprocessing step.'
)
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/preprocessor_builder_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for preprocessor_builder."""
import
tensorflow
as
tf
from
google.protobuf
import
text_format
from
object_detection.builders
import
preprocessor_builder
from
object_detection.core
import
preprocessor
from
object_detection.protos
import
preprocessor_pb2
class
PreprocessorBuilderTest
(
tf
.
test
.
TestCase
):
def
assert_dictionary_close
(
self
,
dict1
,
dict2
):
"""Helper to check if two dicts with floatst or integers are close."""
self
.
assertEqual
(
sorted
(
dict1
.
keys
()),
sorted
(
dict2
.
keys
()))
for
key
in
dict1
:
value
=
dict1
[
key
]
if
isinstance
(
value
,
float
):
self
.
assertAlmostEqual
(
value
,
dict2
[
key
])
else
:
self
.
assertEqual
(
value
,
dict2
[
key
])
def
test_build_normalize_image
(
self
):
preprocessor_text_proto
=
"""
normalize_image {
original_minval: 0.0
original_maxval: 255.0
target_minval: -1.0
target_maxval: 1.0
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
normalize_image
)
self
.
assertEqual
(
args
,
{
'original_minval'
:
0.0
,
'original_maxval'
:
255.0
,
'target_minval'
:
-
1.0
,
'target_maxval'
:
1.0
,
})
def
test_build_random_horizontal_flip
(
self
):
preprocessor_text_proto
=
"""
random_horizontal_flip {
keypoint_flip_permutation: 1
keypoint_flip_permutation: 0
keypoint_flip_permutation: 2
keypoint_flip_permutation: 3
keypoint_flip_permutation: 5
keypoint_flip_permutation: 4
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_horizontal_flip
)
self
.
assertEqual
(
args
,
{
'keypoint_flip_permutation'
:
(
1
,
0
,
2
,
3
,
5
,
4
)})
def
test_build_random_vertical_flip
(
self
):
preprocessor_text_proto
=
"""
random_vertical_flip {
keypoint_flip_permutation: 1
keypoint_flip_permutation: 0
keypoint_flip_permutation: 2
keypoint_flip_permutation: 3
keypoint_flip_permutation: 5
keypoint_flip_permutation: 4
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_vertical_flip
)
self
.
assertEqual
(
args
,
{
'keypoint_flip_permutation'
:
(
1
,
0
,
2
,
3
,
5
,
4
)})
def
test_build_random_rotation90
(
self
):
preprocessor_text_proto
=
"""
random_rotation90 {}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_rotation90
)
self
.
assertEqual
(
args
,
{})
def
test_build_random_pixel_value_scale
(
self
):
preprocessor_text_proto
=
"""
random_pixel_value_scale {
minval: 0.8
maxval: 1.2
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_pixel_value_scale
)
self
.
assert_dictionary_close
(
args
,
{
'minval'
:
0.8
,
'maxval'
:
1.2
})
def
test_build_random_image_scale
(
self
):
preprocessor_text_proto
=
"""
random_image_scale {
min_scale_ratio: 0.8
max_scale_ratio: 2.2
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_image_scale
)
self
.
assert_dictionary_close
(
args
,
{
'min_scale_ratio'
:
0.8
,
'max_scale_ratio'
:
2.2
})
def
test_build_random_rgb_to_gray
(
self
):
preprocessor_text_proto
=
"""
random_rgb_to_gray {
probability: 0.8
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_rgb_to_gray
)
self
.
assert_dictionary_close
(
args
,
{
'probability'
:
0.8
})
def
test_build_random_adjust_brightness
(
self
):
preprocessor_text_proto
=
"""
random_adjust_brightness {
max_delta: 0.2
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_adjust_brightness
)
self
.
assert_dictionary_close
(
args
,
{
'max_delta'
:
0.2
})
def
test_build_random_adjust_contrast
(
self
):
preprocessor_text_proto
=
"""
random_adjust_contrast {
min_delta: 0.7
max_delta: 1.1
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_adjust_contrast
)
self
.
assert_dictionary_close
(
args
,
{
'min_delta'
:
0.7
,
'max_delta'
:
1.1
})
def
test_build_random_adjust_hue
(
self
):
preprocessor_text_proto
=
"""
random_adjust_hue {
max_delta: 0.01
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_adjust_hue
)
self
.
assert_dictionary_close
(
args
,
{
'max_delta'
:
0.01
})
def
test_build_random_adjust_saturation
(
self
):
preprocessor_text_proto
=
"""
random_adjust_saturation {
min_delta: 0.75
max_delta: 1.15
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_adjust_saturation
)
self
.
assert_dictionary_close
(
args
,
{
'min_delta'
:
0.75
,
'max_delta'
:
1.15
})
def
test_build_random_distort_color
(
self
):
preprocessor_text_proto
=
"""
random_distort_color {
color_ordering: 1
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_distort_color
)
self
.
assertEqual
(
args
,
{
'color_ordering'
:
1
})
def
test_build_random_jitter_boxes
(
self
):
preprocessor_text_proto
=
"""
random_jitter_boxes {
ratio: 0.1
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_jitter_boxes
)
self
.
assert_dictionary_close
(
args
,
{
'ratio'
:
0.1
})
def
test_build_random_crop_image
(
self
):
preprocessor_text_proto
=
"""
random_crop_image {
min_object_covered: 0.75
min_aspect_ratio: 0.75
max_aspect_ratio: 1.5
min_area: 0.25
max_area: 0.875
overlap_thresh: 0.5
random_coef: 0.125
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_crop_image
)
self
.
assertEqual
(
args
,
{
'min_object_covered'
:
0.75
,
'aspect_ratio_range'
:
(
0.75
,
1.5
),
'area_range'
:
(
0.25
,
0.875
),
'overlap_thresh'
:
0.5
,
'random_coef'
:
0.125
,
})
def
test_build_random_pad_image
(
self
):
preprocessor_text_proto
=
"""
random_pad_image {
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_pad_image
)
self
.
assertEqual
(
args
,
{
'min_image_size'
:
None
,
'max_image_size'
:
None
,
'pad_color'
:
None
,
})
def
test_build_random_crop_pad_image
(
self
):
preprocessor_text_proto
=
"""
random_crop_pad_image {
min_object_covered: 0.75
min_aspect_ratio: 0.75
max_aspect_ratio: 1.5
min_area: 0.25
max_area: 0.875
overlap_thresh: 0.5
random_coef: 0.125
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_crop_pad_image
)
self
.
assertEqual
(
args
,
{
'min_object_covered'
:
0.75
,
'aspect_ratio_range'
:
(
0.75
,
1.5
),
'area_range'
:
(
0.25
,
0.875
),
'overlap_thresh'
:
0.5
,
'random_coef'
:
0.125
,
})
def
test_build_random_crop_pad_image_with_optional_parameters
(
self
):
preprocessor_text_proto
=
"""
random_crop_pad_image {
min_object_covered: 0.75
min_aspect_ratio: 0.75
max_aspect_ratio: 1.5
min_area: 0.25
max_area: 0.875
overlap_thresh: 0.5
random_coef: 0.125
min_padded_size_ratio: 0.5
min_padded_size_ratio: 0.75
max_padded_size_ratio: 0.5
max_padded_size_ratio: 0.75
pad_color: 0.5
pad_color: 0.5
pad_color: 1.0
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_crop_pad_image
)
self
.
assertEqual
(
args
,
{
'min_object_covered'
:
0.75
,
'aspect_ratio_range'
:
(
0.75
,
1.5
),
'area_range'
:
(
0.25
,
0.875
),
'overlap_thresh'
:
0.5
,
'random_coef'
:
0.125
,
'min_padded_size_ratio'
:
(
0.5
,
0.75
),
'max_padded_size_ratio'
:
(
0.5
,
0.75
),
'pad_color'
:
(
0.5
,
0.5
,
1.0
)
})
def
test_build_random_crop_to_aspect_ratio
(
self
):
preprocessor_text_proto
=
"""
random_crop_to_aspect_ratio {
aspect_ratio: 0.85
overlap_thresh: 0.35
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_crop_to_aspect_ratio
)
self
.
assert_dictionary_close
(
args
,
{
'aspect_ratio'
:
0.85
,
'overlap_thresh'
:
0.35
})
def
test_build_random_black_patches
(
self
):
preprocessor_text_proto
=
"""
random_black_patches {
max_black_patches: 20
probability: 0.95
size_to_image_ratio: 0.12
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_black_patches
)
self
.
assert_dictionary_close
(
args
,
{
'max_black_patches'
:
20
,
'probability'
:
0.95
,
'size_to_image_ratio'
:
0.12
})
def
test_build_random_resize_method
(
self
):
preprocessor_text_proto
=
"""
random_resize_method {
target_height: 75
target_width: 100
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
random_resize_method
)
self
.
assert_dictionary_close
(
args
,
{
'target_size'
:
[
75
,
100
]})
def
test_build_scale_boxes_to_pixel_coordinates
(
self
):
preprocessor_text_proto
=
"""
scale_boxes_to_pixel_coordinates {}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
scale_boxes_to_pixel_coordinates
)
self
.
assertEqual
(
args
,
{})
def
test_build_resize_image
(
self
):
preprocessor_text_proto
=
"""
resize_image {
new_height: 75
new_width: 100
method: BICUBIC
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
resize_image
)
self
.
assertEqual
(
args
,
{
'new_height'
:
75
,
'new_width'
:
100
,
'method'
:
tf
.
image
.
ResizeMethod
.
BICUBIC
})
def
test_build_rgb_to_gray
(
self
):
preprocessor_text_proto
=
"""
rgb_to_gray {}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
rgb_to_gray
)
self
.
assertEqual
(
args
,
{})
def
test_build_subtract_channel_mean
(
self
):
preprocessor_text_proto
=
"""
subtract_channel_mean {
means: [1.0, 2.0, 3.0]
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
subtract_channel_mean
)
self
.
assertEqual
(
args
,
{
'means'
:
[
1.0
,
2.0
,
3.0
]})
def
test_build_ssd_random_crop
(
self
):
preprocessor_text_proto
=
"""
ssd_random_crop {
operations {
min_object_covered: 0.0
min_aspect_ratio: 0.875
max_aspect_ratio: 1.125
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.0
random_coef: 0.375
}
operations {
min_object_covered: 0.25
min_aspect_ratio: 0.75
max_aspect_ratio: 1.5
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.25
random_coef: 0.375
}
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
ssd_random_crop
)
self
.
assertEqual
(
args
,
{
'min_object_covered'
:
[
0.0
,
0.25
],
'aspect_ratio_range'
:
[(
0.875
,
1.125
),
(
0.75
,
1.5
)],
'area_range'
:
[(
0.5
,
1.0
),
(
0.5
,
1.0
)],
'overlap_thresh'
:
[
0.0
,
0.25
],
'random_coef'
:
[
0.375
,
0.375
]})
def
test_build_ssd_random_crop_empty_operations
(
self
):
preprocessor_text_proto
=
"""
ssd_random_crop {
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
ssd_random_crop
)
self
.
assertEqual
(
args
,
{})
def
test_build_ssd_random_crop_pad
(
self
):
preprocessor_text_proto
=
"""
ssd_random_crop_pad {
operations {
min_object_covered: 0.0
min_aspect_ratio: 0.875
max_aspect_ratio: 1.125
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.0
random_coef: 0.375
min_padded_size_ratio: [1.0, 1.0]
max_padded_size_ratio: [2.0, 2.0]
pad_color_r: 0.5
pad_color_g: 0.5
pad_color_b: 0.5
}
operations {
min_object_covered: 0.25
min_aspect_ratio: 0.75
max_aspect_ratio: 1.5
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.25
random_coef: 0.375
min_padded_size_ratio: [1.0, 1.0]
max_padded_size_ratio: [2.0, 2.0]
pad_color_r: 0.5
pad_color_g: 0.5
pad_color_b: 0.5
}
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
ssd_random_crop_pad
)
self
.
assertEqual
(
args
,
{
'min_object_covered'
:
[
0.0
,
0.25
],
'aspect_ratio_range'
:
[(
0.875
,
1.125
),
(
0.75
,
1.5
)],
'area_range'
:
[(
0.5
,
1.0
),
(
0.5
,
1.0
)],
'overlap_thresh'
:
[
0.0
,
0.25
],
'random_coef'
:
[
0.375
,
0.375
],
'min_padded_size_ratio'
:
[(
1.0
,
1.0
),
(
1.0
,
1.0
)],
'max_padded_size_ratio'
:
[(
2.0
,
2.0
),
(
2.0
,
2.0
)],
'pad_color'
:
[(
0.5
,
0.5
,
0.5
),
(
0.5
,
0.5
,
0.5
)]})
def
test_build_ssd_random_crop_fixed_aspect_ratio
(
self
):
preprocessor_text_proto
=
"""
ssd_random_crop_fixed_aspect_ratio {
operations {
min_object_covered: 0.0
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.0
random_coef: 0.375
}
operations {
min_object_covered: 0.25
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.25
random_coef: 0.375
}
aspect_ratio: 0.875
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
ssd_random_crop_fixed_aspect_ratio
)
self
.
assertEqual
(
args
,
{
'min_object_covered'
:
[
0.0
,
0.25
],
'aspect_ratio'
:
0.875
,
'area_range'
:
[(
0.5
,
1.0
),
(
0.5
,
1.0
)],
'overlap_thresh'
:
[
0.0
,
0.25
],
'random_coef'
:
[
0.375
,
0.375
]})
def
test_build_ssd_random_crop_pad_fixed_aspect_ratio
(
self
):
preprocessor_text_proto
=
"""
ssd_random_crop_pad_fixed_aspect_ratio {
operations {
min_object_covered: 0.0
min_aspect_ratio: 0.875
max_aspect_ratio: 1.125
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.0
random_coef: 0.375
}
operations {
min_object_covered: 0.25
min_aspect_ratio: 0.75
max_aspect_ratio: 1.5
min_area: 0.5
max_area: 1.0
overlap_thresh: 0.25
random_coef: 0.375
}
aspect_ratio: 0.875
min_padded_size_ratio: [1.0, 1.0]
max_padded_size_ratio: [2.0, 2.0]
}
"""
preprocessor_proto
=
preprocessor_pb2
.
PreprocessingStep
()
text_format
.
Merge
(
preprocessor_text_proto
,
preprocessor_proto
)
function
,
args
=
preprocessor_builder
.
build
(
preprocessor_proto
)
self
.
assertEqual
(
function
,
preprocessor
.
ssd_random_crop_pad_fixed_aspect_ratio
)
self
.
assertEqual
(
args
,
{
'min_object_covered'
:
[
0.0
,
0.25
],
'aspect_ratio'
:
0.875
,
'aspect_ratio_range'
:
[(
0.875
,
1.125
),
(
0.75
,
1.5
)],
'area_range'
:
[(
0.5
,
1.0
),
(
0.5
,
1.0
)],
'overlap_thresh'
:
[
0.0
,
0.25
],
'random_coef'
:
[
0.375
,
0.375
],
'min_padded_size_ratio'
:
(
1.0
,
1.0
),
'max_padded_size_ratio'
:
(
2.0
,
2.0
)})
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Builder for region similarity calculators."""
from
object_detection.core
import
region_similarity_calculator
from
object_detection.protos
import
region_similarity_calculator_pb2
def
build
(
region_similarity_calculator_config
):
"""Builds region similarity calculator based on the configuration.
Builds one of [IouSimilarity, IoaSimilarity, NegSqDistSimilarity] objects. See
core/region_similarity_calculator.proto for details.
Args:
region_similarity_calculator_config: RegionSimilarityCalculator
configuration proto.
Returns:
region_similarity_calculator: RegionSimilarityCalculator object.
Raises:
ValueError: On unknown region similarity calculator.
"""
if
not
isinstance
(
region_similarity_calculator_config
,
region_similarity_calculator_pb2
.
RegionSimilarityCalculator
):
raise
ValueError
(
'region_similarity_calculator_config not of type '
'region_similarity_calculator_pb2.RegionsSimilarityCalculator'
)
similarity_calculator
=
region_similarity_calculator_config
.
WhichOneof
(
'region_similarity'
)
if
similarity_calculator
==
'iou_similarity'
:
return
region_similarity_calculator
.
IouSimilarity
()
if
similarity_calculator
==
'ioa_similarity'
:
return
region_similarity_calculator
.
IoaSimilarity
()
if
similarity_calculator
==
'neg_sq_dist_similarity'
:
return
region_similarity_calculator
.
NegSqDistSimilarity
()
raise
ValueError
(
'Unknown region similarity calculator.'
)
research/mlperf_object_detection/Mask_RCNN/object_detection/builders/region_similarity_calculator_builder_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for region_similarity_calculator_builder."""
import
tensorflow
as
tf
from
google.protobuf
import
text_format
from
object_detection.builders
import
region_similarity_calculator_builder
from
object_detection.core
import
region_similarity_calculator
from
object_detection.protos
import
region_similarity_calculator_pb2
as
sim_calc_pb2
class
RegionSimilarityCalculatorBuilderTest
(
tf
.
test
.
TestCase
):
def
testBuildIoaSimilarityCalculator
(
self
):
similarity_calc_text_proto
=
"""
ioa_similarity {
}
"""
similarity_calc_proto
=
sim_calc_pb2
.
RegionSimilarityCalculator
()
text_format
.
Merge
(
similarity_calc_text_proto
,
similarity_calc_proto
)
similarity_calc
=
region_similarity_calculator_builder
.
build
(
similarity_calc_proto
)
self
.
assertTrue
(
isinstance
(
similarity_calc
,
region_similarity_calculator
.
IoaSimilarity
))
def
testBuildIouSimilarityCalculator
(
self
):
similarity_calc_text_proto
=
"""
iou_similarity {
}
"""
similarity_calc_proto
=
sim_calc_pb2
.
RegionSimilarityCalculator
()
text_format
.
Merge
(
similarity_calc_text_proto
,
similarity_calc_proto
)
similarity_calc
=
region_similarity_calculator_builder
.
build
(
similarity_calc_proto
)
self
.
assertTrue
(
isinstance
(
similarity_calc
,
region_similarity_calculator
.
IouSimilarity
))
def
testBuildNegSqDistSimilarityCalculator
(
self
):
similarity_calc_text_proto
=
"""
neg_sq_dist_similarity {
}
"""
similarity_calc_proto
=
sim_calc_pb2
.
RegionSimilarityCalculator
()
text_format
.
Merge
(
similarity_calc_text_proto
,
similarity_calc_proto
)
similarity_calc
=
region_similarity_calculator_builder
.
build
(
similarity_calc_proto
)
self
.
assertTrue
(
isinstance
(
similarity_calc
,
region_similarity_calculator
.
NegSqDistSimilarity
))
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/core/__init__.py
deleted
100644 → 0
View file @
ad3526a9
research/mlperf_object_detection/Mask_RCNN/object_detection/core/anchor_generator.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Base anchor generator.
The job of the anchor generator is to create (or load) a collection
of bounding boxes to be used as anchors.
Generated anchors are assumed to match some convolutional grid or list of grid
shapes. For example, we might want to generate anchors matching an 8x8
feature map and a 4x4 feature map. If we place 3 anchors per grid location
on the first feature map and 6 anchors per grid location on the second feature
map, then 3*8*8 + 6*4*4 = 288 anchors are generated in total.
To support fully convolutional settings, feature map shapes are passed
dynamically at generation time. The number of anchors to place at each location
is static --- implementations of AnchorGenerator must always be able return
the number of anchors that it uses per location for each feature map.
"""
from
abc
import
ABCMeta
from
abc
import
abstractmethod
import
tensorflow
as
tf
class
AnchorGenerator
(
object
):
"""Abstract base class for anchor generators."""
__metaclass__
=
ABCMeta
@
abstractmethod
def
name_scope
(
self
):
"""Name scope.
Must be defined by implementations.
Returns:
a string representing the name scope of the anchor generation operation.
"""
pass
@
property
def
check_num_anchors
(
self
):
"""Whether to dynamically check the number of anchors generated.
Can be overridden by implementations that would like to disable this
behavior.
Returns:
a boolean controlling whether the Generate function should dynamically
check the number of anchors generated against the mathematically
expected number of anchors.
"""
return
True
@
abstractmethod
def
num_anchors_per_location
(
self
):
"""Returns the number of anchors per spatial location.
Returns:
a list of integers, one for each expected feature map to be passed to
the `generate` function.
"""
pass
def
generate
(
self
,
feature_map_shape_list
,
**
params
):
"""Generates a collection of bounding boxes to be used as anchors.
TODO(rathodv): remove **params from argument list and make stride and
offsets (for multiple_grid_anchor_generator) constructor arguments.
Args:
feature_map_shape_list: list of (height, width) pairs in the format
[(height_0, width_0), (height_1, width_1), ...] that the generated
anchors must align with. Pairs can be provided as 1-dimensional
integer tensors of length 2 or simply as tuples of integers.
**params: parameters for anchor generation op
Returns:
boxes_list: a list of BoxLists each holding anchor boxes corresponding to
the input feature map shapes.
Raises:
ValueError: if the number of feature map shapes does not match the length
of NumAnchorsPerLocation.
"""
if
self
.
check_num_anchors
and
(
len
(
feature_map_shape_list
)
!=
len
(
self
.
num_anchors_per_location
())):
raise
ValueError
(
'Number of feature maps is expected to equal the length '
'of `num_anchors_per_location`.'
)
with
tf
.
name_scope
(
self
.
name_scope
()):
anchors_list
=
self
.
_generate
(
feature_map_shape_list
,
**
params
)
if
self
.
check_num_anchors
:
with
tf
.
control_dependencies
([
self
.
_assert_correct_number_of_anchors
(
anchors_list
,
feature_map_shape_list
)]):
for
item
in
anchors_list
:
item
.
set
(
tf
.
identity
(
item
.
get
()))
return
anchors_list
@
abstractmethod
def
_generate
(
self
,
feature_map_shape_list
,
**
params
):
"""To be overridden by implementations.
Args:
feature_map_shape_list: list of (height, width) pairs in the format
[(height_0, width_0), (height_1, width_1), ...] that the generated
anchors must align with.
**params: parameters for anchor generation op
Returns:
boxes_list: a list of BoxList, each holding a collection of N anchor
boxes.
"""
pass
def
_assert_correct_number_of_anchors
(
self
,
anchors_list
,
feature_map_shape_list
):
"""Assert that correct number of anchors was generated.
Args:
anchors_list: A list of box_list.BoxList object holding anchors generated.
feature_map_shape_list: list of (height, width) pairs in the format
[(height_0, width_0), (height_1, width_1), ...] that the generated
anchors must align with.
Returns:
Op that raises InvalidArgumentError if the number of anchors does not
match the number of expected anchors.
"""
expected_num_anchors
=
0
actual_num_anchors
=
0
for
num_anchors_per_location
,
feature_map_shape
,
anchors
in
zip
(
self
.
num_anchors_per_location
(),
feature_map_shape_list
,
anchors_list
):
expected_num_anchors
+=
(
num_anchors_per_location
*
feature_map_shape
[
0
]
*
feature_map_shape
[
1
])
actual_num_anchors
+=
anchors
.
num_boxes
()
return
tf
.
assert_equal
(
expected_num_anchors
,
actual_num_anchors
)
research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Class to subsample minibatches by balancing positives and negatives.
Subsamples minibatches based on a pre-specified positive fraction in range
[0,1]. The class presumes there are many more negatives than positive examples:
if the desired batch_size cannot be achieved with the pre-specified positive
fraction, it fills the rest with negative examples. If this is not sufficient
for obtaining the desired batch_size, it returns fewer examples.
The main function to call is Subsample(self, indicator, labels). For convenience
one can also call SubsampleWeights(self, weights, labels) which is defined in
the minibatch_sampler base class.
"""
import
tensorflow
as
tf
from
object_detection.core
import
minibatch_sampler
class
BalancedPositiveNegativeSampler
(
minibatch_sampler
.
MinibatchSampler
):
"""Subsamples minibatches to a desired balance of positives and negatives."""
def
__init__
(
self
,
positive_fraction
=
0.5
):
"""Constructs a minibatch sampler.
Args:
positive_fraction: desired fraction of positive examples (scalar in [0,1])
in the batch.
Raises:
ValueError: if positive_fraction < 0, or positive_fraction > 1
"""
if
positive_fraction
<
0
or
positive_fraction
>
1
:
raise
ValueError
(
'positive_fraction should be in range [0,1]. '
'Received: %s.'
%
positive_fraction
)
self
.
_positive_fraction
=
positive_fraction
def
subsample
(
self
,
indicator
,
batch_size
,
labels
):
"""Returns subsampled minibatch.
Args:
indicator: boolean tensor of shape [N] whose True entries can be sampled.
batch_size: desired batch size. If None, keeps all positive samples and
randomly selects negative samples so that the positive sample fraction
matches self._positive_fraction.
labels: boolean tensor of shape [N] denoting positive(=True) and negative
(=False) examples.
Returns:
is_sampled: boolean tensor of shape [N], True for entries which are
sampled.
Raises:
ValueError: if labels and indicator are not 1D boolean tensors.
"""
if
len
(
indicator
.
get_shape
().
as_list
())
!=
1
:
raise
ValueError
(
'indicator must be 1 dimensional, got a tensor of '
'shape %s'
%
indicator
.
get_shape
())
if
len
(
labels
.
get_shape
().
as_list
())
!=
1
:
raise
ValueError
(
'labels must be 1 dimensional, got a tensor of '
'shape %s'
%
labels
.
get_shape
())
if
labels
.
dtype
!=
tf
.
bool
:
raise
ValueError
(
'labels should be of type bool. Received: %s'
%
labels
.
dtype
)
if
indicator
.
dtype
!=
tf
.
bool
:
raise
ValueError
(
'indicator should be of type bool. Received: %s'
%
indicator
.
dtype
)
# Only sample from indicated samples
negative_idx
=
tf
.
logical_not
(
labels
)
positive_idx
=
tf
.
logical_and
(
labels
,
indicator
)
negative_idx
=
tf
.
logical_and
(
negative_idx
,
indicator
)
# Sample positive and negative samples separately
if
batch_size
is
None
:
max_num_pos
=
tf
.
reduce_sum
(
tf
.
to_int32
(
positive_idx
))
else
:
max_num_pos
=
int
(
self
.
_positive_fraction
*
batch_size
)
sampled_pos_idx
=
self
.
subsample_indicator
(
positive_idx
,
max_num_pos
)
num_sampled_pos
=
tf
.
reduce_sum
(
tf
.
cast
(
sampled_pos_idx
,
tf
.
int32
))
if
batch_size
is
None
:
negative_positive_ratio
=
(
1
-
self
.
_positive_fraction
)
/
self
.
_positive_fraction
max_num_neg
=
tf
.
to_int32
(
negative_positive_ratio
*
tf
.
to_float
(
num_sampled_pos
))
else
:
max_num_neg
=
batch_size
-
num_sampled_pos
sampled_neg_idx
=
self
.
subsample_indicator
(
negative_idx
,
max_num_neg
)
sampled_idx
=
tf
.
logical_or
(
sampled_pos_idx
,
sampled_neg_idx
)
return
sampled_idx
research/mlperf_object_detection/Mask_RCNN/object_detection/core/balanced_positive_negative_sampler_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for object_detection.core.balanced_positive_negative_sampler."""
import
numpy
as
np
import
tensorflow
as
tf
from
object_detection.core
import
balanced_positive_negative_sampler
from
object_detection.utils
import
test_case
class
BalancedPositiveNegativeSamplerTest
(
test_case
.
TestCase
):
def
test_subsample_all_examples
(
self
):
numpy_labels
=
np
.
random
.
permutation
(
300
)
indicator
=
tf
.
constant
(
np
.
ones
(
300
)
==
1
)
numpy_labels
=
(
numpy_labels
-
200
)
>
0
labels
=
tf
.
constant
(
numpy_labels
)
sampler
=
(
balanced_positive_negative_sampler
.
BalancedPositiveNegativeSampler
())
is_sampled
=
sampler
.
subsample
(
indicator
,
64
,
labels
)
with
self
.
test_session
()
as
sess
:
is_sampled
=
sess
.
run
(
is_sampled
)
self
.
assertTrue
(
sum
(
is_sampled
)
==
64
)
self
.
assertTrue
(
sum
(
np
.
logical_and
(
numpy_labels
,
is_sampled
))
==
32
)
self
.
assertTrue
(
sum
(
np
.
logical_and
(
np
.
logical_not
(
numpy_labels
),
is_sampled
))
==
32
)
def
test_subsample_selection
(
self
):
# Test random sampling when only some examples can be sampled:
# 100 samples, 20 positives, 10 positives cannot be sampled
numpy_labels
=
np
.
arange
(
100
)
numpy_indicator
=
numpy_labels
<
90
indicator
=
tf
.
constant
(
numpy_indicator
)
numpy_labels
=
(
numpy_labels
-
80
)
>=
0
labels
=
tf
.
constant
(
numpy_labels
)
sampler
=
(
balanced_positive_negative_sampler
.
BalancedPositiveNegativeSampler
())
is_sampled
=
sampler
.
subsample
(
indicator
,
64
,
labels
)
with
self
.
test_session
()
as
sess
:
is_sampled
=
sess
.
run
(
is_sampled
)
self
.
assertTrue
(
sum
(
is_sampled
)
==
64
)
self
.
assertTrue
(
sum
(
np
.
logical_and
(
numpy_labels
,
is_sampled
))
==
10
)
self
.
assertTrue
(
sum
(
np
.
logical_and
(
np
.
logical_not
(
numpy_labels
),
is_sampled
))
==
54
)
self
.
assertAllEqual
(
is_sampled
,
np
.
logical_and
(
is_sampled
,
numpy_indicator
))
def
test_subsample_selection_no_batch_size
(
self
):
# Test random sampling when only some examples can be sampled:
# 1000 samples, 6 positives (5 can be sampled).
numpy_labels
=
np
.
arange
(
1000
)
numpy_indicator
=
numpy_labels
<
999
indicator
=
tf
.
constant
(
numpy_indicator
)
numpy_labels
=
(
numpy_labels
-
994
)
>=
0
labels
=
tf
.
constant
(
numpy_labels
)
sampler
=
(
balanced_positive_negative_sampler
.
BalancedPositiveNegativeSampler
(
0.01
))
is_sampled
=
sampler
.
subsample
(
indicator
,
None
,
labels
)
with
self
.
test_session
()
as
sess
:
is_sampled
=
sess
.
run
(
is_sampled
)
self
.
assertTrue
(
sum
(
is_sampled
)
==
500
)
self
.
assertTrue
(
sum
(
np
.
logical_and
(
numpy_labels
,
is_sampled
))
==
5
)
self
.
assertTrue
(
sum
(
np
.
logical_and
(
np
.
logical_not
(
numpy_labels
),
is_sampled
))
==
495
)
self
.
assertAllEqual
(
is_sampled
,
np
.
logical_and
(
is_sampled
,
numpy_indicator
))
def
test_raises_error_with_incorrect_label_shape
(
self
):
labels
=
tf
.
constant
([[
True
,
False
,
False
]])
indicator
=
tf
.
constant
([
True
,
False
,
True
])
sampler
=
(
balanced_positive_negative_sampler
.
BalancedPositiveNegativeSampler
())
with
self
.
assertRaises
(
ValueError
):
sampler
.
subsample
(
indicator
,
64
,
labels
)
def
test_raises_error_with_incorrect_indicator_shape
(
self
):
labels
=
tf
.
constant
([
True
,
False
,
False
])
indicator
=
tf
.
constant
([[
True
,
False
,
True
]])
sampler
=
(
balanced_positive_negative_sampler
.
BalancedPositiveNegativeSampler
())
with
self
.
assertRaises
(
ValueError
):
sampler
.
subsample
(
indicator
,
64
,
labels
)
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Provides functions to batch a dictionary of input tensors."""
import
collections
import
tensorflow
as
tf
from
object_detection.core
import
prefetcher
rt_shape_str
=
'_runtime_shapes'
class
BatchQueue
(
object
):
"""BatchQueue class.
This class creates a batch queue to asynchronously enqueue tensors_dict.
It also adds a FIFO prefetcher so that the batches are readily available
for the consumers. Dequeue ops for a BatchQueue object can be created via
the Dequeue method which evaluates to a batch of tensor_dict.
Example input pipeline with batching:
------------------------------------
key, string_tensor = slim.parallel_reader.parallel_read(...)
tensor_dict = decoder.decode(string_tensor)
tensor_dict = preprocessor.preprocess(tensor_dict, ...)
batch_queue = batcher.BatchQueue(tensor_dict,
batch_size=32,
batch_queue_capacity=2000,
num_batch_queue_threads=8,
prefetch_queue_capacity=20)
tensor_dict = batch_queue.dequeue()
outputs = Model(tensor_dict)
...
-----------------------------------
Notes:
-----
This class batches tensors of unequal sizes by zero padding and unpadding
them after generating a batch. This can be computationally expensive when
batching tensors (such as images) that are of vastly different sizes. So it is
recommended that the shapes of such tensors be fully defined in tensor_dict
while other lightweight tensors such as bounding box corners and class labels
can be of varying sizes. Use either crop or resize operations to fully define
the shape of an image in tensor_dict.
It is also recommended to perform any preprocessing operations on tensors
before passing to BatchQueue and subsequently calling the Dequeue method.
Another caveat is that this class does not read the last batch if it is not
full. The current implementation makes it hard to support that use case. So,
for evaluation, when it is critical to run all the examples through your
network use the input pipeline example mentioned in core/prefetcher.py.
"""
def
__init__
(
self
,
tensor_dict
,
batch_size
,
batch_queue_capacity
,
num_batch_queue_threads
,
prefetch_queue_capacity
):
"""Constructs a batch queue holding tensor_dict.
Args:
tensor_dict: dictionary of tensors to batch.
batch_size: batch size.
batch_queue_capacity: max capacity of the queue from which the tensors are
batched.
num_batch_queue_threads: number of threads to use for batching.
prefetch_queue_capacity: max capacity of the queue used to prefetch
assembled batches.
"""
# Remember static shapes to set shapes of batched tensors.
static_shapes
=
collections
.
OrderedDict
(
{
key
:
tensor
.
get_shape
()
for
key
,
tensor
in
tensor_dict
.
items
()})
# Remember runtime shapes to unpad tensors after batching.
runtime_shapes
=
collections
.
OrderedDict
(
{(
key
+
rt_shape_str
):
tf
.
shape
(
tensor
)
for
key
,
tensor
in
tensor_dict
.
items
()})
all_tensors
=
tensor_dict
all_tensors
.
update
(
runtime_shapes
)
batched_tensors
=
tf
.
train
.
batch
(
all_tensors
,
capacity
=
batch_queue_capacity
,
batch_size
=
batch_size
,
dynamic_pad
=
True
,
num_threads
=
num_batch_queue_threads
)
self
.
_queue
=
prefetcher
.
prefetch
(
batched_tensors
,
prefetch_queue_capacity
)
self
.
_static_shapes
=
static_shapes
self
.
_batch_size
=
batch_size
def
dequeue
(
self
):
"""Dequeues a batch of tensor_dict from the BatchQueue.
TODO: use allow_smaller_final_batch to allow running over the whole eval set
Returns:
A list of tensor_dicts of the requested batch_size.
"""
batched_tensors
=
self
.
_queue
.
dequeue
()
# Separate input tensors from tensors containing their runtime shapes.
tensors
=
{}
shapes
=
{}
for
key
,
batched_tensor
in
batched_tensors
.
items
():
unbatched_tensor_list
=
tf
.
unstack
(
batched_tensor
)
for
i
,
unbatched_tensor
in
enumerate
(
unbatched_tensor_list
):
if
rt_shape_str
in
key
:
shapes
[(
key
[:
-
len
(
rt_shape_str
)],
i
)]
=
unbatched_tensor
else
:
tensors
[(
key
,
i
)]
=
unbatched_tensor
# Undo that padding using shapes and create a list of size `batch_size` that
# contains tensor dictionaries.
tensor_dict_list
=
[]
batch_size
=
self
.
_batch_size
for
batch_id
in
range
(
batch_size
):
tensor_dict
=
{}
for
key
in
self
.
_static_shapes
:
tensor_dict
[
key
]
=
tf
.
slice
(
tensors
[(
key
,
batch_id
)],
tf
.
zeros_like
(
shapes
[(
key
,
batch_id
)]),
shapes
[(
key
,
batch_id
)])
tensor_dict
[
key
].
set_shape
(
self
.
_static_shapes
[
key
])
tensor_dict_list
.
append
(
tensor_dict
)
return
tensor_dict_list
research/mlperf_object_detection/Mask_RCNN/object_detection/core/batcher_test.py
deleted
100644 → 0
View file @
ad3526a9
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# 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
#
# http://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.
# ==============================================================================
"""Tests for object_detection.core.batcher."""
import
numpy
as
np
import
tensorflow
as
tf
from
object_detection.core
import
batcher
slim
=
tf
.
contrib
.
slim
class
BatcherTest
(
tf
.
test
.
TestCase
):
def
test_batch_and_unpad_2d_tensors_of_different_sizes_in_1st_dimension
(
self
):
with
self
.
test_session
()
as
sess
:
batch_size
=
3
num_batches
=
2
examples
=
tf
.
Variable
(
tf
.
constant
(
2
,
dtype
=
tf
.
int32
))
counter
=
examples
.
count_up_to
(
num_batches
*
batch_size
+
2
)
boxes
=
tf
.
tile
(
tf
.
reshape
(
tf
.
range
(
4
),
[
1
,
4
]),
tf
.
stack
([
counter
,
tf
.
constant
(
1
)]))
batch_queue
=
batcher
.
BatchQueue
(
tensor_dict
=
{
'boxes'
:
boxes
},
batch_size
=
batch_size
,
batch_queue_capacity
=
100
,
num_batch_queue_threads
=
1
,
prefetch_queue_capacity
=
100
)
batch
=
batch_queue
.
dequeue
()
for
tensor_dict
in
batch
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
([
None
,
4
],
tensor
.
get_shape
().
as_list
())
tf
.
initialize_all_variables
().
run
()
with
slim
.
queues
.
QueueRunners
(
sess
):
i
=
2
for
_
in
range
(
num_batches
):
batch_np
=
sess
.
run
(
batch
)
for
tensor_dict
in
batch_np
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
(
tensor
,
np
.
tile
(
np
.
arange
(
4
),
(
i
,
1
)))
i
+=
1
with
self
.
assertRaises
(
tf
.
errors
.
OutOfRangeError
):
sess
.
run
(
batch
)
def
test_batch_and_unpad_2d_tensors_of_different_sizes_in_all_dimensions
(
self
):
with
self
.
test_session
()
as
sess
:
batch_size
=
3
num_batches
=
2
examples
=
tf
.
Variable
(
tf
.
constant
(
2
,
dtype
=
tf
.
int32
))
counter
=
examples
.
count_up_to
(
num_batches
*
batch_size
+
2
)
image
=
tf
.
reshape
(
tf
.
range
(
counter
*
counter
),
tf
.
stack
([
counter
,
counter
]))
batch_queue
=
batcher
.
BatchQueue
(
tensor_dict
=
{
'image'
:
image
},
batch_size
=
batch_size
,
batch_queue_capacity
=
100
,
num_batch_queue_threads
=
1
,
prefetch_queue_capacity
=
100
)
batch
=
batch_queue
.
dequeue
()
for
tensor_dict
in
batch
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
([
None
,
None
],
tensor
.
get_shape
().
as_list
())
tf
.
initialize_all_variables
().
run
()
with
slim
.
queues
.
QueueRunners
(
sess
):
i
=
2
for
_
in
range
(
num_batches
):
batch_np
=
sess
.
run
(
batch
)
for
tensor_dict
in
batch_np
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
(
tensor
,
np
.
arange
(
i
*
i
).
reshape
((
i
,
i
)))
i
+=
1
with
self
.
assertRaises
(
tf
.
errors
.
OutOfRangeError
):
sess
.
run
(
batch
)
def
test_batch_and_unpad_2d_tensors_of_same_size_in_all_dimensions
(
self
):
with
self
.
test_session
()
as
sess
:
batch_size
=
3
num_batches
=
2
examples
=
tf
.
Variable
(
tf
.
constant
(
1
,
dtype
=
tf
.
int32
))
counter
=
examples
.
count_up_to
(
num_batches
*
batch_size
+
1
)
image
=
tf
.
reshape
(
tf
.
range
(
1
,
13
),
[
4
,
3
])
*
counter
batch_queue
=
batcher
.
BatchQueue
(
tensor_dict
=
{
'image'
:
image
},
batch_size
=
batch_size
,
batch_queue_capacity
=
100
,
num_batch_queue_threads
=
1
,
prefetch_queue_capacity
=
100
)
batch
=
batch_queue
.
dequeue
()
for
tensor_dict
in
batch
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
([
4
,
3
],
tensor
.
get_shape
().
as_list
())
tf
.
initialize_all_variables
().
run
()
with
slim
.
queues
.
QueueRunners
(
sess
):
i
=
1
for
_
in
range
(
num_batches
):
batch_np
=
sess
.
run
(
batch
)
for
tensor_dict
in
batch_np
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
(
tensor
,
np
.
arange
(
1
,
13
).
reshape
((
4
,
3
))
*
i
)
i
+=
1
with
self
.
assertRaises
(
tf
.
errors
.
OutOfRangeError
):
sess
.
run
(
batch
)
def
test_batcher_when_batch_size_is_one
(
self
):
with
self
.
test_session
()
as
sess
:
batch_size
=
1
num_batches
=
2
examples
=
tf
.
Variable
(
tf
.
constant
(
2
,
dtype
=
tf
.
int32
))
counter
=
examples
.
count_up_to
(
num_batches
*
batch_size
+
2
)
image
=
tf
.
reshape
(
tf
.
range
(
counter
*
counter
),
tf
.
stack
([
counter
,
counter
]))
batch_queue
=
batcher
.
BatchQueue
(
tensor_dict
=
{
'image'
:
image
},
batch_size
=
batch_size
,
batch_queue_capacity
=
100
,
num_batch_queue_threads
=
1
,
prefetch_queue_capacity
=
100
)
batch
=
batch_queue
.
dequeue
()
for
tensor_dict
in
batch
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
([
None
,
None
],
tensor
.
get_shape
().
as_list
())
tf
.
initialize_all_variables
().
run
()
with
slim
.
queues
.
QueueRunners
(
sess
):
i
=
2
for
_
in
range
(
num_batches
):
batch_np
=
sess
.
run
(
batch
)
for
tensor_dict
in
batch_np
:
for
tensor
in
tensor_dict
.
values
():
self
.
assertAllEqual
(
tensor
,
np
.
arange
(
i
*
i
).
reshape
((
i
,
i
)))
i
+=
1
with
self
.
assertRaises
(
tf
.
errors
.
OutOfRangeError
):
sess
.
run
(
batch
)
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
Prev
1
2
3
4
5
6
7
…
9
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment