keras网络下vgg的迁移学习,代码详解

吃水不忘挖井人

参考博客:https://blog.csdn.net/u012524708/article/details/79609118
https://blog.csdn.net/sinat_26917383/article/details/72861152
简单的keras网络搭建参考,很清楚
https://www.jianshu.com/p/09b5a5d82eec
接下来编写两种VGG 迁移方法训练

1. fine-tuning方式一:使用预训练网络的bottleneck特征

1、加载预训练权重
2、运行,提取bottleneck feature(网络在全连接之前的最后一层激活的feature
map,卷积-全连接层之间),单独拿出来,并保存
3、bottleneck层数据,之后 + dense全连接层,进行fine-tuning

加载预训练权重
#from keras.applications.vgg16_matt import VGG16  
from keras.applications import VGG16
model=applications.VGG16(weights="imagenet",include_top=False,input_shape=(img_size, img_size, 3))
model.summary()
提取bottleneck特征

需要步骤:

载入图片;
灌入pre-model的权重;
得到bottleneck feature

数据目录格式
date

  • class1
  • class2
读取数据,载入训练集,测试集
#本实验用pkl保存数据
#读取数据
Train_Combined = pd.read_pickle("./date/engage_Dateframe/df_human_train.pkl")  # no animate,only rename
Test_Humans = pd.read_pickle("./date/engage_Dateframe/df_human_test.pkl")

print(Train_Combined.shape, Test_Humans.shape)  # (141, 4) (29, 4) (43, 4)
TrainCombined_batch_pointer = 0
CVHumans_batch_pointer = 0
TestHumans_batch_pointer = 0

print("now training")

TrainCombined_Labels = pd.get_dummies(Train_Combined["Labels"]).as_matrix()
print(TrainCombined_Labels.shape)

TestHuman_Labels = pd.get_dummies(Test_Humans["Labels"]).as_matrix()
print(TestHuman_Labels.shape)


# model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['acc'])
# model.compile(loss='categorical_crossentropy', optimizer=SGD(lr=0.001, momentum=0.9, nesterov=True), metrics=["acc"])由于pkl
#由于pkl文件的格式,这里需要进行对其处理

def loadCombinedTrainBatch(size): #训练集
   global TrainCombined_batch_pointer
   batch_images = []
   batch_labels = []
   for i in range(size):
       path1 = Train_Combined.iloc[TrainCombined_batch_pointer + i]["folderName"]
       path2 = Train_Combined.iloc[TrainCombined_batch_pointer + i]["imageName"]
       read_image = Image.open(os.path.join(path1, path2))
       read_image_final = np.array(read_image) / 255.0  # here, we are normalizing the images
       #         print(read_image_final.shape)
       batch_images.append(read_image_final)
       #         print(batch_images)
       batch_labels.append(TrainCombined_Labels[TrainCombined_batch_pointer + i])  # appending corresponding labels

   TrainCombined_batch_pointer += size
   return np.array(batch_images), np.array(batch_labels)


def loadCombinedTestBatch(size):  #测试集
   global TestHumans_batch_pointer
   batch_images = []
   batch_labels = []
   for i in range(size):
       path1 = Test_Humans.iloc[TestHumans_batch_pointer + i]["folderName"]
       path2 = Test_Humans.iloc[TestHumans_batch_pointer + i]["imageName"]
       read_image = Image.open(os.path.join(path1, path2))
       read_image_final = np.array(read_image) / 255.0  # here, we are normalizing the images
       #         print(read_image_final.shape)
       batch_images.append(read_image_final)
       #         print(batch_images)
       batch_labels.append(TestHuman_Labels[TestHumans_batch_pointer + i])  # appending corresponding labels

   TestHumans_batch_pointer  += size
   return np.array(batch_images), np.array(batch_labels)


x_train, y_train = loadCombinedTrainBatch(len(Train_Combined)) 
x_test, y_test = loadCombinedTestBatch(len(Test_Humans)) 
提取bottleneck特征
bottleneck_features_train = model.predict(x_train)
np.save(('bottle_feature/bottleneck_features_train.npy'), bottleneck_features_train)
np.save(('bottle_feature/bottleneck_features_train_labels.npy'), y_train)

bottleneck_features_validation = model.predict(x_test)
np.save(('bottle_feature/bottleneck_features_validation.npy'), bottleneck_features_validation)
np.save(('bottle_feature/bottleneck_features_validation_labels.npy'), y_test)

训练

#全链接层,顶层设计
def train_top_model():
    train_data = np.load('bottle_feature/bottleneck_features_train.npy')
    print('train_data shape',train_data.shape)
    train_labels = np.load('bottle_feature/bottleneck_features_train_labels.npy')
    validation_data = np.load('bottle_feature/bottleneck_features_validation.npy')
    print("validation_data.shape",validation_data.shape)
    validation_labels = np.load('bottle_feature/bottleneck_features_validation_labels.npy')

    model = Sequential()
    print(train_data.shape[1:])
    model.add(Flatten(input_shape=train_data.shape[1:]))
    model.add(Dense(256,activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(2,activation='sigmoid'))

    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
	#training
    history=model.fit(train_data,train_labels, #此处用fit,遗憾不可以在线数据增强
              epochs=epochs,
              batch_size=batch_size,
              validation_data=(validation_data,validation_labels))
    model.save_weights('date/model_save/bottleneck_fc_model.h5')
    model.save('date/model_save/model.h5')
    return history,model
#可视化
history,model_all=train_top_model()
print(history.history)
# 绘制训练 & 验证的准确率值
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['acc', "val_acc"], loc='upper right')
plt.show()

