keras-hub-nightly 0.16.1.dev202410020340__py3-none-any.whl → 0.16.1.dev202410040340__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. keras_hub/api/layers/__init__.py +3 -3
  2. keras_hub/api/models/__init__.py +10 -1
  3. keras_hub/src/layers/preprocessing/audio_converter.py +3 -7
  4. keras_hub/src/layers/preprocessing/image_converter.py +164 -34
  5. keras_hub/src/models/backbone.py +3 -9
  6. keras_hub/src/models/csp_darknet/csp_darknet_image_classifier.py +0 -109
  7. keras_hub/src/models/deeplab_v3/__init__.py +7 -0
  8. keras_hub/src/models/deeplab_v3/deeplab_v3_backbone.py +196 -0
  9. keras_hub/src/models/deeplab_v3/deeplab_v3_image_converter.py +10 -0
  10. keras_hub/src/models/deeplab_v3/deeplab_v3_image_segmeter_preprocessor.py +16 -0
  11. keras_hub/src/models/deeplab_v3/deeplab_v3_layers.py +215 -0
  12. keras_hub/src/models/deeplab_v3/deeplab_v3_presets.py +4 -0
  13. keras_hub/src/models/deeplab_v3/deeplab_v3_segmenter.py +109 -0
  14. keras_hub/src/models/densenet/densenet_image_classifier.py +0 -128
  15. keras_hub/src/models/densenet/densenet_image_converter.py +2 -4
  16. keras_hub/src/models/feature_pyramid_backbone.py +1 -1
  17. keras_hub/src/models/image_classifier.py +147 -2
  18. keras_hub/src/models/image_classifier_preprocessor.py +3 -3
  19. keras_hub/src/models/image_segmenter.py +0 -5
  20. keras_hub/src/models/image_segmenter_preprocessor.py +29 -4
  21. keras_hub/src/models/mix_transformer/mix_transformer_classifier.py +0 -109
  22. keras_hub/src/models/mobilenet/mobilenet_image_classifier.py +0 -92
  23. keras_hub/src/models/pali_gemma/pali_gemma_image_converter.py +2 -4
  24. keras_hub/src/models/preprocessor.py +3 -5
  25. keras_hub/src/models/resnet/resnet_backbone.py +1 -11
  26. keras_hub/src/models/resnet/resnet_image_classifier.py +0 -137
  27. keras_hub/src/models/resnet/resnet_image_converter.py +2 -4
  28. keras_hub/src/models/sam/__init__.py +5 -0
  29. keras_hub/src/models/sam/sam_image_converter.py +2 -4
  30. keras_hub/src/models/sam/sam_image_segmenter_preprocessor.py +11 -1
  31. keras_hub/src/models/sam/sam_presets.py +3 -3
  32. keras_hub/src/models/stable_diffusion_3/flow_match_euler_discrete_scheduler.py +8 -1
  33. keras_hub/src/models/stable_diffusion_3/stable_diffusion_3_backbone.py +57 -93
  34. keras_hub/src/models/stable_diffusion_3/stable_diffusion_3_presets.py +3 -3
  35. keras_hub/src/models/stable_diffusion_3/stable_diffusion_3_text_to_image.py +5 -3
  36. keras_hub/src/models/task.py +39 -36
  37. keras_hub/src/models/vae/__init__.py +1 -0
  38. keras_hub/src/models/vae/vae_backbone.py +172 -0
  39. keras_hub/src/models/vae/vae_layers.py +740 -0
  40. keras_hub/src/models/vgg/vgg_backbone.py +1 -20
  41. keras_hub/src/models/vgg/vgg_image_classifier.py +108 -29
  42. keras_hub/src/tokenizers/tokenizer.py +3 -6
  43. keras_hub/src/utils/preset_utils.py +103 -61
  44. keras_hub/src/utils/timm/preset_loader.py +8 -9
  45. keras_hub/src/version_utils.py +1 -1
  46. {keras_hub_nightly-0.16.1.dev202410020340.dist-info → keras_hub_nightly-0.16.1.dev202410040340.dist-info}/METADATA +1 -1
  47. {keras_hub_nightly-0.16.1.dev202410020340.dist-info → keras_hub_nightly-0.16.1.dev202410040340.dist-info}/RECORD +49 -41
  48. keras_hub/src/layers/preprocessing/resizing_image_converter.py +0 -138
  49. keras_hub/src/models/stable_diffusion_3/vae_image_decoder.py +0 -320
  50. {keras_hub_nightly-0.16.1.dev202410020340.dist-info → keras_hub_nightly-0.16.1.dev202410040340.dist-info}/WHEEL +0 -0
  51. {keras_hub_nightly-0.16.1.dev202410020340.dist-info → keras_hub_nightly-0.16.1.dev202410040340.dist-info}/top_level.txt +0 -0
