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-nightly --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-best-practices" ,
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