1
1
2
2
# Xception
3
3
4
- xception.py (procedural - academic)
5
- xception_c.py (OOP - composable)
4
+ [ xception.py] ( xception.py ) - academic (idiomatic)< br />
5
+ [ xception_c.py] ( xception_c.py ) - production ( composable)< br />
6
6
7
7
[ Paper] ( https://arxiv.org/pdf/1610.02357.pdf )
8
8
9
9
## Macro-Architecture
10
10
11
11
<img src =' macro.jpg ' >
12
12
13
- ``` python
14
- # Create the input vector
15
- inputs = Input(shape = (299 , 299 , 3 ))
16
-
17
- # Create entry section
18
- x = entryFlow(inputs)
19
-
20
- # Create the middle section
21
- x = middleFlow(x)
22
-
23
- # Create the exit section for 1000 classes
24
- outputs = exitFlow(x, 1000 )
25
-
26
- # Instantiate the model
27
- model = Model(inputs, outputs)
28
- ```
29
-
30
13
## Micro-Architecture - Entry Flow
31
14
32
15
<img src =' micro-entry.jpg ' >
33
16
34
- ``` python
35
- def entryFlow (inputs ):
36
- """ Create the entry flow section
37
- inputs : input tensor to neural network
38
- """
39
-
40
- def stem (inputs ):
41
- """ Create the stem entry into the neural network
42
- inputs : input tensor to neural network
43
- """
44
- # Strided convolution - dimensionality reduction
45
- # Reduce feature maps by 75%
46
- x = Conv2D(32 , (3 , 3 ), strides = (2 , 2 ))(inputs)
47
- x = BatchNormalization()(x)
48
- x = ReLU()(x)
49
-
50
- # Convolution - dimensionality expansion
51
- # Double the number of filters
52
- x = Conv2D(64 , (3 , 3 ), strides = (1 , 1 ))(x)
53
- x = BatchNormalization()(x)
54
- x = ReLU()(x)
55
- return x
56
-
57
- # Create the stem to the neural network
58
- x = stem(inputs)
59
-
60
- # Create three residual blocks using linear projection
61
- for n_filters in [128 , 256 , 728 ]:
62
- x = projection_block(x, n_filters)
63
-
64
- return x
65
- ```
66
-
67
17
### Entry Flow Stem Group
68
18
69
19
<img src =" stem.jpg " >
@@ -72,151 +22,18 @@ def entryFlow(inputs):
72
22
73
23
<img src =" block-projection.jpg " >
74
24
75
- ``` python
76
- def projection_block (x , n_filters ):
77
- """ Create a residual block using Depthwise Separable Convolutions with Projection shortcut
78
- x : input into residual block
79
- n_filters: number of filters
80
- """
81
- # Remember the input
82
- shortcut = x
83
-
84
- # Strided convolution to double number of filters in identity link to
85
- # match output of residual block for the add operation (projection shortcut)
86
- shortcut = Conv2D(n_filters, (1 , 1 ), strides = (2 , 2 ), padding = ' same' )(shortcut)
87
- shortcut = BatchNormalization()(shortcut)
88
-
89
- # First Depthwise Separable Convolution
90
- x = SeparableConv2D(n_filters, (3 , 3 ), padding = ' same' )(x)
91
- x = BatchNormalization()(x)
92
- x = ReLU()(x)
93
-
94
- # Second depthwise Separable Convolution
95
- x = SeparableConv2D(n_filters, (3 , 3 ), padding = ' same' )(x)
96
- x = BatchNormalization()(x)
97
- x = ReLU()(x)
98
-
99
- # Create pooled feature maps, reduce size by 75%
100
- x = MaxPooling2D((3 , 3 ), strides = (2 , 2 ), padding = ' same' )(x)
101
-
102
- # Add the projection shortcut to the output of the block
103
- x = Add()([x, shortcut])
104
-
105
- return x
106
- ```
107
-
108
25
## Micro-Architecture - Middle Flow
109
26
110
27
<img src =" micro-middle.jpg " >
111
28
112
- ``` python
113
- def middleFlow (x ):
114
- """ Create the middle flow section
115
- x : input tensor into section
116
- """
117
- # Create 8 residual blocks
118
- for _ in range (8 ):
119
- x = residual_block(x, 728 )
120
- return x
121
- ```
122
-
123
29
### Middle Flow Block
124
30
125
31
<img src =" block-middle.jpg " >
126
32
127
- ``` python
128
- def residual_block (x , n_filters ):
129
- """ Create a residual block using Depthwise Separable Convolutions
130
- x : input into residual block
131
- n_filters: number of filters
132
- """
133
- # Remember the input
134
- shortcut = x
135
-
136
- # First Depthwise Separable Convolution
137
- x = SeparableConv2D(n_filters, (3 , 3 ), padding = ' same' )(x)
138
- x = BatchNormalization()(x)
139
- x = ReLU()(x)
140
-
141
- # Second depthwise Separable Convolution
142
- x = SeparableConv2D(n_filters, (3 , 3 ), padding = ' same' )(x)
143
- x = BatchNormalization()(x)
144
- x = ReLU()(x)
145
-
146
- # Third depthwise Separable Convolution
147
- x = SeparableConv2D(n_filters, (3 , 3 ), padding = ' same' )(x)
148
- x = BatchNormalization()(x)
149
- x = ReLU()(x)
150
-
151
- # Add the identity link to the output of the block
152
- x = Add()([x, shortcut])
153
- return x
154
- ```
155
-
156
33
## Micro-Architecture - Exit Flow
157
34
158
35
<img src =" micro-exit.jpg " >
159
36
160
- ``` python
161
- def exitFlow (x , n_classes ):
162
- """ Create the exit flow section
163
- x : input to the exit flow section
164
- n_classes : number of output classes
165
- """
166
- def classifier (x , n_classes ):
167
- """ The output classifier
168
- x : input to the classifier
169
- n_classes : number of output classes
170
- """
171
- # Global Average Pooling will flatten the 10x10 feature maps into 1D
172
- # feature maps
173
- x = GlobalAveragePooling2D()(x)
174
-
175
- # Fully connected output layer (classification)
176
- x = Dense(n_classes, activation = ' softmax' )(x)
177
- return x
178
-
179
- # Remember the input
180
- shortcut = x
181
-
182
- # Strided convolution to double number of filters in identity link to
183
- # match output of residual block for the add operation (projection shortcut)
184
- shortcut = Conv2D(1024 , (1 , 1 ), strides = (2 , 2 ), padding = ' same' )(shortcut)
185
- shortcut = BatchNormalization()(shortcut)
186
-
187
- # First Depthwise Separable Convolution
188
- # Dimensionality reduction - reduce number of filters
189
- x = SeparableConv2D(728 , (3 , 3 ), padding = ' same' )(x)
190
- x = BatchNormalization()(x)
191
-
192
- # Second Depthwise Separable Convolution
193
- # Dimensionality restoration
194
- x = SeparableConv2D(1024 , (3 , 3 ), padding = ' same' )(x)
195
- x = BatchNormalization()(x)
196
- x = ReLU()(x)
197
-
198
- # Create pooled feature maps, reduce size by 75%
199
- x = MaxPooling2D((3 , 3 ), strides = (2 , 2 ), padding = ' same' )(x)
200
-
201
- # Add the projection shortcut to the output of the pooling layer
202
- x = Add()([x, shortcut])
203
-
204
- # Third Depthwise Separable Convolution
205
- x = SeparableConv2D(1556 , (3 , 3 ), padding = ' same' )(x)
206
- x = BatchNormalization()(x)
207
- x = ReLU()(x)
208
-
209
- # Fourth Depthwise Separable Convolution
210
- x = SeparableConv2D(2048 , (3 , 3 ), padding = ' same' )(x)
211
- x = BatchNormalization()(x)
212
- x = ReLU()(x)
213
-
214
- # Create classifier section
215
- x = classifier(x, n_classes)
216
-
217
- return x
218
- ```
219
-
220
37
### Exit Flow Residual Block
221
38
222
39
<img src =" block-exit-residual.jpg " >
@@ -231,7 +48,7 @@ def exitFlow(x, n_classes):
231
48
232
49
## Composable
233
50
234
- * Example Instantiate a Xception model*
51
+ * Example: Instantiate a stock Xception model*
235
52
236
53
``` python
237
54
from xception_c import Xception
@@ -246,98 +63,16 @@ xception = Xception(input_shape=(128, 128, 3), n_classes=50)
246
63
model = xception.model
247
64
```
248
65
249
- * Example: Composable Group/Block*
250
-
251
- ``` python
252
- # Make a mini-xception for CIFAR-10
253
- from tensorflow.keras import Input, Model
254
- from tensorflow.keras.layers import Conv2D, Flatten, Dense
255
-
256
- # Stem
257
- inputs = Input((32 , 32 , 3 ))
258
- x = Conv2D(32 , (3 , 3 ), strides = 1 , padding = ' same' , activation = ' relu' )(inputs)
259
-
260
- # Learner
261
- # Xception entry:
262
- # Xception middle:
263
- x = Xception.entry(x, [{ ' n_filters' : 16 }, { ' n_filters' : 32 }, { ' n_filters' : 64 }])
264
- x = Xception.middle(x, [{ ' n_filters' : 64 }, { ' n_filters' : 64 }, { ' n_filters' : 64 }])
265
-
266
-
267
- # Classifier
268
- # Xception exit:
269
- outputs = Xception.exit(x, n_classes = 10 )
270
- model = Model(inputs, outputs)
271
- model.compile(loss = ' sparse_categorical_crossentropy' , optimizer = ' adam' , metrics = [' acc' ])
272
- model.summary()
273
- ```
274
-
275
- ``` python
276
- # REMOVED for Brevity
277
-
278
- batch_normalization_117 (BatchN (None , 2 , 2 , 1024 ) 4096 separable_conv2d_85[0 ][0 ]
279
- __________________________________________________________________________________________________
280
- re_lu_94 (ReLU) (None , 2 , 2 , 1024 ) 0 batch_normalization_117[0 ][0 ]
281
- __________________________________________________________________________________________________
282
- conv2d_32 (Conv2D) (None , 1 , 1 , 1024 ) 66560 add_32[0 ][0 ]
283
- __________________________________________________________________________________________________
284
- max_pooling2d_19 (MaxPooling2D) (None , 1 , 1 , 1024 ) 0 re_lu_94[0 ][0 ]
285
- __________________________________________________________________________________________________
286
- batch_normalization_115 (BatchN (None , 1 , 1 , 1024 ) 4096 conv2d_32[0 ][0 ]
287
- __________________________________________________________________________________________________
288
- add_33 (Add) (None , 1 , 1 , 1024 ) 0 max_pooling2d_19[0 ][0 ]
289
- batch_normalization_115[0 ][0 ]
290
- __________________________________________________________________________________________________
291
- separable_conv2d_86 (SeparableC (None , 1 , 1 , 1556 ) 1604116 add_33[0 ][0 ]
292
- __________________________________________________________________________________________________
293
- batch_normalization_118 (BatchN (None , 1 , 1 , 1556 ) 6224 separable_conv2d_86[0 ][0 ]
294
- __________________________________________________________________________________________________
295
- re_lu_95 (ReLU) (None , 1 , 1 , 1556 ) 0 batch_normalization_118[0 ][0 ]
296
- __________________________________________________________________________________________________
297
- separable_conv2d_87 (SeparableC (None , 1 , 1 , 2048 ) 3202740 re_lu_95[0 ][0 ]
298
- __________________________________________________________________________________________________
299
- batch_normalization_119 (BatchN (None , 1 , 1 , 2048 ) 8192 separable_conv2d_87[0 ][0 ]
300
- __________________________________________________________________________________________________
301
- re_lu_96 (ReLU) (None , 1 , 1 , 2048 ) 0 batch_normalization_119[0 ][0 ]
302
- __________________________________________________________________________________________________
303
- global_average_pooling2d_2 (Glo (None , 2048 ) 0 re_lu_96[0 ][0 ]
304
- __________________________________________________________________________________________________
305
- dense_2 (Dense) (None , 10 ) 20490 global_average_pooling2d_2[0 ][0 ]
306
- ==================================================================================================
307
- Total params: 5 ,801 ,314
308
- Trainable params: 5 ,786 ,538
309
- Non- trainable params: 14 ,776
310
- ```
311
-
312
- from tensorflow.keras.datasets import cifar10
313
- import numpy as np
314
-
315
- (x_train, y_train), (x_test, y_test) = cifar10.load_data()
316
- x_train = (x_train / 255.0 ).astype(np.float342)
317
- x_test = (x_test / 255.0 ).astype(np.float342)
318
- model.fit(x_train, y_train, epochs = 10 , batch_size = 32 , validation_split = 0.1 , verbose = 1 )
319
- ```python
66
+ * Example: Compose and Train an Xception model*
320
67
321
68
``` python
322
- Epoch 1 / 10
323
- 45000 / 45000 [============================== ] - 467s 10ms / sample - loss: 1.5985 - acc: 0.4127 - val_loss: 1.8141 - val_acc: 0.3506
324
- Epoch 2 / 10
325
- 45000 / 45000 [============================== ] - 461s 10ms / sample - loss: 1.3191 - acc: 0.5251 - val_loss: 1.3030 - val_acc: 0.5358
326
- Epoch 3 / 10
327
- 45000 / 45000 [============================== ] - 463s 10ms / sample - loss: 1.1777 - acc: 0.5784 - val_loss: 1.3208 - val_acc: 0.5198
328
- Epoch 4 / 10
329
- 45000 / 45000 [============================== ] - 461s 10ms / sample - loss: 1.0758 - acc: 0.6188 - val_loss: 1.2506 - val_acc: 0.5522
330
- Epoch 5 / 10
331
- 45000 / 45000 [============================== ] - 478s 11ms / sample - loss: 0.9912 - acc: 0.6474 - val_loss: 1.3534 - val_acc: 0.5602
332
- Epoch 6 / 10
333
- 45000 / 45000 [============================== ] - 469s 10ms / sample - loss: 0.9333 - acc: 0.6712 - val_loss: 0.9447 - val_acc: 0.6672
334
- Epoch 7 / 10
335
- 45000 / 45000 [============================== ] - 468s 10ms / sample - loss: 0.8793 - acc: 0.6921 - val_loss: 0.9720 - val_acc: 0.6538
336
- Epoch 8 / 10
337
- 45000 / 45000 [============================== ] - 468s 10ms / sample - loss: 0.8312 - acc: 0.7095 - val_loss: 0.9185 - val_acc: 0.6756
338
- Epoch 9 / 10
339
- 45000 / 45000 [============================== ] - 463s 10ms / sample - loss: 0.7845 - acc: 0.7250 - val_loss: 0.8992 - val_acc: 0.6912
340
- Epoch 10 / 10
341
- 45000 / 45000 [============================== ] - 463s 10ms / sample - loss: 0.7501 - acc: 0.7366 - val_loss: 1.0348 - val_acc: 0.6428
342
-
69
+ ''' Example for constructing/training a Xception model on CIFAR-10
70
+ '''
71
+ # Example of constructing a mini-Xception
72
+ entry = [{ ' n_filters' : 128 }, { ' n_filters' : 728 }]
73
+ middle = [{ ' n_filters' : 728 }, { ' n_filters' : 728 }, { ' n_filters' : 728 }]
74
+
75
+ xception = Xception(entry = entry, middle = middle, input_shape = (32 , 32 , 3 ), n_classes = 10 )
76
+ xception.model.summary()
77
+ xception.cifar10()
343
78
```
0 commit comments