@@ -33,10 +33,10 @@ from keras_hub.src.layers.preprocessing.multi_segment_packer import (
33
33
  )
34
34
  from keras_hub.src.layers.preprocessing.random_deletion import RandomDeletion
35
35
  from keras_hub.src.layers.preprocessing.random_swap import RandomSwap
36
- from keras_hub.src.layers.preprocessing.resizing_image_converter import (
37
- ResizingImageConverter,
38
- )
39
36
  from keras_hub.src.layers.preprocessing.start_end_packer import StartEndPacker
37
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_image_converter import (
38
+ DeepLabV3ImageConverter,
39
+ )
40
40
  from keras_hub.src.models.densenet.densenet_image_converter import (
41
41
  DenseNetImageConverter,
42
42
  )
@@ -85,6 +85,15 @@ from keras_hub.src.models.deberta_v3.deberta_v3_text_classifier_preprocessor imp
85
85
  from keras_hub.src.models.deberta_v3.deberta_v3_tokenizer import (
86
86
  DebertaV3Tokenizer,
87
87
  )
88
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_backbone import (
89
+ DeepLabV3Backbone,
90
+ )
91
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_image_segmeter_preprocessor import (
92
+ DeepLabV3ImageSegmenterPreprocessor,
93
+ )
94
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_segmenter import (
95
+ DeepLabV3ImageSegmenter,
96
+ )
88
97
  from keras_hub.src.models.densenet.densenet_backbone import DenseNetBackbone
