Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
fchollet
GitHub Repository: fchollet/deep-learning-with-python-notebooks
Path: blob/master/second_edition/chapter09_part02_modern-convnet-architecture-patterns.ipynb
713 views
Kernel: Python 3

This is a companion notebook for the book Deep Learning with Python, Second Edition. For readability, it only contains runnable code blocks and section titles, and omits everything else in the book: text paragraphs, figures, and pseudocode.

If you want to be able to follow what's going on, I recommend reading the notebook side by side with your copy of the book.

This notebook was generated for TensorFlow 2.6.

Modern convnet architecture patterns

Modularity, hierarchy, and reuse

Residual connections

Residual block where the number of filters changes

from tensorflow import keras from tensorflow.keras import layers inputs = keras.Input(shape=(32, 32, 3)) x = layers.Conv2D(32, 3, activation="relu")(inputs) residual = x x = layers.Conv2D(64, 3, activation="relu", padding="same")(x) residual = layers.Conv2D(64, 1)(residual) x = layers.add([x, residual])

Case where target block includes a max pooling layer

inputs = keras.Input(shape=(32, 32, 3)) x = layers.Conv2D(32, 3, activation="relu")(inputs) residual = x x = layers.Conv2D(64, 3, activation="relu", padding="same")(x) x = layers.MaxPooling2D(2, padding="same")(x) residual = layers.Conv2D(64, 1, strides=2)(residual) x = layers.add([x, residual])
inputs = keras.Input(shape=(32, 32, 3)) x = layers.Rescaling(1./255)(inputs) def residual_block(x, filters, pooling=False): residual = x x = layers.Conv2D(filters, 3, activation="relu", padding="same")(x) x = layers.Conv2D(filters, 3, activation="relu", padding="same")(x) if pooling: x = layers.MaxPooling2D(2, padding="same")(x) residual = layers.Conv2D(filters, 1, strides=2)(residual) elif filters != residual.shape[-1]: residual = layers.Conv2D(filters, 1)(residual) x = layers.add([x, residual]) return x x = residual_block(x, filters=32, pooling=True) x = residual_block(x, filters=64, pooling=True) x = residual_block(x, filters=128, pooling=False) x = layers.GlobalAveragePooling2D()(x) outputs = layers.Dense(1, activation="sigmoid")(x) model = keras.Model(inputs=inputs, outputs=outputs) model.summary()

Batch normalization

Depthwise separable convolutions

Putting it together: A mini Xception-like model

from google.colab import files files.upload()
!mkdir ~/.kaggle !cp kaggle.json ~/.kaggle/ !chmod 600 ~/.kaggle/kaggle.json !kaggle competitions download -c dogs-vs-cats !unzip -qq train.zip
import os, shutil, pathlib from tensorflow.keras.utils import image_dataset_from_directory original_dir = pathlib.Path("train") new_base_dir = pathlib.Path("cats_vs_dogs_small") def make_subset(subset_name, start_index, end_index): for category in ("cat", "dog"): dir = new_base_dir / subset_name / category os.makedirs(dir) fnames = [f"{category}.{i}.jpg" for i in range(start_index, end_index)] for fname in fnames: shutil.copyfile(src=original_dir / fname, dst=dir / fname) make_subset("train", start_index=0, end_index=1000) make_subset("validation", start_index=1000, end_index=1500) make_subset("test", start_index=1500, end_index=2500) train_dataset = image_dataset_from_directory( new_base_dir / "train", image_size=(180, 180), batch_size=32) validation_dataset = image_dataset_from_directory( new_base_dir / "validation", image_size=(180, 180), batch_size=32) test_dataset = image_dataset_from_directory( new_base_dir / "test", image_size=(180, 180), batch_size=32)
data_augmentation = keras.Sequential( [ layers.RandomFlip("horizontal"), layers.RandomRotation(0.1), layers.RandomZoom(0.2), ] )
inputs = keras.Input(shape=(180, 180, 3)) x = data_augmentation(inputs) x = layers.Rescaling(1./255)(x) x = layers.Conv2D(filters=32, kernel_size=5, use_bias=False)(x) for size in [32, 64, 128, 256, 512]: residual = x x = layers.BatchNormalization()(x) x = layers.Activation("relu")(x) x = layers.SeparableConv2D(size, 3, padding="same", use_bias=False)(x) x = layers.BatchNormalization()(x) x = layers.Activation("relu")(x) x = layers.SeparableConv2D(size, 3, padding="same", use_bias=False)(x) x = layers.MaxPooling2D(3, strides=2, padding="same")(x) residual = layers.Conv2D( size, 1, strides=2, padding="same", use_bias=False)(residual) x = layers.add([x, residual]) x = layers.GlobalAveragePooling2D()(x) x = layers.Dropout(0.5)(x) outputs = layers.Dense(1, activation="sigmoid")(x) model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss="binary_crossentropy", optimizer="rmsprop", metrics=["accuracy"]) history = model.fit( train_dataset, epochs=100, validation_data=validation_dataset)