Skip to content

Commit be0f6b0

Browse files
committed
finally figure it out
1 parent 6dd14ad commit be0f6b0

File tree

3 files changed

+218
-16
lines changed

3 files changed

+218
-16
lines changed

pre-process.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ def save_train_data(fnames, labels, bboxes):
1919
src_folder = 'cars_train'
2020
num_samples = len(fnames)
2121

22-
num_train = int(round(num_samples * 0.8))
23-
num_valid = num_samples - num_train
24-
train_indexes = random.sample(range(num_samples), num_valid)
22+
train_split = 0.8
23+
num_train = int(round(num_samples * train_split))
24+
train_indexes = random.sample(range(num_samples), num_train)
2525

2626
pb = ProgressBar(total=100, prefix='Save train data', suffix='', decimals=3, length=50, fill='=')
2727

@@ -135,7 +135,7 @@ def process_test_data():
135135

136136
if __name__ == '__main__':
137137
# parameters
138-
img_width, img_height = 227, 227
138+
img_width, img_height = 224, 224
139139

140140
print('Extracting cars_train.tgz...')
141141
if not os.path.exists('cars_train'):
@@ -164,6 +164,6 @@ def process_test_data():
164164
# process_test_data()
165165

166166
# clean up
167-
# shutil.rmtree('cars_train')
168-
# shutil.rmtree('cars_test')
169-
# shutil.rmtree('devkit')
167+
shutil.rmtree('cars_train')
168+
shutil.rmtree('cars_test')
169+
shutil.rmtree('devkit')

resnet_152.py

