Visualize Object-Detection Datasets using Weights & Biases¶
This notebook demostrates how you can visualize and debug your data input pipeline for object detetction using Weights & Biases.
Original Notebook: https://keras.io/guides/keras_cv/object_detection_keras_cv/
Install Dependencies¶
In [ ]:
Copied!
!pip install --upgrade -q git+https://github.com/keras-team/keras-cv
!pip install --upgrade -q git+https://github.com/soumik12345/wandb-addons
!pip install --upgrade -q git+https://github.com/keras-team/keras-cv
!pip install --upgrade -q git+https://github.com/soumik12345/wandb-addons
In [ ]:
Copied!
import tensorflow as tf
from tensorflow import keras
import tensorflow_datasets as tfds
import keras_cv
import wandb
from wandb_addons.keras.detection import visualize_dataset
import tensorflow as tf
from tensorflow import keras
import tensorflow_datasets as tfds
import keras_cv
import wandb
from wandb_addons.keras.detection import visualize_dataset
Initialize a Weights & Biases run and Set up the Configs¶
In [ ]:
Copied!
wandb.init(project="keras-community-days", job_type="visualization")
config = wandb.config
config.batch_size = 4
config.base_lr = 0.005
config.model_name = "retinanet_resnet50_pascalvoc"
config.momentum = 0.9
config.global_clipnorm = 10.0
class_ids = [
    "Aeroplane",
    "Bicycle",
    "Bird",
    "Boat",
    "Bottle",
    "Bus",
    "Car",
    "Cat",
    "Chair",
    "Cow",
    "Dining Table",
    "Dog",
    "Horse",
    "Motorbike",
    "Person",
    "Potted Plant",
    "Sheep",
    "Sofa",
    "Train",
    "Tvmonitor",
    "Total",
]
config.class_mapping = dict(zip(range(len(class_ids)), class_ids))
wandb.init(project="keras-community-days", job_type="visualization")
config = wandb.config
config.batch_size = 4
config.base_lr = 0.005
config.model_name = "retinanet_resnet50_pascalvoc"
config.momentum = 0.9
config.global_clipnorm = 10.0
class_ids = [
    "Aeroplane",
    "Bicycle",
    "Bird",
    "Boat",
    "Bottle",
    "Bus",
    "Car",
    "Cat",
    "Chair",
    "Cow",
    "Dining Table",
    "Dog",
    "Horse",
    "Motorbike",
    "Person",
    "Potted Plant",
    "Sheep",
    "Sofa",
    "Train",
    "Tvmonitor",
    "Total",
]
config.class_mapping = dict(zip(range(len(class_ids)), class_ids))
Load Pascal VOC Dataset¶
In [ ]:
Copied!
def unpackage_raw_tfds_inputs(inputs, bounding_box_format):
    image = inputs["image"]
    boxes = keras_cv.bounding_box.convert_format(
        inputs["objects"]["bbox"],
        images=image,
        source="rel_yxyx",
        target=bounding_box_format,
    )
    bounding_boxes = {
        "classes": tf.cast(inputs["objects"]["label"], dtype=tf.float32),
        "boxes": tf.cast(boxes, dtype=tf.float32),
    }
    return {
        "images": tf.cast(image, tf.float32),
        "bounding_boxes": bounding_boxes
    }
def load_pascal_voc(split, dataset, bounding_box_format):
    ds = tfds.load(dataset, split=split, with_info=False, shuffle_files=True)
    ds = ds.map(
        lambda x: unpackage_raw_tfds_inputs(
            x, bounding_box_format=bounding_box_format
        ),
        num_parallel_calls=tf.data.AUTOTUNE,
    )
    return ds
train_ds = load_pascal_voc(
    split="train", dataset="voc/2007", bounding_box_format="xywh"
)
eval_ds = load_pascal_voc(split="test", dataset="voc/2007", bounding_box_format="xywh")
train_ds = train_ds.shuffle(config.batch_size * 4)
def unpackage_raw_tfds_inputs(inputs, bounding_box_format):
    image = inputs["image"]
    boxes = keras_cv.bounding_box.convert_format(
        inputs["objects"]["bbox"],
        images=image,
        source="rel_yxyx",
        target=bounding_box_format,
    )
    bounding_boxes = {
        "classes": tf.cast(inputs["objects"]["label"], dtype=tf.float32),
        "boxes": tf.cast(boxes, dtype=tf.float32),
    }
    return {
        "images": tf.cast(image, tf.float32),
        "bounding_boxes": bounding_boxes
    }
def load_pascal_voc(split, dataset, bounding_box_format):
    ds = tfds.load(dataset, split=split, with_info=False, shuffle_files=True)
    ds = ds.map(
        lambda x: unpackage_raw_tfds_inputs(
            x, bounding_box_format=bounding_box_format
        ),
        num_parallel_calls=tf.data.AUTOTUNE,
    )
    return ds
