-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCNN.py
288 lines (245 loc) · 12.8 KB
/
CNN.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# -*- coding: utf-8 -*-
from keras.optimizers import SGD
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, AveragePooling2D, ZeroPadding2D, Flatten, Dropout, Activation, add
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras import backend as K
from sklearn.metrics import log_loss
from custom_layers.scale_layer import Scale
import sys
import numpy as np
from keras.datasets import cifar10
from keras import backend as K
from keras.utils import np_utils
import mxnet as mx
import gluoncv
# nb_train_samples = 3000 # 3000 training samples
# nb_valid_samples = 100 # 100 validation samples
# num_classes = 10
# sys.setrecursionlimit(3000)手工设置递归调用深度
sys.setrecursionlimit(3000)
def identity_block(input_tensor, kernel_size, filters, stage, block):
eps = 1.1e-5
nb_filter1, nb_filter2, nb_filter3 = filters
# 卷积名
conv_name_base = 'res' + str(stage) + block + '_branch'
# 偏置
bn_name_base = 'bn' + str(stage) + block + '_branch'
# 尺度
scale_name_base = 'scale' + str(stage) + block + '_branch'
# 步长(1,1)
x = Conv2D(nb_filter1, (1, 1), name=conv_name_base + '2a', use_bias=False)(input_tensor)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
x = Conv2D(nb_filter2, (kernel_size, kernel_size),
name=conv_name_base + '2b', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
x = add([x, input_tensor], name='res' + str(stage) + block)
x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)
return x
def identity_block_tanh(input_tensor, kernel_size, filters, stage, block):
eps = 1.1e-5
nb_filter1, nb_filter2, nb_filter3 = filters
# 卷积名
conv_name_base = 'res' + str(stage) + block + '_branch'
# 偏置
bn_name_base = 'bn' + str(stage) + block + '_branch'
# 尺度
scale_name_base = 'scale' + str(stage) + block + '_branch'
# 步长(1,1)
x = Conv2D(nb_filter1, (1, 1), name=conv_name_base + '2a', use_bias=False)(input_tensor)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
x = Conv2D(nb_filter2, (kernel_size, kernel_size),
name=conv_name_base + '2b', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
x = add([x, input_tensor], name='res' + str(stage) + block)
x = Activation('tanh', name='res' + str(stage) + block + '_relu')(x)
return x
# y = F(x) + W*x
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
eps = 1.1e-5
nb_filter1, nb_filter2, nb_filter3 = filters
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
scale_name_base = 'scale' + str(stage) + block + '_branch'
x = Conv2D(nb_filter1, (1, 1), strides=strides,
name=conv_name_base + '2a', use_bias=False)(input_tensor)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
x = Conv2D(nb_filter2, (kernel_size, kernel_size),
name=conv_name_base + '2b', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
shortcut = Conv2D(nb_filter3, (1, 1), strides=strides,
name=conv_name_base + '1', use_bias=False)(input_tensor)
shortcut = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '1')(shortcut)
shortcut = Scale(axis=bn_axis, name=scale_name_base + '1')(shortcut)
x = add([x, shortcut], name='res' + str(stage) + block)
x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)
return x
def conv_block_D(input_tensor, kernel_size, filters, stage, block):
eps = 1.1e-5
nb_filter1, nb_filter2, nb_filter3 = filters
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
scale_name_base = 'scale' + str(stage) + block + '_branch'
x = Conv2D(nb_filter1, (1, 1),
name=conv_name_base + '2a', use_bias=False)(input_tensor)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
x = Conv2D(nb_filter2, (kernel_size, kernel_size), strides=(2, 2),
name=conv_name_base + '2b', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
input_tensor = AveragePooling2D((2, 2), strides=(2, 2), padding='same',
name='AvgPloo'+str(stage))(input_tensor)
shortcut = Conv2D(nb_filter3, (1, 1),
name=conv_name_base + '1', use_bias=False)(input_tensor)
shortcut = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '1')(shortcut)
shortcut = Scale(axis=bn_axis, name=scale_name_base + '1')(shortcut)
x = add([x, shortcut], name='res' + str(stage) + block)
x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)
return x
def cnn_model(img_rows, img_cols, color_type=1, num_classes=None):
eps = 1.1e-5
# 处理尺寸不同的后端
global bn_axis
# ## th : if image_dim_ordering = channels_first”数据组织为(3,128,128,128),
# ## tf : ...=“channels_last”数据组织为(128,128,128,3)
if K.image_data_format() == 'channels_last':
bn_axis = 3
img_input = Input(shape=(img_rows, img_cols, color_type), name='data')
else:
bn_axis = 1
img_input = Input(shape=(color_type, img_rows, img_cols), name='data')
x = ZeroPadding2D((3, 3), name='conv1_zeropadding')(img_input)
# x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1', use_bias=False)(x)
# 7X7 ==> 3X3 + 3X3 + 3X3
x = Conv2D(32, (3, 3), strides=(2, 2), name='conv1a', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name='bn_conv1a')(x)
x = Scale(axis=bn_axis, name='scale_conv1a')(x)
x = Activation('relu', name='conv1a_relu')(x)
x = Conv2D(32, (3, 3), strides=(2, 2), name='conv1b', use_bias=False)(x)
x = BatchNormalization(epsilon=eps, axis=bn_axis, name='bn_conv1b')(x)
x = Scale(axis=bn_axis, name='scale_conv1b')(x)
x = Activation('relu', name='conv1b_relu')(x)
x = Conv2D(64, (3, 3), strides=(1, 1), name='conv1c', use_bias=False)(x)
#
x = BatchNormalization(epsilon=eps, axis=bn_axis, name='bn_conv1c')(x)
x = Scale(axis=bn_axis, name='scale_conv1c')(x)
x = Activation('relu', name='conv1c_relu')(x)
x = MaxPooling2D((3, 3), strides=(2, 2), name='pool1')(x)
x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
x = conv_block_D(x, 3, [128, 128, 512], stage=3, block='a')
for i in range(1, 8):
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b'+str(i))
x = conv_block_D(x, 3, [256, 256, 1024], stage=4, block='a')
for i in range(1, 36):
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b'+str(i))
x = conv_block_D(x, 3, [512, 512, 2048], stage=5, block='a')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
x = identity_block_tanh(x, 3, [512, 512, 2048], stage=5, block='c')
x_fc = AveragePooling2D((4, 4), name='avg_pool')(x)
x_fc = Flatten()(x_fc)
x_fc = Dropout(0.5)(x_fc)
# Dense(units:输出维度,activation=激活函数)全连接层(对上一层的神经元进行全部连接,实现特征的非线性组合)
x_fc = Dense(1000, activation='softmax', name='fc1000')(x_fc)
model = Model(img_input, x_fc)
if K.image_data_format() == 'channels_first':
# 使用预先训练过的权重进行Theano后端
weights_path = 'models/resnet152_v1d-cddbc86f.params'
# weights_path = 'models/resnet152_v1d-cddbc86f.params'
else:
# 在Tensorflow后端使用预先训练的权重
weights_path = 'models/resnet152_v1d-cddbc86f.params'
# weights_path = 'models/resnet152_v1d-cddbc86f.params'
model.load_weights(weights_path, by_name=True)
# 截断并替换softmax层以进行传输学习
# 不能使用model.layers.pop(),因为model不是Sequential()类型
# 下面的方法有效,因为预训练的权重存储在图层中但不存储在模型中
x_newfc = AveragePooling2D((4, 4), name='avg_pool')(x)
x_newfc = Flatten()(x_newfc)
x_newfc = Dropout(0.5)(x_newfc)
x_newfc = Dense(num_classes, activation='softmax', name='fc8')(x_newfc)
model = Model(img_input, x_newfc)
# 学习率改为0.001
sgd = SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])
return model
# def load_cifar10_data(img_rows, img_cols):
#
# # Load cifar10 training and validation sets
# (X_train, Y_train), (X_valid, Y_valid) = cifar10.load_data()
#
# # Resize trainging images
# if K.image_dim_ordering() == 'th':
# X_train = np.array([cv2.resize(img.transpose(1,2,0), (img_rows,img_cols)).transpose(2,0,1) for img in X_train[:nb_train_samples,:,:,:]])
# X_valid = np.array([cv2.resize(img.transpose(1,2,0), (img_rows,img_cols)).transpose(2,0,1) for img in X_valid[:nb_valid_samples,:,:,:]])
# else:
# X_train = np.array([cv2.resize(img, (img_rows,img_cols)) for img in X_train[:nb_train_samples,:,:,:]])
# X_valid = np.array([cv2.resize(img, (img_rows,img_cols)) for img in X_valid[:nb_valid_samples,:,:,:]])
#
# # Transform targets to keras compatible format
# Y_train = np_utils.to_categorical(Y_train[:nb_train_samples], num_classes)
# Y_valid = np_utils.to_categorical(Y_valid[:nb_valid_samples], num_classes)
#
# return X_train, Y_train, X_valid, Y_valid
# if __name__ == '__main__':
#
# # 从Cifar10微调3000个样本的示例
#
# img_rows, img_cols = 224, 224 # 输入分辨率
# channel = 3
# num_classes = 10
# batch_size = 8
# epochs = 10
#
# # 下面的报错不用管
# X_train, Y_train, X_valid, Y_valid = load_cifar10_data(img_rows, img_cols)
#
# # 加载我们的模型
# model = cnn_model(img_rows, img_cols, channel, num_classes)
#
# # 开始微调
# model.fit(X_train, Y_train,
# batch_size=batch_size,
# epochs=epochs,
# shuffle=True,
# verbose=1,
# validation_data=(X_valid, Y_valid),
# )
#
# # 作出预测
# predictions_valid = model.predict(X_valid, batch_size=batch_size, verbose=1)
#
# # 交叉熵损失评分
# score = log_loss(Y_valid, predictions_valid)