+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from keras.optimizers import SGD
4+
from keras.layers import Input, Dense, Conv2D, MaxPooling2D, AveragePooling2D, ZeroPadding2D, Flatten, Activation, add
5+
from keras.layers.normalization import BatchNormalization
6+
from keras.models import Model
7+
from keras import backend as K
8+
9+
from sklearn.metrics import log_loss
10+
11+
from custom_layers.scale_layer import Scale
12+
13+
import sys
14+
sys.setrecursionlimit(3000)
15+
16+
def identity_block(input_tensor, kernel_size, filters, stage, block):
17+
'''The identity_block is the block that has no conv layer at shortcut
18+
# Arguments
19+
input_tensor: input tensor
20+
kernel_size: defualt 3, the kernel size of middle conv layer at main path
21+
filters: list of integers, the nb_filters of 3 conv layer at main path
22+
stage: integer, current stage label, used for generating layer names
23+
block: 'a','b'..., current block label, used for generating layer names
24+
'''
25+
eps = 1.1e-5
26+
nb_filter1, nb_filter2, nb_filter3 = filters
27+
conv_name_base = 'res' + str(stage) + block + '_branch'
28+
bn_name_base = 'bn' + str(stage) + block + '_branch'
29+
scale_name_base = 'scale' + str(stage) + block + '_branch'
30+
31+
x = Conv2D(nb_filter1, (1, 1), name=conv_name_base + '2a', use_bias=False)(input_tensor)
32+
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
33+
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
34+
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
35+
36+
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
37+
x = Conv2D(nb_filter2, (kernel_size, kernel_size),
38+
name=conv_name_base + '2b', use_bias=False)(x)
39+
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
40+
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
41+
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
42+
43+
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
44+
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
45+
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
46+
47+
x = add([x, input_tensor], name='res' + str(stage) + block)
48+
x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)
49+
return x
50+
51+
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
52+
'''conv_block is the block that has a conv layer at shortcut
53+
# Arguments
54+
input_tensor: input tensor
55+
kernel_size: defualt 3, the kernel size of middle conv layer at main path
56+
filters: list of integers, the nb_filters of 3 conv layer at main path
57+
stage: integer, current stage label, used for generating layer names
58+
block: 'a','b'..., current block label, used for generating layer names
59+
Note that from stage 3, the first conv layer at main path is with subsample=(2,2)
60+
And the shortcut should have subsample=(2,2) as well
61+
'''
62+
eps = 1.1e-5
63+
nb_filter1, nb_filter2, nb_filter3 = filters
64+
conv_name_base = 'res' + str(stage) + block + '_branch'
65+
bn_name_base = 'bn' + str(stage) + block + '_branch'
66+
scale_name_base = 'scale' + str(stage) + block + '_branch'
67+
68+
x = Conv2D(nb_filter1, (1, 1), strides=strides,
69+
name=conv_name_base + '2a', use_bias=False)(input_tensor)
70+
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2a')(x)
71+
x = Scale(axis=bn_axis, name=scale_name_base + '2a')(x)
72+
x = Activation('relu', name=conv_name_base + '2a_relu')(x)
73+
74+
x = ZeroPadding2D((1, 1), name=conv_name_base + '2b_zeropadding')(x)
75+
x = Conv2D(nb_filter2, (kernel_size, kernel_size),
76+
name=conv_name_base + '2b', use_bias=False)(x)
77+
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2b')(x)
78+
x = Scale(axis=bn_axis, name=scale_name_base + '2b')(x)
79+
x = Activation('relu', name=conv_name_base + '2b_relu')(x)
80+
81+
x = Conv2D(nb_filter3, (1, 1), name=conv_name_base + '2c', use_bias=False)(x)
82+
x = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '2c')(x)
83+
x = Scale(axis=bn_axis, name=scale_name_base + '2c')(x)
84+
85+
shortcut = Conv2D(nb_filter3, (1, 1), strides=strides,
86+
name=conv_name_base + '1', use_bias=False)(input_tensor)
87+
shortcut = BatchNormalization(epsilon=eps, axis=bn_axis, name=bn_name_base + '1')(shortcut)
88+
shortcut = Scale(axis=bn_axis, name=scale_name_base + '1')(shortcut)
89+
90+
x = add([x, shortcut], name='res' + str(stage) + block)
91+
x = Activation('relu', name='res' + str(stage) + block + '_relu')(x)
92+
return x
93+
94+
def resnet152_model(img_rows, img_cols, color_type=1, num_classes=None):
95+
"""
96+
Resnet 152 Model for Keras
97+
98+
Model Schema and layer naming follow that of the original Caffe implementation
99+
https://github.com/KaimingHe/deep-residual-networks
100+
101+
ImageNet Pretrained Weights
102+
Theano: https://drive.google.com/file/d/0Byy2AcGyEVxfZHhUT3lWVWxRN28/view?usp=sharing
103+
TensorFlow: https://drive.google.com/file/d/0Byy2AcGyEVxfeXExMzNNOHpEODg/view?usp=sharing
104+
105+
Parameters:
106+
img_rows, img_cols - resolution of inputs
107+
channel - 1 for grayscale, 3 for color
108+
num_classes - number of class labels for our classification task
109+
"""
110+
eps = 1.1e-5
111+
112+
# Handle Dimension Ordering for different backends
113+
global bn_axis
114+
if K.image_dim_ordering() == 'tf':
115+
bn_axis = 3
116+
img_input = Input(shape=(img_rows, img_cols, color_type), name='data')
117+
else:
118+
bn_axis = 1
119+
img_input = Input(shape=(color_type, img_rows, img_cols), name='data')
120+
121+
x = ZeroPadding2D((3, 3), name='conv1_zeropadding')(img_input)
122+
x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1', use_bias=False)(x)
123+
x = BatchNormalization(epsilon=eps, axis=bn_axis, name='bn_conv1')(x)
124+
x = Scale(axis=bn_axis, name='scale_conv1')(x)
125+
x = Activation('relu', name='conv1_relu')(x)
126+
x = MaxPooling2D((3, 3), strides=(2, 2), name='pool1')(x)
127+
128+
x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
129+
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
130+
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
131+
132+
x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
133+
for i in range(1,8):
134+
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b'+str(i))
135+
136+
x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
137+
for i in range(1,36):
138+
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b'+str(i))
139+
140+
x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')
141+
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
142+
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')
143+
144+
x_fc = AveragePooling2D((7, 7), name='avg_pool')(x)
145+
x_fc = Flatten()(x_fc)
146+
x_fc = Dense(1000, activation='softmax', name='fc1000')(x_fc)
147+
148+
model = Model(img_input, x_fc)
149+
150+
if K.image_dim_ordering() == 'th':
151+
# Use pre-trained weights for Theano backend
152+
weights_path = 'imagenet_models/resnet152_weights_th.h5'
153+
else:
154+
# Use pre-trained weights for Tensorflow backend
155+
weights_path = 'imagenet_models/resnet152_weights_tf.h5'
156+
157+
model.load_weights(weights_path, by_name=True)
158+
159+
# Truncate and replace softmax layer for transfer learning
160+
# Cannot use model.layers.pop() since model is not of Sequential() type
161+
# The method below works since pre-trained weights are stored in layers but not in the model
162+
x_newfc = AveragePooling2D((7, 7), name='avg_pool')(x)
163+
x_newfc = Flatten()(x_newfc)
164+
x_newfc = Dense(num_classes, activation='softmax', name='fc8')(x_newfc)
165+
166+
model = Model(img_input, x_newfc)
167+
168+
# Learning rate is changed to 0.001
169+
sgd = SGD(lr=1e-3, decay=1e-6, momentum=0.9, nesterov=True)
170+
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])
171+
172+
return model
173+
174+
if __name__ == '__main__':
175+
176+
# Example to fine-tune on 3000 samples from Cifar10
177+
178+
img_rows, img_cols = 224, 224 # Resolution of inputs
179+
channel = 3
180+
num_classes = 10
181+
batch_size = 8
182+
epochs = 10
183+
184+
# Load Cifar10 data. Please implement your own load_data() module for your own dataset
185+
X_train, Y_train, X_valid, Y_valid = load_cifar10_data(img_rows, img_cols)
186+
187+
# Load our model
188+
model = resnet152_model(img_rows, img_cols, channel, num_classes)
189+
190+
# Start Fine-tuning
191+
model.fit(X_train, Y_train,
192+
batch_size=batch_size,
193+
epochs=epochs,
194+
shuffle=True,
195+
verbose=1,
196+
validation_data=(X_valid, Y_valid),
197+
)
198+
199+
# Make predictions
200+
predictions_valid = model.predict(X_valid, batch_size=batch_size, verbose=1)
201+
202+
# Cross-entropy loss score
203+
score = log_loss(Y_valid, predictions_valid)

