Предоставленная конфигурация SSD MobileNet 1 PPN работает очень хорошо, но мне любопытно посмотреть, может ли «магистральная сеть» быть реально заменена на MobileNet 2.
Я сделал это в некоторой степени, иМои конфигурации PPN V2 хорошо работают по сравнению с соответствующими конфигурациями PPN V1 , которые также сходятся плавно и быстро (т. е. полезный график с шагом 10 тыс. [по моим собственным данным]).
Я экспериментировал с различными конечными точками и просматривал полученные графики в Tensorboard, в частности, рассматривая форму соединения между последним слоем MNet2 и первым слоем PPN MaxPool.
Для существующего PPN MNet1 с размером изображения 512x288:
Для моего случая (т.е. 320 жестко запрограммированы в файле ниже)
Другие конечные точки MNet2, которые я выбрал, создавали жизнеспособные графики, но с очень разными размерами файлов, когда были заморожены.Слои PPN MaxPool создаются на основе формы последнего слоя MNet2, поэтому я скопировал метод из примеров FPN, который добавляет окончательную свертку для манипулирования этим.
Я хотел бы понять следующее:
- Должен ли уровень конечной точки из MNet2 быть расширенным слоем или сжатым слоем?
- Какой PPN лучше всего подходит в качестве входного слоя и нужно ли его создавать дополнительно (например, как FPN)MNet2 - см.
_create_modified_mobilenet_config
)?
ssd_mobilenet_v2_ppn
Я взял код из примеров SSD PPN и FPN.
- Создать новый файл ssd_mobilenet_v2_ppn_feature_extractor.py in object_detection / models путем копирования и изменения значения для v1 .
- Редактирование файла model_builder.py в object_detection / builders до зарегистрируйте новый экстрактор функций.
- Ссылка на новый экстрактор функций PPN V2 в файле конфигурации обучения графов иустановите глубину box_detector равной значению, которое вы выбрали для num_outputs в новом экстракторе возможностей.
Я показал весь файл экстрактора объектов, так как он не большой, и это единственный важный код, необходимый:
import tensorflow as tf
from object_detection.meta_architectures import ssd_meta_arch
from object_detection.models import feature_map_generators
from object_detection.utils import context_manager
from object_detection.utils import ops
from object_detection.utils import shape_utils
import copy
import functools
from nets.mobilenet import mobilenet
from nets.mobilenet import mobilenet_v2
slim = tf.contrib.slim
# should num_outputs match ssd.box_predictor.depth?
def _create_modified_mobilenet_config( num_outputs=320 ):
conv_op = functools.partial( slim.separable_conv2d, depth_multiplier=1 )
#conv_op = slim.conv2d
conv_defs = copy.deepcopy( mobilenet_v2.V2_DEF )
conv_defs['spec'][-1] = mobilenet.op( conv_op, stride=1, kernel_size=[1, 1], num_outputs=num_outputs )
return conv_defs
class SSDMobileNetV2PpnFeatureExtractor(ssd_meta_arch.SSDFeatureExtractor):
def __init__(
self,
is_training,
depth_multiplier,
min_depth,
pad_to_multiple,
conv_hyperparams_fn,
reuse_weights=None,
use_explicit_padding=False,
use_depthwise=False,
override_base_feature_extractor_hyperparams=False
):
super( SSDMobileNetV2PpnFeatureExtractor, self ).__init__(
is_training=is_training,
depth_multiplier=depth_multiplier,
min_depth=min_depth,
pad_to_multiple=pad_to_multiple,
conv_hyperparams_fn=conv_hyperparams_fn,
reuse_weights=reuse_weights,
use_explicit_padding=use_explicit_padding,
use_depthwise=use_depthwise,
override_base_feature_extractor_hyperparams=override_base_feature_extractor_hyperparams)
self._conv_defs = None
if self._use_depthwise:
self._conv_defs = _create_modified_mobilenet_config()
def preprocess(self, resized_inputs):
return (2.0 / 255.0) * resized_inputs - 1.0
def extract_features(self, preprocessed_inputs):
preprocessed_inputs = shape_utils.check_min_image_dim( 33, preprocessed_inputs )
final_endpoint = 'layer_19'
feature_endpoint = 'layer_19'
with tf.variable_scope( 'MobilenetV2', reuse=self._reuse_weights ) as scope:
# NB: checked all other MNet feature extractors have: is_training=None
with slim.arg_scope( mobilenet_v2.training_scope( is_training=None, bn_decay=0.9997 ) ), \
slim.arg_scope( [ mobilenet.depth_multiplier ], min_depth=self._min_depth ):
with (
slim.arg_scope( self._conv_hyperparams_fn() )
if self._override_base_feature_extractor_hyperparams
else context_manager.IdentityContextManager()
):
_, image_features = mobilenet_v2.mobilenet_base(
ops.pad_to_multiple( preprocessed_inputs, self._pad_to_multiple ),
final_endpoint=final_endpoint,
min_depth=self._min_depth,
depth_multiplier=self._depth_multiplier,
conv_defs=self._conv_defs,
use_explicit_padding=self._use_explicit_padding,
scope=scope
)
with slim.arg_scope( self._conv_hyperparams_fn() ):
feature_maps = feature_map_generators.pooling_pyramid_feature_maps(
base_feature_map_depth=0,
num_layers=6,
image_features={
'image_features': image_features[ feature_endpoint ]
}
)
return feature_maps.values()