├── .idea
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
└── vcs.xml
├── Architectures
├── Inception ResNet-v1.png
├── Inception ResNet-v2.png
└── Inception-v4.png
├── LICENSE
├── README.md
├── inception_resnet_v1.py
├── inception_resnet_v2.py
├── inception_v4.py
└── weights
└── ADD_WEIGHT_FILES_HERE.txt
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Architectures/Inception ResNet-v1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titu1994/Inception-v4/52417ac0e878d9e67031fda1323a73760ec08049/Architectures/Inception ResNet-v1.png
--------------------------------------------------------------------------------
/Architectures/Inception ResNet-v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titu1994/Inception-v4/52417ac0e878d9e67031fda1323a73760ec08049/Architectures/Inception ResNet-v2.png
--------------------------------------------------------------------------------
/Architectures/Inception-v4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titu1994/Inception-v4/52417ac0e878d9e67031fda1323a73760ec08049/Architectures/Inception-v4.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Somshubra Majumdar
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Inception v4 in Keras
2 | Implementations of the Inception-v4, Inception - Resnet-v1 and v2 Architectures in Keras using the Functional API. The paper on these architectures is available at "Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning".
3 |
4 | The models are plotted and shown in the architecture sub folder. Due to lack of suitable training data (ILSVR 2015 dataset) and limited GPU processing power, the weights are not provided.
5 |
6 | ## Inception v4
7 | The python script 'inception_v4.py' contains the methods necessary to create the Inception v4 network.
8 |
9 | Usage:
10 | ```
11 | from inception_v4 import create_inception_v4
12 |
13 | model = create_inception_v4()
14 |
15 | ```
16 |
17 | ## Inception ResNet v1
18 | The python script 'inception_resnet_v1.py' contains the methods necessary to create the Inception ResNet v1 network.
19 | It is to be noted that scaling of the residuals is turned OFF by default. This can be rectified by supplying 'scale=True' in the create method.
20 |
21 | Usage:
22 | ```
23 | from inception_resnet_v1 import create_inception_resnet_v1
24 |
25 | model = create_inception_resnet_v1()
26 |
27 | ```
28 |
29 | ## Inception ResNet v2
30 | The python script 'inception_resnet_v2.py' contains the methods necessary to create the Inception ResNet v2 network.
31 | It is to be noted that scaling of the residuals is turned ON by default.
32 |
33 | There are a few differences in the v2 network from the original paper:
34 | [1] In the B blocks: 'ir_conv' nb of filters is given as 1154 in the paper, however input size is 1152.
35 | This causes inconsistencies in the merge-sum mode, therefore the 'ir_conv' filter size
36 | is reduced to 1152 to match input size.
37 |
38 | [2] In the C blocks: 'ir_conv' nb of filter is given as 2048 in the paper, however input size is 2144.
39 | This causes inconsistencies in the merge-sum mode, therefore the 'ir_conv' filter size
40 | is increased to 2144 to match input size.
41 |
42 | Usage:
43 | ```
44 | from inception_resnet_v2 import create_inception_resnet_v2
45 |
46 | model = create_inception_resnet_v2(scale=True)
47 | ```
48 |
49 | # Architectures
50 | ## Inception v4
51 |
52 |
53 |
54 | ## Inception ResNet v1
55 |
56 |
57 |
58 | ## Inception ResNet v2
59 |
60 |
61 |
--------------------------------------------------------------------------------
/inception_resnet_v1.py:
--------------------------------------------------------------------------------
1 | from keras.layers import Input, merge, Dropout, Dense, Lambda, Flatten, Activation
2 | from keras.layers.normalization import BatchNormalization
3 | from keras.layers.convolutional import MaxPooling2D, Convolution2D, AveragePooling2D
4 | from keras.models import Model
5 |
6 | from keras import backend as K
7 |
8 | import warnings
9 | warnings.filterwarnings('ignore')
10 |
11 | """
12 | Implementation of Inception-Residual Network v1 [Inception Network v4 Paper](http://arxiv.org/pdf/1602.07261v1.pdf) in Keras.
13 |
14 | Some additional details:
15 | [1] Each of the A, B and C blocks have a 'scale_residual' parameter.
16 | The scale residual parameter is according to the paper. It is however turned OFF by default.
17 |
18 | Simply setting 'scale=True' in the create_inception_resnet_v1() method will add scaling.
19 | """
20 |
21 |
22 | def inception_resnet_stem(input):
23 | if K.image_dim_ordering() == "th":
24 | channel_axis = 1
25 | else:
26 | channel_axis = -1
27 |
28 | # Input Shape is 299 x 299 x 3 (tf) or 3 x 299 x 299 (th)
29 | c = Convolution2D(32, 3, 3, activation='relu', subsample=(2, 2))(input)
30 | c = Convolution2D(32, 3, 3, activation='relu', )(c)
31 | c = Convolution2D(64, 3, 3, activation='relu', )(c)
32 | c = MaxPooling2D((3, 3), strides=(2, 2))(c)
33 | c = Convolution2D(80, 1, 1, activation='relu', border_mode='same')(c)
34 | c = Convolution2D(192, 3, 3, activation='relu')(c)
35 | c = Convolution2D(256, 3, 3, activation='relu', subsample=(2,2), border_mode='same')(c)
36 | b = BatchNormalization(axis=channel_axis)(c)
37 | b = Activation('relu')(b)
38 | return b
39 |
40 | def inception_resnet_A(input, scale_residual=True):
41 | if K.image_dim_ordering() == "th":
42 | channel_axis = 1
43 | else:
44 | channel_axis = -1
45 |
46 | # Input is relu activation
47 | init = input
48 |
49 | ir1 = Convolution2D(32, 1, 1, activation='relu', border_mode='same')(input)
50 |
51 | ir2 = Convolution2D(32, 1, 1, activation='relu', border_mode='same')(input)
52 | ir2 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(ir2)
53 |
54 | ir3 = Convolution2D(32, 1, 1, activation='relu', border_mode='same')(input)
55 | ir3 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(ir3)
56 | ir3 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(ir3)
57 |
58 | ir_merge = merge([ir1, ir2, ir3], concat_axis=channel_axis, mode='concat')
59 |
60 | ir_conv = Convolution2D(256, 1, 1, activation='linear', border_mode='same')(ir_merge)
61 | if scale_residual: ir_conv = Lambda(lambda x: x * 0.1)(ir_conv)
62 |
63 | out = merge([init, ir_conv], mode='sum')
64 | out = BatchNormalization(axis=channel_axis)(out)
65 | out = Activation("relu")(out)
66 | return out
67 |
68 | def inception_resnet_B(input, scale_residual=True):
69 | if K.image_dim_ordering() == "th":
70 | channel_axis = 1
71 | else:
72 | channel_axis = -1
73 |
74 | # Input is relu activation
75 | init = input
76 |
77 | ir1 = Convolution2D(128, 1, 1, activation='relu', border_mode='same')(input)
78 |
79 | ir2 = Convolution2D(128, 1, 1, activation='relu', border_mode='same')(input)
80 | ir2 = Convolution2D(128, 1, 7, activation='relu', border_mode='same')(ir2)
81 | ir2 = Convolution2D(128, 7, 1, activation='relu', border_mode='same')(ir2)
82 |
83 | ir_merge = merge([ir1, ir2], mode='concat', concat_axis=channel_axis)
84 |
85 | ir_conv = Convolution2D(896, 1, 1, activation='linear', border_mode='same')(ir_merge)
86 | if scale_residual: ir_conv = Lambda(lambda x: x * 0.1)(ir_conv)
87 |
88 | out = merge([init, ir_conv], mode='sum')
89 | out = BatchNormalization(axis=channel_axis)(out)
90 | out = Activation("relu")(out)
91 | return out
92 |
93 | def inception_resnet_C(input, scale_residual=True):
94 | if K.image_dim_ordering() == "th":
95 | channel_axis = 1
96 | else:
97 | channel_axis = -1
98 |
99 | # Input is relu activation
100 | init = input
101 |
102 | ir1 = Convolution2D(128, 1, 1, activation='relu', border_mode='same')(input)
103 |
104 | ir2 = Convolution2D(192, 1, 1, activation='relu', border_mode='same')(input)
105 | ir2 = Convolution2D(192, 1, 3, activation='relu', border_mode='same')(ir2)
106 | ir2 = Convolution2D(192, 3, 1, activation='relu', border_mode='same')(ir2)
107 |
108 | ir_merge = merge([ir1, ir2], mode='concat', concat_axis=channel_axis)
109 |
110 | ir_conv = Convolution2D(1792, 1, 1, activation='linear', border_mode='same')(ir_merge)
111 | if scale_residual: ir_conv = Lambda(lambda x: x * 0.1)(ir_conv)
112 |
113 | out = merge([init, ir_conv], mode='sum')
114 | out = BatchNormalization(axis=channel_axis)(out)
115 | out = Activation("relu")(out)
116 | return out
117 |
118 | def reduction_A(input, k=192, l=224, m=256, n=384):
119 | if K.image_dim_ordering() == "th":
120 | channel_axis = 1
121 | else:
122 | channel_axis = -1
123 |
124 | r1 = MaxPooling2D((3,3), strides=(2,2))(input)
125 |
126 | r2 = Convolution2D(n, 3, 3, activation='relu', subsample=(2,2))(input)
127 |
128 | r3 = Convolution2D(k, 1, 1, activation='relu', border_mode='same')(input)
129 | r3 = Convolution2D(l, 3, 3, activation='relu', border_mode='same')(r3)
130 | r3 = Convolution2D(m, 3, 3, activation='relu', subsample=(2,2))(r3)
131 |
132 | m = merge([r1, r2, r3], mode='concat', concat_axis=channel_axis)
133 | m = BatchNormalization(axis=channel_axis)(m)
134 | m = Activation('relu')(m)
135 | return m
136 |
137 |
138 | def reduction_resnet_B(input):
139 | if K.image_dim_ordering() == "th":
140 | channel_axis = 1
141 | else:
142 | channel_axis = -1
143 |
144 | r1 = MaxPooling2D((3,3), strides=(2,2), border_mode='valid')(input)
145 |
146 | r2 = Convolution2D(256, 1, 1, activation='relu', border_mode='same')(input)
147 | r2 = Convolution2D(384, 3, 3, activation='relu', subsample=(2,2))(r2)
148 |
149 | r3 = Convolution2D(256, 1, 1, activation='relu', border_mode='same')(input)
150 | r3 = Convolution2D(256, 3, 3, activation='relu', subsample=(2, 2))(r3)
151 |
152 | r4 = Convolution2D(256, 1, 1, activation='relu', border_mode='same')(input)
153 | r4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(r4)
154 | r4 = Convolution2D(256, 3, 3, activation='relu', subsample=(2, 2))(r4)
155 |
156 | m = merge([r1, r2, r3, r4], concat_axis=channel_axis, mode='concat')
157 | m = BatchNormalization(axis=channel_axis)(m)
158 | m = Activation('relu')(m)
159 | return m
160 |
161 | def create_inception_resnet_v1(nb_classes=1001, scale=True):
162 | '''
163 | Creates a inception resnet v1 network
164 |
165 | :param nb_classes: number of classes.txt
166 | :param scale: flag to add scaling of activations
167 | :return: Keras Model with 1 input (299x299x3) input shape and 2 outputs (final_output, auxiliary_output)
168 | '''
169 |
170 | if K.image_dim_ordering() == 'th':
171 | init = Input((3, 299, 299))
172 | else:
173 | init = Input((299, 299, 3))
174 |
175 | # Input Shape is 299 x 299 x 3 (tf) or 3 x 299 x 299 (th)
176 | x = inception_resnet_stem(init)
177 |
178 | # 5 x Inception Resnet A
179 | for i in range(5):
180 | x = inception_resnet_A(x, scale_residual=scale)
181 |
182 | # Reduction A - From Inception v4
183 | x = reduction_A(x, k=192, l=192, m=256, n=384)
184 |
185 | # 10 x Inception Resnet B
186 | for i in range(10):
187 | x = inception_resnet_B(x, scale_residual=scale)
188 |
189 | # Auxiliary tower
190 | aux_out = AveragePooling2D((5, 5), strides=(3, 3))(x)
191 | aux_out = Convolution2D(128, 1, 1, border_mode='same', activation='relu')(aux_out)
192 | aux_out = Convolution2D(768, 5, 5, activation='relu')(aux_out)
193 | aux_out = Flatten()(aux_out)
194 | aux_out = Dense(nb_classes, activation='softmax')(aux_out)
195 |
196 | # Reduction Resnet B
197 | x = reduction_resnet_B(x)
198 |
199 | # 5 x Inception Resnet C
200 | for i in range(5):
201 | x = inception_resnet_C(x, scale_residual=scale)
202 |
203 | # Average Pooling
204 | x = AveragePooling2D((8,8))(x)
205 |
206 | # Dropout
207 | x = Dropout(0.8)(x)
208 | x = Flatten()(x)
209 |
210 | # Output
211 | out = Dense(output_dim=nb_classes, activation='softmax')(x)
212 |
213 | model = Model(init, output=[out, aux_out], name='Inception-Resnet-v1')
214 |
215 | return model
216 |
217 | if __name__ == "__main__":
218 | from keras.utils.visualize_util import plot
219 |
220 | inception_resnet_v1 = create_inception_resnet_v1()
221 |
222 | plot(inception_resnet_v1, to_file="Inception ResNet-v1.png", show_shapes=True)
--------------------------------------------------------------------------------
/inception_resnet_v2.py:
--------------------------------------------------------------------------------
1 | from keras.layers import Input, merge, Dropout, Dense, Lambda, Flatten, Activation
2 | from keras.layers.convolutional import MaxPooling2D, Convolution2D, AveragePooling2D
3 | from keras.layers.normalization import BatchNormalization
4 | from keras.models import Model
5 |
6 | from keras import backend as K
7 |
8 | import warnings
9 | warnings.filterwarnings('ignore')
10 |
11 | """
12 | Implementation of Inception-Residual Network v1 [Inception Network v4 Paper](http://arxiv.org/pdf/1602.07261v1.pdf) in Keras.
13 |
14 | Some additional details:
15 | [1] Each of the A, B and C blocks have a 'scale_residual' parameter.
16 | The scale residual parameter is according to the paper. It is however turned OFF by default.
17 |
18 | Simply setting 'scale=True' in the create_inception_resnet_v2() method will add scaling.
19 |
20 | [2] There were minor inconsistencies with filter size in both B and C blocks.
21 |
22 | In the B blocks: 'ir_conv' nb of filters is given as 1154, however input size is 1152.
23 | This causes inconsistencies in the merge-add mode, therefore the 'ir_conv' filter size
24 | is reduced to 1152 to match input size.
25 |
26 | In the C blocks: 'ir_conv' nb of filter is given as 2048, however input size is 2144.
27 | This causes inconsistencies in the merge-add mode, therefore the 'ir_conv' filter size
28 | is increased to 2144 to match input size.
29 |
30 | Currently trying to find a proper solution with original nb of filters.
31 |
32 | [3] In the stem function, the last Convolutional2D layer has 384 filters instead of the original 256.
33 | This is to correctly match the nb of filters in 'ir_conv' of the next A blocks.
34 | """
35 |
36 | def inception_resnet_stem(input):
37 | if K.image_dim_ordering() == "th":
38 | channel_axis = 1
39 | else:
40 | channel_axis = -1
41 |
42 | # Input Shape is 299 x 299 x 3 (th) or 3 x 299 x 299 (th)
43 | c = Convolution2D(32, 3, 3, activation='relu', subsample=(2, 2))(input)
44 | c = Convolution2D(32, 3, 3, activation='relu', )(c)
45 | c = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(c)
46 |
47 | c1 = MaxPooling2D((3, 3), strides=(2, 2))(c)
48 | c2 = Convolution2D(96, 3, 3, activation='relu', subsample=(2, 2))(c)
49 |
50 | m = merge([c1, c2], mode='concat', concat_axis=channel_axis)
51 |
52 | c1 = Convolution2D(64, 1, 1, activation='relu', border_mode='same')(m)
53 | c1 = Convolution2D(96, 3, 3, activation='relu', )(c1)
54 |
55 | c2 = Convolution2D(64, 1, 1, activation='relu', border_mode='same')(m)
56 | c2 = Convolution2D(64, 7, 1, activation='relu', border_mode='same')(c2)
57 | c2 = Convolution2D(64, 1, 7, activation='relu', border_mode='same')(c2)
58 | c2 = Convolution2D(96, 3, 3, activation='relu', border_mode='valid')(c2)
59 |
60 | m2 = merge([c1, c2], mode='concat', concat_axis=channel_axis)
61 |
62 | p1 = MaxPooling2D((3, 3), strides=(2, 2), )(m2)
63 | p2 = Convolution2D(192, 3, 3, activation='relu', subsample=(2, 2))(m2)
64 |
65 | m3 = merge([p1, p2], mode='concat', concat_axis=channel_axis)
66 | m3 = BatchNormalization(axis=channel_axis)(m3)
67 | m3 = Activation('relu')(m3)
68 | return m3
69 |
70 | def inception_resnet_v2_A(input, scale_residual=True):
71 | if K.image_dim_ordering() == "th":
72 | channel_axis = 1
73 | else:
74 | channel_axis = -1
75 |
76 | # Input is relu activation
77 | init = input
78 |
79 | ir1 = Convolution2D(32, 1, 1, activation='relu', border_mode='same')(input)
80 |
81 | ir2 = Convolution2D(32, 1, 1, activation='relu', border_mode='same')(input)
82 | ir2 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(ir2)
83 |
84 | ir3 = Convolution2D(32, 1, 1, activation='relu', border_mode='same')(input)
85 | ir3 = Convolution2D(48, 3, 3, activation='relu', border_mode='same')(ir3)
86 | ir3 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(ir3)
87 |
88 | ir_merge = merge([ir1, ir2, ir3], concat_axis=channel_axis, mode='concat')
89 |
90 | ir_conv = Convolution2D(384, 1, 1, activation='linear', border_mode='same')(ir_merge)
91 | if scale_residual: ir_conv = Lambda(lambda x: x * 0.1)(ir_conv)
92 |
93 | out = merge([init, ir_conv], mode='sum')
94 | out = BatchNormalization(axis=channel_axis)(out)
95 | out = Activation("relu")(out)
96 | return out
97 |
98 | def inception_resnet_v2_B(input, scale_residual=True):
99 | if K.image_dim_ordering() == "th":
100 | channel_axis = 1
101 | else:
102 | channel_axis = -1
103 |
104 | # Input is relu activation
105 | init = input
106 |
107 | ir1 = Convolution2D(192, 1, 1, activation='relu', border_mode='same')(input)
108 |
109 | ir2 = Convolution2D(128, 1, 1, activation='relu', border_mode='same')(input)
110 | ir2 = Convolution2D(160, 1, 7, activation='relu', border_mode='same')(ir2)
111 | ir2 = Convolution2D(192, 7, 1, activation='relu', border_mode='same')(ir2)
112 |
113 | ir_merge = merge([ir1, ir2], mode='concat', concat_axis=channel_axis)
114 |
115 | ir_conv = Convolution2D(1152, 1, 1, activation='linear', border_mode='same')(ir_merge)
116 | if scale_residual: ir_conv = Lambda(lambda x: x * 0.1)(ir_conv)
117 |
118 | out = merge([init, ir_conv], mode='sum')
119 | out = BatchNormalization(axis=channel_axis)(out)
120 | out = Activation("relu")(out)
121 | return out
122 |
123 | def inception_resnet_v2_C(input, scale_residual=True):
124 | if K.image_dim_ordering() == "th":
125 | channel_axis = 1
126 | else:
127 | channel_axis = -1
128 |
129 | # Input is relu activation
130 | init = input
131 |
132 | ir1 = Convolution2D(192, 1, 1, activation='relu', border_mode='same')(input)
133 |
134 | ir2 = Convolution2D(192, 1, 1, activation='relu', border_mode='same')(input)
135 | ir2 = Convolution2D(224, 1, 3, activation='relu', border_mode='same')(ir2)
136 | ir2 = Convolution2D(256, 3, 1, activation='relu', border_mode='same')(ir2)
137 |
138 | ir_merge = merge([ir1, ir2], mode='concat', concat_axis=channel_axis)
139 |
140 | ir_conv = Convolution2D(2144, 1, 1, activation='linear', border_mode='same')(ir_merge)
141 | if scale_residual: ir_conv = Lambda(lambda x: x * 0.1)(ir_conv)
142 |
143 | out = merge([init, ir_conv], mode='sum')
144 | out = BatchNormalization(axis=channel_axis)(out)
145 | out = Activation("relu")(out)
146 | return out
147 |
148 |
149 | def reduction_A(input, k=192, l=224, m=256, n=384):
150 | if K.image_dim_ordering() == "th":
151 | channel_axis = 1
152 | else:
153 | channel_axis = -1
154 |
155 | r1 = MaxPooling2D((3,3), strides=(2,2))(input)
156 |
157 | r2 = Convolution2D(n, 3, 3, activation='relu', subsample=(2,2))(input)
158 |
159 | r3 = Convolution2D(k, 1, 1, activation='relu', border_mode='same')(input)
160 | r3 = Convolution2D(l, 3, 3, activation='relu', border_mode='same')(r3)
161 | r3 = Convolution2D(m, 3, 3, activation='relu', subsample=(2,2))(r3)
162 |
163 | m = merge([r1, r2, r3], mode='concat', concat_axis=channel_axis)
164 | m = BatchNormalization(axis=1)(m)
165 | m = Activation('relu')(m)
166 | return m
167 |
168 |
169 | def reduction_resnet_v2_B(input):
170 | if K.image_dim_ordering() == "th":
171 | channel_axis = 1
172 | else:
173 | channel_axis = -1
174 |
175 | r1 = MaxPooling2D((3,3), strides=(2,2), border_mode='valid')(input)
176 |
177 | r2 = Convolution2D(256, 1, 1, activation='relu', border_mode='same')(input)
178 | r2 = Convolution2D(384, 3, 3, activation='relu', subsample=(2,2))(r2)
179 |
180 | r3 = Convolution2D(256, 1, 1, activation='relu', border_mode='same')(input)
181 | r3 = Convolution2D(288, 3, 3, activation='relu', subsample=(2, 2))(r3)
182 |
183 | r4 = Convolution2D(256, 1, 1, activation='relu', border_mode='same')(input)
184 | r4 = Convolution2D(288, 3, 3, activation='relu', border_mode='same')(r4)
185 | r4 = Convolution2D(320, 3, 3, activation='relu', subsample=(2, 2))(r4)
186 |
187 | m = merge([r1, r2, r3, r4], concat_axis=channel_axis, mode='concat')
188 | m = BatchNormalization(axis=channel_axis)(m)
189 | m = Activation('relu')(m)
190 | return m
191 |
192 | def create_inception_resnet_v2(nb_classes=1001, scale=True):
193 | '''
194 | Creates a inception resnet v2 network
195 |
196 | :param nb_classes: number of classes.txt
197 | :param scale: flag to add scaling of activations
198 | :return: Keras Model with 1 input (299x299x3) input shape and 2 outputs (final_output, auxiliary_output)
199 | '''
200 |
201 | if K.image_dim_ordering() == 'th':
202 | init = Input((3, 299, 299))
203 | else:
204 | init = Input((299, 299, 3))
205 |
206 | # Input Shape is 299 x 299 x 3 (tf) or 3 x 299 x 299 (th)
207 | x = inception_resnet_stem(init)
208 |
209 | # 10 x Inception Resnet A
210 | for i in range(10):
211 | x = inception_resnet_v2_A(x, scale_residual=scale)
212 |
213 | # Reduction A
214 | x = reduction_A(x, k=256, l=256, m=384, n=384)
215 |
216 | # 20 x Inception Resnet B
217 | for i in range(20):
218 | x = inception_resnet_v2_B(x, scale_residual=scale)
219 |
220 | # Auxiliary tower
221 | aux_out = AveragePooling2D((5, 5), strides=(3, 3))(x)
222 | aux_out = Convolution2D(128, 1, 1, border_mode='same', activation='relu')(aux_out)
223 | aux_out = Convolution2D(768, 5, 5, activation='relu')(aux_out)
224 | aux_out = Flatten()(aux_out)
225 | aux_out = Dense(nb_classes, activation='softmax')(aux_out)
226 |
227 | # Reduction Resnet B
228 | x = reduction_resnet_v2_B(x)
229 |
230 | # 10 x Inception Resnet C
231 | for i in range(10):
232 | x = inception_resnet_v2_C(x, scale_residual=scale)
233 |
234 | # Average Pooling
235 | x = AveragePooling2D((8,8))(x)
236 |
237 | # Dropout
238 | x = Dropout(0.8)(x)
239 | x = Flatten()(x)
240 |
241 | # Output
242 | out = Dense(output_dim=nb_classes, activation='softmax')(x)
243 |
244 | model = Model(init, output=[out, aux_out], name='Inception-Resnet-v2')
245 | return model
246 |
247 | if __name__ == "__main__":
248 | from keras.utils.visualize_util import plot
249 |
250 | inception_resnet_v2 = create_inception_resnet_v2()
251 | #inception_resnet_v2.summary()
252 |
253 | plot(inception_resnet_v2, to_file="Inception ResNet-v2.png", show_shapes=True)
--------------------------------------------------------------------------------
/inception_v4.py:
--------------------------------------------------------------------------------
1 | from keras.layers import Input, merge, Dropout, Dense, Flatten, Activation
2 | from keras.layers.convolutional import MaxPooling2D, Convolution2D, AveragePooling2D
3 | from keras.layers.normalization import BatchNormalization
4 | from keras.models import Model
5 |
6 | from keras import backend as K
7 | from keras.utils.data_utils import get_file
8 |
9 | """
10 | Implementation of Inception Network v4 [Inception Network v4 Paper](http://arxiv.org/pdf/1602.07261v1.pdf) in Keras.
11 | """
12 |
13 | TH_BACKEND_TH_DIM_ORDERING = "https://github.com/titu1994/Inception-v4/releases/download/v1.2/inception_v4_weights_th_dim_ordering_th_kernels.h5"
14 | TH_BACKEND_TF_DIM_ORDERING = "https://github.com/titu1994/Inception-v4/releases/download/v1.2/inception_v4_weights_tf_dim_ordering_th_kernels.h5"
15 | TF_BACKEND_TF_DIM_ORDERING = "https://github.com/titu1994/Inception-v4/releases/download/v1.2/inception_v4_weights_tf_dim_ordering_tf_kernels.h5"
16 | TF_BACKEND_TH_DIM_ORDERING = "https://github.com/titu1994/Inception-v4/releases/download/v1.2/inception_v4_weights_th_dim_ordering_tf_kernels.h5"
17 |
18 |
19 | def conv_block(x, nb_filter, nb_row, nb_col, border_mode='same', subsample=(1, 1), bias=False):
20 | if K.image_dim_ordering() == "th":
21 | channel_axis = 1
22 | else:
23 | channel_axis = -1
24 |
25 | x = Convolution2D(nb_filter, nb_row, nb_col, subsample=subsample, border_mode=border_mode, bias=bias)(x)
26 | x = BatchNormalization(axis=channel_axis)(x)
27 | x = Activation('relu')(x)
28 | return x
29 |
30 |
31 | def inception_stem(input):
32 | if K.image_dim_ordering() == "th":
33 | channel_axis = 1
34 | else:
35 | channel_axis = -1
36 |
37 | # Input Shape is 299 x 299 x 3 (th) or 3 x 299 x 299 (th)
38 | x = conv_block(input, 32, 3, 3, subsample=(2, 2), border_mode='valid')
39 | x = conv_block(x, 32, 3, 3, border_mode='valid')
40 | x = conv_block(x, 64, 3, 3)
41 |
42 | x1 = MaxPooling2D((3, 3), strides=(2, 2), border_mode='valid')(x)
43 | x2 = conv_block(x, 96, 3, 3, subsample=(2, 2), border_mode='valid')
44 |
45 | x = merge([x1, x2], mode='concat', concat_axis=channel_axis)
46 |
47 | x1 = conv_block(x, 64, 1, 1)
48 | x1 = conv_block(x1, 96, 3, 3, border_mode='valid')
49 |
50 | x2 = conv_block(x, 64, 1, 1)
51 | x2 = conv_block(x2, 64, 1, 7)
52 | x2 = conv_block(x2, 64, 7, 1)
53 | x2 = conv_block(x2, 96, 3, 3, border_mode='valid')
54 |
55 | x = merge([x1, x2], mode='concat', concat_axis=channel_axis)
56 |
57 | x1 = conv_block(x, 192, 3, 3, subsample=(2, 2), border_mode='valid')
58 | x2 = MaxPooling2D((3, 3), strides=(2, 2), border_mode='valid')(x)
59 |
60 | x = merge([x1, x2], mode='concat', concat_axis=channel_axis)
61 | return x
62 |
63 |
64 | def inception_A(input):
65 | if K.image_dim_ordering() == "th":
66 | channel_axis = 1
67 | else:
68 | channel_axis = -1
69 |
70 | a1 = conv_block(input, 96, 1, 1)
71 |
72 | a2 = conv_block(input, 64, 1, 1)
73 | a2 = conv_block(a2, 96, 3, 3)
74 |
75 | a3 = conv_block(input, 64, 1, 1)
76 | a3 = conv_block(a3, 96, 3, 3)
77 | a3 = conv_block(a3, 96, 3, 3)
78 |
79 | a4 = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same')(input)
80 | a4 = conv_block(a4, 96, 1, 1)
81 |
82 | m = merge([a1, a2, a3, a4], mode='concat', concat_axis=channel_axis)
83 | return m
84 |
85 |
86 | def inception_B(input):
87 | if K.image_dim_ordering() == "th":
88 | channel_axis = 1
89 | else:
90 | channel_axis = -1
91 |
92 | b1 = conv_block(input, 384, 1, 1)
93 |
94 | b2 = conv_block(input, 192, 1, 1)
95 | b2 = conv_block(b2, 224, 1, 7)
96 | b2 = conv_block(b2, 256, 7, 1)
97 |
98 | b3 = conv_block(input, 192, 1, 1)
99 | b3 = conv_block(b3, 192, 7, 1)
100 | b3 = conv_block(b3, 224, 1, 7)
101 | b3 = conv_block(b3, 224, 7, 1)
102 | b3 = conv_block(b3, 256, 1, 7)
103 |
104 | b4 = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same')(input)
105 | b4 = conv_block(b4, 128, 1, 1)
106 |
107 | m = merge([b1, b2, b3, b4], mode='concat', concat_axis=channel_axis)
108 | return m
109 |
110 |
111 | def inception_C(input):
112 | if K.image_dim_ordering() == "th":
113 | channel_axis = 1
114 | else:
115 | channel_axis = -1
116 |
117 | c1 = conv_block(input, 256, 1, 1)
118 |
119 | c2 = conv_block(input, 384, 1, 1)
120 | c2_1 = conv_block(c2, 256, 1, 3)
121 | c2_2 = conv_block(c2, 256, 3, 1)
122 | c2 = merge([c2_1, c2_2], mode='concat', concat_axis=channel_axis)
123 |
124 | c3 = conv_block(input, 384, 1, 1)
125 | c3 = conv_block(c3, 448, 3, 1)
126 | c3 = conv_block(c3, 512, 1, 3)
127 | c3_1 = conv_block(c3, 256, 1, 3)
128 | c3_2 = conv_block(c3, 256, 3, 1)
129 | c3 = merge([c3_1, c3_2], mode='concat', concat_axis=channel_axis)
130 |
131 | c4 = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same')(input)
132 | c4 = conv_block(c4, 256, 1, 1)
133 |
134 | m = merge([c1, c2, c3, c4], mode='concat', concat_axis=channel_axis)
135 | return m
136 |
137 |
138 | def reduction_A(input):
139 | if K.image_dim_ordering() == "th":
140 | channel_axis = 1
141 | else:
142 | channel_axis = -1
143 |
144 | r1 = conv_block(input, 384, 3, 3, subsample=(2, 2), border_mode='valid')
145 |
146 | r2 = conv_block(input, 192, 1, 1)
147 | r2 = conv_block(r2, 224, 3, 3)
148 | r2 = conv_block(r2, 256, 3, 3, subsample=(2, 2), border_mode='valid')
149 |
150 | r3 = MaxPooling2D((3, 3), strides=(2, 2), border_mode='valid')(input)
151 |
152 | m = merge([r1, r2, r3], mode='concat', concat_axis=channel_axis)
153 | return m
154 |
155 |
156 | def reduction_B(input):
157 | if K.image_dim_ordering() == "th":
158 | channel_axis = 1
159 | else:
160 | channel_axis = -1
161 |
162 | r1 = conv_block(input, 192, 1, 1)
163 | r1 = conv_block(r1, 192, 3, 3, subsample=(2, 2), border_mode='valid')
164 |
165 | r2 = conv_block(input, 256, 1, 1)
166 | r2 = conv_block(r2, 256, 1, 7)
167 | r2 = conv_block(r2, 320, 7, 1)
168 | r2 = conv_block(r2, 320, 3, 3, subsample=(2, 2), border_mode='valid')
169 |
170 | r3 = MaxPooling2D((3, 3), strides=(2, 2), border_mode='valid')(input)
171 |
172 | m = merge([r1, r2, r3], mode='concat', concat_axis=channel_axis)
173 | return m
174 |
175 |
176 | def create_inception_v4(nb_classes=1001, load_weights=True):
177 | '''
178 | Creates a inception v4 network
179 |
180 | :param nb_classes: number of classes.txt
181 | :return: Keras Model with 1 input and 1 output
182 | '''
183 |
184 | if K.image_dim_ordering() == 'th':
185 | init = Input((3, 299, 299))
186 | else:
187 | init = Input((299, 299, 3))
188 |
189 | # Input Shape is 299 x 299 x 3 (tf) or 3 x 299 x 299 (th)
190 | x = inception_stem(init)
191 |
192 | # 4 x Inception A
193 | for i in range(4):
194 | x = inception_A(x)
195 |
196 | # Reduction A
197 | x = reduction_A(x)
198 |
199 | # 7 x Inception B
200 | for i in range(7):
201 | x = inception_B(x)
202 |
203 | # Reduction B
204 | x = reduction_B(x)
205 |
206 | # 3 x Inception C
207 | for i in range(3):
208 | x = inception_C(x)
209 |
210 | # Average Pooling
211 | x = AveragePooling2D((8, 8))(x)
212 |
213 | # Dropout
214 | x = Dropout(0.8)(x)
215 | x = Flatten()(x)
216 |
217 | # Output
218 | out = Dense(output_dim=nb_classes, activation='softmax')(x)
219 |
220 | model = Model(init, out, name='Inception-v4')
221 |
222 | if load_weights:
223 | if K.backend() == "theano":
224 | if K.image_dim_ordering() == "th":
225 | weights = get_file('inception_v4_weights_th_dim_ordering_th_kernels.h5', TH_BACKEND_TH_DIM_ORDERING,
226 | cache_subdir='models')
227 | else:
228 | weights = get_file('inception_v4_weights_tf_dim_ordering_th_kernels.h5', TH_BACKEND_TF_DIM_ORDERING,
229 | cache_subdir='models')
230 | else:
231 | if K.image_dim_ordering() == "th":
232 | weights = get_file('inception_v4_weights_th_dim_ordering_tf_kernels.h5', TF_BACKEND_TH_DIM_ORDERING,
233 | cache_subdir='models')
234 | else:
235 | weights = get_file('inception_v4_weights_tf_dim_ordering_tf_kernels.h5', TH_BACKEND_TF_DIM_ORDERING,
236 | cache_subdir='models')
237 |
238 | model.load_weights(weights)
239 | print("Model weights loaded.")
240 |
241 | return model
242 |
243 |
244 | if __name__ == "__main__":
245 | # from keras.utils.visualize_util import plot
246 |
247 | inception_v4 = create_inception_v4(load_weights=True)
248 | # inception_v4.summary()
249 |
250 | # plot(inception_v4, to_file="Inception-v4.png", show_shapes=True)
251 |
--------------------------------------------------------------------------------
/weights/ADD_WEIGHT_FILES_HERE.txt:
--------------------------------------------------------------------------------
1 | Download the appropriate weight file from Release tab (https://github.com/titu1994/Inception-v4/releases/tag/v1.0)
2 |
3 | Acknowledgements : Weight for Inception V4 (Tensorflow backend, Tensorflow dim ordering) is provided by
4 | Kent Sommer (@kentsommer) in his repository - https://github.com/kentsommer/keras-inceptionV4
5 |
6 |
--------------------------------------------------------------------------------