keras實現基於vgg16的貓-狗二分類網路
阿新 • • 發佈:2018-12-20
import keras from keras.models import Sequential from keras.layers import Dense,MaxPooling2D,Input,Flatten,Convolution2D,Dropout from keras.optimizers import SGD from keras.callbacks import TensorBoard,ModelCheckpoint from PIL import Image import os import numpy as np from scipy import misc root_path = os.getcwd() def load_data(): tran_imags = [] labels = [] seq_names = ['cat','dog'] for seq_name in seq_names: frames = sorted(os.listdir(os.path.join(root_path,'data','train_data', seq_name))) for frame in frames: imgs = [os.path.join(root_path, 'data', 'train_data', seq_name, frame)] imgs = np.array(Image.open(imgs[0])) tran_imags.append(imgs) if seq_name=='cat': labels.append(0) else: labels.append(1) return np.array(tran_imags), np.array(labels) def vgg_cat_dog(weights_path=None): model = Sequential() model.add(Convolution2D(64,(3,3),activation='relu',padding='same',input_shape=(224,224,3))) model.add(Convolution2D(64,(3,3),activation='relu',padding='same')) model.add(MaxPooling2D((2,2),strides=(2,2))) model.add(Convolution2D(128,(3,3),activation='relu',padding='same')) model.add(Convolution2D(128,(3,3),activation='relu',padding='same')) model.add(MaxPooling2D((2,2),strides=(2,2))) model.add(Convolution2D(256,(3,3),activation='relu',padding='same')) model.add(Convolution2D(256,(3,3),activation='relu',padding='same')) model.add(Convolution2D(256,(3,3),activation='relu',padding='same')) model.add(MaxPooling2D((2,2),strides=(2,2))) model.add(Convolution2D(512,(3,3),activation='relu',padding='same')) model.add(Convolution2D(512,(3,3),activation='relu',padding='same')) model.add(Convolution2D(512,(3,3),activation='relu',padding='same')) model.add(MaxPooling2D((2,2),strides=(2,2))) model.add(Convolution2D(512,(3,3),activation='relu',padding='same')) model.add(Convolution2D(512,(3,3),activation='relu',padding='same')) model.add(Convolution2D(512,(3,3),activation='relu',padding='same')) model.add(MaxPooling2D((2,2),strides=(2,2))) if weights_path: model.load_weights(weights_path) model.add(Flatten()) model.add(Dense(500,activation='relu')) model.add(Dropout(0.5)) model.add(Dense(100,activation='relu')) model.add(Dropout(0.5)) model.add(Dense(2,activation='softmax')) return model train_data,train_labs = load_data() train = True if train: model = vgg_cat_dog('model/vgg_16_without_fc.h5') sgd = SGD(lr=1e-6,momentum=0.9,decay=1e-6,nesterov=True) model.compile(optimizer=sgd,loss='categorical_crossentropy',metrics=['accuracy']) tensorboard = TensorBoard(log_dir='log/cat_dog',histogram_freq=10,write_images=True) ckpt = ModelCheckpoint(os.path.join(root_path,'model','cat_dog','vgg.h5'),verbose=1,period=5) model.fit(train_data,keras.utils.to_categorical(train_labs),batch_size=32,epochs=50,verbose=1, callbacks=[tensorboard,ckpt],validation_split=0.1,shuffle=True) else: model = vgg_cat_dog() model.load_weights('model/cat_dog/vgg.h5') frames = sorted(os.listdir(os.path.join(root_path,'data','test', 'cat'))) for frame in frames: imgs = [os.path.join(root_path, 'data', 'test', 'cat', frame)] im = np.expand_dims(np.array(misc.imresize(Image.open(imgs[0]), [224, 224])), axis=0) cal = np.argmax(model.predict(im)) if cal: print('dog') else: print('cat')
使用在imagenet上的預訓練好的前13層的權重進行fine-tune,訓練集貓狗各420張左右,進行了50輪訓練,效果還不錯
記:1,開始未加dropout. 微調時,引數調的不多,第一次設定的學習率過大(0.1),損失居高不下一條直線,精度也是一條直線(0.1)。 第二次設定的1e-8,網路開始收斂,比較慢,最後選擇1e-6,訓練集精度達到95左右,驗證集只有50左右的精度,過擬合。
2. 新增dropout層,引數不變,驗證集精度飆升,由上圖可見40輪左右基本穩定下來了,不得不感嘆,dropout真是好啊。