keras 預訓練模型finetune,多模型ensemble,修改loss函式,調節學習率
阿新 • • 發佈:2018-12-11
keras 預訓練模型finetune,多模型ensemble,修改loss函式,調節學習率
載入預訓練模型並finetune
這裡使用的是keras庫裡的MobileNet模型,預訓練權重也是官方自帶的,最終finetune為自己需要的分類
from keras.layers import Activation, Convolution2D, Dropout, Conv2D, Average from keras.layers import AveragePooling2D, BatchNormalization from keras.layers import GlobalAveragePooling2D from keras.models import Sequential from keras.layers import Flatten from keras.models import Model from keras.layers import Input from keras.layers import MaxPooling2D from keras.layers import SeparableConv2D from keras import layers from keras.regularizers import l2 from keras.applications.mobilenet import MobileNet from keras import models from keras import layers input_shape = (224,224,3) img_input = Input(input_shape) num_classes = 7 def mobilenet(img_input, num_classes): #載入ImageNet的預訓練權重 base_model = MobileNet(weights='imagenet', include_top = False, input_tensor=img_input) #不凍結網路層,這裡可以自己選擇是否要訓練某一層網路 for layer in base_model.layers: layer.trainable = True last = base_model.output x = Conv2D(num_classes,(3,3),padding='same')(last) x = GlobalAveragePooling2D()(x) output = Activation('softmax',name='predictions1')(x) model = Model(img_input, output) return model
修改loss函式
from keras import backend as K #這裡可以自己修改想要的loss函式 def my_object(y_true,y_pred): l1 = -1*K.sum(y_true*K.log(y_pred)) l2 = (1-y_true)*(y_pred) s = -1*K.sum(l2*l2*K.log(1-l2)) return l1+s #model.compile(optimizer='adam', loss='categorical_crossentropy',metrics=['accuracy']) model.compile(optimizer='adam', loss=my_object,metrics=['accuracy']) model.summary()
兩個網路做ensemble,進行網路訓練,調節learning rate
這裡我做的是最簡單的對兩個網路的輸出進行平均值操作
定義另外一個網路
def CNN(img_input, num_classes): x = Conv2D(8, (3, 3), strides=(1, 1),use_bias=False)(img_input) x = BatchNormalization()(x) x = Activation('relu')(x) x = Conv2D(8, (3, 3), strides=(1, 1),use_bias=False)(x) x = BatchNormalization()(x) x = Activation('relu')(x) x = Conv2D(num_classes, (3, 3), padding='same')(x) x = GlobalAveragePooling2D()(x) output = Activation('softmax',name='predictions')(x) model = Model(img_input, output) return model
還有一個就是上面提到的MobileNet,這裡要注意一點,兩個網路裡面的結構命名不能重複,否則會報錯
from keras.layers import Activation, Convolution2D, Dropout, Conv2D, Average
from keras.models import Model
def ensemble(models, img_input):
outputs = [model.outputs[0] for model in models]
y = Average()(outputs)
model = Model(img_input,y,name='ensemble')
return model
訓練網路,並且調節學習速率
from keras.layers import Input
input_shape = (224,224,3)
img_input = Input(input_shape)
num_classes = 7
model1 = CNN(img_input,num_classes)
model2 = mobilenet(img_input,num_classes)
models = [model1,model2]
#將兩個網路的結果融合起來
model = ensemble(models,img_input)
model.compile(optimizer='adam', loss=my_object,metrics=['accuracy'])
model.summary()
#開始訓練 調節學習率
for index in range(45000):
if index%15000 == 0 and index != 0:
lr = K.get_value(model.optimizer.lr)
K.set_value(model.optimizer.lr, lr*0.1)
print("lr: ",lr)
#訓練自己的資料
log = model.train_on_batch(x_train,y_train)
print(index,log)