XCEPTION
https://arxiv.org/abs/1610.02357

entry = NetGraph[
<|
"conv_1" -> ConvolutionLayer[32, {3, 3}, "Stride" -> 2],
"relu_1" -> Ramp,
"conv_2" -> ConvolutionLayer[64, {3, 3}],
"relu_2" -> Ramp,
"resid_1" -> ConvolutionLayer[128, {1, 1}, "Stride" -> 2],
"sep_conv_1" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[128, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_3" -> Ramp,
"sep_conv_2" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[128, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"max_pool_1" ->
PoolingLayer[{3, 3}, "Stride" -> 2, "PaddingSize" -> 1],
"add_1" -> ThreadingLayer[Plus],
"resid_2" -> ConvolutionLayer[256, {1, 1}, "Stride" -> 2],
"relu_4" -> Ramp,
"sep_conv_3" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[256, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_5" -> Ramp,
"sep_conv_4" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[256, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"max_pool_2" ->
PoolingLayer[{3, 3}, "Stride" -> 2, "PaddingSize" -> 1],
"add_2" -> ThreadingLayer[Plus],
"resid_3" -> ConvolutionLayer[728, {1, 1}, "Stride" -> 2],
"relu_6" -> Ramp,
"sep_conv_5" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[728, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_7" -> Ramp,
"sep_conv_6" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[728, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"max_pool_3" ->
PoolingLayer[{3, 3}, "Stride" -> 2, "PaddingSize" -> 1],
"add_3" -> ThreadingLayer[Plus]
|>
,
{
NetPort["Input"] ->
"conv_1" ->
"relu_1" -> "conv_2" -> "relu_2" -> "resid_1" -> "add_1",
"relu_2" ->
"sep_conv_1" ->
"relu_3" -> "sep_conv_2" -> "max_pool_1" -> "add_1",
"add_1" -> "resid_2" -> "add_2",
"add_1" ->
"relu_4" ->
"sep_conv_3" ->
"relu_5" -> "sep_conv_4" -> "max_pool_2" -> "add_2",
"add_2" -> "resid_3" -> "add_3",
"add_2" ->
"relu_6" ->
"sep_conv_5" ->
"relu_7" -> "sep_conv_6" -> "max_pool_3" -> "add_3"
}
,
"Input" -> NetEncoder[{"Image", {299, 299}, ColorSpace -> "RGB"}]
]

middle = NetGraph[
<|
"relu_1" -> Ramp,
"sep_conv_1" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[728, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_2" -> Ramp,
"sep_conv_2" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[728, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_3" -> Ramp,
"sep_conv_3" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[728, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"add" -> ThreadingLayer[Plus]
|>
,
{
NetPort["Input"] ->
"relu_1" ->
"sep_conv_1" ->
"relu_2" -> "sep_conv_2" -> "relu_3" -> "sep_conv_3" -> "add",
NetPort["Input"] -> "add"
}
,
"Input" -> {728, 19, 19}
]

exit = NetGraph[
<|
"resid" -> ConvolutionLayer[1024, {1, 1}, "Stride" -> 2],
"relu_1" -> Ramp,
"sep_conv_1" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[728, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_2" -> Ramp,
"sep_conv_2" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[1024, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"max_pool" ->
PoolingLayer[{3, 3}, "Stride" -> 2, "PaddingSize" -> 1],
"add" -> ThreadingLayer[Plus],
"sep_conv_3" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[1536, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_3" -> Ramp,
"sep_conv_4" ->
NetGraph[
{
ReplicateLayer[1],
TransposeLayer[],
NetMapOperator[ConvolutionLayer[1, {3, 3}, "PaddingSize" -> 1]],
FlattenLayer[1],
ConvolutionLayer[2048, {1, 1}]
},
{1 -> 2 -> 3 -> 4 -> 5}
],
"relu_4" -> Ramp,
"global_pool" -> AggregationLayer[Mean],
"softmax" -> {2048, SoftmaxLayer[]}
|>
,
{
NetPort["Input"] -> "resid" -> "add",
NetPort["Input"] ->
"relu_1" ->
"sep_conv_1" -> "relu_2" -> "sep_conv_2" -> "max_pool" -> "add",
"add" ->
"sep_conv_3" ->
"relu_3" -> "sep_conv_4" -> "relu_4" -> "global_pool" -> "softmax"
}
,
"Input" -> {728, 19, 19},
"Output" -> NetDecoder[{"Class", Range[2048]}]
]

xception = NetChain[
<|
"entry_flow" -> entry,
"middle_flow" -> NetNestOperator[middle, 8],
"exit_flow" -> exit
|>
]
