1+ {
2+ "cells" : [
3+ {
4+ "cell_type" : " markdown" ,
5+ "metadata" : {
6+ "colab_type" : " text"
7+ },
8+ "source" : [
9+ " This is a companion notebook for the book [Deep Learning with Python, Third Edition](TODO). For readability, it only contains runnable code blocks and section titles, and omits everything else in the book: text paragraphs, figures, and pseudocode.\n\n **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.**"
10+ ]
11+ },
12+ {
13+ "cell_type" : " code" ,
14+ "execution_count" : 0 ,
15+ "metadata" : {
16+ "colab_type" : " code"
17+ },
18+ "outputs" : [],
19+ "source" : [
20+ " !pip install keras keras-hub --upgrade -q"
21+ ]
22+ },
23+ {
24+ "cell_type" : " code" ,
25+ "execution_count" : 0 ,
26+ "metadata" : {
27+ "colab_type" : " code"
28+ },
29+ "outputs" : [],
30+ "source" : [
31+ " import os\n " ,
32+ " os.environ[\" KERAS_BACKEND\" ] = \" jax\" "
33+ ]
34+ },
35+ {
36+ "cell_type" : " markdown" ,
37+ "metadata" : {
38+ "colab_type" : " text"
39+ },
40+ "source" : [
41+ " ### Modularity, hierarchy, and reuse"
42+ ]
43+ },
44+ {
45+ "cell_type" : " markdown" ,
46+ "metadata" : {
47+ "colab_type" : " text"
48+ },
49+ "source" : [
50+ " ### Residual connections"
51+ ]
52+ },
53+ {
54+ "cell_type" : " code" ,
55+ "execution_count" : 0 ,
56+ "metadata" : {
57+ "colab_type" : " code"
58+ },
59+ "outputs" : [],
60+ "source" : [
61+ " import keras\n " ,
62+ " from keras import layers\n " ,
63+ " \n " ,
64+ " inputs = keras.Input(shape=(32, 32, 3))\n " ,
65+ " x = layers.Conv2D(32, 3, activation=\" relu\" )(inputs)\n " ,
66+ " residual = x\n " ,
67+ " x = layers.Conv2D(64, 3, activation=\" relu\" , padding=\" same\" )(x)\n " ,
68+ " residual = layers.Conv2D(64, 1)(residual)\n " ,
69+ " x = layers.add([x, residual])"
70+ ]
71+ },
72+ {
73+ "cell_type" : " code" ,
74+ "execution_count" : 0 ,
75+ "metadata" : {
76+ "colab_type" : " code"
77+ },
78+ "outputs" : [],
79+ "source" : [
80+ " inputs = keras.Input(shape=(32, 32, 3))\n " ,
81+ " x = layers.Conv2D(32, 3, activation=\" relu\" )(inputs)\n " ,
82+ " residual = x\n " ,
83+ " x = layers.Conv2D(64, 3, activation=\" relu\" , padding=\" same\" )(x)\n " ,
84+ " x = layers.MaxPooling2D(2, padding=\" same\" )(x)\n " ,
85+ " residual = layers.Conv2D(64, 1, strides=2)(residual)\n " ,
86+ " x = layers.add([x, residual])"
87+ ]
88+ },
89+ {
90+ "cell_type" : " code" ,
91+ "execution_count" : 0 ,
92+ "metadata" : {
93+ "colab_type" : " code"
94+ },
95+ "outputs" : [],
96+ "source" : [
97+ " inputs = keras.Input(shape=(32, 32, 3))\n " ,
98+ " x = layers.Rescaling(1.0 / 255)(inputs)\n " ,
99+ " \n " ,
100+ " def residual_block(x, filters, pooling=False):\n " ,
101+ " residual = x\n " ,
102+ " x = layers.Conv2D(filters, 3, activation=\" relu\" , padding=\" same\" )(x)\n " ,
103+ " x = layers.Conv2D(filters, 3, activation=\" relu\" , padding=\" same\" )(x)\n " ,
104+ " if pooling:\n " ,
105+ " x = layers.MaxPooling2D(2, padding=\" same\" )(x)\n " ,
106+ " residual = layers.Conv2D(filters, 1, strides=2)(residual)\n " ,
107+ " elif filters != residual.shape[-1]:\n " ,
108+ " residual = layers.Conv2D(filters, 1)(residual)\n " ,
109+ " x = layers.add([x, residual])\n " ,
110+ " return x\n " ,
111+ " \n " ,
112+ " x = residual_block(x, filters=32, pooling=True)\n " ,
113+ " x = residual_block(x, filters=64, pooling=True)\n " ,
114+ " x = residual_block(x, filters=128, pooling=False)\n " ,
115+ " \n " ,
116+ " x = layers.GlobalAveragePooling2D()(x)\n " ,
117+ " outputs = layers.Dense(1, activation=\" sigmoid\" )(x)\n " ,
118+ " model = keras.Model(inputs=inputs, outputs=outputs)"
119+ ]
120+ },
121+ {
122+ "cell_type" : " markdown" ,
123+ "metadata" : {
124+ "colab_type" : " text"
125+ },
126+ "source" : [
127+ " ### Batch normalization"
128+ ]
129+ },
130+ {
131+ "cell_type" : " markdown" ,
132+ "metadata" : {
133+ "colab_type" : " text"
134+ },
135+ "source" : [
136+ " ### Depthwise separable convolutions"
137+ ]
138+ },
139+ {
140+ "cell_type" : " markdown" ,
141+ "metadata" : {
142+ "colab_type" : " text"
143+ },
144+ "source" : [
145+ " ### Putting it together: a mini Xception-like model"
146+ ]
147+ },
148+ {
149+ "cell_type" : " code" ,
150+ "execution_count" : 0 ,
151+ "metadata" : {
152+ "colab_type" : " code"
153+ },
154+ "outputs" : [],
155+ "source" : [
156+ " import kagglehub\n " ,
157+ " \n " ,
158+ " kagglehub.login()"
159+ ]
160+ },
161+ {
162+ "cell_type" : " code" ,
163+ "execution_count" : 0 ,
164+ "metadata" : {
165+ "colab_type" : " code"
166+ },
167+ "outputs" : [],
168+ "source" : [
169+ " import zipfile\n " ,
170+ " \n " ,
171+ " download_path = kagglehub.competition_download(\" dogs-vs-cats\" )\n " ,
172+ " \n " ,
173+ " with zipfile.ZipFile(download_path + \" /train.zip\" , \" r\" ) as zip_ref:\n " ,
174+ " zip_ref.extractall(\" .\" )"
175+ ]
176+ },
177+ {
178+ "cell_type" : " code" ,
179+ "execution_count" : 0 ,
180+ "metadata" : {
181+ "colab_type" : " code"
182+ },
183+ "outputs" : [],
184+ "source" : [
185+ " import os, shutil, pathlib\n " ,
186+ " from keras.utils import image_dataset_from_directory\n " ,
187+ " \n " ,
188+ " original_dir = pathlib.Path(\" train\" )\n " ,
189+ " new_base_dir = pathlib.Path(\" dogs_vs_cats_small\" )\n " ,
190+ " \n " ,
191+ " def make_subset(subset_name, start_index, end_index):\n " ,
192+ " for category in (\" cat\" , \" dog\" ):\n " ,
193+ " dir = new_base_dir / subset_name / category\n " ,
194+ " os.makedirs(dir)\n " ,
195+ " fnames = [f\" {category}.{i}.jpg\" for i in range(start_index, end_index)]\n " ,
196+ " for fname in fnames:\n " ,
197+ " shutil.copyfile(src=original_dir / fname, dst=dir / fname)\n " ,
198+ " \n " ,
199+ " make_subset(\" train\" , start_index=0, end_index=1000)\n " ,
200+ " make_subset(\" validation\" , start_index=1000, end_index=1500)\n " ,
201+ " make_subset(\" test\" , start_index=1500, end_index=2500)\n " ,
202+ " \n " ,
203+ " batch_size = 64\n " ,
204+ " image_size = (180, 180)\n " ,
205+ " train_dataset = image_dataset_from_directory(\n " ,
206+ " new_base_dir / \" train\" ,\n " ,
207+ " image_size=image_size,\n " ,
208+ " batch_size=batch_size,\n " ,
209+ " )\n " ,
210+ " validation_dataset = image_dataset_from_directory(\n " ,
211+ " new_base_dir / \" validation\" ,\n " ,
212+ " image_size=image_size,\n " ,
213+ " batch_size=batch_size,\n " ,
214+ " )\n " ,
215+ " test_dataset = image_dataset_from_directory(\n " ,
216+ " new_base_dir / \" test\" ,\n " ,
217+ " image_size=image_size,\n " ,
218+ " batch_size=batch_size,\n " ,
219+ " )"
220+ ]
221+ },
222+ {
223+ "cell_type" : " code" ,
224+ "execution_count" : 0 ,
225+ "metadata" : {
226+ "colab_type" : " code"
227+ },
228+ "outputs" : [],
229+ "source" : [
230+ " import tensorflow as tf\n " ,
231+ " from keras import layers\n " ,
232+ " \n " ,
233+ " data_augmentation_layers = [\n " ,
234+ " layers.RandomFlip(\" horizontal\" ),\n " ,
235+ " layers.RandomRotation(0.1),\n " ,
236+ " layers.RandomZoom(0.2),\n " ,
237+ " ]\n " ,
238+ " \n " ,
239+ " def data_augmentation(images, targets):\n " ,
240+ " for layer in data_augmentation_layers:\n " ,
241+ " images = layer(images)\n " ,
242+ " return images, targets\n " ,
243+ " \n " ,
244+ " augmented_train_dataset = train_dataset.map(\n " ,
245+ " data_augmentation, num_parallel_calls=8\n " ,
246+ " )\n " ,
247+ " augmented_train_dataset = augmented_train_dataset.prefetch(tf.data.AUTOTUNE)"
248+ ]
249+ },
250+ {
251+ "cell_type" : " code" ,
252+ "execution_count" : 0 ,
253+ "metadata" : {
254+ "colab_type" : " code"
255+ },
256+ "outputs" : [],
257+ "source" : [
258+ " import keras\n " ,
259+ " \n " ,
260+ " inputs = keras.Input(shape=(180, 180, 3))\n " ,
261+ " x = layers.Rescaling(1.0 / 255)(inputs)\n " ,
262+ " x = layers.Conv2D(filters=32, kernel_size=5, use_bias=False)(x)\n " ,
263+ " \n " ,
264+ " for size in [32, 64, 128, 256, 512]:\n " ,
265+ " residual = x\n " ,
266+ " \n " ,
267+ " x = layers.BatchNormalization()(x)\n " ,
268+ " x = layers.Activation(\" relu\" )(x)\n " ,
269+ " x = layers.SeparableConv2D(size, 3, padding=\" same\" , use_bias=False)(x)\n " ,
270+ " \n " ,
271+ " x = layers.BatchNormalization()(x)\n " ,
272+ " x = layers.Activation(\" relu\" )(x)\n " ,
273+ " x = layers.SeparableConv2D(size, 3, padding=\" same\" , use_bias=False)(x)\n " ,
274+ " \n " ,
275+ " x = layers.MaxPooling2D(3, strides=2, padding=\" same\" )(x)\n " ,
276+ " \n " ,
277+ " residual = layers.Conv2D(\n " ,
278+ " size, 1, strides=2, padding=\" same\" , use_bias=False\n " ,
279+ " )(residual)\n " ,
280+ " x = layers.add([x, residual])\n " ,
281+ " \n " ,
282+ " x = layers.GlobalAveragePooling2D()(x)\n " ,
283+ " x = layers.Dropout(0.5)(x)\n " ,
284+ " outputs = layers.Dense(1, activation=\" sigmoid\" )(x)\n " ,
285+ " model = keras.Model(inputs=inputs, outputs=outputs)"
286+ ]
287+ },
288+ {
289+ "cell_type" : " code" ,
290+ "execution_count" : 0 ,
291+ "metadata" : {
292+ "colab_type" : " code"
293+ },
294+ "outputs" : [],
295+ "source" : [
296+ " model.compile(\n " ,
297+ " loss=\" binary_crossentropy\" ,\n " ,
298+ " optimizer=\" adam\" ,\n " ,
299+ " metrics=[\" accuracy\" ],\n " ,
300+ " )\n " ,
301+ " history = model.fit(\n " ,
302+ " augmented_train_dataset,\n " ,
303+ " epochs=100,\n " ,
304+ " validation_data=validation_dataset,\n " ,
305+ " )"
306+ ]
307+ },
308+ {
309+ "cell_type" : " markdown" ,
310+ "metadata" : {
311+ "colab_type" : " text"
312+ },
313+ "source" : [
314+ " ### Beyond convolution: Vision Transformers"
315+ ]
316+ },
317+ {
318+ "cell_type" : " markdown" ,
319+ "metadata" : {
320+ "colab_type" : " text"
321+ },
322+ "source" : [
323+ " ### Chapter summary"
324+ ]
325+ }
326+ ],
327+ "metadata" : {
328+ "accelerator" : " GPU" ,
329+ "colab" : {
330+ "collapsed_sections" : [],
331+ "name" : " chapter09_convnet-architecture-patterns" ,
332+ "private_outputs" : false ,
333+ "provenance" : [],
334+ "toc_visible" : true
335+ },
336+ "kernelspec" : {
337+ "display_name" : " Python 3" ,
338+ "language" : " python" ,
339+ "name" : " python3"
340+ },
341+ "language_info" : {
342+ "codemirror_mode" : {
343+ "name" : " ipython" ,
344+ "version" : 3
345+ },
346+ "file_extension" : " .py" ,
347+ "mimetype" : " text/x-python" ,
348+ "name" : " python" ,
349+ "nbconvert_exporter" : " python" ,
350+ "pygments_lexer" : " ipython3" ,
351+ "version" : " 3.10.0"
352+ }
353+ },
354+ "nbformat" : 4 ,
355+ "nbformat_minor" : 0
356+ }
0 commit comments