MobileNetV1.py
from tensorflow import keras
from tensorflow.keras import layers
def ConvBlock(input, filters, stride, idx):
x = layers.Conv2D(filters, 3, use_bias=False, strides=stride, padding='same', name='conv'+str(idx))(input)
x = layers.BatchNormalization(name='conv'+str(idx)+'_bn')(x)
x = layers.Activation('relu', name='conv'+str(idx)+'_relu')(x)
return x
def DepthwiseBlock(input, pointwise_conv_filters, depthstride, depth_multiplier, idx):
x = layers.DepthwiseConv2D(3, use_bias=False, strides=depthstride, padding='same', depth_multiplier=depth_multiplier, name='conv_dw_'+str(idx))(input)
x = layers.BatchNormalization(name='conv_dw_'+str(idx)+'_bn')(x)
x = layers.ReLU(max_value=6, name='conv_dw_'+str(idx)+'_relu')(x)
x = layers.Conv2D(pointwise_conv_filters, 1, use_bias=False, strides=(1, 1), padding='same', name='conv_pw_'+str(idx))(x)
x = layers.BatchNormalization(name='conv_pw_'+str(idx)+'_bn')(x)
x = layers.Activation('relu', name='conv_pw_'+str(idx)+'_relu')(x)
return x
def MobileNetV1(input_shape, num_class):
input = keras.Input(shape=input_shape, name='input')
x = ConvBlock(input, 32, stride=(2, 2), idx=1)
x = DepthwiseBlock(x, 64, depthstride=(1, 1), depth_multiplier=1, idx=1)
x = DepthwiseBlock(x, 128, depthstride=(2, 2), depth_multiplier=1, idx=2)
x = DepthwiseBlock(x, 128, depthstride=(1, 1), depth_multiplier=1, idx=3)
x = DepthwiseBlock(x, 256, depthstride=(2, 2), depth_multiplier=1, idx=4)
x = DepthwiseBlock(x, 256, depthstride=(1, 1), depth_multiplier=1, idx=5)
x = DepthwiseBlock(x, 512, depthstride=(2, 2), depth_multiplier=1, idx=6)
x = DepthwiseBlock(x, 512, depthstride=(1, 1), depth_multiplier=1, idx=7)
x = DepthwiseBlock(x, 512, depthstride=(1, 1), depth_multiplier=1, idx=8)
x = DepthwiseBlock(x, 512, depthstride=(1, 1), depth_multiplier=1, idx=9)
x = DepthwiseBlock(x, 512, depthstride=(1, 1), depth_multiplier=1, idx=10)
x = DepthwiseBlock(x, 512, depthstride=(1, 1), depth_multiplier=1, idx=11)
x = DepthwiseBlock(x, 1024, depthstride=(2, 2), depth_multiplier=1, idx=12)
x = DepthwiseBlock(x, 1024, depthstride=(1, 1), depth_multiplier=1, idx=13)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Reshape((1, 1, 1024), name='reshape_1')(x)
x = layers.Dropout(0.001, name='dropout')(x)
x = layers.Conv2D(num_class, 1, padding='same', activation='softmax', name='conv_preds')(x)
x = layers.Reshape((num_class, ), name='reshape_2')(x)
model = keras.Model(input, x, name='mobilenetv1')
model.summary()
return model
if __name__ == '__main__':
model = MobileNetV1((224, 224, 3), 1000)
print('done.')
train_MobileNetV1.py
import numpy as np
import cv2
from MobileNetV1 import MobileNetV1
from tensorflow.keras import backend as K # K.set_image_dim_ordering('tf')
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, LearningRateScheduler, ReduceLROnPlateau
from tensorflow.keras import optimizers
import matplotlib.pyplot as plt
NUM_CLASSES = 2
INPUT_IMG_SIZE = 224
def show_train_history(train_history, train, validation):
plt.plot(train_history.history[train])
plt.plot(train_history.history[validation])
plt.title('Train history')
plt.ylabel(train)
plt.xlabel('Epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()
def generate_arrays_from_file(root_path, lines, num_classes, batch_size):
num = len(lines) # 数据总个数
i = 0
while 1:
x_images_normalize = []
y_labels_onehot = []
# 获取一个batch_size大小的数据
for b in range(batch_size):
if i == 0:
np.random.shuffle(lines)
img_path = root_path + "\\image\\train\\" + lines[i].split(";")[0] # cat dog datasets
# img_path = root_path + lines[i].split(" ")[0] # FlowerPhotos datasets
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (INPUT_IMG_SIZE, INPUT_IMG_SIZE))
img = img / 255
x_images_normalize.append(img)
label = to_categorical(lines[i].split(";")[1], num_classes=num_classes) # cat dog datasets
# label = to_categorical(lines[i].split(" ")[1], num_classes=num_classes) # FlowerPhotos datasets
y_labels_onehot.append(label)
i = (i+1) % num # 遍历一个epoch重新打乱数据
x_images_normalize = np.array(x_images_normalize)
#x_images_normalize = x_images_normalize.reshape(-1, 224, 224, 3)
y_labels_onehot = np.array(y_labels_onehot)
yield (x_images_normalize, y_labels_onehot)
if __name__ == "__main__":
anchors = np.zeros((9, 4))
lines = []
### cat dog dataset
root_path = r"D:\03.Data\01.CatDog"
with open(root_path + "\\dataset.txt") as f:
lines = f.readlines()
### FlowerPhotos dataset
# root_path = r"D:\03.Data\02.FlowerPhotos"
# with open(root_path + "\\train.txt") as f:
# lines = f.readlines()
np.random.shuffle(lines) # 随机打乱数据
val_ratio = 0.1
val_num = int(len(lines) * val_ratio)
val_lines = lines[0:val_num]
train_lines = lines[val_num:]
model = MobileNetV1((INPUT_IMG_SIZE, INPUT_IMG_SIZE, 3), NUM_CLASSES)
# 保存的方式,3个epoch保存一次
# https://keras-zh.readthedocs.io/callbacks/#modelcheckpoint
log_path = r"D:\02.Work\00.LearnML\003.Net\MobileNetV1\log\\"
checkpoint = ModelCheckpoint(log_path + "weights.epoch{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.hdf5",
monitor='accuracy', # loss或accuracy或val_loss或val_accuracy或lr
verbose=0,
save_best_only=False, # True
save_weights_only=False,
period=1)
# 学习率下降的方式,acc三次不下降就下降学习率继续训练
# https://keras-zh.readthedocs.io/callbacks/#reducelronplateau
reduce_lr = ReduceLROnPlateau(monitor='accuracy', factor=0.5, patience=3) # monitor=loss、accuracy、val_loss、val_accuracy、lr
# 当val_loss一直不下降的时候意味着模型基本训练完毕,可以停止
# https://keras-zh.readthedocs.io/callbacks/#earlystopping
early_stopping = EarlyStopping(monitor='val_loss', min_delta=0.0001, patience=10, verbose=0)
# 交叉熵损失
# opti = optimizers.SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)
opti = optimizers.Adam(lr=1e-3)
model.compile(optimizer=opti, loss='categorical_crossentropy', metrics=['accuracy'])
batch_size = 128//8
print('Train on {} samples, val on {} samples, with batch size {}.'.format(len(train_lines), len(val_lines), batch_size))
# 开始训练
train_history = model.fit_generator(generate_arrays_from_file(root_path, train_lines, NUM_CLASSES, batch_size),
steps_per_epoch=max(len(train_lines)//batch_size, 1),
epochs=10,
verbose=1,
callbacks=[checkpoint, reduce_lr, early_stopping],
validation_data=generate_arrays_from_file(root_path, val_lines, NUM_CLASSES, batch_size),
validation_steps=max(len(val_lines)//batch_size, 1),
validation_freq=1,
initial_epoch=0)
# 保存模型
model.save_weights(log_path+'MobileNetV1.h5')
show_train_history(train_history, 'accuracy', 'val_accuracy')
show_train_history(train_history, 'loss', 'val_loss')
print('Done.')
# 评估模型准确率
# scores = model.evaluate(x_img_test_normalize, y_label_test_onehot, verbose=0)
# print(len(scores))
# 进行预测
# prediction = model.predict_classes(x_test_image_normalize)
# prediction[:10] # 查看预测结果的前10项数据
predict_MobileNetV1.py
import matplotlib.pyplot as plt
from MobileNetV1 import MobileNetV1
import cv2
import numpy as np
from tensorflow.keras import backend as K # K.set_image_dim_ordering('tf')
from tensorflow.keras.utils import to_categorical
INPUT_IMG_SIZE = 224
NUM_CLASSES = 2
label_dict = {0:'CAT', 1:'DOG'}
def show_predict_probability(y_gts, predictions, x_imgs, predict_probabilitys, idx):
for i in range(len(label_dict)):
print(label_dict[i]+', Probability:%1.9f'%(predict_probabilitys[idx][i]))
print('label: ', label_dict[int(y_gts[idx])], ', predict: ', label_dict[predictions[idx]])
plt.figure(figsize=(2, 2))
plt.imshow(np.reshape(x_imgs[idx], (INPUT_IMG_SIZE, INPUT_IMG_SIZE, 3)))
plt.show()
def plot_images_labels_prediction(images, labels, prediction, idx, num):
fig = plt.gcf()
fig.set_size_inches(12, 14)
if num>25: num=25
for i in range(0, num):
ax = plt.subplot(2, 5, 1+i)
ax.imshow(images[idx], cmap='binary')
title = 'labels='+str(labels[idx])
if len(prediction) > 0:
title += "prediction="+str(prediction[idx])
ax.set_title(title, fontsize=10)
idx += 1
plt.show()
if __name__ == '__main__':
log_path = r"D:\02.Work\00.LearnML\003.Net\MobileNetV1\log\\"
model = MobileNetV1((224, 224, 3), NUM_CLASSES)
model.load_weights(log_path+"MobileNetV1.h5")
### cat dog dataset
lines = []
root_path = r"D:\03.Data\01.CatDog"
with open(root_path + "\\test.txt") as f:
lines = f.readlines()
x_images_normalize = []
y_labels_onehot = []
y_labels = []
for i in range(len(lines)):
img_path = lines[i].split(";")[0]
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (INPUT_IMG_SIZE, INPUT_IMG_SIZE))
img = img / 255
x_images_normalize.append(img)
label = to_categorical(lines[i].split(";")[1], num_classes=NUM_CLASSES)
y_labels_onehot.append(label)
y_labels.append(lines[i].split(";")[1])
x_images_normalize = np.array(x_images_normalize)
# x_images_normalize = x_images_normalize.reshape(-1, INPUT_IMG_SIZE, INPUT_IMG_SIZE, 3)
y_labels_onehot = np.array(y_labels_onehot)
predict_probability = model.predict(x_images_normalize, verbose=1)
predict = np.argmax(predict_probability, axis=1)
plot_images_labels_prediction(x_images_normalize, y_labels, predict, 0, 10)
show_predict_probability(y_labels, predict, x_images_normalize, predict_probability, 0)
print('done')