参考

#如何提取bottleneck feature
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense

# (1)载入图片
# 图像生成器初始化
from keras.preprocessing.image import ImageDataGenerator
import numpy as np
datagen = ImageDataGenerator(rescale=1./255)

# 训练集图像生成器
generator = datagen.flow_from_directory(
        '/home/ubuntu/keras/animal5/train',
        target_size=(150, 150),
        batch_size=32,
        class_mode=None,
        shuffle=False) 

# 验证集图像生成器
generator = datagen.flow_from_directory(
        '/home/ubuntu/keras/animal5/validation',
        target_size=(150, 150),
        batch_size=32,
        class_mode=None,
        shuffle=False)

#(2)灌入pre-model的权重
model.load_weights('/.../vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5')

#(3)得到bottleneck feature
bottleneck_features_train = model.predict_generator(generator, 500)
# 核心,steps是生成器要返回数据的轮数,每个epoch含有500张图片,与model.fit(samples_per_epoch)相对
np.save(open('bottleneck_features_train.npy', 'w'), bottleneck_features_train)

bottleneck_features_validation = model.predict_generator(generator, 100)
# 与model.fit(nb_val_samples)相对,一个epoch有800张图片,验证集
np.save(open('bottleneck_features_validation.npy', 'w'), bottleneck_features_validation)

fine-tuning方式二:要调整权重

在这里插入图片描述

文件格式
date

  • train
    • 0
    • 1
  • test
    • 0
    • 1

fine-tune分三个步骤:

搭建vgg-16并载入权重,将之前定义的全连接网络加在模型的顶部,并载入权重
冻结vgg16网络的一部分参数
模型训练

此方法与上述方法有所不同
1.不需提取离线特征
2.图像文件格式不同
3.此方法将全链接层与卷基层连在一起,并冻结之前的卷基层。

注意:

1、fine-tune,所有的层都应该以训练好的权重为初始值,例如,你不能将随机初始的全连接放在预训练的卷积层之上,这是因为由随机权重产生的大梯度将会破坏卷积层预训练的权重。
2、选择只fine-tune最后的卷积块,而不是整个网络,这是为了防止过拟合。整个网络具有巨大的熵容量,因此具有很高的过拟合倾向。由底层卷积模块学习到的特征更加一般,更加不具有抽象性,因此我们要保持前两个卷积块(学习一般特征)不动,只fine-tune后面的卷积块(学习特别的特征)
3、fine-tune应该在很低的学习率下进行,通常使用SGD优化而不是其他自适应学习率的优化算法,如RMSProp。这是为了保证更新的幅度保持在较低的程度,以免毁坏预训练的特征

1.加载权重

model=applications.VGG16(weights="imagenet",include_top=False,input_shape=(img_size, img_size, 3))
model.summary()

2.顶层网络添加方法

x = model.output
# 最有问题的层:flatten层
x = Flatten(name='flatten')(x)
x = Dense(256, activation='relu', name='fc1')(x)
x = Dropout(0.5)(x)
predictions = Dense(2, activation='softmax')(x)

from keras.models import Model
vgg_model = Model(inputs=model.input, outputs=predictions) #网络链接要注意
print(model)

print(len(vgg_model.layers)) #23
dict_layers = dict([(layer.name,layer) for layer in vgg_model.layers])
print(len(dict_layers) )# 23
plot_model(vgg_model,to_file='vgg16_fc.png',show_shapes=True)
# 冻结了conv block5之前的所有卷积层权重,不包括输入层
for layer in vgg_model.layers[1:15]:
    # print layer.name,layer
    layer.trainable = False
vgg_model.compile(loss='binary_crossentropy', optimizer=SGD(lr=1e-4, momentum=0.9), metrics=['acc'])
训练模型
# 准备数据
train_data_dir = '/.../train'
validation_data_dir = '/.../validation'
img_width, img_height = 150, 150
nb_train_samples = 500
nb_validation_samples = 100
epochs = 50
batch_size = 16

# 图片预处理生成器
train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)

# 图片generator
train_generator = train_datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_height, img_width),
        batch_size=32,
        class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_height, img_width),
        batch_size=32,
        class_mode='categorical')

# 训练
vgg_model.fit_generator(
        train_generator,
        steps_per_epoch=nb_train_samples // batch_size,
        epochs=epochs,
        validation_data=validation_generator,
        validation_steps=nb_validation_samples // batch_size)

相比第二种更简单。
但是会报各种错误。
好吧,都报错,第二种相对于可视化更为方便。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值