diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 8f4569030f..a80bc1b735 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -41,6 +41,8 @@ jobs: pip install -e ".[tests]" --progress-bar off --upgrade - name: Test with pytest env: + KAGGLE_USERNAME: ${{ secrets.KAGGLE_USERNAME }} + KAGGLE_KEY: ${{ secrets.KAGGLE_KEY }} TEST_CUSTOM_OPS: false run: | pytest keras_cv/ --ignore keras_cv/models/legacy/ --durations 0 @@ -77,6 +79,8 @@ jobs: env: TEST_CUSTOM_OPS: false # TODO(ianstenbit): test custom ops, or figure out what our story is here KERAS_BACKEND: ${{ matrix.backend }} + KAGGLE_USERNAME: ${{ secrets.KAGGLE_USERNAME}} + KAGGLE_KEY: ${{ secrets.KAGGLE_KEY}} JAX_ENABLE_X64: true run: | pytest keras_cv/bounding_box \ diff --git a/keras_cv/__init__.py b/keras_cv/__init__.py index fbe6c6da23..afea823f72 100644 --- a/keras_cv/__init__.py +++ b/keras_cv/__init__.py @@ -42,4 +42,4 @@ from keras_cv.core import NormalFactorSampler from keras_cv.core import UniformFactorSampler -__version__ = "0.8.0" +__version__ = "0.8.0.dev0" diff --git a/keras_cv/models/backbones/backbone.py b/keras_cv/models/backbones/backbone.py index 5e302b78b3..6130945308 100644 --- a/keras_cv/models/backbones/backbone.py +++ b/keras_cv/models/backbones/backbone.py @@ -13,10 +13,10 @@ # limitations under the License. """Base class for Backbone models.""" -import os - from keras_cv.api_export import keras_cv_export from keras_cv.backend import keras +from keras_cv.utils.preset_utils import check_preset_class +from keras_cv.utils.preset_utils import load_from_preset from keras_cv.utils.python_utils import classproperty from keras_cv.utils.python_utils import format_docstring @@ -32,6 +32,20 @@ class Backbone(keras.Model): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._pyramid_level_inputs = {} + self._functional_layer_ids = set( + id(layer) for layer in self._flatten_layers() + ) + + def __dir__(self): + # Temporary fixes for weight saving. This mimics the following PR for + # older version of Keras: https://github.com/keras-team/keras/pull/18982 + def filter_fn(attr): + try: + return id(getattr(self, attr)) not in self._functional_layer_ids + except: + return True + + return filter(filter_fn, super().__dir__()) def get_config(self): # Don't chain to super here. The default `get_config()` for functional @@ -95,43 +109,18 @@ def from_preset( load_weights=False, ``` """ - - if not cls.presets: - raise NotImplementedError( - "No presets have been created for this class." - ) - - if preset not in cls.presets: - raise ValueError( - "`preset` must be one of " - f"""{", ".join(cls.presets)}. Received: {preset}.""" - ) - - if load_weights and preset not in cls.presets_with_weights: - raise ValueError( - f"""Pretrained weights not available for preset "{preset}". """ - "Set `load_weights=False` to use this preset or choose one of " - "the following presets with weights:" - f""" "{'", "'.join(cls.presets_with_weights)}".""" - ) - - metadata = cls.presets[preset] - config = metadata["config"] - model = cls.from_config({**config, **kwargs}) - - if preset not in cls.presets_with_weights or load_weights is False: - return model - - weights = keras.utils.get_file( - "model.h5", - metadata["weights_url"], - cache_subdir=os.path.join("models", preset), - file_hash=metadata["weights_hash"], + # We support short IDs for official presets, e.g. `"bert_base_en"`. + # Map these to a Kaggle Models handle. + if preset in cls.presets: + preset = cls.presets[preset]["kaggle_handle"] + + check_preset_class(preset, cls) + return load_from_preset( + preset, + load_weights=load_weights, + config_overrides=kwargs, ) - model.load_weights(weights) - return model - def __init_subclass__(cls, **kwargs): # Use __init_subclass__ to set up a correct docstring for from_preset. super().__init_subclass__(**kwargs) diff --git a/keras_cv/models/backbones/csp_darknet/csp_darknet_backbone_presets.py b/keras_cv/models/backbones/csp_darknet/csp_darknet_backbone_presets.py index c4d4b0f2ef..fb3738a92b 100644 --- a/keras_cv/models/backbones/csp_darknet/csp_darknet_backbone_presets.py +++ b/keras_cv/models/backbones/csp_darknet/csp_darknet_backbone_presets.py @@ -26,15 +26,7 @@ "official_name": "CSPDarkNet", "path": "csp_darknet", }, - "class_name": "keras_cv>CSPDarkNetBackbone", - "config": { - "stackwise_channels": [48, 96, 192, 384], - "stackwise_depth": [1, 3, 3, 1], - "include_rescaling": True, - "use_depthwise": False, - "input_shape": (None, None, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/cspdarknet/csp_darknet_tiny/2", }, "csp_darknet_s": { "metadata": { @@ -47,15 +39,7 @@ "official_name": "CSPDarkNet", "path": "csp_darknet", }, - "class_name": "keras_cv>CSPDarkNetBackbone", - "config": { - "stackwise_channels": [64, 128, 256, 512], - "stackwise_depth": [1, 3, 3, 1], - "include_rescaling": True, - "use_depthwise": False, - "input_shape": (None, None, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/cspdarknet/csp_darknet_s/2", }, "csp_darknet_m": { "metadata": { @@ -68,15 +52,7 @@ "official_name": "CSPDarkNet", "path": "csp_darknet", }, - "class_name": "keras_cv>CSPDarkNetBackbone", - "config": { - "stackwise_channels": [96, 192, 384, 768], - "stackwise_depth": [2, 6, 6, 2], - "include_rescaling": True, - "use_depthwise": False, - "input_shape": (None, None, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/cspdarknet/csp_darknet_m/2", }, "csp_darknet_l": { "metadata": { @@ -89,15 +65,7 @@ "official_name": "CSPDarkNet", "path": "csp_darknet", }, - "class_name": "keras_cv>CSPDarkNetBackbone", - "config": { - "stackwise_channels": [128, 256, 512, 1024], - "stackwise_depth": [3, 9, 9, 3], - "include_rescaling": True, - "use_depthwise": False, - "input_shape": (None, None, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/cspdarknet/csp_darknet_l/2", }, "csp_darknet_xl": { "metadata": { @@ -110,15 +78,7 @@ "official_name": "CSPDarkNet", "path": "csp_darknet", }, - "class_name": "keras_cv>CSPDarkNetBackbone", - "config": { - "stackwise_channels": [170, 340, 680, 1360], - "stackwise_depth": [4, 12, 12, 4], - "include_rescaling": True, - "use_depthwise": False, - "input_shape": (None, None, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/cspdarknet/csp_darknet_xl/2", }, } @@ -135,10 +95,7 @@ "official_name": "CSPDarkNet", "path": "csp_darknet", }, - "class_name": "keras_cv>CSPDarkNetBackbone", - "config": backbone_presets_no_weights["csp_darknet_tiny"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/cspdarknettiny/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "0007ae82c95be4d4aef06368a7c38e006381324d77e5df029b04890e18a8ad19", # noqa: E501 + "kaggle_handle": "kaggle://keras/cspdarknet/csp_darknet_tiny_imagenet/2", # noqa: E501 }, "csp_darknet_l_imagenet": { "metadata": { @@ -152,10 +109,7 @@ "official_name": "CSPDarkNet", "path": "csp_darknet", }, - "class_name": "keras_cv>CSPDarkNetBackbone", - "config": backbone_presets_no_weights["csp_darknet_l"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/cspdarknetl/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "9303aabfadffbff8447171fce1e941f96d230d8f3cef30d3f05a9c85097f8f1e", # noqa: E501 + "kaggle_handle": "kaggle://keras/cspdarknet/csp_darknet_l_imagenet/2", }, } diff --git a/keras_cv/models/backbones/densenet/densenet_backbone_presets.py b/keras_cv/models/backbones/densenet/densenet_backbone_presets.py index 50230b8d89..01056593bd 100644 --- a/keras_cv/models/backbones/densenet/densenet_backbone_presets.py +++ b/keras_cv/models/backbones/densenet/densenet_backbone_presets.py @@ -18,43 +18,19 @@ "metadata": { "description": "DenseNet model with 121 layers.", }, - "class_name": "keras_cv>DenseNetBackbone", - "config": { - "stackwise_num_repeats": [6, 12, 24, 16], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "compression_ratio": 0.5, - "growth_rate": 32, - }, + "kaggle_handle": "kaggle://keras/densenet/densenet121/2", }, "densenet169": { "metadata": { "description": "DenseNet model with 169 layers.", }, - "class_name": "keras_cv>DenseNetBackbone", - "config": { - "stackwise_num_repeats": [6, 12, 32, 32], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "compression_ratio": 0.5, - "growth_rate": 32, - }, + "kaggle_handle": "kaggle://keras/densenet/densenet169/2", }, "densenet201": { "metadata": { "description": "DenseNet model with 201 layers.", }, - "class_name": "keras_cv>DenseNetBackbone", - "config": { - "stackwise_num_repeats": [6, 12, 48, 32], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "compression_ratio": 0.5, - "growth_rate": 32, - }, + "kaggle_handle": "kaggle://keras/densenet/densenet201/2", }, } @@ -66,10 +42,7 @@ "classification task." ), }, - "class_name": "keras_cv>DenseNetBackbone", - "config": backbone_presets_no_weights["densenet121"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/densenet121/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "709afe0321d9f2b2562e562ff9d0dc44cca10ed09e0e2cfba08d783ff4dab6bf", # noqa: E501 + "kaggle_handle": "kaggle://keras/densenet/densenet121_imagenet/2", }, "densenet169_imagenet": { "metadata": { @@ -78,10 +51,7 @@ "classification task." ), }, - "class_name": "keras_cv>DenseNetBackbone", - "config": backbone_presets_no_weights["densenet169"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/densenet169/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "a99d1bb2cbe1a59a1cdd1f435fb265453a97c2a7b723d26f4ebee96e5fb49d62", # noqa: E501 + "kaggle_handle": "kaggle://keras/densenet/densenet169_imagenet/2", }, "densenet201_imagenet": { "metadata": { @@ -90,10 +60,7 @@ "classification task." ), }, - "class_name": "keras_cv>DenseNetBackbone", - "config": backbone_presets_no_weights["densenet201"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/densenet201/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "c1189a934f12c1a676a9cf52238e5994401af925e2adfc0365bad8133c052060", # noqa: E501 + "kaggle_handle": "kaggle://keras/densenet/densenet201_imagenet/2", }, } diff --git a/keras_cv/models/backbones/efficientnet_lite/efficientnet_lite_backbone_presets.py b/keras_cv/models/backbones/efficientnet_lite/efficientnet_lite_backbone_presets.py index db9838e3de..5405742151 100644 --- a/keras_cv/models/backbones/efficientnet_lite/efficientnet_lite_backbone_presets.py +++ b/keras_cv/models/backbones/efficientnet_lite/efficientnet_lite_backbone_presets.py @@ -26,24 +26,7 @@ "official_name": "EfficientNetLite", "path": "EfficientNetLite", }, - "class_name": "keras_cv.models>EfficientNetLiteBackbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "dropout_rate": 0.2, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "relu6", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetlite_b0", }, "efficientnetlite_b1": { "metadata": { @@ -56,24 +39,7 @@ "official_name": "EfficientNetLite", "path": "EfficientNetLite", }, - "class_name": "keras_cv.models>EfficientNetLiteBackbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.1, - "dropout_rate": 0.2, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "relu6", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetlite_b1", }, "efficientnetlite_b2": { "metadata": { @@ -86,24 +52,7 @@ "official_name": "EfficientNetLite", "path": "EfficientNetLite", }, - "class_name": "keras_cv.models>EfficientNetLiteBackbone", - "config": { - "width_coefficient": 1.1, - "depth_coefficient": 1.2, - "dropout_rate": 0.3, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "relu6", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetlite_b2", }, "efficientnetlite_b3": { "metadata": { @@ -116,24 +65,7 @@ "official_name": "EfficientNetLite", "path": "EfficientNetLite", }, - "class_name": "keras_cv.models>EfficientNetLiteBackbone", - "config": { - "width_coefficient": 1.2, - "depth_coefficient": 1.4, - "dropout_rate": 0.3, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "relu6", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetlite_b3", }, "efficientnetlite_b4": { "metadata": { @@ -146,24 +78,7 @@ "official_name": "EfficientNetLite", "path": "EfficientNetLite", }, - "class_name": "keras_cv.models>EfficientNetLiteBackbone", - "config": { - "width_coefficient": 1.4, - "depth_coefficient": 1.8, - "dropout_rate": 0.3, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "relu6", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetlite_b4", }, } diff --git a/keras_cv/models/backbones/efficientnet_v1/efficientnet_v1_backbone_presets.py b/keras_cv/models/backbones/efficientnet_v1/efficientnet_v1_backbone_presets.py index a2aac81d26..8d0e0c6f7d 100644 --- a/keras_cv/models/backbones/efficientnet_v1/efficientnet_v1_backbone_presets.py +++ b/keras_cv/models/backbones/efficientnet_v1/efficientnet_v1_backbone_presets.py @@ -26,33 +26,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "dropout_rate": 0.2, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b0", }, "efficientnetv1_b1": { "metadata": { @@ -65,33 +39,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.1, - "dropout_rate": 0.2, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b1", }, "efficientnetv1_b2": { "metadata": { @@ -104,33 +52,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 1.1, - "depth_coefficient": 1.2, - "dropout_rate": 0.3, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b2", }, "efficientnetv1_b3": { "metadata": { @@ -143,33 +65,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 1.2, - "depth_coefficient": 1.4, - "dropout_rate": 0.3, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b3", }, "efficientnetv1_b4": { "metadata": { @@ -182,33 +78,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 1.4, - "depth_coefficient": 1.8, - "dropout_rate": 0.4, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b4", }, "efficientnetv1_b5": { "metadata": { @@ -221,33 +91,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 1.6, - "depth_coefficient": 2.2, - "dropout_rate": 0.4, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b5", }, "efficientnetv1_b6": { "metadata": { @@ -260,33 +104,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 1.8, - "depth_coefficient": 2.6, - "dropout_rate": 0.5, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b6", }, "efficientnetv1_b7": { "metadata": { @@ -299,33 +117,7 @@ "official_name": "EfficientNetV1", "path": "efficientnetv1", }, - "class_name": "keras_cv.models>EfficientNetV1Backbone", - "config": { - "width_coefficient": 2.0, - "depth_coefficient": 3.1, - "dropout_rate": 0.5, - "drop_connect_rate": 0.2, - "depth_divisor": 8, - "stackwise_kernel_sizes": [3, 3, 5, 3, 5, 5, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 3, 4, 1], - "stackwise_input_filters": [32, 16, 24, 40, 80, 112, 192], - "stackwise_output_filters": [16, 24, 40, 80, 112, 192, 320], - "stackwise_expansion_ratios": [1, 6, 6, 6, 6, 6, 6], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_squeeze_and_excite_ratios": [ - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "activation": "swish", - }, + "kaggle_handle": "gs://keras-cv-kaggle/efficientnetv1_b7", }, } diff --git a/keras_cv/models/backbones/efficientnet_v2/efficientnet_v2_backbone_presets.py b/keras_cv/models/backbones/efficientnet_v2/efficientnet_v2_backbone_presets.py index 4bdc099c13..07b830962a 100644 --- a/keras_cv/models/backbones/efficientnet_v2/efficientnet_v2_backbone_presets.py +++ b/keras_cv/models/backbones/efficientnet_v2/efficientnet_v2_backbone_presets.py @@ -24,40 +24,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [2, 4, 4, 6, 9, 15], - "stackwise_input_filters": [24, 24, 48, 64, 128, 160], - "stackwise_output_filters": [24, 48, 64, 128, 160, 256], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [ - 0.0, - 0.0, - 0, - 0.25, - 0.25, - 0.25, - ], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_s/2", }, "efficientnetv2_m": { "metadata": { @@ -68,42 +35,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [3, 5, 5, 7, 14, 18, 5], - "stackwise_input_filters": [24, 24, 48, 80, 160, 176, 304], - "stackwise_output_filters": [24, 48, 80, 160, 176, 304, 512], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6, 6], - "stackwise_squeeze_and_excite_ratios": [ - 0, - 0, - 0, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - "unfused", - ], - }, + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_m/2", }, "efficientnetv2_l": { "metadata": { @@ -115,42 +47,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [4, 7, 7, 10, 19, 25, 7], - "stackwise_input_filters": [32, 32, 64, 96, 192, 224, 384], - "stackwise_output_filters": [32, 64, 96, 192, 224, 384, 640], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6, 6], - "stackwise_squeeze_and_excite_ratios": [ - 0, - 0, - 0, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "stackwise_strides": [1, 2, 2, 2, 1, 2, 1], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - "unfused", - ], - }, + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_l/2", }, "efficientnetv2_b0": { "metadata": { @@ -163,33 +60,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 5, 8], - "stackwise_input_filters": [32, 16, 32, 48, 96, 112], - "stackwise_output_filters": [16, 32, 48, 96, 112, 192], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [0, 0, 0, 0.25, 0.25, 0.25], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b0/2", }, "efficientnetv2_b1": { "metadata": { @@ -202,33 +73,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.1, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 5, 8], - "stackwise_input_filters": [32, 16, 32, 48, 96, 112], - "stackwise_output_filters": [16, 32, 48, 96, 112, 192], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [0, 0, 0, 0.25, 0.25, 0.25], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b1/2", }, "efficientnetv2_b2": { "metadata": { @@ -241,33 +86,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.1, - "depth_coefficient": 1.2, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 5, 8], - "stackwise_input_filters": [32, 16, 32, 48, 96, 112], - "stackwise_output_filters": [16, 32, 48, 96, 112, 192], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [0, 0, 0, 0.25, 0.25, 0.25], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b2/2", }, "efficientnetv2_b3": { "metadata": { @@ -280,33 +99,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.2, - "depth_coefficient": 1.4, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 5, 8], - "stackwise_input_filters": [32, 16, 32, 48, 96, 112], - "stackwise_output_filters": [16, 32, 48, 96, 112, 192], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [0, 0, 0, 0.25, 0.25, 0.25], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b3/2", }, } @@ -324,42 +117,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [2, 4, 4, 6, 9, 15], - "stackwise_input_filters": [24, 24, 48, 64, 128, 160], - "stackwise_output_filters": [24, 48, 64, 128, 160, 256], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [ - 0.0, - 0.0, - 0, - 0.25, - 0.25, - 0.25, - ], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnetv2s/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "80555436ea49100893552614b4dce98de461fa3b6c14f8132673817d28c83654", # noqa: E501 + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_s_imagenet/2", # noqa: E501 }, "efficientnetv2_b0_imagenet": { "metadata": { @@ -376,35 +134,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.0, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 5, 8], - "stackwise_input_filters": [32, 16, 32, 48, 96, 112], - "stackwise_output_filters": [16, 32, 48, 96, 112, 192], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [0, 0, 0, 0.25, 0.25, 0.25], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnetv2b0/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "ac95f13a8ad1cee41184fc16fd0eb769f7c5b3131151c6abf7fcee5cc3d09bc8", # noqa: E501 + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b0_imagenet/2", # noqa: E501 }, "efficientnetv2_b1_imagenet": { "metadata": { @@ -421,35 +151,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.0, - "depth_coefficient": 1.1, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 5, 8], - "stackwise_input_filters": [32, 16, 32, 48, 96, 112], - "stackwise_output_filters": [16, 32, 48, 96, 112, 192], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [0, 0, 0, 0.25, 0.25, 0.25], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnetv2b1/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "82da111f8411f47e3f5eef090da76340f38e222f90a08bead53662f2ebafb01c", # noqa: E501 + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b1_imagenet/2", # noqa: E501 }, "efficientnetv2_b2_imagenet": { "metadata": { @@ -466,35 +168,7 @@ "official_name": "EfficientNetV2", "path": "efficientnetv2", }, - "class_name": "keras_cv>EfficientNetV2Backbone", - "config": { - "width_coefficient": 1.1, - "depth_coefficient": 1.2, - "skip_connection_dropout": 0.2, - "depth_divisor": 8, - "min_depth": 8, - "activation": "swish", - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "stackwise_kernel_sizes": [3, 3, 3, 3, 3, 3], - "stackwise_num_repeats": [1, 2, 2, 3, 5, 8], - "stackwise_input_filters": [32, 16, 32, 48, 96, 112], - "stackwise_output_filters": [16, 32, 48, 96, 112, 192], - "stackwise_expansion_ratios": [1, 4, 4, 4, 6, 6], - "stackwise_squeeze_and_excite_ratios": [0, 0, 0, 0.25, 0.25, 0.25], - "stackwise_strides": [1, 2, 2, 2, 1, 2], - "stackwise_conv_types": [ - "fused", - "fused", - "fused", - "unfused", - "unfused", - "unfused", - ], - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnetv2b2/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "02d12c9d1589b540b4e84ffdb54ff30c96099bd59e311a85ddc7180efc65e955", # noqa: E501 + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b2_imagenet/2", # noqa: E501 }, } diff --git a/keras_cv/models/backbones/mix_transformer/mix_transformer_backbone_presets.py b/keras_cv/models/backbones/mix_transformer/mix_transformer_backbone_presets.py index a4c1c2a3e1..ec474987ba 100644 --- a/keras_cv/models/backbones/mix_transformer/mix_transformer_backbone_presets.py +++ b/keras_cv/models/backbones/mix_transformer/mix_transformer_backbone_presets.py @@ -23,14 +23,7 @@ "official_name": "MiT", "path": "mit", }, - "class_name": "keras_cv>MiTBackbone", - "config": { - "embedding_dims": [32, 64, 160, 256], - "depths": [2, 2, 2, 2], - "include_rescaling": True, - "input_shape": (224, 224, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/mit/mit_b0/2", }, "mit_b1": { "metadata": { @@ -41,14 +34,7 @@ "official_name": "MiT", "path": "mit", }, - "class_name": "keras_cv>MiTBackbone", - "config": { - "embedding_dims": [64, 128, 320, 512], - "depths": [2, 2, 2, 2], - "include_rescaling": True, - "input_shape": (224, 224, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/mit/mit_b1/2", }, "mit_b2": { "metadata": { @@ -59,14 +45,7 @@ "official_name": "MiT", "path": "mit", }, - "class_name": "keras_cv>MiTBackbone", - "config": { - "embedding_dims": [64, 128, 320, 512], - "depths": [3, 4, 6, 3], - "include_rescaling": True, - "input_shape": (224, 224, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/mit/mit_b2/2", }, "mit_b3": { "metadata": { @@ -77,14 +56,7 @@ "official_name": "MiT", "path": "mit", }, - "class_name": "keras_cv>MiTBackbone", - "config": { - "embedding_dims": [64, 128, 320, 512], - "depths": [3, 4, 18, 3], - "include_rescaling": True, - "input_shape": (224, 224, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/mit/mit_b3/2", }, "mit_b4": { "metadata": { @@ -95,14 +67,7 @@ "official_name": "MiT", "path": "mit", }, - "class_name": "keras_cv>MiTBackbone", - "config": { - "embedding_dims": [64, 128, 320, 512], - "depths": [3, 8, 27, 3], - "include_rescaling": True, - "input_shape": (224, 224, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/mit/mit_b4/2", }, "mit_b5": { "metadata": { @@ -113,14 +78,7 @@ "official_name": "MiT", "path": "mit", }, - "class_name": "keras_cv>MiTBackbone", - "config": { - "embedding_dims": [64, 128, 320, 512], - "depths": [3, 6, 40, 3], - "include_rescaling": True, - "input_shape": (224, 224, 3), - "input_tensor": None, - }, + "kaggle_handle": "kaggle://keras/mit/mit_b5/2", }, } @@ -134,16 +92,7 @@ "official_name": "MiT", "path": "mit", }, - "class_name": "keras_cv>MiTBackbone", - "config": { - "embedding_dims": [32, 64, 160, 256], - "depths": [2, 2, 2, 2], - "include_rescaling": True, - "input_shape": (224, 224, 3), - "input_tensor": None, - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/mitb0/imagenet/classification-v0.h5", # noqa: E501 - "weights_hash": "8e0c416cd330b6fa0bcfb3a5ccc43edcbcabf6a463aee3c2a9b6a1398c207d10", # noqa: E501 + "kaggle_handle": "kaggle://keras/mit/mit_b0_imagenet/2", }, } diff --git a/keras_cv/models/backbones/mobilenet_v3/mobilenet_v3_backbone_presets.py b/keras_cv/models/backbones/mobilenet_v3/mobilenet_v3_backbone_presets.py index 75ad436fe1..2c8dd67964 100644 --- a/keras_cv/models/backbones/mobilenet_v3/mobilenet_v3_backbone_presets.py +++ b/keras_cv/models/backbones/mobilenet_v3/mobilenet_v3_backbone_presets.py @@ -25,55 +25,7 @@ "official_name": "MobileNetV3", "path": "mobilenetv3", }, - "class_name": "keras_cv>MobileNetV3Backbone", - "config": { - "stackwise_expansion": [ - 1, - 72.0 / 16, - 88.0 / 24, - 4, - 6, - 6, - 3, - 3, - 6, - 6, - 6, - ], - "stackwise_filters": [16, 24, 24, 40, 40, 40, 48, 48, 96, 96, 96], - "stackwise_kernel_size": [3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5], - "stackwise_stride": [2, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1], - "stackwise_se_ratio": [ - 0.25, - None, - None, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "stackwise_activation": [ - "relu", - "relu", - "relu", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "alpha": 1.0, - }, + "kaggle_handle": "kaggle://keras/mobilenetv3/mobilenet_v3_small/2", }, "mobilenet_v3_large": { "metadata": { @@ -86,99 +38,7 @@ "official_name": "MobileNetV3", "path": "mobilenetv3", }, - "class_name": "keras_cv>MobileNetV3Backbone", - "config": { - "stackwise_expansion": [ - 1, - 4, - 3, - 3, - 3, - 3, - 6, - 2.5, - 2.3, - 2.3, - 6, - 6, - 6, - 6, - 6, - ], - "stackwise_filters": [ - 16, - 24, - 24, - 40, - 40, - 40, - 80, - 80, - 80, - 80, - 112, - 112, - 160, - 160, - 160, - ], - "stackwise_kernel_size": [ - 3, - 3, - 3, - 5, - 5, - 5, - 3, - 3, - 3, - 3, - 3, - 3, - 5, - 5, - 5, - ], - "stackwise_stride": [1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1], - "stackwise_se_ratio": [ - None, - None, - None, - 0.25, - 0.25, - 0.25, - None, - None, - None, - None, - 0.25, - 0.25, - 0.25, - 0.25, - 0.25, - ], - "stackwise_activation": [ - "relu", - "relu", - "relu", - "relu", - "relu", - "relu", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - "hard_swish", - ], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "alpha": 1.0, - }, + "kaggle_handle": "kaggle://keras/mobilenetv3/mobilenet_v3_large/2", }, } @@ -195,10 +55,7 @@ "official_name": "MobileNetV3", "path": "mobilenetv3", }, - "class_name": "keras_cv>MobileNetV3Backbone", - "config": backbone_presets_no_weights["mobilenet_v3_large"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/mobilenetv3/mobilenetv3_large_imagenet_backbone.h5", # noqa: E501 - "weights_hash": "ec55ea2f4f4ee9a2ddf3ee8e2dd784e9d5732690c1fc5afc7e1b2a66703f3337", # noqa: E501 + "kaggle_handle": "kaggle://keras/mobilenetv3/mobilenet_v3_large_imagenet/2", # noqa: E501 }, "mobilenet_v3_small_imagenet": { "metadata": { @@ -212,10 +69,7 @@ "official_name": "MobileNetV3", "path": "mobilenetv3", }, - "class_name": "keras_cv>MobileNetV3Backbone", - "config": backbone_presets_no_weights["mobilenet_v3_small"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/mobilenetv3/mobilenetv3_small_imagenet_backbone.h5", # noqa: E501 - "weights_hash": "592c2707edfc6c673a3b2d9aaf76dee678557f4a32d573c74f96c8122effa503", # noqa: E501 + "kaggle_handle": "kaggle://keras/mobilenetv3/mobilenet_v3_small_imagenet/2", # noqa: E501 }, } diff --git a/keras_cv/models/backbones/resnet_v1/resnet_v1_backbone_presets.py b/keras_cv/models/backbones/resnet_v1/resnet_v1_backbone_presets.py index 370a31cf03..319f0fbb1c 100644 --- a/keras_cv/models/backbones/resnet_v1/resnet_v1_backbone_presets.py +++ b/keras_cv/models/backbones/resnet_v1/resnet_v1_backbone_presets.py @@ -25,16 +25,7 @@ "official_name": "ResNetV1", "path": "resnet_v1", }, - "class_name": "keras_cv>ResNetBackbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [2, 2, 2, 2], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "basic_block", - }, + "kaggle_handle": "kaggle://keras/resnetv1/resnet18/2", }, "resnet34": { "metadata": { @@ -47,16 +38,7 @@ "official_name": "ResNetV1", "path": "resnet_v1", }, - "class_name": "keras_cv>ResNetBackbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 4, 6, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "basic_block", - }, + "kaggle_handle": "kaggle://keras/resnetv1/resnet34/2", }, "resnet50": { "metadata": { @@ -69,16 +51,7 @@ "official_name": "ResNetV1", "path": "resnet_v1", }, - "class_name": "keras_cv>ResNetBackbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 4, 6, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "block", - }, + "kaggle_handle": "kaggle://keras/resnetv1/resnet50/2", }, "resnet101": { "metadata": { @@ -91,16 +64,7 @@ "official_name": "ResNetV1", "path": "resnet_v1", }, - "class_name": "keras_cv>ResNetBackbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 4, 23, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "block", - }, + "kaggle_handle": "kaggle://keras/resnetv1/resnet101/2", }, "resnet152": { "metadata": { @@ -113,16 +77,7 @@ "official_name": "ResNetV1", "path": "resnet_v1", }, - "class_name": "keras_cv>ResNetBackbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 8, 36, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "block", - }, + "kaggle_handle": "kaggle://keras/resnetv1/resnet152/2", }, } @@ -139,10 +94,7 @@ "official_name": "ResNetV1", "path": "resnet_v1", }, - "class_name": "keras_cv>ResNetBackbone", - "config": backbone_presets_no_weights["resnet50"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/resnet50/imagenet/classification-v0-notop.h5", # noqa: E501 - "weights_hash": "dc5f6d8f929c78d0fc192afecc67b11ac2166e9d8b9ef945742368ae254c07af", # noqa: E501 + "kaggle_handle": "kaggle://keras/resnetv1/resnet50_imagenet/2", }, } diff --git a/keras_cv/models/backbones/resnet_v2/resnet_v2_backbone_presets.py b/keras_cv/models/backbones/resnet_v2/resnet_v2_backbone_presets.py index 815ff5ee39..5a65e58f93 100644 --- a/keras_cv/models/backbones/resnet_v2/resnet_v2_backbone_presets.py +++ b/keras_cv/models/backbones/resnet_v2/resnet_v2_backbone_presets.py @@ -24,17 +24,7 @@ "official_name": "ResNetV2", "path": "resnet_v2", }, - "class_name": "keras_cv>ResNetV2Backbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [2, 2, 2, 2], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "stackwise_dilations": None, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "basic_block", - }, + "kaggle_handle": "kaggle://keras/resnetv2/resnet18_v2/2", }, "resnet34_v2": { "metadata": { @@ -46,17 +36,7 @@ "official_name": "ResNetV2", "path": "resnet_v2", }, - "class_name": "keras_cv>ResNetV2Backbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 4, 6, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "stackwise_dilations": None, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "basic_block", - }, + "kaggle_handle": "kaggle://keras/resnetv2/resnet34_v2/2", }, "resnet50_v2": { "metadata": { @@ -68,17 +48,7 @@ "official_name": "ResNetV2", "path": "resnet_v2", }, - "class_name": "keras_cv>ResNetV2Backbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 4, 6, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "stackwise_dilations": None, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "block", - }, + "kaggle_handle": "kaggle://keras/resnetv2/resnet50_v2/2", }, "resnet101_v2": { "metadata": { @@ -90,17 +60,7 @@ "official_name": "ResNetV2", "path": "resnet_v2", }, - "class_name": "keras_cv>ResNetV2Backbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 4, 23, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "stackwise_dilations": None, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "block", - }, + "kaggle_handle": "kaggle://keras/resnetv2/resnet101_v2/2", }, "resnet152_v2": { "metadata": { @@ -112,17 +72,7 @@ "official_name": "ResNetV2", "path": "resnet_v2", }, - "class_name": "keras_cv>ResNetV2Backbone", - "config": { - "stackwise_filters": [64, 128, 256, 512], - "stackwise_blocks": [3, 8, 36, 3], - "stackwise_strides": [1, 2, 2, 2], - "include_rescaling": True, - "stackwise_dilations": None, - "input_shape": (None, None, 3), - "input_tensor": None, - "block_type": "block", - }, + "kaggle_handle": "kaggle://keras/resnetv2/resnet152_v2/2", }, } @@ -138,10 +88,7 @@ "official_name": "ResNetV2", "path": "resnet_v2", }, - "class_name": "keras_cv>ResNetV2Backbone", - "config": backbone_presets_no_weights["resnet50_v2"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/resnet50v2/imagenet/classification-v2-notop.h5", # noqa: E501 - "weights_hash": "e711c83d6db7034871f6d345a476c8184eab99dbf3ffcec0c1d8445684890ad9", # noqa: E501 + "kaggle_handle": "kaggle://keras/resnetv2/resnet50_v2_imagenet/2", }, } diff --git a/keras_cv/models/backbones/vit_det/vit_det_backbone_presets.py b/keras_cv/models/backbones/vit_det/vit_det_backbone_presets.py index decb487a89..1b3148a1b5 100644 --- a/keras_cv/models/backbones/vit_det/vit_det_backbone_presets.py +++ b/keras_cv/models/backbones/vit_det/vit_det_backbone_presets.py @@ -26,24 +26,7 @@ "official_name": "VitDet", "path": "vit_det", }, - "class_name": "keras_cv.models>ViTDetBackbone", - "config": { - "input_shape": (1024, 1024, 3), - "input_tensor": None, - "include_rescaling": True, - "patch_size": 16, - "embed_dim": 768, - "depth": 12, - "mlp_dim": 768 * 4, - "num_heads": 12, - "out_chans": 256, - "use_bias": True, - "use_abs_pos": True, - "use_rel_pos": True, - "window_size": 14, - "global_attention_indices": [2, 5, 8, 11], - "layer_norm_epsilon": 1e-6, - }, + "kaggle_handle": "kaggle://keras/vitdet/vitdet_base/2", }, "vitdet_large": { "metadata": { @@ -57,24 +40,7 @@ "official_name": "VitDet", "path": "vit_det", }, - "class_name": "keras_cv.models>ViTDetBackbone", - "config": { - "input_shape": (1024, 1024, 3), - "input_tensor": None, - "include_rescaling": True, - "patch_size": 16, - "embed_dim": 1024, - "depth": 24, - "mlp_dim": 1024 * 4, - "num_heads": 16, - "out_chans": 256, - "use_bias": True, - "use_abs_pos": True, - "use_rel_pos": True, - "window_size": 14, - "global_attention_indices": [5, 11, 17, 23], - "layer_norm_epsilon": 1e-6, - }, + "kaggle_handle": "kaggle://keras/vitdet/vitdet_large/2", }, "vitdet_huge": { "metadata": { @@ -88,24 +54,7 @@ "official_name": "VitDet", "path": "vit_det", }, - "class_name": "keras_cv.models>ViTDetBackbone", - "config": { - "input_shape": (1024, 1024, 3), - "input_tensor": None, - "include_rescaling": True, - "patch_size": 16, - "embed_dim": 1280, - "depth": 32, - "mlp_dim": 1280 * 4, - "num_heads": 16, - "out_chans": 256, - "use_bias": True, - "use_abs_pos": True, - "use_rel_pos": True, - "window_size": 14, - "global_attention_indices": [7, 15, 23, 31], - "layer_norm_epsilon": 1e-6, - }, + "kaggle_handle": "kaggle://keras/vitdet/vitdet_huge/2", }, } @@ -120,10 +69,7 @@ "official_name": "VitDet", "path": "vit_det", }, - "class_name": "keras_cv.models>ViTDetBackbone", - "config": backbone_presets_no_weights["vitdet_base"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/vitdet/vitdet_base.h5", # noqa: E501 - "weights_hash": "63c0ca6ff422142f95c24a0223445906728b353469be10c8e34018392207c93a", # noqa: E501 + "kaggle_handle": "kaggle://keras/vitdet/vitdet_base_sa1b/2", }, "vitdet_large_sa1b": { "metadata": { @@ -134,10 +80,7 @@ "official_name": "VitDet", "path": "vit_det", }, - "class_name": "keras_cv.models>ViTDetBackbone", - "config": backbone_presets_no_weights["vitdet_large"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/vitdet/vitdet_large.h5", # noqa: E501 - "weights_hash": "b85f73ee5a82842aecbc7c706ca69530aaa828d3324d0793a93730c94727b30e", # noqa: E501 + "kaggle_handle": "kaggle://keras/vitdet/vitdet_large_sa1b/2", }, "vitdet_huge_sa1b": { "metadata": { @@ -148,10 +91,7 @@ "official_name": "VitDet", "path": "vit_det", }, - "class_name": "keras_cv.models>ViTDetBackbone", - "config": backbone_presets_no_weights["vitdet_huge"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/vitdet/vitdet_huge.h5", # noqa: E501 - "weights_hash": "ae6e1a95acd748f783bddeadd5915fdc6d1c15d23909df3cd4fa446c7d6b9fc1", # noqa: E501 + "kaggle_handle": "kaggle://keras/vitdet/vitdet_huge_sa1b/2", }, } diff --git a/keras_cv/models/classification/image_classifier_presets.py b/keras_cv/models/classification/image_classifier_presets.py index c210997951..b1697b3f25 100644 --- a/keras_cv/models/classification/image_classifier_presets.py +++ b/keras_cv/models/classification/image_classifier_presets.py @@ -13,11 +13,6 @@ # limitations under the License. """ImageClassifier Task presets.""" -from keras_cv.models.backbones.efficientnet_v2 import ( - efficientnet_v2_backbone_presets, -) -from keras_cv.models.backbones.mobilenet_v3 import mobilenet_v3_backbone_presets -from keras_cv.models.backbones.resnet_v2 import resnet_v2_backbone_presets classifier_presets = { "resnet50_v2_imagenet_classifier": { @@ -32,16 +27,7 @@ "official_name": "ImageClassifier", "path": "image_classifier", }, - "config": { - "backbone": resnet_v2_backbone_presets.backbone_presets[ - "resnet50_v2" - ], - "num_classes": 1000, - "pooling": "avg", - "activation": "softmax", - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/resnet50v2/imagenet-classifier-v0.h5", # noqa: E501 - "weights_hash": "77fa9f1cd1de0e202309e51d4e598e441d1111dacb6c41a182b6c63f76ff26cd", # noqa: E501 + "kaggle_handle": "kaggle://keras/resnetv2/resnet50_v2_imagenet_classifier/2", # noqa: E501 }, "efficientnetv2_s_imagenet_classifier": { "metadata": { @@ -58,16 +44,7 @@ "official_name": "ImageClassifier", "path": "image_classifier", }, - "config": { - "backbone": efficientnet_v2_backbone_presets.backbone_presets[ - "efficientnetv2_s" - ], - "num_classes": 1000, - "pooling": "avg", - "activation": "softmax", - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnet_v2/efficientnetv2-s_imagenet_classifier.h5", # noqa: E501 - "weights_hash": "4da57ade035e11aff7e1c5cb04c4235e", + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_s_imagenet_classifier/2", # noqa: E501 }, "efficientnetv2_b0_imagenet_classifier": { "metadata": { @@ -87,16 +64,7 @@ "official_name": "ImageClassifier", "path": "image_classifier", }, - "config": { - "backbone": efficientnet_v2_backbone_presets.backbone_presets[ - "efficientnetv2_b0" - ], - "num_classes": 1000, - "pooling": "avg", - "activation": "softmax", - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnet_v2/efficientnetv2-b0_imagenet_classifier.h5", # noqa: E501 - "weights_hash": "4b739de648c346b7e4156e11a223c338", + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b0_imagenet_classifier/2", # noqa: E501 }, "efficientnetv2_b1_imagenet_classifier": { "metadata": { @@ -116,16 +84,7 @@ "official_name": "ImageClassifier", "path": "image_classifier", }, - "config": { - "backbone": efficientnet_v2_backbone_presets.backbone_presets[ - "efficientnetv2_b1" - ], - "num_classes": 1000, - "pooling": "avg", - "activation": "softmax", - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnet_v2/efficientnetv2-b1_imagenet_classifier.h5", # noqa: E501 - "weights_hash": "78c1c879143dbd8f74e6ffc4d3180197", + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b1_imagenet_classifier/2", # noqa: E501 }, "efficientnetv2_b2_imagenet_classifier": { "metadata": { @@ -145,16 +104,7 @@ "official_name": "ImageClassifier", "path": "image_classifier", }, - "config": { - "backbone": efficientnet_v2_backbone_presets.backbone_presets[ - "efficientnetv2_b2" - ], - "num_classes": 1000, - "pooling": "avg", - "activation": "softmax", - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/efficientnet_v2/efficientnetv2-b2_imagenet_classifier.h5", # noqa: E501 - "weights_hash": "07eda1c48aee27e12a3fe2545e6c65ed", + "kaggle_handle": "kaggle://keras/efficientnetv2/efficientnetv2_b2_imagenet_classifier/2", # noqa: E501 }, "mobilenet_v3_large_imagenet_classifier": { "metadata": { @@ -171,15 +121,6 @@ "official_name": "ImageClassifier", "path": "image_classifier", }, - "config": { - "backbone": mobilenet_v3_backbone_presets.backbone_presets[ - "mobilenet_v3_large" - ], - "num_classes": 1000, - "pooling": "avg", - "activation": "softmax", - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/mobilenetv3/mobilenetv3_large_imagenet_classifier.h5", # noqa: E501 - "weights_hash": "4130fbc249d3812719396439031d89042dce440dd256cda941a109bce6d4e305", # noqa: E501 + "kaggle_handle": "kaggle://keras/mobilenetv3/mobilenet_v3_large_imagenet_classifier/2", # noqa: E501 }, } diff --git a/keras_cv/models/object_detection/retinanet/retinanet_label_encoder.py b/keras_cv/models/object_detection/retinanet/retinanet_label_encoder.py index 4142f7bac5..8b08bbc87a 100644 --- a/keras_cv/models/object_detection/retinanet/retinanet_label_encoder.py +++ b/keras_cv/models/object_detection/retinanet/retinanet_label_encoder.py @@ -68,7 +68,7 @@ def __init__( self.box_variance = ops.array(box_variance, "float32") self.background_class = background_class self.ignore_class = ignore_class - self.matched_boxes_metric = keras.metrics.BinaryAccuracy( + self.matched_boxes_metric = MatchedBoxesMetric( name="percent_boxes_matched_with_anchor" ) self.positive_threshold = positive_threshold @@ -244,3 +244,9 @@ def from_config(cls, config): ) return super().from_config(config) + + +class MatchedBoxesMetric(keras.metrics.BinaryAccuracy): + # Prevent `load_weights` from accessing metric + def load_own_variables(self, store): + return diff --git a/keras_cv/models/object_detection/retinanet/retinanet_presets.py b/keras_cv/models/object_detection/retinanet/retinanet_presets.py index 6bcd6d616b..1ddaab59e1 100644 --- a/keras_cv/models/object_detection/retinanet/retinanet_presets.py +++ b/keras_cv/models/object_detection/retinanet/retinanet_presets.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. """RetinaNet Task presets.""" -from keras_cv.models.backbones.resnet_v1 import resnet_v1_backbone_presets retinanet_presets = { "retinanet_resnet50_pascalvoc": { @@ -27,13 +26,6 @@ "official_name": "RetinaNet", "path": "retinanet", }, - "config": { - "backbone": resnet_v1_backbone_presets.backbone_presets["resnet50"], - # 21 used as an implicit background class marginally improves - # performance. - "num_classes": 20, - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/retinanet/pascal_voc/resnet50-v4.h5", # noqa: E501 - "weights_hash": "961f6f9a03c869900d61ae74a9f0c31c6439b4f81f13593f5c16c4733061fbac", # noqa: E501 + "kaggle_handle": "kaggle://keras/retinanet/retinanet_resnet50_pascalvoc/2", # noqa: E501 }, } diff --git a/keras_cv/models/object_detection/yolo_v8/yolo_v8_backbone_presets.py b/keras_cv/models/object_detection/yolo_v8/yolo_v8_backbone_presets.py index 6113ea2d4b..0a5dcc9290 100644 --- a/keras_cv/models/object_detection/yolo_v8/yolo_v8_backbone_presets.py +++ b/keras_cv/models/object_detection/yolo_v8/yolo_v8_backbone_presets.py @@ -22,14 +22,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": { - "include_rescaling": True, - "input_shape": (None, None, 3), - "stackwise_channels": [32, 64, 128, 256], - "stackwise_depth": [1, 2, 2, 1], - "activation": "swish", - }, + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_xs_backbone/2", }, "yolo_v8_s_backbone": { "metadata": { @@ -38,14 +31,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": { - "include_rescaling": True, - "input_shape": (None, None, 3), - "stackwise_channels": [64, 128, 256, 512], - "stackwise_depth": [1, 2, 2, 1], - "activation": "swish", - }, + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_s_backbone/2", }, "yolo_v8_m_backbone": { "metadata": { @@ -54,14 +40,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": { - "include_rescaling": True, - "input_shape": (None, None, 3), - "stackwise_channels": [96, 192, 384, 576], - "stackwise_depth": [2, 4, 4, 2], - "activation": "swish", - }, + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_m_backbone/2", }, "yolo_v8_l_backbone": { "metadata": { @@ -70,14 +49,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": { - "include_rescaling": True, - "input_shape": (None, None, 3), - "stackwise_channels": [128, 256, 512, 512], - "stackwise_depth": [3, 6, 6, 3], - "activation": "swish", - }, + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_l_backbone/2", }, "yolo_v8_xl_backbone": { "metadata": { @@ -86,14 +58,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": { - "include_rescaling": True, - "input_shape": (None, None, 3), - "stackwise_channels": [160, 320, 640, 640], - "stackwise_depth": [3, 6, 6, 3], - "activation": "swish", - }, + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_xl_backbone/2", }, } @@ -107,10 +72,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": backbone_presets_no_weights["yolo_v8_xs_backbone"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/yolov8/coco/yolov8_n_backbone.h5", # noqa: E501 - "weights_hash": "636ba3cba064c7c457e30a0e4759716006c305c30876df1c1caf2e56b99eab6c", # noqa: E501 + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_xs_backbone_coco/2", }, "yolo_v8_s_backbone_coco": { "metadata": { @@ -119,10 +81,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": backbone_presets_no_weights["yolo_v8_s_backbone"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/yolov8/coco/yolov8_s_backbone.h5", # noqa: E501 - "weights_hash": "49ab5da87d6b36a1943e7f111a1960355171332c25312b6cc01526baaecf1b69", # noqa: E501 + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_s_backbone_coco/2", }, "yolo_v8_m_backbone_coco": { "metadata": { @@ -131,10 +90,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": backbone_presets_no_weights["yolo_v8_m_backbone"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/yolov8/coco/yolov8_m_backbone.h5", # noqa: E501 - "weights_hash": "a9719807699a2540da14aa7f9a0dda272d400d30c40a956298a63a2805aa6436", # noqa: E501 + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_m_backbone_coco/2", }, "yolo_v8_l_backbone_coco": { "metadata": { @@ -143,10 +99,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": backbone_presets_no_weights["yolo_v8_l_backbone"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/yolov8/coco/yolov8_l_backbone.h5", # noqa: E501 - "weights_hash": "2c94ffe75492491974c6d7347d5c1d1aa209d8f6d78c63ab62df0f5dd51680b9", # noqa: E501 + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_l_backbone_coco/2", }, "yolo_v8_xl_backbone_coco": { "metadata": { @@ -157,10 +110,7 @@ "official_name": "YOLOV8", "path": "yolo_v8", }, - "class_name": "keras_cv>YOLOV8Backbone", - "config": backbone_presets_no_weights["yolo_v8_xl_backbone"]["config"], - "weights_url": "https://storage.googleapis.com/keras-cv/models/yolov8/coco/yolov8_x_backbone.h5", # noqa: E501 - "weights_hash": "ce0cc3235eacaffc4a9824e28b2366e674b6d42befc4c7b77f3be7d1d39960bd", # noqa: E501 + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_xl_backbone_coco/2", }, } diff --git a/keras_cv/models/object_detection/yolo_v8/yolo_v8_detector_presets.py b/keras_cv/models/object_detection/yolo_v8/yolo_v8_detector_presets.py index dfbbe512c1..33eb8fab34 100644 --- a/keras_cv/models/object_detection/yolo_v8/yolo_v8_detector_presets.py +++ b/keras_cv/models/object_detection/yolo_v8/yolo_v8_detector_presets.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. """YOLOv8 Task presets.""" -from keras_cv.models.object_detection.yolo_v8 import yolo_v8_backbone_presets yolo_v8_detector_presets = { "yolo_v8_m_pascalvoc": { @@ -26,14 +25,6 @@ "official_name": "YOLOV8Detector", "path": "yolo_v8_detector", }, - "config": { - "backbone": yolo_v8_backbone_presets.backbone_presets[ - "yolo_v8_m_backbone" - ], - "num_classes": 20, - "fpn_depth": 2, - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/yolov8/pascal_voc/yolov8_m_v1.h5", # noqa: E501 - "weights_hash": "2891fbd66f71e0b9da0cb02ef3afbccb819e1b8f18204157f643f4ec058a71a8", # noqa: E501 + "kaggle_handle": "kaggle://keras/yolov8/yolo_v8_m_pascalvoc/2", }, } diff --git a/keras_cv/models/object_detection_3d/center_pillar_backbone.py b/keras_cv/models/object_detection_3d/center_pillar_backbone.py index f7b1f731bb..01554f260b 100644 --- a/keras_cv/models/object_detection_3d/center_pillar_backbone.py +++ b/keras_cv/models/object_detection_3d/center_pillar_backbone.py @@ -52,6 +52,10 @@ def __init__( input_shape=(None, None, 128), **kwargs ): + self.stackwise_down_blocks = stackwise_down_blocks + self.stackwise_down_filters = stackwise_down_filters + self.stackwise_up_filters = stackwise_up_filters + input = keras.layers.Input(shape=input_shape) x = input @@ -88,6 +92,17 @@ def __init__( **kwargs, ) + def get_config(self): + config = super().get_config() + config.update( + { + "stackwise_down_blocks": self.stackwise_down_blocks, + "stackwise_down_filters": self.stackwise_down_filters, + "stackwise_up_filters": self.stackwise_up_filters, + } + ) + return config + @classproperty def presets(cls): """Dictionary of preset names and configurations.""" diff --git a/keras_cv/models/object_detection_3d/center_pillar_backbone_presets.py b/keras_cv/models/object_detection_3d/center_pillar_backbone_presets.py index cc063f43ac..8f875e638a 100644 --- a/keras_cv/models/object_detection_3d/center_pillar_backbone_presets.py +++ b/keras_cv/models/object_detection_3d/center_pillar_backbone_presets.py @@ -19,16 +19,8 @@ "metadata": { "description": "An example CenterPillar backbone for WOD.", "params": 1277680, - "official_name": "WaymoOpenDataset", - }, - "class_name": ( - "keras_cv.models.object_detection_3d>CenterPillarBackbone" - ), - "config": { - "stackwise_down_blocks": [6, 2, 1], - "stackwise_down_filters": [128, 256, 512], - "stackwise_up_filters": [512, 256, 256], - "input_shape": (None, None, 128), + "official_name": "CenterPillar", }, + "kaggle_handle": "gs://keras-cv-kaggle/center_pillar_waymo_open_dataset", # noqa: E501 }, } diff --git a/keras_cv/models/segmentation/deeplab_v3_plus/deeplab_v3_plus_presets.py b/keras_cv/models/segmentation/deeplab_v3_plus/deeplab_v3_plus_presets.py index 8525dec7f8..0fcf852d7d 100644 --- a/keras_cv/models/segmentation/deeplab_v3_plus/deeplab_v3_plus_presets.py +++ b/keras_cv/models/segmentation/deeplab_v3_plus/deeplab_v3_plus_presets.py @@ -13,7 +13,6 @@ # limitations under the License. """DeepLabV3Plus presets.""" -from keras_cv.models.backbones.resnet_v2 import resnet_v2_backbone_presets deeplab_v3_plus_presets = { "deeplab_v3_plus_resnet50_pascalvoc": { @@ -30,15 +29,6 @@ "official_name": "DeepLabV3Plus", "path": "deeplab_v3_plus", }, - "config": { - "backbone": resnet_v2_backbone_presets.backbone_presets[ - "resnet50_v2_imagenet" - ], - # 21 used as an implicit background class marginally improves - # performance. - "num_classes": 21, - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/deeplab_v3_plus/voc/deeplabv3plus_resenet50_pascal_voc.weights.h5", # noqa: E501 - "weights_hash": "9681410a57bea2bc5cb7d79a1802d872ac263faab749cfe5ffdae6d6c3082041", # noqa: E501 + "kaggle_handle": "kaggle://keras/deeplabv3plus/deeplab_v3_plus_resnet50_pascalvoc/2", # noqa: E501 }, } diff --git a/keras_cv/models/segmentation/segformer/segformer_presets.py b/keras_cv/models/segmentation/segformer/segformer_presets.py index 6f01a82d4d..b183fddda7 100644 --- a/keras_cv/models/segmentation/segformer/segformer_presets.py +++ b/keras_cv/models/segmentation/segformer/segformer_presets.py @@ -25,10 +25,7 @@ "official_name": "SegFormerB0", "path": "segformer_b0", }, - "class_name": "keras_cv>SegFormer", - "config": { - "backbone": backbone_presets["mit_b0"], - }, + "kaggle_handle": "kaggle://keras/segformer/segformer_b0/2", }, "segformer_b1": { "metadata": { @@ -37,8 +34,7 @@ "official_name": "SegFormerB1", "path": "segformer_b1", }, - "class_name": "keras_cv>SegFormer", - "config": {"backbone": backbone_presets["mit_b1"]}, + "kaggle_handle": "kaggle://keras/segformer/segformer_b1/2", }, "segformer_b2": { "metadata": { @@ -47,8 +43,7 @@ "official_name": "SegFormerB2", "path": "segformer_b2", }, - "class_name": "keras_cv>SegFormer", - "config": {"backbone": backbone_presets["mit_b2"]}, + "kaggle_handle": "kaggle://keras/segformer/segformer_b2/2", }, "segformer_b3": { "metadata": { @@ -57,8 +52,7 @@ "official_name": "SegFormerB3", "path": "segformer_b3", }, - "class_name": "keras_cv>SegFormer", - "config": {"backbone": backbone_presets["mit_b3"]}, + "kaggle_handle": "kaggle://keras/segformer/segformer_b3/2", }, "segformer_b4": { "metadata": { @@ -67,8 +61,7 @@ "official_name": "SegFormerB4", "path": "segformer_b4", }, - "class_name": "keras_cv>SegFormer", - "config": {"backbone": backbone_presets["mit_b4"]}, + "kaggle_handle": "kaggle://keras/segformer/segformer_b4/2", }, "segformer_b5": { "metadata": { @@ -77,8 +70,7 @@ "official_name": "SegFormerB5", "path": "segformer_b5", }, - "class_name": "keras_cv>SegFormer", - "config": {"backbone": backbone_presets["mit_b5"]}, + "kaggle_handle": "kaggle://keras/segformer/segformer_b5/2", }, } @@ -92,10 +84,7 @@ "official_name": "SegFormerB0", "path": "segformer_b0", }, - "class_name": "keras_cv>SegFormer", - "config": { - "backbone": backbone_presets["mit_b0_imagenet"], - }, + "kaggle_handle": "kaggle://keras/segformer/segformer_b0_imagenet/2", }, } diff --git a/keras_cv/models/segmentation/segformer/segformer_test.py b/keras_cv/models/segmentation/segformer/segformer_test.py index 233df20b9c..5f33b033da 100644 --- a/keras_cv/models/segmentation/segformer/segformer_test.py +++ b/keras_cv/models/segmentation/segformer/segformer_test.py @@ -52,16 +52,14 @@ def test_segformer_preset_error(self): @pytest.mark.large def test_segformer_call(self): - backbone = MiTBackbone.from_preset("mit_b0", input_shape=[512, 512, 3]) + backbone = MiTBackbone.from_preset("mit_b0") mit_model = SegFormer(backbone=backbone, num_classes=1) - images = np.random.uniform(size=(2, 512, 512, 3)) + images = np.random.uniform(size=(2, 224, 224, 3)) mit_output = mit_model(images) mit_pred = mit_model.predict(images) - seg_model = SegFormer.from_preset( - "segformer_b0", num_classes=1, input_shape=[512, 512, 3] - ) + seg_model = SegFormer.from_preset("segformer_b0", num_classes=1) seg_output = seg_model(images) seg_pred = seg_model.predict(images) @@ -121,11 +119,9 @@ def test_saved_model(self): @pytest.mark.large # Saving is slow, so mark these large. def test_preset_saved_model(self): - target_size = [512, 512, 3] + target_size = [224, 224, 3] - model = SegFormer.from_preset( - "segformer_b0", num_classes=1, input_shape=[512, 512, 3] - ) + model = SegFormer.from_preset("segformer_b0", num_classes=1) input_batch = np.ones(shape=[2] + target_size) model_output = model(input_batch) diff --git a/keras_cv/models/segmentation/segment_anything/sam_presets.py b/keras_cv/models/segmentation/segment_anything/sam_presets.py index 6460e5f517..4040679c66 100644 --- a/keras_cv/models/segmentation/segment_anything/sam_presets.py +++ b/keras_cv/models/segmentation/segment_anything/sam_presets.py @@ -13,40 +13,6 @@ # limitations under the License. """SAM model preset configurations.""" -from keras_cv.models.backbones.vit_det import vit_det_backbone_presets - -prompt_encoder_preset = { - "class_name": "keras_cv.models>SAMPromptEncoder", - "config": { - "embed_dim": 256, - "image_embedding_size": (64, 64), - "input_image_size": (1024, 1024), - "mask_in_chans": 16, - "activation": "gelu", - }, -} - -mask_decoder_preset = { - "class_name": "keras_cv.models>SAMMaskDecoder", - "config": { - "transformer_dim": 256, - "transformer": { - "class_name": "keras_cv.models>TwoWayTransformer", - "config": { - "depth": 2, - "embed_dim": 256, - "num_heads": 8, - "mlp_dim": 2048, - "activation": "relu", - "attention_downsample_rate": 2, - }, - }, - "num_multimask_outputs": 3, - "iou_head_depth": 3, - "iou_head_hidden_dim": 256, - "activation": "gelu", - }, -} sam_presets = { "sam_base_sa1b": { @@ -56,15 +22,7 @@ "official_name": "SAM", "path": "segment_anything", }, - "config": { - "backbone": vit_det_backbone_presets.backbone_presets[ - "vitdet_base" - ], - "prompt_encoder": prompt_encoder_preset, - "mask_decoder": mask_decoder_preset, - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/segment_anything/sam_base.h5", # noqa: E501 - "weights_hash": "5a18868ed227b6f093d4a6cb7ed689868dd11f288a8311ae69002a9a9d86d192", # noqa: E501 + "kaggle_handle": "kaggle://keras/sam/sam_base_sa1b/2", }, "sam_large_sa1b": { "metadata": { @@ -73,15 +31,7 @@ "official_name": "SAM", "path": "segment_anything", }, - "config": { - "backbone": vit_det_backbone_presets.backbone_presets[ - "vitdet_large" - ], - "prompt_encoder": prompt_encoder_preset, - "mask_decoder": mask_decoder_preset, - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/segment_anything/sam_large.h5", # noqa: E501 - "weights_hash": "4ef43d3a8e24200c14a086a043dec8e956fef500c6171268a35029ea720305f0", # noqa: E501 + "kaggle_handle": "kaggle://keras/sam/sam_large_sa1b/2", }, "sam_huge_sa1b": { "metadata": { @@ -90,14 +40,6 @@ "official_name": "SAM", "path": "segment_anything", }, - "config": { - "backbone": vit_det_backbone_presets.backbone_presets[ - "vitdet_huge" - ], - "prompt_encoder": prompt_encoder_preset, - "mask_decoder": mask_decoder_preset, - }, - "weights_url": "https://storage.googleapis.com/keras-cv/models/segment_anything/sam_huge.h5", # noqa: E501 - "weights_hash": "3284c7c3c91274e8cb1ec2de69da3b6d6cee4483f7d8b0e17e1042b9dfc86fe5", # noqa: E501 + "kaggle_handle": "kaggle://keras/sam/sam_huge_sa1b/2", }, } diff --git a/keras_cv/models/task.py b/keras_cv/models/task.py index 684a479778..79a80d584e 100644 --- a/keras_cv/models/task.py +++ b/keras_cv/models/task.py @@ -13,10 +13,11 @@ # limitations under the License. """Base class for Task models.""" -import os - from keras_cv.api_export import keras_cv_export from keras_cv.backend import keras +from keras_cv.models.backbones.backbone import Backbone +from keras_cv.utils.preset_utils import check_preset_class +from keras_cv.utils.preset_utils import load_from_preset from keras_cv.utils.python_utils import classproperty from keras_cv.utils.python_utils import format_docstring @@ -28,6 +29,22 @@ class Task(keras.Model): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._backbone = None + self._functional_layer_ids = set( + id(layer) for layer in self._flatten_layers() + ) + + def __dir__(self): + # Temporary fixes for weight saving. This mimics the following PR for + # older version of Keras: https://github.com/keras-team/keras/pull/18982 + def filter_fn(attr): + if attr in ["backbone", "_backbone"]: + return False + try: + return id(getattr(self, attr)) not in self._functional_layer_ids + except: + return True + + return filter(filter_fn, super().__dir__()) @property def backbone(self): @@ -111,63 +128,29 @@ def from_preset( load_weights=False, ``` """ - - if not cls.presets: - raise NotImplementedError( - "No presets have been created for this class." - ) - - if preset not in cls.presets: - raise ValueError( - "`preset` must be one of " - f"""{", ".join(cls.presets)}. Received: {preset}.""" - ) - - if load_weights and preset not in cls.presets_with_weights: - raise ValueError( - f"""Pretrained weights not available for preset "{preset}". """ - "Set `load_weights=False` to use this preset or choose one of " - "the following presets with weights:" - f""" "{'", "'.join(cls.presets_with_weights)}".""" + # We support short IDs for official presets, e.g. `"bert_base_en"`. + # Map these to a Kaggle Models handle. + if preset in cls.presets: + preset = cls.presets[preset]["kaggle_handle"] + + preset_cls = check_preset_class(preset, (cls, Backbone)) + + # Backbone case. + if issubclass(preset_cls, Backbone): + backbone = load_from_preset( + preset, + load_weights=load_weights, ) - - metadata = cls.presets[preset] - # Check if preset is backbone-only model - if preset in cls.backbone_presets: - backbone_cls = keras.saving.get_registered_object( - metadata["class_name"] - ) - backbone_kwargs = {} - if input_shape is not None: - backbone_kwargs["input_shape"] = input_shape - backbone = backbone_cls.from_preset( - preset, load_weights, **backbone_kwargs - ) - return cls(backbone, **kwargs) - - # Otherwise must be one of class presets - config = metadata["config"] - if input_shape is not None: - config["backbone"]["config"]["input_shape"] = input_shape - model = cls.from_config({**config, **kwargs}) - - if preset not in cls.presets_with_weights or load_weights is False: - return model - - local_weights_path = "model.h5" - if metadata["weights_url"].endswith(".weights.h5"): - local_weights_path = "model.weights.h5" - - weights = keras.utils.get_file( - local_weights_path, - metadata["weights_url"], - cache_subdir=os.path.join("models", preset), - file_hash=metadata["weights_hash"], + return cls(backbone=backbone, **kwargs) + + # Task case. + return load_from_preset( + preset, + load_weights=load_weights, + input_shape=input_shape, + config_overrides=kwargs, ) - model.load_weights(weights) - return model - @property def layers(self): # Some of our task models don't use the Backbone directly, but create diff --git a/keras_cv/models/utils_test.py b/keras_cv/models/utils_test.py index cc6c1ac596..4fd55dec4d 100644 --- a/keras_cv/models/utils_test.py +++ b/keras_cv/models/utils_test.py @@ -24,7 +24,7 @@ def test_parse_model_inputs(self): input_shape = (224, 244, 3) inputs = utils.parse_model_inputs(input_shape, None) - self.assertEqual(inputs.shape.as_list(), list((None,) + input_shape)) + self.assertEqual(list(inputs.shape), list((None,) + input_shape)) input_tensor = layers.Input(shape=input_shape) self.assertIs( diff --git a/keras_cv/tools/convert_presets.py b/keras_cv/tools/convert_presets.py new file mode 100644 index 0000000000..e4f5886ff7 --- /dev/null +++ b/keras_cv/tools/convert_presets.py @@ -0,0 +1,139 @@ +# Copyright 2023 The KerasCV Authors +# +# 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 +# +# https://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. + +import os +import re + +import keras_cv # noqa: E402 + +BUCKET = "keras-cv-kaggle" + + +def to_snake_case(name): + name = re.sub(r"\W+", "", name) + name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) + name = re.sub("([a-z])([A-Z])", r"\1_\2", name).lower() + return name + + +def convert_backbone_presets(): + # Save and upload Backbone presets + + backbone_models = [ + keras_cv.models.ResNetBackbone, + keras_cv.models.ResNet18Backbone, + keras_cv.models.ResNet34Backbone, + keras_cv.models.ResNet50Backbone, + keras_cv.models.ResNet101Backbone, + keras_cv.models.ResNet152Backbone, + keras_cv.models.ResNetV2Backbone, + keras_cv.models.ResNet18V2Backbone, + keras_cv.models.ResNet34V2Backbone, + keras_cv.models.ResNet50V2Backbone, + keras_cv.models.ResNet101V2Backbone, + keras_cv.models.ResNet152V2Backbone, + keras_cv.models.YOLOV8Backbone, + keras_cv.models.MobileNetV3Backbone, + keras_cv.models.MobileNetV3SmallBackbone, + keras_cv.models.MobileNetV3LargeBackbone, + keras_cv.models.EfficientNetV2Backbone, + keras_cv.models.EfficientNetV2B0Backbone, + keras_cv.models.EfficientNetV2B1Backbone, + keras_cv.models.EfficientNetV2B2Backbone, + keras_cv.models.EfficientNetV2B3Backbone, + keras_cv.models.EfficientNetV2SBackbone, + keras_cv.models.EfficientNetV2MBackbone, + keras_cv.models.EfficientNetV2LBackbone, + keras_cv.models.CSPDarkNetBackbone, + keras_cv.models.DenseNetBackbone, + keras_cv.src.models.EfficientNetV1Backbone, + keras_cv.src.models.EfficientNetLiteBackbone, + keras_cv.models.MiTBackbone, + keras_cv.models.ViTDetBackbone, + keras_cv.models.CenterPillarBackbone, + ] + for backbone_cls in backbone_models: + for preset in backbone_cls.presets: + backbone = backbone_cls.from_preset( + preset, name=to_snake_case(backbone_cls.__name__) + ) + save_weights = preset in backbone_cls.presets_with_weights + save_to_preset( + backbone, + preset, + save_weights=save_weights, + config_filename="config.json", + ) + # Delete first to clean up any exising version. + os.system(f"gsutil rm -rf gs://{BUCKET}/{preset}") + os.system(f"gsutil cp -r {preset} gs://{BUCKET}/{preset}") + for root, _, files in os.walk(preset): + for file in files: + path = os.path.join(BUCKET, root, file) + os.system( + f"gcloud storage objects update gs://{path} " + "--add-acl-grant=entity=AllUsers,role=READER" + ) + + +def convert_task_presets(): + # Save and upload task presets + + task_models = [ + keras_cv.models.RetinaNet, + keras_cv.models.YOLOV8Detector, + keras_cv.models.ImageClassifier, + keras_cv.models.DeepLabV3Plus, + # keras_cv.models.SegFormer, + keras_cv.models.SegmentAnythingModel, + ] + for task_cls in task_models: + # Remove backbone-specific keys + task_preset_keys = set(task_cls.presets) ^ set( + task_cls.backbone_presets + ) + for preset in task_preset_keys: + save_weights = preset in task_cls.presets_with_weights + kwargs = {"name": to_snake_case(task_cls.__name__)} + if task_cls in [ + keras_cv.models.RetinaNet, + keras_cv.models.YOLOV8Detector, + ]: + kwargs.update({"bounding_box_format": "xywh"}) + task = task_cls.from_preset(preset, **kwargs) + else: + task = task_cls.from_preset(preset, **kwargs) + save_to_preset( + task, + preset, + save_weights=save_weights, + config_filename="config.json", + ) + # Delete first to clean up any exising version. + os.system(f"gsutil rm -rf gs://{BUCKET}/{preset}") + os.system(f"gsutil cp -r {preset} gs://{BUCKET}/{preset}") + for root, _, files in os.walk(preset): + for file in files: + path = os.path.join(BUCKET, root, file) + os.system( + f"gcloud storage objects update gs://{path} " + "--add-acl-grant=entity=AllUsers,role=READER" + ) + + +if __name__ == "__main__": + from keras_cv.src.utils.preset_utils import save_to_preset # noqa: E402 + + convert_backbone_presets() + convert_task_presets() diff --git a/keras_cv/utils/preset_utils.py b/keras_cv/utils/preset_utils.py new file mode 100644 index 0000000000..a3fa56dcb7 --- /dev/null +++ b/keras_cv/utils/preset_utils.py @@ -0,0 +1,226 @@ +# Copyright 2023 The KerasCV Authors +# +# 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 +# +# https://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. + +import datetime +import inspect +import json +import os + +from keras_cv.backend import keras + +try: + import kagglehub +except ImportError: + kagglehub = None + +KAGGLE_PREFIX = "kaggle://" +GS_PREFIX = "gs://" + + +def get_file(preset, path): + """Download a preset file in necessary and return the local path.""" + if not isinstance(preset, str): + raise ValueError( + f"A preset identifier must be a string. Received: preset={preset}" + ) + if preset.startswith(KAGGLE_PREFIX): + if kagglehub is None: + raise ImportError( + "`from_preset()` requires the `kagglehub` package. " + "Please install with `pip install kagglehub`." + ) + segments = preset.removeprefix(KAGGLE_PREFIX).split("/") + # Insert the kaggle framework into the handle. + if len(segments) == 3: + org, model, variant = segments + kaggle_handle = f"{org}/{model}/keras/{variant}/2" + elif len(segments) == 4: + org, model, variant, version = segments + kaggle_handle = f"{org}/{model}/keras/{variant}/{version}" + else: + raise ValueError( + "Unexpected kaggle preset handle. Kaggle model handles should " + "have the form kaggle://{org}/{model}/{variant}[/{version}]. " + "For example, 'kaggle://keras/retinanet/retinanet_base_en'. " + f"Received: preset={preset}" + ) + return kagglehub.model_download(kaggle_handle, path) + elif preset.startswith(GS_PREFIX): + url = os.path.join(preset, path) + url = url.replace(GS_PREFIX, "https://storage.googleapis.com/") + subdir = preset.replace(GS_PREFIX, "gs_") + subdir = subdir.replace("/", "_").replace("-", "_") + filename = os.path.basename(path) + subdir = os.path.join(subdir, os.path.dirname(path)) + return keras.utils.get_file( + filename, + url, + cache_subdir=os.path.join("models", subdir), + ) + elif os.path.exists(preset): + # Assume a local filepath. + return os.path.join(preset, path) + else: + raise ValueError( + "Unknown preset identifier. A preset must be a one of:\n" + "1) a built in preset identifier like `'mobilenet_v3_small'`\n" + "2) a Kaggle Models handle like `'kaggle://keras/mobilenetv3/mobilenet_v3_small'`\n" # noqa: E501 + "3) a path to a local preset directory like `'./mobilenet_v3_small`\n" # noqa: E501 + "Use `print(cls.presets.keys())` to view all built-in presets for " + "API symbol `cls`.\n" + f"Received: preset='{preset}'" + ) + + +def recursive_pop(config, key): + """Remove a key from a nested config object""" + config.pop(key, None) + for value in config.values(): + if isinstance(value, dict): + recursive_pop(value, key) + if isinstance(value, list): + for v in value: + if isinstance(v, dict): + recursive_pop(v, key) + + +def save_to_preset( + layer, + preset, + save_weights=True, + config_filename="config.json", + weights_filename="model.weights.h5", +): + """Save a KerasCV layer to a preset directory.""" + os.makedirs(preset, exist_ok=True) + + # Optionally save weights. + save_weights = save_weights and hasattr(layer, "save_weights") + if save_weights: + weights_path = os.path.join(preset, weights_filename) + layer.save_weights(weights_path) + + # Save a serialized Keras object. + config_path = os.path.join(preset, config_filename) + config = keras.saving.serialize_keras_object(layer) + # Include references to weights. + config["weights"] = weights_filename if save_weights else None + recursive_pop(config, "compile_config") + recursive_pop(config, "build_config") + with open(config_path, "w") as config_file: + config_file.write(json.dumps(config, indent=4)) + + from keras_cv import __version__ as keras_cv_version + + keras_version = keras.version() if hasattr(keras, "version") else None + + # Save any associated metadata. + if config_filename == "config.json": + metadata = { + "keras_version": keras_version, + "keras_cv_version": keras_cv_version, + "parameter_count": layer.count_params(), + "date_saved": datetime.datetime.now().strftime("%Y-%m-%d@%H:%M:%S"), + } + metadata_path = os.path.join(preset, "metadata.json") + with open(metadata_path, "w") as metadata_file: + metadata_file.write(json.dumps(metadata, indent=4)) + + +def load_from_preset( + preset, + load_weights=None, + input_shape=None, + config_file="config.json", + config_overrides={}, +): + """Load a KerasCV layer to a preset directory.""" + # Load a serialized Keras object. + config_path = get_file(preset, config_file) + with open(config_path) as config_file: + config = json.load(config_file) + config["config"] = {**config["config"], **config_overrides} + layer = keras.saving.deserialize_keras_object(config) + if input_shape is not None: + layer.build(input_shape) + + # Check load_weights flag does not violate preset config. + if load_weights is True and config["weights"] is None: + raise ValueError( + f"The specified preset `{preset}` does not include weights. " + "Please remove the `load_weights` flag when calling " + "`from_preset()` on this preset." + ) + # Default to loading weights if available. + if load_weights is not False and config["weights"] is not None: + weights_path = get_file(preset, config["weights"]) + import h5py + + f = h5py.File(weights_path) + f.visititems(lambda name, _: print(name)) + + if hasattr(layer, "_layer_checkpoint_dependencies"): + legacy_load_weights(layer, weights_path) + else: + layer.load_weights(weights_path) + + return layer + + +def check_preset_class( + preset, + classes, + config_file="config.json", +): + """Validate a preset is being loaded on the correct class.""" + config_path = get_file(preset, config_file) + try: + with open(config_path) as config_file: + config = json.load(config_file) + except: + raise ValueError( + f"The specified preset `{preset}` is unknown. " + "Please check documentation to ensure the correct preset " + "handle is being used." + ) + cls = keras.saving.get_registered_object(config["registered_name"]) + if not isinstance(classes, (tuple, list)): + classes = (classes,) + + # Subclass checking and alias checking + if not any(issubclass(cls, obj) for obj in classes) and not any( + issubclass(alias, cls) for alias in classes + ): + raise ValueError( + f"Unexpected class in preset `'{preset}'`. " + "When calling `from_preset()` on a class object, the preset class " + f"much match allowed classes. Allowed classes are `{classes}`. " + f"Received: `{cls}`." + ) + return cls + + +def legacy_load_weights(layer, weights_path): + # Hacky fix for TensorFlow 2.13 and 2.14 when loading a `.weights.h5` file. + # We find the `Functional` class, and temporarily remove the + # `_layer_checkpoint_dependencies` property, which on older version of + # TensorFlow complete broke the variable paths for functional models. + functional_cls = None + for cls in inspect.getmro(layer.__class__): + if cls.__name__ == "Functional": + functional_cls = cls + property = functional_cls._layer_checkpoint_dependencies + functional_cls._layer_checkpoint_dependencies = {} + layer.load_weights(weights_path) + functional_cls._layer_checkpoint_dependencies = property diff --git a/keras_cv/utils/preset_utils_test.py b/keras_cv/utils/preset_utils_test.py new file mode 100644 index 0000000000..53546dd0d0 --- /dev/null +++ b/keras_cv/utils/preset_utils_test.py @@ -0,0 +1,87 @@ +# Copyright 2023 The KerasCV Authors +# +# 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 +# +# https://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. + +import json +import os + +import numpy as np +import pytest +from absl.testing import parameterized + +from keras_cv.models import DeepLabV3Plus +from keras_cv.models import ImageClassifier +from keras_cv.models import RetinaNet +from keras_cv.models import YOLOV8Detector +from keras_cv.tests.test_case import TestCase +from keras_cv.utils import preset_utils + + +class PresetUtilsTest(TestCase): + @parameterized.parameters( + (ImageClassifier, "resnet50_v2_imagenet_classifier", "classification"), + ( + ImageClassifier, + "efficientnetv2_s_imagenet_classifier", + "classification", + ), + ( + ImageClassifier, + "mobilenet_v3_large_imagenet_classifier", + "classification", + ), + (YOLOV8Detector, "yolo_v8_m_pascalvoc", "detection"), + (RetinaNet, "retinanet_resnet50_pascalvoc", "detection"), + (DeepLabV3Plus, "deeplab_v3_plus_resnet50_pascalvoc", "segmentation"), + ) + @pytest.mark.large + def test_preset_saving(self, cls, preset_name, task_type): + save_dir = self.get_temp_dir() + if task_type == "detection": + model = cls.from_preset(preset_name, bounding_box_format="xywh") + else: + model = cls.from_preset(preset_name) + preset_utils.save_to_preset(model, save_dir) + + # Check existence of files + self.assertTrue(os.path.exists(os.path.join(save_dir, "config.json"))) + self.assertTrue( + os.path.exists(os.path.join(save_dir, "model.weights.h5")) + ) + self.assertTrue(os.path.exists(os.path.join(save_dir, "metadata.json"))) + + # Check the model config (`config.json`) + with open(os.path.join(save_dir, "config.json"), "r") as f: + config_json = f.read() + self.assertTrue( + "build_config" not in config_json + ) # Test on raw json to include nested keys + self.assertTrue( + "compile_config" not in config_json + ) # Test on raw json to include nested keys + config = json.loads(config_json) + self.assertEqual(config["weights"], "model.weights.h5") + + # Try loading the model from preset directory + restored_model = preset_utils.load_from_preset(save_dir) + + input_batch = np.ones(shape=(2, 224, 224, 3)) + expected_output = model(input_batch) + restored_output = restored_model(input_batch) + self.assertAllClose(expected_output, restored_output) + + def test_preset_errors(self): + with self.assertRaisesRegex(ValueError, "must be a string"): + ImageClassifier.from_preset(ImageClassifier) + with self.assertRaisesRegex(ValueError, "Unknown preset identifier"): + ImageClassifier.from_preset("taggle://rednet/rednet/rednet") diff --git a/requirements-common.txt b/requirements-common.txt index 5741b63606..fc21cc5f96 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -2,6 +2,7 @@ absl-py regex pandas +kagglehub keras-core>=0.1.6 tensorflow-datasets pycocotools diff --git a/setup.py b/setup.py index 6ca3d37aa6..ffe7cbb4a8 100644 --- a/setup.py +++ b/setup.py @@ -55,6 +55,7 @@ def is_pure(self): "regex", "tensorflow-datasets", "keras-core", + "kagglehub", ], extras_require={ "tests": [