Reformat code examples.

This commit is contained in:
Francois Chollet 2023-06-10 11:59:22 -07:00
parent f6cb396158
commit 89e5669fab
5 changed files with 169 additions and 57 deletions

@ -112,13 +112,21 @@ def split_data(images, labels, train_size=0.9, shuffle=True):
# 3. Get the size of training samples
train_samples = int(size * train_size)
# 4. Split data into training and validation sets
x_train, y_train = images[indices[:train_samples]], labels[indices[:train_samples]]
x_valid, y_valid = images[indices[train_samples:]], labels[indices[train_samples:]]
x_train, y_train = (
images[indices[:train_samples]],
labels[indices[:train_samples]],
)
x_valid, y_valid = (
images[indices[train_samples:]],
labels[indices[train_samples:]],
)
return x_train, x_valid, y_train, y_valid
# Splitting data into training and validation sets
x_train, x_valid, y_train, y_valid = split_data(np.array(images), np.array(labels))
x_train, x_valid, y_train, y_valid = split_data(
np.array(images), np.array(labels)
)
def encode_single_sample(img_path, label):
@ -153,7 +161,9 @@ train_dataset = (
validation_dataset = tf.data.Dataset.from_tensor_slices((x_valid, y_valid))
validation_dataset = (
validation_dataset.map(encode_single_sample, num_parallel_calls=tf.data.AUTOTUNE)
validation_dataset.map(
encode_single_sample, num_parallel_calls=tf.data.AUTOTUNE
)
.batch(batch_size)
.prefetch(buffer_size=tf.data.AUTOTUNE)
)
@ -169,7 +179,11 @@ for batch in train_dataset.take(1):
labels = batch["label"]
for i in range(16):
img = (images[i] * 255).numpy().astype("uint8")
label = tf.strings.reduce_join(num_to_char(labels[i])).numpy().decode("utf-8")
label = (
tf.strings.reduce_join(num_to_char(labels[i]))
.numpy()
.decode("utf-8")
)
ax[i // 4, i % 4].imshow(img[:, :, 0].T, cmap="gray")
ax[i // 4, i % 4].set_title(label)
ax[i // 4, i % 4].axis("off")
@ -192,8 +206,12 @@ class CTCLayer(layers.Layer):
input_length = tf.cast(tf.shape(y_pred)[1], dtype="int64")
label_length = tf.cast(tf.shape(y_true)[1], dtype="int64")
input_length = input_length * tf.ones(shape=(batch_len, 1), dtype="int64")
label_length = label_length * tf.ones(shape=(batch_len, 1), dtype="int64")
input_length = input_length * tf.ones(
shape=(batch_len, 1), dtype="int64"
)
label_length = label_length * tf.ones(
shape=(batch_len, 1), dtype="int64"
)
loss = self.loss_fn(y_true, y_pred, input_length, label_length)
self.add_loss(loss)
@ -241,12 +259,18 @@ def build_model():
x = layers.Dropout(0.2)(x)
# RNNs
x = layers.Bidirectional(layers.LSTM(128, return_sequences=True, dropout=0.25))(x)
x = layers.Bidirectional(layers.LSTM(64, return_sequences=True, dropout=0.25))(x)
x = layers.Bidirectional(
layers.LSTM(128, return_sequences=True, dropout=0.25)
)(x)
x = layers.Bidirectional(
layers.LSTM(64, return_sequences=True, dropout=0.25)
)(x)
# Output layer
x = layers.Dense(
len(char_to_num.get_vocabulary()) + 1, activation="softmax", name="dense2"
len(char_to_num.get_vocabulary()) + 1,
activation="softmax",
name="dense2",
)(x)
# Add CTC layer for calculating CTC loss at each step
@ -276,7 +300,9 @@ epochs = 1
early_stopping_patience = 10
# Add early stopping
early_stopping = keras.callbacks.EarlyStopping(
monitor="val_loss", patience=early_stopping_patience, restore_best_weights=True
monitor="val_loss",
patience=early_stopping_patience,
restore_best_weights=True,
)
# Train the model
@ -307,9 +333,9 @@ prediction_model.summary()
def decode_batch_predictions(pred):
input_len = np.ones(pred.shape[0]) * pred.shape[1]
# Use greedy search. For complex tasks, you can use beam search
results = keras.backend.ctc_decode(pred, input_length=input_len, greedy=True)[0][0][
:, :max_length
]
results = keras.backend.ctc_decode(
pred, input_length=input_len, greedy=True
)[0][0][:, :max_length]
# Iterate over the results and get back the text
output_text = []
for res in results:
@ -328,7 +354,9 @@ for batch in validation_dataset.take(1):
orig_texts = []
for label in batch_labels:
label = tf.strings.reduce_join(num_to_char(label)).numpy().decode("utf-8")
label = (
tf.strings.reduce_join(num_to_char(label)).numpy().decode("utf-8")
)
orig_texts.append(label)
_, ax = plt.subplots(4, 4, figsize=(15, 5))
@ -339,4 +367,4 @@ for batch in validation_dataset.take(1):
ax[i // 4, i % 4].imshow(img, cmap="gray")
ax[i // 4, i % 4].set_title(title)
ax[i // 4, i % 4].axis("off")
plt.show()
plt.show()

@ -58,15 +58,21 @@ path_to_downloaded_file = keras.utils.get_file(
)
# Extracting tar files found inside main zip file
shutil.unpack_archive("./datasets/caltech-101/101_ObjectCategories.tar.gz", "./")
shutil.unpack_archive(
"./datasets/caltech-101/101_ObjectCategories.tar.gz", "./"
)
shutil.unpack_archive("./datasets/caltech-101/Annotations.tar", "./")
# list of paths to images and annotations
image_paths = [
f for f in os.listdir(path_images) if os.path.isfile(os.path.join(path_images, f))
f
for f in os.listdir(path_images)
if os.path.isfile(os.path.join(path_images, f))
]
annot_paths = [
f for f in os.listdir(path_annot) if os.path.isfile(os.path.join(path_annot, f))
f
for f in os.listdir(path_annot)
if os.path.isfile(os.path.join(path_annot, f))
]
image_paths.sort()
@ -186,7 +192,9 @@ plt.axis("off")
patches = Patches(patch_size)(tf.convert_to_tensor([x_train[0]]))
print(f"Image size: {image_size} X {image_size}")
print(f"Patch size: {patch_size} X {patch_size}")
print(f"{patches.shape[1]} patches per image \n{patches.shape[-1]} elements per patch")
print(
f"{patches.shape[1]} patches per image \n{patches.shape[-1]} elements per patch"
)
n = int(np.sqrt(patches.shape[1]))
@ -289,7 +297,9 @@ def create_vit_object_detector(
representation = layers.Flatten()(representation)
representation = layers.Dropout(0.3)(representation)
# Add MLP.
features = mlp(representation, hidden_units=mlp_head_units, dropout_rate=0.3)
features = mlp(
representation, hidden_units=mlp_head_units, dropout_rate=0.3
)
bounding_box = layers.Dense(4)(
features
@ -461,7 +471,9 @@ for input_image in x_test[:10]:
top_left_x, top_left_y = int(y_test[i][0] * w), int(y_test[i][1] * h)
bottom_right_x, bottom_right_y = int(y_test[i][2] * w), int(y_test[i][3] * h)
bottom_right_x, bottom_right_y = int(y_test[i][2] * w), int(
y_test[i][3] * h
)
box_truth = top_left_x, top_left_y, bottom_right_x, bottom_right_y
@ -500,4 +512,4 @@ This example demonstrates that a pure Transformer can be trained
to predict the bounding boxes of an object in a given image,
thus extending the use of Transformers to object detection tasks.
The model can be improved further by tuning hyper-parameters and pre-training.
"""
"""

@ -68,6 +68,7 @@ check out
# Make sure we are able to handle large datasets
import resource
low, high = resource.getrlimit(resource.RLIMIT_NOFILE)
resource.setrlimit(resource.RLIMIT_NOFILE, (high, high))
@ -95,7 +96,11 @@ width = 128
temperature = 0.1
# Stronger augmentations for contrastive, weaker ones for supervised training
contrastive_augmentation = {"min_area": 0.25, "brightness": 0.6, "jitter": 0.2}
classification_augmentation = {"min_area": 0.75, "brightness": 0.3, "jitter": 0.1}
classification_augmentation = {
"min_area": 0.75,
"brightness": 0.3,
"jitter": 0.1,
}
"""
## Dataset
@ -108,7 +113,9 @@ smaller batch of labeled images.
def prepare_dataset():
# Labeled and unlabeled samples are loaded synchronously
# with batch sizes selected accordingly
steps_per_epoch = (unlabeled_dataset_size + labeled_dataset_size) // batch_size
steps_per_epoch = (
unlabeled_dataset_size + labeled_dataset_size
) // batch_size
unlabeled_batch_size = unlabeled_dataset_size // steps_per_epoch
labeled_batch_size = labeled_dataset_size // steps_per_epoch
print(
@ -117,12 +124,16 @@ def prepare_dataset():
# Turning off shuffle to lower resource usage
unlabeled_train_dataset = (
tfds.load("stl10", split="unlabelled", as_supervised=True, shuffle_files=False)
tfds.load(
"stl10", split="unlabelled", as_supervised=True, shuffle_files=False
)
.shuffle(buffer_size=10 * unlabeled_batch_size)
.batch(unlabeled_batch_size)
)
labeled_train_dataset = (
tfds.load("stl10", split="train", as_supervised=True, shuffle_files=False)
tfds.load(
"stl10", split="train", as_supervised=True, shuffle_files=False
)
.shuffle(buffer_size=10 * labeled_batch_size)
.batch(labeled_batch_size)
)
@ -193,7 +204,9 @@ class RandomColorAffine(layers.Layer):
# Same for all colors
brightness_scales = 1 + tf.random.uniform(
(batch_size, 1, 1, 1), minval=-self.brightness, maxval=self.brightness
(batch_size, 1, 1, 1),
minval=-self.brightness,
maxval=self.brightness,
)
# Different for all colors
jitter_matrices = tf.random.uniform(
@ -356,7 +369,9 @@ class ContrastiveModel(keras.Model):
self.temperature = temperature
self.contrastive_augmenter = get_augmenter(**contrastive_augmentation)
self.classification_augmenter = get_augmenter(**classification_augmentation)
self.classification_augmenter = get_augmenter(
**classification_augmentation
)
self.encoder = get_encoder()
# Non-linear MLP as projection head
self.projection_head = keras.Sequential(
@ -369,7 +384,8 @@ class ContrastiveModel(keras.Model):
)
# Single dense layer for linear probing
self.linear_probe = keras.Sequential(
[layers.Input(shape=(width,)), layers.Dense(10)], name="linear_probe"
[layers.Input(shape=(width,)), layers.Dense(10)],
name="linear_probe",
)
self.encoder.summary()
@ -383,14 +399,18 @@ class ContrastiveModel(keras.Model):
self.probe_optimizer = probe_optimizer
# self.contrastive_loss will be defined as a method
self.probe_loss = keras.losses.SparseCategoricalCrossentropy(from_logits=True)
self.probe_loss = keras.losses.SparseCategoricalCrossentropy(
from_logits=True
)
self.contrastive_loss_tracker = keras.metrics.Mean(name="c_loss")
self.contrastive_accuracy = keras.metrics.SparseCategoricalAccuracy(
name="c_acc"
)
self.probe_loss_tracker = keras.metrics.Mean(name="p_loss")
self.probe_accuracy = keras.metrics.SparseCategoricalAccuracy(name="p_acc")
self.probe_accuracy = keras.metrics.SparseCategoricalAccuracy(
name="p_acc"
)
@property
def metrics(self):
@ -409,7 +429,8 @@ class ContrastiveModel(keras.Model):
projections_1 = tf.math.l2_normalize(projections_1, axis=1)
projections_2 = tf.math.l2_normalize(projections_2, axis=1)
similarities = (
tf.matmul(projections_1, projections_2, transpose_b=True) / self.temperature
tf.matmul(projections_1, projections_2, transpose_b=True)
/ self.temperature
)
# The similarity between the representations of two augmented views of the
@ -445,15 +466,19 @@ class ContrastiveModel(keras.Model):
# The representations are passed through a projection mlp
projections_1 = self.projection_head(features_1, training=True)
projections_2 = self.projection_head(features_2, training=True)
contrastive_loss = self.contrastive_loss(projections_1, projections_2)
contrastive_loss = self.contrastive_loss(
projections_1, projections_2
)
gradients = tape.gradient(
contrastive_loss,
self.encoder.trainable_weights + self.projection_head.trainable_weights,
self.encoder.trainable_weights
+ self.projection_head.trainable_weights,
)
self.contrastive_optimizer.apply_gradients(
zip(
gradients,
self.encoder.trainable_weights + self.projection_head.trainable_weights,
self.encoder.trainable_weights
+ self.projection_head.trainable_weights,
)
)
self.contrastive_loss_tracker.update_state(contrastive_loss)
@ -468,7 +493,9 @@ class ContrastiveModel(keras.Model):
features = self.encoder(preprocessed_images, training=False)
class_logits = self.linear_probe(features, training=True)
probe_loss = self.probe_loss(labels, class_logits)
gradients = tape.gradient(probe_loss, self.linear_probe.trainable_weights)
gradients = tape.gradient(
probe_loss, self.linear_probe.trainable_weights
)
self.probe_optimizer.apply_gradients(
zip(gradients, self.linear_probe.trainable_weights)
)
@ -548,11 +575,14 @@ print(
# The classification accuracies of the baseline and the pretraining + finetuning process:
def plot_training_curves(pretraining_history, finetuning_history, baseline_history):
def plot_training_curves(
pretraining_history, finetuning_history, baseline_history
):
for metric_key, metric_name in zip(["acc", "loss"], ["accuracy", "loss"]):
plt.figure(figsize=(8, 5), dpi=100)
plt.plot(
baseline_history.history[f"val_{metric_key}"], label="supervised baseline"
baseline_history.history[f"val_{metric_key}"],
label="supervised baseline",
)
plt.plot(
pretraining_history.history[f"val_p_{metric_key}"],
@ -670,4 +700,4 @@ performance at smaller batch sizes.
You can use the trained model hosted on [Hugging Face Hub](https://huggingface.co/keras-io/semi-supervised-classification-simclr)
and try the demo on [Hugging Face Spaces](https://huggingface.co/spaces/keras-io/semi-supervised-classification).
"""
"""

@ -100,7 +100,15 @@ def window_partition(x, window_size):
patch_num_y = height // window_size
patch_num_x = width // window_size
x = tf.reshape(
x, shape=(-1, patch_num_y, window_size, patch_num_x, window_size, channels)
x,
shape=(
-1,
patch_num_y,
window_size,
patch_num_x,
window_size,
channels,
),
)
x = tf.transpose(x, (0, 1, 3, 2, 4, 5))
windows = tf.reshape(x, shape=(-1, window_size, window_size, channels))
@ -112,7 +120,14 @@ def window_reverse(windows, window_size, height, width, channels):
patch_num_x = width // window_size
x = tf.reshape(
windows,
shape=(-1, patch_num_y, patch_num_x, window_size, window_size, channels),
shape=(
-1,
patch_num_y,
patch_num_x,
window_size,
window_size,
channels,
),
)
x = tf.transpose(x, perm=(0, 1, 3, 2, 4, 5))
x = tf.reshape(x, shape=(-1, height, width, channels))
@ -129,7 +144,9 @@ class DropPath(layers.Layer):
batch_size = input_shape[0]
rank = x.shape.rank
shape = (batch_size,) + (1,) * (rank - 1)
random_tensor = (1 - self.drop_prob) + tf.random.uniform(shape, dtype=x.dtype)
random_tensor = (1 - self.drop_prob) + tf.random.uniform(
shape, dtype=x.dtype
)
path_mask = tf.floor(random_tensor)
output = tf.math.divide(x, 1 - self.drop_prob) * path_mask
return output
@ -149,7 +166,13 @@ whereas window-based self-attention leads to linear complexity and is easily sca
class WindowAttention(layers.Layer):
def __init__(
self, dim, window_size, num_heads, qkv_bias=True, dropout_rate=0.0, **kwargs
self,
dim,
window_size,
num_heads,
qkv_bias=True,
dropout_rate=0.0,
**kwargs,
):
super().__init__(**kwargs)
self.dim = dim
@ -174,7 +197,9 @@ class WindowAttention(layers.Layer):
coords_matrix = np.meshgrid(coords_h, coords_w, indexing="ij")
coords = np.stack(coords_matrix)
coords_flatten = coords.reshape(2, -1)
relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]
relative_coords = (
coords_flatten[:, :, None] - coords_flatten[:, None, :]
)
relative_coords = relative_coords.transpose([1, 2, 0])
relative_coords[:, :, 0] += self.window_size[0] - 1
relative_coords[:, :, 1] += self.window_size[1] - 1
@ -182,7 +207,8 @@ class WindowAttention(layers.Layer):
relative_position_index = relative_coords.sum(-1)
self.relative_position_index = tf.Variable(
initial_value=lambda: tf.convert_to_tensor(relative_position_index), trainable=False
initial_value=lambda: tf.convert_to_tensor(relative_position_index),
trainable=False,
)
def call(self, x, mask=None):
@ -204,9 +230,12 @@ class WindowAttention(layers.Layer):
self.relative_position_bias_table, relative_position_index_flat
)
relative_position_bias = tf.reshape(
relative_position_bias, shape=(num_window_elements, num_window_elements, -1)
relative_position_bias,
shape=(num_window_elements, num_window_elements, -1),
)
relative_position_bias = tf.transpose(
relative_position_bias, perm=(2, 0, 1)
)
relative_position_bias = tf.transpose(relative_position_bias, perm=(2, 0, 1))
attn = attn + tf.expand_dims(relative_position_bias, axis=0)
if mask is not None:
@ -329,7 +358,9 @@ class SwinTransformer(layers.Layer):
)
attn_mask = tf.where(attn_mask != 0, -100.0, attn_mask)
attn_mask = tf.where(attn_mask == 0, 0.0, attn_mask)
self.attn_mask = tf.Variable(initial_value=attn_mask, trainable=False)
self.attn_mask = tf.Variable(
initial_value=attn_mask, trainable=False
)
def call(self, x):
height, width = self.num_patch
@ -351,7 +382,8 @@ class SwinTransformer(layers.Layer):
attn_windows = self.attn(x_windows, mask=self.attn_mask)
attn_windows = tf.reshape(
attn_windows, shape=(-1, self.window_size, self.window_size, channels)
attn_windows,
shape=(-1, self.window_size, self.window_size, channels),
)
shifted_x = window_reverse(
attn_windows, self.window_size, height, width, channels
@ -401,7 +433,9 @@ class PatchExtract(layers.Layer):
)
patch_dim = patches.shape[-1]
patch_num = patches.shape[1]
return tf.reshape(patches, (batch_size, patch_num * patch_num, patch_dim))
return tf.reshape(
patches, (batch_size, patch_num * patch_num, patch_dim)
)
class PatchEmbedding(layers.Layer):
@ -409,7 +443,9 @@ class PatchEmbedding(layers.Layer):
super().__init__(**kwargs)
self.num_patch = num_patch
self.proj = layers.Dense(embed_dim)
self.pos_embed = layers.Embedding(input_dim=num_patch, output_dim=embed_dim)
self.pos_embed = layers.Embedding(
input_dim=num_patch, output_dim=embed_dim
)
def call(self, patch):
pos = tf.range(start=0, limit=self.num_patch, delta=1)
@ -544,4 +580,4 @@ for these. You are strongly advised to also check out the
This example takes inspiration from the official
[PyTorch](https://github.com/microsoft/Swin-Transformer) and
[TensorFlow](https://github.com/VcampSoldiers/Swin-Transformer-Tensorflow) implementations.
"""
"""

@ -136,15 +136,21 @@ via random search using [KerasTuner](https://github.com/keras-team/keras-tuner).
def make_model(input_shape):
input_layer = keras.layers.Input(input_shape)
conv1 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(input_layer)
conv1 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(
input_layer
)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.ReLU()(conv1)
conv2 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(conv1)
conv2 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(
conv1
)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.ReLU()(conv2)
conv3 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(conv2)
conv3 = keras.layers.Conv1D(filters=64, kernel_size=3, padding="same")(
conv2
)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.ReLU()(conv3)
@ -178,7 +184,7 @@ callbacks = [
model.compile(
optimizer="adam",
loss="sparse_categorical_crossentropy",
metrics=["sparse_categorical_accuracy"]
metrics=["sparse_categorical_accuracy"],
)
history = model.fit(
x_train,