Spaces:
Sleeping
Sleeping
| from dataclasses import dataclass | |
| from pathlib import Path | |
| import keras | |
| import keras_hub | |
| from keras import layers | |
| from .losses import box_loss | |
| from deep_learning.models.spec import ModelArtifact, SupervisedModelBuilder | |
| def build_yolo_preprocessor(image_size: int = 448): | |
| inputs = keras.Input(shape=(None, None, 3), dtype="uint8") | |
| x = layers.Resizing( | |
| image_size, | |
| image_size, | |
| interpolation="bicubic", | |
| crop_to_aspect_ratio=True | |
| )(inputs) | |
| x = layers.Rescaling( | |
| scale=[0.017124753831663668, 0.01750700280112045, 0.017429193899782133], | |
| offset=[-2.1179039301310043, -2.0357142857142856, -1.8044444444444445] | |
| )(x) | |
| return keras.Model(inputs, x, name="yolo_preprocessor") | |
| class YoloModelBuilder(SupervisedModelBuilder): | |
| image_size: int | |
| grid_size: int | |
| num_labels: int | |
| backbone_preset: str = "resnet_50_imagenet" | |
| def build_training_artifact(self) -> ModelArtifact: | |
| backbone = keras_hub.models.Backbone.from_preset(self.backbone_preset) | |
| inputs = keras.Input(shape=(self.image_size, self.image_size, 3)) | |
| x = backbone(inputs) | |
| x = layers.Conv2D(512, (3, 3), strides=(2, 2))(x) | |
| x = layers.Flatten()(x) | |
| x = layers.Dense(2048, activation="relu", kernel_initializer="glorot_normal")(x) | |
| x = layers.Dropout(0.5)(x) | |
| x = layers.Dense(self.grid_size * self.grid_size * (self.num_labels + 5))(x) | |
| x = layers.Reshape((self.grid_size, self.grid_size, self.num_labels + 5))(x) | |
| box_predictions = x[..., :5] | |
| class_predictions = layers.Activation("softmax")(x[..., 5:]) | |
| outputs = {"box": box_predictions, "class": class_predictions} | |
| model = keras.Model(inputs, outputs, name="yolo") | |
| return ModelArtifact(model=model) | |
| def convert_to_inference_artifact( | |
| self, | |
| training_artifact: ModelArtifact | |
| ) -> ModelArtifact: | |
| inputs = keras.Input(shape=(None, None, 3), dtype="uint8") | |
| preprocessor = build_yolo_preprocessor(image_size=self.image_size) | |
| x = preprocessor(inputs) | |
| outputs = training_artifact.model(x) | |
| inference_model = keras.Model(inputs, outputs, name="yolo_inference") | |
| return ModelArtifact(model=inference_model) | |
| def load_inference_artifact(self, model_path: Path) -> ModelArtifact: | |
| model = keras.models.load_model( | |
| str(model_path), | |
| custom_objects=self._custom_objects() | |
| ) | |
| return ModelArtifact(model=model) | |
| def _custom_objects(self) -> dict: | |
| return { | |
| "box_loss": box_loss | |
| } | |
| def compile_training_model(self, model: keras.Model) -> None: | |
| model.compile( | |
| optimizer=keras.optimizers.Adam(2e-4), | |
| loss={ | |
| "box": box_loss, | |
| "class": "sparse_categorical_crossentropy" | |
| } | |
| ) | |