In short, the Logits layer of the pre-trained mobilenet_v2_0.5_224 checkpoint linked to in slim/nets/mobilenet/README.md appears to have had its original depth of 1280 preserved during training while the rest of the network was scaled down by 50%. When using nets_factory to instantiate a network having a depth_multiplier of 0.5, the entire network is scaled down by 50%, including the Logits layer. Consequently, the checkpoint fails to be restored and the following error is presented:
InvalidArgumentError (see above for traceback): Assign requires shapes of both tensors to match. lhs shape= [640] rhs shape= [1280]
[[Node: save_1/Assign_7 = Assign[T=DT_FLOAT, _class=["loc:@MobilenetV2/Conv_1/BatchNorm/moving_mean"], use_locking=true, validate_shape=true, _device="/job:localhost/replica:0/task:0/device:CPU:0"](MobilenetV2/Conv_1/BatchNorm/moving_mean, save_1/RestoreV2:7)]]
This failure also occurs for mobilenet_v2_0.75_224, but not for mobilenet_v2_1.4_224 (using a similar wrapper function that I added to mobilenet_v2.py to make using mobilenets of various sizes convenient). I have not tested other sizes.
If mobilenet_v2 is intended to have a minimum Logits layer size of 1280, then the tf-slim implementation should enforce that (assuming I'm right that it does not). I would much prefer, though, that the smaller mobilenet_v2 models be re-trained, and that the current depth_multiplier behavior remain unchanged.
Source code that I added to slim/nets/mobilenet/mobilenet_v2.py:
@slim.add_arg_scope
def mobilenet_050(input_tensor, num_classes=1001, depth_multiplier=0.5, scope='MobilenetV2', conv_defs=None, finegrain_classification_mode=False, min_depth=None, divisible_by=None, *kwargs):
return mobilenet(input_tensor, num_classes=num_classes, depth_multiplier=depth_multiplier, scope=scope, conv_defs=conv_defs, finegrain_classification_mode=finegrain_classification_mode, min_depth=min_depth, divisible_by=divisible_by, *kwargs)
mobilenet_050.default_image_size = 224
Source code that I added to slim/nets/nets_factory.py:
networks_map = { ..., 'mobilenet_v2_050': mobilenet_v2.mobilenet_050, ... }
arg_scopes_map = { ..., 'mobilenet_v2_050': mobilenet_v2.training_scope, ... }
default_image_size_map = { ..., 'mobilenet_v2_050': mobilenet_v2.mobilenet_050.default_image_size, ... }
Source code that I added to slim/preprocessing/preprocessing_factory.py:
preprocessing_fn_map = { ..., 'mobilenet_v2_050': inception_preprocessing, ... }
Traceback log
Have you tride finegrain_classification_mode=True in your call to mobilenet (nets_factory diverts here)? This looks like intended behaviour, and they just haven't released weights for models trained with finegrain_classification_mode=False
@jackd It looks like you are 100% right. Thank you for pointing out this argument!
Most helpful comment
Have you tride
finegrain_classification_mode=Truein your call tomobilenet(nets_factorydiverts here)? This looks like intended behaviour, and they just haven't released weights for models trained withfinegrain_classification_mode=False