1. 程式人生 > >keras 預訓練模型finetune,多模型ensemble,修改loss函式,調節學習率

keras 預訓練模型finetune,多模型ensemble,修改loss函式,調節學習率

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)