【火炉炼AI】深度学习007-Keras微调进一步提升性能

【火炉炼AI】深度学习007-Keras微调进一步提升性能

(本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, Keras 2.1.6, Tensorflow 1.9.0)

本文使用微调(Fine-tune)技术来提升模型的性能,是前面的两篇文章(编号为005和006)的延续。前面我们通过迁移学习(文章006)将这个猫狗大战二分类问题的预测准确率提升到了90%左右,但是还能不能进一步提升了?

前面我们没有对VGG16的卷积层进行参数的优化,那么我们这里就可以来优化这部分的参数,当然,优化是很细微的调整,所以称为Fine-tune。

微调也不是对VGG16的所有结构参数都进行调整,而是仅仅调整后面几个卷积层的参数,因为有很多学者发现,对不同的数据集,VGG16提取的特征在底层基本一样,主要区别在于高层,即卷积层的后面几层,所以只需要对这几层进行修改即可。如下我们要调整的层数为:

image

可以看出,主要调整Conv block 5,前面的4个block不需调整。

我这篇博文主要参考了:keras系列︱图像多分类训练与利用bottleneck features进行微调(三),这篇博文也是参考的Building powerful image classification models using very little data,但我发现这两篇博文有很多地方的代码跑不起来,主要原因可能是Keras或Tensorflow升级造成的,所以我做了一些必要的修改。


1. 准备数据集

这一部分和前面文章(编号005)一模一样,故而省略。


2. 构建模型

在模型的构建上,相当于是取VGG16模型的“身子”,再加上自己定义的模型作为“头”,将这两部分加在一起,组成一个完整的模型,“身子”模型仍然采用VGG16在ImageNet上得到的weights,而“头”模型则采用我们上一篇文章中训练得到的weights,然后用这个模型来训练和预测,将“身子”的一部分weights和“头”的全部weights都进行调整。

这里有几个注意点:

1,自己定义的分类器模型作为“头”,但是“头”的weights不能是随机初始值,而应该用已经训练好的weights,因为随机初始值会产生较大的梯队,会破坏前面VGG16卷积层的预训练后weights。

2,微调仅仅针对VGG16网络的后面几层卷积层,而不是全部卷积层,是为了防止过拟合,整个模型结构具有绝大的熵容量,因此有很高的过拟合倾向。并且底层的特征更加具有一般性,不需要调整。

3,在learning rate上,训练“头”的weights时可以用较大的lr,使其快速收敛,而在微调阶段,需要用较小的lr,使其性能达到最优,并且使用的optimizer也通常使用SGD而不是其他自适应学习率的优化算法,比如RMSProp,就是为了保证每次改进的幅度比较低,以免破坏VGG16提取的特征。

# 上面的build_model2中间的my_model.layers[:25]要修改为my_model.layers[:15],原博文此处也是错的。
# 4,构建模型
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras import applications
from keras import optimizers
from keras.models import Model
def build_model2():
    base_model = applications.VGG16(weights='imagenet', include_top=False,input_shape=(IMG_W, IMG_H,IMG_CH))
    # 此处我们只需要卷积层不需要全连接层,故而inclue_top=False,一定要设置input_shape,否则后面会报错
    # 这一步使用applications模块自带的VGG16函数直接加载了模型和参数,作为我们自己模型的“身子”
    
    # 下面定义我们自己的分类器,作为我们自己模型的“头”
    top_model = Sequential()
    top_model.add(Flatten(input_shape=base_model.output_shape[1:])) # 如果没有设置input_shape,这个地方报错,显示output_shape有很多None
    top_model.add(Dense(256, activation='relu'))
    top_model.add(Dropout(0.5))
    top_model.add(Dense(1, activation='sigmoid')) # 二分类问题
    
    top_model.load_weights('E:\PyProjects\DataSet\FireAI\DeepLearning\FireAI006/top_FC_model') 
    # 上面定义了模型结构,此处要把训练好的参数加载进来,
    
    my_model = Model(inputs=base_model.input, outputs=top_model(base_model.output)) # 将“身子”和“头”组装到一起
    # my_model就是我们组装好的完整的模型,也已经加载了各自的weights
    
    # 普通的模型需要对所有层的weights进行训练调整,但是此处我们只调整VGG16的后面几个卷积层,所以前面的卷积层要冻结起来
    for layer in my_model.layers[:15]: # 15层之前都是不需训练的,原博文此处也是错的。我晕。。。。
        layer.trainable = False
        
    # 模型的配置
    my_model.compile(loss='binary_crossentropy',
                  optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), # 使用一个非常小的lr来微调
                  metrics=['accuracy'])
    return my_model

这个模型的构建中需要将不训练的层冻结,如上设置trainable=False即可,下面进行微调训练:

# 开始用train set来微调模型的参数
print('start to train model2')
my_model2=build_model2()
history_ft2 = my_model2.fit_generator(
        train_generator,
        steps_per_epoch=train_samples_num // batch_size,
        epochs=epochs,
        validation_data=val_generator,
        validation_steps=val_samples_num // batch_size)

-------------------------------------输---------出--------------------------------

start to train model2
Epoch 1/20
125/125 [==============================] - 727s 6s/step - loss: 0.3288 - acc: 0.8865 - val_loss: 0.2991 - val_acc: 0.9113
Epoch 2/20
125/125 [==============================] - 732s 6s/step - loss: 0.1822 - acc: 0.9395 - val_loss: 0.2988 - val_acc: 0.9113
Epoch 3/20
125/125 [==============================] - 724s 6s/step - loss: 0.1557 - acc: 0.9445 - val_loss: 0.2742 - val_acc: 0.9125

...

Epoch 18/20
125/125 [==============================] - 703s 6s/step - loss: 0.0260 - acc: 0.9905 - val_loss: 0.3304 - val_acc: 0.9313
Epoch 19/20
125/125 [==============================] - 704s 6s/step - loss: 0.0138 - acc: 0.9955 - val_loss: 0.3267 - val_acc: 0.9413
Epoch 20/20
125/125 [==============================] - 705s 6s/step - loss: 0.0103 - acc: 0.9960 - val_loss: 0.3551 - val_acc: 0.9325

--------------------------------------------完-------------------------------------

在我这个破笔记本上训练非常耗时,20个epoch花了将近四个小时,唉。所以就不打算继续训练下去了。看一下loss和acc的结果:

image

可以看出test上的acc还可以继续改进一下,train 和test上的loss也没有达到平台期,可以增大epoch继续训练。但是也可以看出有些过拟合现象。

########################小**********结###############################

1,Fine-Tune的核心是对原始的骨架网络(此处为VGG16)进行参数的微调,所以需要用非常小的学习率,而且要用SGD优化器。

2,在使用微调之后,准确率从90%左右提升到了约93%,增加epoch数目可以提升的更多。

#################################################################


注:本部分代码已经全部上传到(我的github)上,欢迎下载。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355

推荐阅读更多精彩内容