【深度学习】迁移学习方法的妙用(有效提升准确率)

这把我C 2021-04-26 17:26:00 8563

..```python
文章目录
1 一个普通的神经网络
1.1 数据预处理
1.2 分割训练集和测试集合
1.3 搭建模型
2 使用ImageNet数据集
2.1 搭建模型
2.2 训练后结果
3 快速迁移学习
3.1 搭建特征提取模型并导出特征
3.2 训练全联接分类器
4 模型融合


# 1 一个普通的神经网络
![在这里插入图片描述](https://ebaina.oss-cn-hangzhou.aliyuncs.com/res/article/202304/26/644879ed48b9c60322.png)

接下来的内容,我们以 gaggle 上的一个比赛一猫狗大战(htps: / www. Kaggle.com/c/dogs-vs-cats-redux-kernels-edition)的数据集为例,来谈谈如何基于迁移学习实现高准确率的猫狗图像分类。该比赛提供了 25000 张图作为训练集,猫狗各占一半,测试集 12500 张,没有标定是猫还是狗。

```python
➜  猫狗大战 ls train | head
cat.0.jpg
cat.1.jpg
cat.10.jpg
cat.100.jpg
cat.1000.jpg
cat.10000.jpg
cat.10001.jpg
cat.10002.jpg
cat.10003.jpg
cat.10004.jpg
➜  猫狗大战 ls test | head
1.jpg
10.jpg
100.jpg
1000.jpg
10000.jpg
10001.jpg
10002.jpg
10003.jpg
10004.jpg
10005.jpg

在这里插入图片描述

1.1 数据预处理

由于我们的数据集的文件名是以type.num.jpg这样的方式命名的,比如cat.0.jpg,但是使用 Keras 的 ImageDataGenerator 需要将不同种类的图片分在不同的文件夹中,因此我们需要对数据集进行预处理。这里我们采取的思路是创建符号链接(symbol link),这样的好处是不用复制一遍图片,占用不必要的空间。

我们可以从下面看到文件夹的结构,train2里面有两个文件夹,分别是猫和狗,每个文件夹里是12500张图。

├── test [12500 images]
├── test.zip
├── test2
│   └── test -> ../test/
├── train [25000 images]
├── train.zip
└── train2
    ├── cat [12500 images]
    └── dog [12500 images]

1.2 分割训练集和测试集合

这部分工作不再赘述。

1.3 搭建模型

inputs = Input((width, width, 3))
x = inputs
for i, layer_num in enumerate([2, 2, 3, 3, 3]):
    for j in range(layer_num):
        x = Conv2D(32*2**i, 3, padding='same', activation='relu')(x)
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
    x = MaxPooling2D(2)(x)

x = GlobalAveragePooling2D()(x)
x = Dropout(0.5)(x)
x = Dense(1, activation='sigmoid')(x)

model = Model(inputs, x)
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
h = model.fit(X_train, y_train, batch_size=32, epochs=50, validation_data=(X_valid, y_valid))

在这里插入图片描述

2 使用ImageNet数据集

迁移学习是一个很有意义的技术,它能够直接利用一个身经百战的模型脑子里的知识来学习新的数据集,达到与之前相当、甚至比之前的模型还好的表现。

在没有迁移学习以前,人们训练一个模型通常要非常久的时间。例如,如果有 4 块 NVIDIA Titan Black 显卡,想在 Imagenet 数据集上训练一个 VGG16 模型,那么进行完整的训练需要 2~3 周的时间。这是非常浪费时间、浪费电费的做法,完全可以利用别人已经训练好的 GG16 模型的权值,然后利用其中的卷积核权重。

在 Imagenet 数据集上预训练过的权重,靠近输入的那几层卷积层一般都是识别各种边缘信息或者颜色信息,除非是与 Imagenet 差异非常大的数据集。
VGG16 是一个很经典的模型,它的特征提取部分只使用了 3×3 的卷积核,以及 2×2 的池化层。在它之前很多人都认为巻积核要比较大才能识别更大的区域,不过根据计算可以知道,两个卷积核大小为 3×3 的卷积层可以有效覆盖 5×5 的区域,同时还可以减少计算量,以及增加非线性能力,这也是 VGG 系列模型的核心思想,就是减小卷积核,加深网络,如图 9-3 所示。

VGG 的名字来自于 Visual Geometry Group,这是牛津大学的一个实验室。他们发的论文标题也很直接:Very Deep Convolutional Networks for Large- Scale Visual Recognition,意思是用于大规模视觉识别的非常深的卷积神经网络。

在这里插入图片描述
在这里插入图片描述

2.1 搭建模型

cnn_model = VGG16(include_top=False, input_shape=(width, width, 3), weights='imagenet')

for layer in cnn_model.layers:
    layer.trainable = False

inputs = Input((width, width, 3))
x = inputs
x = Lambda(preprocess_input, name='preprocessing')(x)
x = cnn_model(x)
x = GlobalAveragePooling2D()(x)
x = Dense(512, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(1, activation='sigmoid')(x)

model = Model(inputs, x)
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

2.2 训练后结果

在这里插入图片描述

3 快速迁移学习

我们知道,迁移学习是不需要修改前面几十层卷积层的,
但是在训练的时候依然会浪费很多时间在 cnn model 上,这是不必要的。
为了节省时间,可以先用 cnn model 预测得到特征,再合并特征,训练分类器进行分类即可。
这种基于原模型直接得到预测的特征,并基于原模型预测特征做进一步分析的方法称为快速迁移学习。

快速迁移学习的步骤如下:

载入数据集

搭建预训练模型(cnn model

导出数据集的特征

搭建简单全连接分类器模型(model

训练模型

3.1 搭建特征提取模型并导出特征

def get_features(MODEL, data=X):
    cnn_model = MODEL(include_top=False, input_shape=(width, width, 3), weights='imagenet')

    inputs = Input((width, width, 3))
    x = inputs
    x = Lambda(preprocess_input, name='preprocessing')(x)
    x = cnn_model(x)
    x = GlobalAveragePooling2D()(x)
    cnn_model = Model(inputs, x)

    features = cnn_model.predict(data, batch_size=64, verbose=1)
    return features

3.2 训练全联接分类器

正常训练流程即可。

4 模型融合

融合模型的方法很简单,首先将特征提取出来,然后拼接在一起,构建一个全连接分类器训练就可以了
模型融合能够提高成绩的理论依据是,有些模型辨认猫准确率高,有些模型辨认狗准确率高,给这些模型不同的权重,让它们能够取长补短,综合各自的优势。为了能够更好地融合模型可以提取特征进行融合,这样会有更好的效果,弱特征的权重会越学越小,强特征会越学越大,最后得到效果非常好的模型。

inputs = Input(features.shape[1:])
x = inputs
x = Dropout(0.5)(x)
x = Dense(1, activation='sigmoid')(x)
model = Model(inputs, x)
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
h = model.fit(features, y, batch_size=128, epochs=10, validation_split=0.2)

在这里插入图片描述

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 94 5 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
这把我C
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区