train_ds = load_pascal_voc(
    split="train", dataset="voc/2007", bounding_box_format="xywh"
)
eval_ds = load_pascal_voc(split="test", dataset="voc/2007", bounding_box_format="xywh")
train_ds = train_ds.shuffle(config.batch_size * 4)
Visualize the Raw Dataset with Bounding Box Annotations¶
In [ ]:
Copied!
train_ds = train_ds.ragged_batch(config.batch_size, drop_remainder=True)
eval_ds = eval_ds.ragged_batch(config.batch_size, drop_remainder=True)
visualize_dataset(
    dataset=train_ds,
    class_mapping=config.class_mapping,
    title="Train-Dataset",
    max_batches_to_visualize=10,
)
visualize_dataset(
    dataset=eval_ds,
    class_mapping=config.class_mapping,
    title="Eval-Dataset",
    max_batches_to_visualize=10,
)
train_ds = train_ds.ragged_batch(config.batch_size, drop_remainder=True)
eval_ds = eval_ds.ragged_batch(config.batch_size, drop_remainder=True)
visualize_dataset(
    dataset=train_ds,
    class_mapping=config.class_mapping,
    title="Train-Dataset",
    max_batches_to_visualize=10,
)
visualize_dataset(
    dataset=eval_ds,
    class_mapping=config.class_mapping,
    title="Eval-Dataset",
    max_batches_to_visualize=10,
)
Visualize the Training Dataset with Augmentations¶
In [ ]:
Copied!
augmenter = keras.Sequential(
    layers=[
        keras_cv.layers.RandomFlip(mode="horizontal", bounding_box_format="xywh"),
        keras_cv.layers.JitteredResize(
            target_size=(640, 640), scale_factor=(0.75, 1.3), bounding_box_format="xywh"
        ),
    ]
)
train_ds = train_ds.map(augmenter, num_parallel_calls=tf.data.AUTOTUNE)
visualize_dataset(
    dataset=train_ds,
    class_mapping=config.class_mapping,
    title="Augmented-Train-Dataset",
    max_batches_to_visualize=10,
)
augmenter = keras.Sequential(
    layers=[
        keras_cv.layers.RandomFlip(mode="horizontal", bounding_box_format="xywh"),
        keras_cv.layers.JitteredResize(
            target_size=(640, 640), scale_factor=(0.75, 1.3), bounding_box_format="xywh"
        ),
    ]
)
train_ds = train_ds.map(augmenter, num_parallel_calls=tf.data.AUTOTUNE)
visualize_dataset(
    dataset=train_ds,
    class_mapping=config.class_mapping,
    title="Augmented-Train-Dataset",
    max_batches_to_visualize=10,
)
Visualize the Resized Validation Dataset¶
In [ ]:
Copied!
inference_resizing = keras_cv.layers.Resizing(
    640, 640, bounding_box_format="xywh", pad_to_aspect_ratio=True
)
eval_ds = eval_ds.map(inference_resizing, num_parallel_calls=tf.data.AUTOTUNE)
visualize_dataset(
    dataset=eval_ds,
    class_mapping=config.class_mapping,
    title="Resized-Train-Dataset",
    max_batches_to_visualize=10,
)
inference_resizing = keras_cv.layers.Resizing(
    640, 640, bounding_box_format="xywh", pad_to_aspect_ratio=True
)
eval_ds = eval_ds.map(inference_resizing, num_parallel_calls=tf.data.AUTOTUNE)
visualize_dataset(
    dataset=eval_ds,
    class_mapping=config.class_mapping,
    title="Resized-Train-Dataset",
    max_batches_to_visualize=10,
)
Prepare Dataset for Evaluation¶
In [ ]:
Copied!
def dict_to_tuple(inputs):
    return inputs["images"], keras_cv.bounding_box.to_dense(
        inputs["bounding_boxes"], max_boxes=32
    )
train_ds = train_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
eval_ds = eval_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.prefetch(tf.data.AUTOTUNE)
eval_ds = eval_ds.prefetch(tf.data.AUTOTUNE)
def dict_to_tuple(inputs):
    return inputs["images"], keras_cv.bounding_box.to_dense(
        inputs["bounding_boxes"], max_boxes=32
    )
train_ds = train_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
eval_ds = eval_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.prefetch(tf.data.AUTOTUNE)
eval_ds = eval_ds.prefetch(tf.data.AUTOTUNE)
Define the Pre-trained Model¶
In [ ]:
Copied!
pretrained_model = keras_cv.models.RetinaNet.from_preset(
    config.model_name, bounding_box_format="xywh"
)
optimizer = keras.optimizers.SGD(
    learning_rate=config.base_lr,
    momentum=config.momentum,
    global_clipnorm=config.global_clipnorm
)
coco_metrics = keras_cv.metrics.BoxCOCOMetrics(
    bounding_box_format="xywh", evaluate_freq=20
)
pretrained_model.compile(
    classification_loss="focal",
    box_loss="smoothl1",
    optimizer=optimizer,
    metrics=[coco_metrics],
)
pretrained_model = keras_cv.models.RetinaNet.from_preset(
    config.model_name, bounding_box_format="xywh"
)
optimizer = keras.optimizers.SGD(
    learning_rate=config.base_lr,
    momentum=config.momentum,
    global_clipnorm=config.global_clipnorm
)
coco_metrics = keras_cv.metrics.BoxCOCOMetrics(
    bounding_box_format="xywh", evaluate_freq=20
)
pretrained_model.compile(
    classification_loss="focal",
    box_loss="smoothl1",
    optimizer=optimizer,
    metrics=[coco_metrics],
)
Evaluate the Pre-trained Model on the Evaluation Dataset¶
In [ ]:
Copied!
coco_metrics.reset_state()
result = pretrained_model.evaluate(eval_ds.take(40))
result = coco_metrics.result(force=True)
wandb.log({f"Evaluation/{k}": v.numpy() for k, v in result.items()})
coco_metrics.reset_state()
result = pretrained_model.evaluate(eval_ds.take(40))
result = coco_metrics.result(force=True)
wandb.log({f"Evaluation/{k}": v.numpy() for k, v in result.items()})
In [ ]:
Copied!
# Finish the experiment
wandb.finish()
# Finish the experiment
wandb.finish()