环境:
基础:
- window 10
- python 3.6
NVIDIA的GPU并行计算架构:
- CUDA 10.0
- cuDNN 7.4.1
python包:
- Keras==2.2.5
- h5py==2.10.0
- matplotlib==3.2.0
- numpy==1.19.5
- opencv-python==3.4.1.15
- opencv-contrib-python==3.4.1.15
- efficientnet==1.1.1
- tensorflow-gpu==1.14.0
代码:
import cv2
from keras.utils import np_utils
from matplotlib import pyplot as plt
from keras import optimizers
from keras.models import *
from keras.layers import *
from keras.callbacks import *
from efficientnet.keras import EfficientNetB3
"""
变量说明:
n_classes:分类的数量(这里为2,即一共有2类)
n_dataset:单类数据集的数量(这里每一类数量要求相同)
a_path,b_path:A、B数据集的地址
X_train,Y_train:数据集,标签集
img_rows, img_cols:图片大小
batch_size:一次训练所选取的样本数
epochs:整个训练数据集被反复训练的次数
optimizer:优化器
"""
n_classes = 2
dataset = 20
a_path = r"C:\d\WPSCloud\dataset\A"
b_path = r"C:\d\WPSCloud\dataset\B"
img_rows, img_cols = 224, 224
batch_size = 16
epochs = 30
freeze_num = 379
optimizer = optimizers.Adam(lr=0.0001)
# 加载数据集
def load_dataset(a_path, b_path):
X_train = []
Y_train = []
for i in range(dataset):
img_path = a_path + '/' + 'a' + str(i) + '.jpg'
img = get_img(img_path, img_rows, img_cols)
X_train.append(img)
Y_train.append(0)
img_path = b_path + '/' + 'b' + str(i) + '.jpg'
img = get_img(img_path, img_rows, img_cols)
X_train.append(img)
Y_train.append(1)
X_train = np.array(X_train, np.float32)
Y_train = oneHot(Y_train)
return X_train, Y_train
# 读取图片
def get_img(file_path, img_rows, img_cols):
img = cv2.imread(file_path)
img = cv2.resize(img, (img_rows, img_cols))
if img.shape[2] == 1:
img = np.dstack([img, img, img])
else:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img.astype(np.float32)
return img
# 对标签数据进行one-hot编码
def oneHot(y):
return np_utils.to_categorical(y, len(np.unique(y)))
# 绘制训练过程中的 loss 和 acc 变化曲线
def history_plot(history_fit):
plt.figure(figsize=(12, 6))
# summarize history for accuracy
plt.subplot(121)
plt.plot(history_fit.history["acc"])
plt.plot(history_fit.history["val_acc"])
plt.title("model accuracy")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(["train", "valid"], loc="upper left")
# summarize history for loss
plt.subplot(122)
plt.plot(history_fit.history["loss"])
plt.plot(history_fit.history["val_loss"])
plt.title("model loss")
plt.ylabel("loss")
plt.xlabel("epoch")
plt.legend(["train", "test"], loc="upper left")
plt.show()
# fine-tune 模型
def fine_tune_model(model, optimizer, batch_size, epochs, freeze_num,X_train,Y_train):
for layer in model.layers[:]:
layer.trainable = True
rc = ReduceLROnPlateau(monitor="val_loss",
factor=0.2,
patience=3,
verbose=1,
mode='min')
model_name = model.name + ".hdf5"
mc = ModelCheckpoint(model_name,
monitor="val_loss",
save_best_only=True,
verbose=1,
mode='min')
el = EarlyStopping(monitor="val_loss",
min_delta=0,
patience=5,
verbose=1,
restore_best_weights=True)
model.compile(optimizer=optimizer,
loss='categorical_crossentropy',
metrics=["accuracy"])
history_fit = model.fit(X_train,
Y_train,
batch_size=batch_size,
epochs=epochs,
shuffle=True,
verbose=1,
validation_split=0.3,
callbacks=[mc, rc, el])
print('Finish fine-tune')
return history_fit
# 定义一个加入Attention模块的Efficient网络架构即efficientnet-with-attention
def efficient_attention_model(img_rows, img_cols,n_classes):
in_lay = Input(shape=(img_rows, img_cols, 3))
base_model = EfficientNetB3(input_shape=(img_rows, img_cols, 3), weights="imagenet", include_top=False)
pt_depth = base_model.get_output_shape_at(0)[-1]
pt_features = base_model(in_lay)
bn_features = BatchNormalization()(pt_features)
# here we do an attention mechanism to turn pixels in the GAP on an off
atten_layer = Conv2D(64, kernel_size=(1, 1), padding="same", activation="relu")(Dropout(0.5)(bn_features))
atten_layer = Conv2D(16, kernel_size=(1, 1), padding="same", activation="relu")(atten_layer)
atten_layer = Conv2D(8, kernel_size=(1, 1), padding="same", activation="relu")(atten_layer)
atten_layer = Conv2D(1, kernel_size=(1, 1), padding="valid", activation="sigmoid")(atten_layer) # H,W,1
# fan it out to all of the channels
up_c2_w = np.ones((1, 1, 1, pt_depth)) # 1,1,C
up_c2 = Conv2D(pt_depth, kernel_size=(1, 1), padding="same", activation="linear", use_bias=False, weights=[up_c2_w])
up_c2.trainable = False
atten_layer = up_c2(atten_layer) # H,W,C
mask_features = multiply([atten_layer, bn_features]) # H,W,C
gap_features = GlobalAveragePooling2D()(mask_features) # 1,1,C
gap_dr = Dropout(0.25)(gap_features)
dr_steps = Dropout(0.25)(Dense(1000, activation="relu")(gap_dr))
out_layer = Dense(n_classes, activation="softmax")(dr_steps)
eb_atten_model = Model(inputs=[in_lay], outputs=[out_layer])
return eb_atten_model
# 加载数据集和标签集
X_train, Y_train = load_dataset(a_path, b_path)
# 创建Efficient模型
eB_atten_model = efficient_attention_model(img_rows,img_cols,n_classes)
# 进行训练
eB_model_history = fine_tune_model(eB_atten_model,optimizer,batch_size,epochs,freeze_num,X_train,Y_train)
# 绘制训练过程中的 loss 和 acc 变化曲线
history_plot(eB_model_history)