89
98
  from keras_hub.src.models.densenet.densenet_image_classifier import (
90
99
  DenseNetImageClassifier,
@@ -254,7 +263,7 @@ from keras_hub.src.models.roberta.roberta_tokenizer import RobertaTokenizer
254
263
  from keras_hub.src.models.sam.sam_backbone import SAMBackbone
255
264
  from keras_hub.src.models.sam.sam_image_segmenter import SAMImageSegmenter
256
265
  from keras_hub.src.models.sam.sam_image_segmenter_preprocessor import (
257
- SAMImageSegmenterPreprocessor as SamImageSegmenterPreprocessor,
266
+ SAMImageSegmenterPreprocessor,
258
267
  )
259
268
  from keras_hub.src.models.seq_2_seq_lm import Seq2SeqLM
260
269
  from keras_hub.src.models.seq_2_seq_lm_preprocessor import Seq2SeqLMPreprocessor
@@ -2,11 +2,10 @@ from keras_hub.src.api_export import keras_hub_export
2
2
  from keras_hub.src.layers.preprocessing.preprocessing_layer import (
3
3
  PreprocessingLayer,
4
4
  )
5
- from keras_hub.src.utils.preset_utils import AUDIO_CONVERTER_CONFIG_FILE
6
5
  from keras_hub.src.utils.preset_utils import builtin_presets
7
6
  from keras_hub.src.utils.preset_utils import find_subclass
8
7
  from keras_hub.src.utils.preset_utils import get_preset_loader
9
- from keras_hub.src.utils.preset_utils import save_serialized_object
8
+ from keras_hub.src.utils.preset_utils import get_preset_saver
10
9
  from keras_hub.src.utils.python_utils import classproperty
11
10
 
12
11
 
@@ -101,8 +100,5 @@ class AudioConverter(PreprocessingLayer):
101
100
  Args:
102
101
  preset_dir: The path to the local model preset directory.
103
102
  """
104
- save_serialized_object(
105
- self,
106
- preset_dir,
107
- config_file=AUDIO_CONVERTER_CONFIG_FILE,
108
- )
103
+ saver = get_preset_saver(preset_dir)
104
+ saver.save_audio_converter(self)
@@ -1,47 +1,184 @@
1
+ import math
2
+
3
+ import keras
4
+ import numpy as np
5
+ from keras import ops
6
+
1
7
  from keras_hub.src.api_export import keras_hub_export
2
8
  from keras_hub.src.layers.preprocessing.preprocessing_layer import (
3
9
  PreprocessingLayer,
4
10
  )
5
- from keras_hub.src.utils.preset_utils import IMAGE_CONVERTER_CONFIG_FILE
11
+ from keras_hub.src.utils.keras_utils import standardize_data_format
6
12
  from keras_hub.src.utils.preset_utils import builtin_presets
7
13
  from keras_hub.src.utils.preset_utils import find_subclass
8
14
  from keras_hub.src.utils.preset_utils import get_preset_loader
9
- from keras_hub.src.utils.preset_utils import save_serialized_object
15
+ from keras_hub.src.utils.preset_utils import get_preset_saver
10
16
  from keras_hub.src.utils.python_utils import classproperty
17
+ from keras_hub.src.utils.tensor_utils import preprocessing_function
11
18
 
12
19
 
13
20
  @keras_hub_export("keras_hub.layers.ImageConverter")
14
21
  class ImageConverter(PreprocessingLayer):
15
- """Convert raw image for models that support image input.
22
+ """Preprocess raw images into model ready inputs.
23
+
24
+ This class converts from raw images to model ready inputs. This conversion
25
+ proceeds in the following steps:
16
26
 
17
- This class converts from raw images of any size, to preprocessed
18
- images for pretrained model inputs. It is meant to be a convenient way to
19
- write custom preprocessing code that is not model specific. This layer
20
- should be instantiated via the `from_preset()` constructor, which will
21
- create the correct subclass of this layer for the model preset.
27
+ 1. Resize the image using to `image_size`. If `image_size` is `None`, this
28
+ step will be skipped.
29
+ 2. Rescale the image by multiplying by `scale`, which can be either global
30
+ or per channel. If `scale` is `None`, this step will be skipped.
31
+ 3. Offset the image by adding `offset`, which can be either global
32
+ or per channel. If `offset` is `None`, this step will be skipped.
22
33
 
23
34
  The layer will take as input a raw image tensor in the channels last or
24
35
  channels first format, and output a preprocessed image input for modeling.
25
- The exact structure of the output will vary per model, though in most cases
26
- this layer will simply resize the image to the size needed by the model
27
- input.
36
+ This tensor can be batched (rank 4), or unbatched (rank 3).
37
+
38
+ This layer can be used with the `from_preset()` constructor to load a layer
39
+ that will rescale and resize an image for a specific pretrained model.
40
+ Using the layer this way allows writing preprocessing code that does not
41
+ need updating when switching between model checkpoints.
42
+
43
+ Args:
44
+ image_size: `(int, int)` tuple or `None`. The output size of the image,
45
+ not including the channels axis. If `None`, the input will not be
46
+ resized.
47
+ scale: float, tuple of floats, or `None`. The scale to apply to the
48
+ inputs. If `scale` is a single float, the entire input will be
49
+ multiplied by `scale`. If `scale` is a tuple, it's assumed to
50
+ contain per-channel scale value multiplied against each channel of
51
+ the input images. If `scale` is `None`, no scaling is applied.
52
+ offset: float, tuple of floats, or `None`. The offset to apply to the
53
+ inputs. If `offset` is a single float, the entire input will be
54
+ summed with `offset`. If `offset` is a tuple, it's assumed to
55
+ contain per-channel offset value summed against each channel of the
56
+ input images. If `offset` is `None`, no scaling is applied.
57
+ crop_to_aspect_ratio: If `True`, resize the images without aspect
58
+ ratio distortion. When the original aspect ratio differs
59
+ from the target aspect ratio, the output image will be
60
+ cropped so as to return the
61
+ largest possible window in the image (of size `(height, width)`)
62
+ that matches the target aspect ratio. By default
63
+ (`crop_to_aspect_ratio=False`), aspect ratio may not be preserved.
64
+ interpolation: String, the interpolation method.
65
+ Supports `"bilinear"`, `"nearest"`, `"bicubic"`,
66
+ `"lanczos3"`, `"lanczos5"`. Defaults to `"bilinear"`.
67
+ data_format: String, either `"channels_last"` or `"channels_first"`.
68
+ The ordering of the dimensions in the inputs. `"channels_last"`
69
+ corresponds to inputs with shape `(batch, height, width, channels)`
70
+ while `"channels_first"` corresponds to inputs with shape
71
+ `(batch, channels, height, width)`. It defaults to the
72
+ `image_data_format` value found in your Keras config file at
73
+ `~/.keras/keras.json`. If you never set it, then it will be
74
+ `"channels_last"`.
28
75
 
29
76
  Examples:
30
77
  ```python
31
- # Resize images for `"pali_gemma_3b_224"`.
32
- converter = keras_hub.layers.ImageConverter.from_preset("pali_gemma_3b_224")
33
- converter(np.ones(2, 512, 512, 3)) # Output shape: (2, 224, 224, 3)
34
- # Resize images for `"pali_gemma_3b_448"`.
35
- converter = keras_hub.layers.ImageConverter.from_preset("pali_gemma_3b_448")
36
- converter(np.ones(2, 512, 512, 3)) # Output shape: (2, 448, 448, 3)
78
+ # Resize raw images and scale them to [0, 1].
79
+ converter = keras_hub.layers.ImageConverter(
80
+ image_size=(128, 128),
81
+ scale=1. / 255,
82
+ )
83
+ converter(np.random.randint(0, 256, size=(2, 512, 512, 3)))
84
+
85
+ # Resize images to the specific size needed for a PaliGemma preset.
86
+ converter = keras_hub.layers.ImageConverter.from_preset(
87
+ "pali_gemma_3b_224"
88
+ )
89
+ converter(np.random.randint(0, 256, size=(2, 512, 512, 3)))
37
90
  ```
38
91
  """
39
92
 
40
93
  backbone_cls = None
41
94
 
95
+ def __init__(
96
+ self,
97
+ image_size=None,
98
+ scale=None,
99
+ offset=None,
100
+ crop_to_aspect_ratio=True,
101
+ interpolation="bilinear",
102
+ data_format=None,
103
+ **kwargs,
104
+ ):
105
+ # TODO: old arg names. Delete this block after resaving Kaggle assets.
106
+ if "height" in kwargs and "width" in kwargs:
107
+ image_size = (kwargs.pop("height"), kwargs.pop("width"))
108
+ if "variance" in kwargs and "mean" in kwargs:
109
+ std = [math.sqrt(v) for v in kwargs.pop("variance")]
110
+ scale = [scale / s for s in std]
111
+ offset = [-m / s for m, s in zip(kwargs.pop("mean"), std)]
112
+
113
+ super().__init__(**kwargs)
114
+
115
+ # Create the `Resizing` layer here even if it's not being used. That
116
+ # allows us to make `image_size` a settable property.
117
+ self.resizing = keras.layers.Resizing(
118
+ height=image_size[0] if image_size else None,
119
+ width=image_size[1] if image_size else None,
120
+ crop_to_aspect_ratio=crop_to_aspect_ratio,
121
+ interpolation=interpolation,
122
+ data_format=data_format,
123
+ dtype=self.dtype_policy,
124
+ name="resizing",
125
+ )
126
+ self.scale = scale
127
+ self.offset = offset
128
+ self.crop_to_aspect_ratio = crop_to_aspect_ratio
129
+ self.interpolation = interpolation
130
+ self.data_format = standardize_data_format(data_format)
131
+
132
+ @property
42
133
  def image_size(self):
43
- """Returns the default size of a single image."""
44
- return (None, None)
134
+ """Settable tuple of `(height, width)` ints. The output image shape."""
135
+ if self.resizing.height is None:
136
+ return None
137
+ return (self.resizing.height, self.resizing.width)
138
+
139
+ @image_size.setter
140
+ def image_size(self, value):
141
+ if value is None:
142
+ value = (None, None)
143
+ self.resizing.height = value[0]
144
+ self.resizing.width = value[1]
145
+
146
+ @preprocessing_function
147
+ def call(self, inputs):
148
+ if self.image_size is not None:
149
+ x = self.resizing(inputs)
150
+ if self.scale is not None:
151
+ x = x * self._expand_non_channel_dims(self.scale, x)
152
+ if self.offset is not None:
153
+ x = x + self._expand_non_channel_dims(self.offset, x)
154
+ return x
155
+
156
+ def _expand_non_channel_dims(self, value, inputs):
157
+ unbatched = len(ops.shape(inputs)) == 3
158
+ channels_first = self.data_format == "channels_first"
159
+ if unbatched:
160
+ broadcast_dims = (1, 2) if channels_first else (0, 1)
161
+ else:
162
+ broadcast_dims = (0, 2, 3) if channels_first else (0, 1, 2)
163
+ # If inputs are not a tensor type, return a numpy array.
164
+ # This might happen when running under tf.data.
165
+ if ops.is_tensor(inputs):
166
+ return ops.expand_dims(value, broadcast_dims)
167
+ else:
168
+ return np.expand_dims(value, broadcast_dims)
169
+
170
+ def get_config(self):
171
+ config = super().get_config()
172
+ config.update(
173
+ {
174
+ "image_size": self.image_size,
175
+ "scale": self.scale,
176
+ "offset": self.offset,
177
+ "interpolation": self.interpolation,
178
+ "crop_to_aspect_ratio": self.crop_to_aspect_ratio,
179
+ }
180
+ )
181
+ return config
45
182
 
46
183
  @classproperty
47
184
  def presets(cls):
@@ -69,13 +206,6 @@ class ImageConverter(PreprocessingLayer):
69
206
  You can run `cls.presets.keys()` to list all built-in presets available
70
207
  on the class.
71
208
 
72
- This constructor can be called in one of two ways. Either from the base
73
- class like `keras_hub.models.ImageConverter.from_preset()`, or from a
74
- model class like
75
- `keras_hub.models.PaliGemmaImageConverter.from_preset()`. If calling
76
- from the base class, the subclass of the returning object will be
77
- inferred from the config in the preset directory.
78
-
79
209
  Args:
80
210
  preset: string. A built-in preset identifier, a Kaggle Models
81
211
  handle, a Hugging Face handle, or a path to a local directory.
@@ -85,17 +215,20 @@ class ImageConverter(PreprocessingLayer):
85
215
 
86
216
  Examples:
87
217
  ```python
218
+ batch = np.random.randint(0, 256, size=(2, 512, 512, 3))
219
+
88
220
  # Resize images for `"pali_gemma_3b_224"`.
89
221
  converter = keras_hub.layers.ImageConverter.from_preset(
90
222
  "pali_gemma_3b_224"
91
223
  )
92
- converter(np.ones(2, 512, 512, 3)) # Output shape: (2, 224, 224, 3)
93
- # Override arguments on the base class.
224
+ converter(batch) # Output shape: (2, 224, 224, 3)
225
+
226
+ # Resize images for `"pali_gemma_3b_448"` without cropping.
94
227
  converter = keras_hub.layers.ImageConverter.from_preset(
95
228
  "pali_gemma_3b_448",
96
229
  crop_to_aspect_ratio=False,
97
230
  )
98
- converter(np.ones(2, 512, 512, 3)) # (2, 448, 448, 3)
231
+ converter(batch) # Output shape: (2, 448, 448, 3)
99
232
  ```
100
233
  """
101
234
  loader = get_preset_loader(preset)
@@ -110,8 +243,5 @@ class ImageConverter(PreprocessingLayer):
110
243
  Args:
111
244
  preset_dir: The path to the local model preset directory.
112
245
  """
113
- save_serialized_object(
114
- self,
115
- preset_dir,
116
- config_file=IMAGE_CONVERTER_CONFIG_FILE,
117
- )
246
+ saver = get_preset_saver(preset_dir)
247
+ saver.save_image_converter(self)
@@ -1,15 +1,10 @@
1
- import os
2
-
3
1
  import keras
4
2
 
5
3
  from keras_hub.src.api_export import keras_hub_export
6
4
  from keras_hub.src.utils.keras_utils import assert_quantization_support
7
- from keras_hub.src.utils.preset_utils import CONFIG_FILE
8
- from keras_hub.src.utils.preset_utils import MODEL_WEIGHTS_FILE
9
5
  from keras_hub.src.utils.preset_utils import builtin_presets
10
6
  from keras_hub.src.utils.preset_utils import get_preset_loader
11
- from keras_hub.src.utils.preset_utils import save_metadata
12
- from keras_hub.src.utils.preset_utils import save_serialized_object
7
+ from keras_hub.src.utils.preset_utils import get_preset_saver
13
8
  from keras_hub.src.utils.python_utils import classproperty
14
9
 
15
10
 
@@ -193,9 +188,8 @@ class Backbone(keras.Model):
193
188
  Args:
194
189
  preset_dir: The path to the local model preset directory.
195
190
  """
196
- save_serialized_object(self, preset_dir, config_file=CONFIG_FILE)
197
- self.save_weights(os.path.join(preset_dir, MODEL_WEIGHTS_FILE))
198
- save_metadata(self, preset_dir)
191
+ saver = get_preset_saver(preset_dir)
192
+ saver.save_backbone(self)
199
193
 
200
194
  def enable_lora(self, rank):
201
195
  """Enable Lora on the backbone.
@@ -1,5 +1,3 @@
1
- import keras
2
-
3
1
  from keras_hub.src.api_export import keras_hub_export
4
2
  from keras_hub.src.models.csp_darknet.csp_darknet_backbone import (
5
3
  CSPDarkNetBackbone,
@@ -9,111 +7,4 @@ from keras_hub.src.models.image_classifier import ImageClassifier
9
7
 
10
8
  @keras_hub_export("keras_hub.models.CSPDarkNetImageClassifier")
11
9
  class CSPDarkNetImageClassifier(ImageClassifier):
12
- """CSPDarkNet image classifier task model.
13
-
14
- Args:
15
- backbone: A `keras_hub.models.CSPDarkNetBackbone` instance.
16
- num_classes: int. The number of classes to predict.
17
- activation: `None`, str or callable. The activation function to use on
18
- the `Dense` layer. Set `activation=None` to return the output
19
- logits. Defaults to `"softmax"`.
20
-
21
- To fine-tune with `fit()`, pass a dataset containing tuples of `(x, y)`
22
- where `x` is a tensor and `y` is a integer from `[0, num_classes)`.
23
- All `ImageClassifier` tasks include a `from_preset()` constructor which can
24
- be used to load a pre-trained config and weights.
25
-
26
- Examples:
27
-
28
- Call `predict()` to run inference.
29
- ```python
30
- # Load preset and train
31
- images = np.ones((2, 224, 224, 3), dtype="float32")
32
- classifier = keras_hub.models.CSPDarkNetImageClassifier.from_preset(
33
- "csp_darknet_tiny_imagenet")
34
- classifier.predict(images)
35
- ```
36
-
37
- Call `fit()` on a single batch.
38
- ```python
39
- # Load preset and train
40
- images = np.ones((2, 224, 224, 3), dtype="float32")
41
- labels = [0, 3]
42
- classifier = keras_hub.models.CSPDarkNetImageClassifier.from_preset(
43
- "csp_darknet_tiny_imagenet")
44
- classifier.fit(x=images, y=labels, batch_size=2)
45
- ```
46
-
47
- Call `fit()` with custom loss, optimizer and backbone.
48
- ```python
49
- classifier = keras_hub.models.CSPDarkNetImageClassifier.from_preset(
50
- "csp_darknet_tiny_imagenet")
51
- classifier.compile(
52
- loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
53
- optimizer=keras.optimizers.Adam(5e-5),
54
- )
55
- classifier.backbone.trainable = False
56
- classifier.fit(x=images, y=labels, batch_size=2)
57
- ```
58
-
59
- Custom backbone.
60
- ```python
61
- images = np.ones((2, 224, 224, 3), dtype="float32")
62
- labels = [0, 3]
63
- backbone = keras_hub.models.CSPDarkNetBackbone(
64
- stackwise_num_filters=[128, 256, 512, 1024],
65
- stackwise_depth=[3, 9, 9, 3],
66
- block_type="basic_block",
67
- image_shape = (224, 224, 3),
68
- )
69
- classifier = keras_hub.models.CSPDarkNetImageClassifier(
70
- backbone=backbone,
71
- num_classes=4,
72
- )
73
- classifier.fit(x=images, y=labels, batch_size=2)
74
- ```
75
- """
76
-
77
10
  backbone_cls = CSPDarkNetBackbone
78
-
79
- def __init__(
80
- self,
81
- backbone,
82
- num_classes,
83
- activation="softmax",
84
- preprocessor=None, # adding this dummy arg for saved model test
85
- # TODO: once preprocessor flow is figured out, this needs to be updated
86
- **kwargs,
87
- ):
88
- # === Layers ===
89
- self.backbone = backbone
90
- self.output_dense = keras.layers.Dense(
91
- num_classes,
92
- activation=activation,
93
- name="predictions",
94
- )
95
-
96
- # === Functional Model ===
97
- inputs = self.backbone.input
98
- x = self.backbone(inputs)
99
- outputs = self.output_dense(x)
100
- super().__init__(
101
- inputs=inputs,
102
- outputs=outputs,
103
- **kwargs,
104
- )
105
-
106
- # === Config ===
107
- self.num_classes = num_classes
108
- self.activation = activation
109
-
110
- def get_config(self):
111
- # Backbone serialized in `super`
112
- config = super().get_config()
113
- config.update(
114
- {
115
- "num_classes": self.num_classes,
116
- "activation": self.activation,
117
- }
118
- )
119
- return config
@@ -0,0 +1,7 @@
1
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_backbone import (
2
+ DeepLabV3Backbone,
3
+ )
4
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_presets import backbone_presets
5
+ from keras_hub.src.utils.preset_utils import register_presets
6
+
7
+ register_presets(backbone_presets, DeepLabV3Backbone)
@@ -0,0 +1,196 @@
1
+ import keras
2
+
3
+ from keras_hub.src.api_export import keras_hub_export
4
+ from keras_hub.src.models.backbone import Backbone
5
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_layers import (
6
+ SpatialPyramidPooling,
7
+ )
8
+
9
+
10
+ @keras_hub_export("keras_hub.models.DeepLabV3Backbone")
11
+ class DeepLabV3Backbone(Backbone):
12
+ """DeepLabV3 & DeepLabV3Plus architecture for semantic segmentation.
13
+
14
+ This class implements a DeepLabV3 & DeepLabV3Plus architecture as described
15
+ in [Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation](
16
+ https://arxiv.org/abs/1802.02611)(ECCV 2018)
17
+ and [Rethinking Atrous Convolution for Semantic Image Segmentation](
18
+ https://arxiv.org/abs/1706.05587)(CVPR 2017)
19
+
20
+ Args:
21
+ image_encoder: `keras.Model`. An instance that is used as a feature
22
+ extractor for the Encoder. Should either be a
23
+ `keras_hub.models.Backbone` or a `keras.Model` that implements the
24
+ `pyramid_outputs` property with keys "P2", "P3" etc as values.
25
+ A somewhat sensible backbone to use in many cases is
26
+ the `keras_hub.models.ResNetBackbone.from_preset("resnet_v2_50")`.
27
+ projection_filters: int. Number of filters in the convolution layer
28
+ projecting low-level features from the `image_encoder`.
29
+ spatial_pyramid_pooling_key: str. A layer level to extract and perform
30
+ `spatial_pyramid_pooling`, one of the key from the `image_encoder`
31
+ `pyramid_outputs` property such as "P4", "P5" etc.
32
+ upsampling_size: int or tuple of 2 integers. The upsampling factors for
33
+ rows and columns of `spatial_pyramid_pooling` layer.
34
+ If `low_level_feature_key` is given then `spatial_pyramid_pooling`s
35
+ layer resolution should match with the `low_level_feature`s layer
36
+ resolution to concatenate both the layers for combined encoder
37
+ outputs.
38
+ dilation_rates: list. A `list` of integers for parallel dilated conv applied to
39
+ `SpatialPyramidPooling`. Usually a
40
+ sample choice of rates are `[6, 12, 18]`.
41
+ low_level_feature_key: str optional. A layer level to extract the feature
42
+ from one of the key from the `image_encoder`s `pyramid_outputs`
43
+ property such as "P2", "P3" etc which will be the Decoder block.
44
+ Required only when the DeepLabV3Plus architecture needs to be applied.
45
+ image_shape: tuple. The input shape without the batch size.
46
+ Defaults to `(None, None, 3)`.
47
+
48
+ Example:
49
+ ```python
50
+ # Load a trained backbone to extract features from it's `pyramid_outputs`.
51
+ image_encoder = keras_hub.models.ResNetBackbone.from_preset("resnet_50_imagenet")
52
+
53
+ model = keras_hub.models.DeepLabV3Backbone(
54
+ image_encoder=image_encoder,
55
+ projection_filters=48,
56
+ low_level_feature_key="P2",
57
+ spatial_pyramid_pooling_key="P5",
58
+ upsampling_size = 8,
59
+ dilation_rates = [6, 12, 18]
60
+ )
61
+ ```
62
+ """
63
+
64
+ def __init__(
65
+ self,
66
+ image_encoder,
67
+ spatial_pyramid_pooling_key,
68
+ upsampling_size,
69
+ dilation_rates,
70
+ low_level_feature_key=None,
71
+ projection_filters=48,
72
+ image_shape=(None, None, 3),
73
+ **kwargs,
74
+ ):
75
+ if not isinstance(image_encoder, keras.Model):
76
+ raise ValueError(
77
+ "Argument `image_encoder` must be a `keras.Model` instance. Received instead "
78
+ f"{image_encoder} (of type {type(image_encoder)})."
79
+ )
80
+ data_format = keras.config.image_data_format()
81
+ channel_axis = -1 if data_format == "channels_last" else 1
82
+
83
+ # === Layers ===
84
+ inputs = keras.layers.Input(image_shape, name="inputs")
85
+
86
+ fpn_model = keras.Model(
87
+ image_encoder.inputs, image_encoder.pyramid_outputs
88
+ )
89
+
90
+ fpn_outputs = fpn_model(inputs)
91
+
92
+ spatial_pyramid_pooling = SpatialPyramidPooling(
93
+ dilation_rates=dilation_rates
94
+ )
95
+ spatial_backbone_features = fpn_outputs[spatial_pyramid_pooling_key]
96
+ spp_outputs = spatial_pyramid_pooling(spatial_backbone_features)
97
+
98
+ encoder_outputs = keras.layers.UpSampling2D(
99
+ size=upsampling_size,
100
+ interpolation="bilinear",
101
+ name="encoder_output_upsampling",
102
+ data_format=data_format,
103
+ )(spp_outputs)
104
+
105
+ if low_level_feature_key:
106
+ decoder_feature = fpn_outputs[low_level_feature_key]
107
+ low_level_projected_features = apply_low_level_feature_network(
108
+ decoder_feature, projection_filters, channel_axis
109
+ )
110
+
111
+ encoder_outputs = keras.layers.Concatenate(
112
+ axis=channel_axis, name="encoder_decoder_concat"
113
+ )([encoder_outputs, low_level_projected_features])
114
+ # upsampling to the original image size
115
+ upsampling = (2 ** int(spatial_pyramid_pooling_key[-1])) // (
116
+ int(upsampling_size[0])
117
+ if isinstance(upsampling_size, tuple)
118
+ else upsampling_size
119
+ )
120
+ # === Functional Model ===
121
+ x = keras.layers.Conv2D(
122
+ name="segmentation_head_conv",
123
+ filters=256,
124
+ kernel_size=1,
125
+ padding="same",
126
+ use_bias=False,
127
+ data_format=data_format,
128
+ )(encoder_outputs)
129
+ x = keras.layers.BatchNormalization(
130
+ name="segmentation_head_norm", axis=channel_axis
131
+ )(x)
132
+ x = keras.layers.ReLU(name="segmentation_head_relu")(x)
133
+ x = keras.layers.UpSampling2D(
134
+ size=upsampling,
135
+ interpolation="bilinear",
136
+ data_format=data_format,
137
+ name="backbone_output_upsampling",
138
+ )(x)
139
+
140
+ super().__init__(inputs=inputs, outputs=x, **kwargs)
141
+
142
+ # === Config ===
143
+ self.image_shape = image_shape
144
+ self.image_encoder = image_encoder
145
+ self.projection_filters = projection_filters
146
+ self.upsampling_size = upsampling_size
147
+ self.dilation_rates = dilation_rates
148
+ self.low_level_feature_key = low_level_feature_key
149
+ self.spatial_pyramid_pooling_key = spatial_pyramid_pooling_key
150
+
151
+ def get_config(self):
152
+ config = super().get_config()
153
+ config.update(
154
+ {
155
+ "image_encoder": keras.saving.serialize_keras_object(
156
+ self.image_encoder
157
+ ),
158
+ "projection_filters": self.projection_filters,
159
+ "dilation_rates": self.dilation_rates,
160
+ "upsampling_size": self.upsampling_size,
161
+ "low_level_feature_key": self.low_level_feature_key,
162
+ "spatial_pyramid_pooling_key": self.spatial_pyramid_pooling_key,
163
+ "image_shape": self.image_shape,
164
+ }
165
+ )
166
+ return config
167
+
168
+ @classmethod
169
+ def from_config(cls, config):
170
+ if "image_encoder" in config and isinstance(
171
+ config["image_encoder"], dict
172
+ ):
173
+ config["image_encoder"] = keras.layers.deserialize(
174
+ config["image_encoder"]
175
+ )
176
+ return super().from_config(config)
177
+
178
+
179
+ def apply_low_level_feature_network(
180
+ input_tensor, projection_filters, channel_axis
181
+ ):
182
+ data_format = keras.config.image_data_format()
183
+ x = keras.layers.Conv2D(
184
+ name="decoder_conv",
185
+ filters=projection_filters,
186
+ kernel_size=1,
187
+ padding="same",
188
+ use_bias=False,
189
+ data_format=data_format,
190
+ )(input_tensor)
191
+
192
+ x = keras.layers.BatchNormalization(name="decoder_norm", axis=channel_axis)(
193
+ x
194
+ )
195
+ x = keras.layers.ReLU(name="decoder_relu")(x)
196
+ return x
@@ -0,0 +1,10 @@
1
+ from keras_hub.src.api_export import keras_hub_export
2
+ from keras_hub.src.layers.preprocessing.image_converter import ImageConverter
3
+ from keras_hub.src.models.deeplab_v3.deeplab_v3_backbone import (
4
+ DeepLabV3Backbone,
5
+ )
6
+
7
+
8
+ @keras_hub_export("keras_hub.layers.DeepLabV3ImageConverter")
9
+ class DeepLabV3ImageConverter(ImageConverter):
10
+ backbone_cls = DeepLabV3Backbone