train.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import keras
2-
from resnet_50 import resnet50_model
2+
from resnet_152 import resnet152_model
33
from keras.preprocessing.image import ImageDataGenerator
44
from keras.callbacks import CSVLogger, ModelCheckpoint, EarlyStopping
55
from keras.callbacks import ReduceLROnPlateau
@@ -18,23 +18,22 @@
1818

1919
if __name__ == '__main__':
2020
# build a classifier model
21-
model = resnet50_model(img_height, img_width, num_channels, num_classes)
21+
model = resnet152_model(img_height, img_width, num_channels, num_classes)
2222

2323
# prepare data augmentation configuration
24-
train_data_gen = ImageDataGenerator(rescale=1/255.,
25-
rotation_range=20.,
24+
train_data_gen = ImageDataGenerator(rotation_range=20.,
2625
width_shift_range=0.1,
2726
height_shift_range=0.1,
2827
zoom_range=0.2,
2928
horizontal_flip=True)
30-
valid_data_gen = ImageDataGenerator(rescale=1/255.)
29+
valid_data_gen = ImageDataGenerator()
3130
# callbacks
3231
tensor_board = keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, write_graph=True, write_images=True)
33-
log_file_path = 'training.log'
32+
log_file_path = 'logs/training.log'
3433
csv_logger = CSVLogger(log_file_path, append=False)
35-
early_stop = EarlyStopping('val_loss', patience=patience)
36-
reduce_lr = ReduceLROnPlateau('val_loss', factor=0.1, patience=int(patience / 4), verbose=1)
37-
trained_models_path = 'model'
34+
early_stop = EarlyStopping('val_acc', patience=patience)
35+
reduce_lr = ReduceLROnPlateau('val_acc', factor=0.1, patience=int(patience / 4), verbose=1)
36+
trained_models_path = 'models/model'
3837
model_names = trained_models_path + '.{epoch:02d}-{val_acc:.2f}.hdf5'
3938
model_checkpoint = ModelCheckpoint(model_names, monitor='val_acc', verbose=1, save_best_only=True)
4039
callbacks = [tensor_board, model_checkpoint, csv_logger, early_stop, reduce_lr]

0 commit comments

Comments
 (0)