很久之前就做完了这个实验,今天有时间整理记录下来!!
首先要去网上下载好vgg16\inceptionv3 ——notop.h5的权重,通过其提取特征,不用输出层如果有没有下载成功的可以给我留言我发给你哦!!然后用cp将其拷贝到~/.keras/models/里面,数据集用的是猫狗2分类(kaggle train2000 test 550)
import numpy as np
np.random.seed(1337)
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.models import Model
from keras.layers import Activation,Dropout, Flatten, Dense,AveragePooling2D
from keras.layers import Conv2D,MaxPooling2D,Input
from keras.applications.vgg16 import VGG16
from keras import backend as K
import matplotlib.pyplot as plt
import h5py
import os
from keras.utils.vis_utils import plot_model
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
if(K.image_dim_ordering()=='th'):
input_tensor=Input(shape=(3,200,200))
else:
input_tensor=Input(shape=(200,200,3))
base_model=VGG16(input_tensor=input_tensor,weights='imagenet',include_top=False)
x=base_model.output
x=AveragePooling2D((4,4),padding='valid',name='avg_pool')(x)
x=Flatten()(x)
x=Dense(64,activation='relu')(x)
x=Dropout(0.4)(x)
predictions=Dense(2,activation='softmax')(x)
model=Model(inputs=base_model.input,outputs=predictions)
for layer in base_model.layers:
layer.trainable=False
print('model.summary:')
#model.summary()
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
train_datagen=ImageDataGenerator(
rescale=1./255,
data_format='channels_last')
test_datagen=ImageDataGenerator(
rescale=1./255,
data_format='channels_last')
train_generator=train_datagen.flow_from_directory(
'train',
target_size=(200,200),
batch_size=32,
class_mode='categorical')
validation_generator=test_datagen.flow_from_directory(
'test',
target_size=(200,200),
batch_size=32,
class_mode='categorical')
history=model.fit_generator(
train_generator,
steps_per_epoch=30,
epochs=10,
validation_data=validation_generator,
validation_steps=10,verbose=1
)
plot_model(model,to_file='model.png',show_shapes=True)
plt.figure(1)
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train','test'],loc='upper left')
plt.figure(2)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train','test'],loc='upper left')
plt.show()
训练集的准确率达到0.8927,测试集达到0.8906
下面是inceptionv3迁移学习的代码:
import numpy as np
np.random.seed(1337)
from keras.preprocessing.image import ImageDataGenerator,array_to_img,img_to_array,load_img
from keras.applications.inception_v3 import InceptionV3
from keras.models import Model
from keras.layers import Dropout, Flatten, Dense,AveragePooling2D,Input
from keras import backend as K
import matplotlib.pyplot as plt
import h5py
from keras.utils.vis_utils import plot_model
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
train_datagen=ImageDataGenerator(
rescale=1./255,
data_format='channels_last')
test_datagen=ImageDataGenerator(
rescale=1./255,
data_format='channels_last')
#train_img='./data/train/'
#validation_img='./data/validation/'
if(K.image_dim_ordering()=='th'):
input_tensor=Input(shape=(3,200,200))
else:
input_tensor=Input(shape=(200,200,3))
base_model=InceptionV3(input_tensor=input_tensor,weights='imagenet',include_top=False)
x=base_model.output
x=AveragePooling2D((4,4),padding='valid',name='avg_pool')(x)
x=Dropout(0.4)(x)
x=Flatten()(x)
x=Dense(64,activation='relu')(x)
predictions=Dense(2,activation='softmax')(x)
model=Model(inputs=base_model.input,outputs=predictions)
for layer in base_model.layers:
layer.trainable=False
print('model.summary:')
#model.summary()
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
train_generator=train_datagen.flow_from_directory(
'train',
target_size=(200,200),
batch_size=32,
class_mode='categorical')
validation_generator=test_datagen.flow_from_directory(
'test',
target_size=(200,200),
batch_size=32,
class_mode='categorical')
history=model.fit_generator(
train_generator,
steps_per_epoch=40,
epochs=10,
validation_data=validation_generator,
validation_steps=10,verbose=1
)
plot_model(model,to_file='modelincepv3.png',show_shapes=True)
plt.figure(1)
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train','test'],loc='upper left')
plt.figure(2)
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train','test'],loc='upper left')
plt.show()
训练集0.89
测试集0.95 ,过程中出现了过拟合,有待解决!
启发:根据论文:A Deep Convolutional Activation Feature for Generic Visual Recognition中的结论:可以保留训练好的VGG/Incepv3所有卷积层的参数,只是替换最后一层全连接层,在最后这一层全连接层之前的网络层称为瓶颈层。一般来说,在数据量足够的情况下,迁移学习的效果不如完全重新训练,但是迁移学习所需要的训练时间和和训练样本数要远远小于训练完整的模型。
fine-tuning:使用已用于其他目标,预训练好模型的权重或部分权重,作为初始值开始训练
why用:首先自己从头开始训练CNN容易出现问题,其次fine-tuning能很快收敛到一个较为理想的状态
怎么做:一般复用相同层的权重,新定义层权重取随机初始值,注意调大新定义层的学习率,调小复用层的学习率
https://blog.csdn.net/cai13160674275/article/details/71078554:从keras看VGG16结构图,里面有详细的参数计算过程和结构
def VGG_16(weights_path=None):
model = Sequential()
model.add(ZeroPadding2D((1,1),input_shape=(3,224,224)))#卷积输入层,指定了输入图像的大小
model.add(Convolution2D(64, 3, 3, activation='relu'))#64个3x3的卷积核,生成64*224*224的图像,激活函数为relu
model.add(ZeroPadding2D((1,1)))#补0,保证图像卷积后图像大小不变,其实用padding = 'valid'参数就可以了
model.add(Convolution2D(64, 3, 3, activation='relu'))#再来一次卷积 生成64*224*224
model.add(MaxPooling2D((2,2), strides=(2,2)))#pooling操作,相当于变成64*112*112
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(128, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(128, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))#128*56*56
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))#256*28*28
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2)))#512*14*14
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(ZeroPadding2D((1,1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
model.add(MaxPooling2D((2,2), strides=(2,2))) #到这里已经变成了512*7*7
model.add(Flatten())#压平上述向量,变成一维25088
model.add(Dense(4096, activation='relu'))#全连接层有4096个神经核,参数个数就是4096*25088
model.add(Dropout(0.5))#0.5的概率抛弃一些连接
model.add(Dense(4096, activation='relu'))#再来一个全连接
model.add(Dropout(0.5))
model.add(Dense(1000, activation='softmax'))
if weights_path:
model.load_weights(weights_path)
return model
网友评论