0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

迁移学习的原理,基于Keras实现迁移学习

zhKF_jqr_AI 来源:未知 作者:李倩 2018-05-09 03:44 次阅读

数据科学家Prakash Jay介绍了迁移学习的原理,基于Keras实现迁移学习,以及迁移学习的常见情形。

Inception-V3

什么是迁移学习?

机器学习中的迁移学习问题,关注如何保存解决一个问题时获得的知识,并将其应用于另一个相关的不同问题。

为什么迁移学习?

在实践中,很少有人从头训练一个卷积网络,因为很难获取足够的数据集。使用预训练的网络有助于解决大多数手头的问题。

训练深度网络代价高昂。即使使用数百台配备了昂贵的GPU的机器,训练最复杂的模型也需要好多周。

决定深度学习的拓扑/特色/训练方法/超参数是没有多少理论指导的黑魔法。

我的经验

不要试图成为英雄。

—— Andrej Karapathy

我面对的大多数计算机视觉问题没有非常大的数据集(5000-40000图像)。即使使用极端的数据增强策略,也很难达到像样的精确度。而在少量数据集上训练数百万参数的网络通常会导致过拟合。所以迁移学习是我的救星。

迁移学习为何有效?

让我们看下深度学习网络学习了什么,靠前的层尝试检测边缘,中间层尝试检测形状,而靠后的层尝试检测高层数据特征。这些训练好的网络通常有助于解决其他计算机视觉问题。

下面,让我们看下如何使用Keras实现迁移学习,以及迁移学习的常见情形。

基于Keras的简单实现

from keras import applications

from keras.preprocessing.image importImageDataGenerator

from keras import optimizers

from keras.models importSequential, Model

from keras.layers importDropout, Flatten, Dense, GlobalAveragePooling2D

from keras import backend as k

from keras.callbacks importModelCheckpoint, LearningRateScheduler, TensorBoard, EarlyStopping

img_width, img_height = 256, 256

train_data_dir = "data/train"

validation_data_dir = "data/val"

nb_train_samples = 4125

nb_validation_samples = 466

batch_size = 16

epochs = 50

model = applications.VGG19(weights = "imagenet", include_top=False, input_shape = (img_width, img_height, 3))

"""

层 (类型) 输出形状 参数数量

=================================================================

input_1 (InputLayer) (None, 256, 256, 3) 0

_________________________________________________________________

block1_conv1 (Conv2D) (None, 256, 256, 64) 1792

_________________________________________________________________

block1_conv2 (Conv2D) (None, 256, 256, 64) 36928

_________________________________________________________________

block1_pool (MaxPooling2D) (None, 128, 128, 64) 0

_________________________________________________________________

block2_conv1 (Conv2D) (None, 128, 128, 128) 73856

_________________________________________________________________

block2_conv2 (Conv2D) (None, 128, 128, 128) 147584

_________________________________________________________________

block2_pool (MaxPooling2D) (None, 64, 64, 128) 0

_________________________________________________________________

block3_conv1 (Conv2D) (None, 64, 64, 256) 295168

_________________________________________________________________

block3_conv2 (Conv2D) (None, 64, 64, 256) 590080

_________________________________________________________________

block3_conv3 (Conv2D) (None, 64, 64, 256) 590080

_________________________________________________________________

block3_conv4 (Conv2D) (None, 64, 64, 256) 590080

_________________________________________________________________

block3_pool (MaxPooling2D) (None, 32, 32, 256) 0

_________________________________________________________________

block4_conv1 (Conv2D) (None, 32, 32, 512) 1180160

_________________________________________________________________

block4_conv2 (Conv2D) (None, 32, 32, 512) 2359808

_________________________________________________________________

block4_conv3 (Conv2D) (None, 32, 32, 512) 2359808

_________________________________________________________________

block4_conv4 (Conv2D) (None, 32, 32, 512) 2359808

_________________________________________________________________

block4_pool (MaxPooling2D) (None, 16, 16, 512) 0

_________________________________________________________________

block5_conv1 (Conv2D) (None, 16, 16, 512) 2359808

_________________________________________________________________

block5_conv2 (Conv2D) (None, 16, 16, 512) 2359808

_________________________________________________________________

block5_conv3 (Conv2D) (None, 16, 16, 512) 2359808

_________________________________________________________________

block5_conv4 (Conv2D) (None, 16, 16, 512) 2359808

_________________________________________________________________

block5_pool (MaxPooling2D) (None, 8, 8, 512) 0

=================================================================

总参数: 20,024,384.0

可训练参数: 20,024,384.0

不可训练参数: 0.0

"""

# 冻结不打算训练的层。这里我冻结了前5层。

for layer in model.layers[:5]:

layer.trainable = False

# 增加定制层

x = model.output

x = Flatten()(x)

x = Dense(1024, activation="relu")(x)

x = Dropout(0.5)(x)

x = Dense(1024, activation="relu")(x)

predictions = Dense(16, activation="softmax")(x)

# 创建最终模型

model_final = Model(input = model.input, output = predictions)

# 编译最终模型

model_final.compile(loss = "categorical_crossentropy", optimizer = optimizers.SGD(lr=0.0001, momentum=0.9), metrics=["accuracy"])

# 数据增强

train_datagen = ImageDataGenerator(

rescale = 1./255,

horizontal_flip = True,

fill_mode = "nearest",

zoom_range = 0.3,

width_shift_range = 0.3,

height_shift_range=0.3,

rotation_range=30)

test_datagen = ImageDataGenerator(

rescale = 1./255,

horizontal_flip = True,

fill_mode = "nearest",

zoom_range = 0.3,

width_shift_range = 0.3,

height_shift_range=0.3,

rotation_range=30)

train_generator = train_datagen.flow_from_directory(

train_data_dir,

target_size = (img_height, img_width),

batch_size = batch_size,

class_mode = "categorical")

validation_generator = test_datagen.flow_from_directory(

validation_data_dir,

target_size = (img_height, img_width),

class_mode = "categorical")

# 保存模型

checkpoint = ModelCheckpoint("vgg16_1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)

early = EarlyStopping(monitor='val_acc', min_delta=0, patience=10, verbose=1, mode='auto')

# 训练模型

model_final.fit_generator(

train_generator,

samples_per_epoch = nb_train_samples,

epochs = epochs,

validation_data = validation_generator,

nb_val_samples = nb_validation_samples,

callbacks = [checkpoint, early])

迁移学习的常见情形

别忘了,靠前的层中的卷积特征更通用,靠后的层中的卷积特征更针对原本的数据集。迁移学习有4种主要场景:

1. 新数据集较小,和原数据集相似

如果我们尝试训练整个网络,容易导致过拟合。由于新数据和原数据相似,因此我们期望卷积网络中的高层特征和新数据集相关。因此,建议冻结所有卷积层,只训练分类器(比如,线性分类器):

for layer in model.layers:

layer.trainable = False

2. 新数据集较大,和原数据集相似

由于我们有更多数据,我们更有自信,如果尝试对整个网络进行精细调整,不会导致过拟合。

for layer in model.layers:

layer.trainable = True

其实默认值就是True,上面的代码明确指定所有层可训练,是为了更清楚地强调这一点。

由于开始的几层检测边缘,你也可以选择冻结这些层。比如,以下代码冻结VGG19的前5层:

for layer in model.layers[:5]:

layer.trainable = False

3. 新数据集很小,但和原数据很不一样

由于数据集很小,我们大概想要从靠前的层提取特征,然后在此之上训练一个分类器:(假定你对h5py有所了解)

from keras import applications

from keras.preprocessing.image importImageDataGenerator

from keras import optimizers

from keras.models importSequential, Model

from keras.layers importDropout, Flatten, Dense, GlobalAveragePooling2D

from keras import backend as k

from keras.callbacks importModelCheckpoint, LearningRateScheduler, TensorBoard, EarlyStopping

img_width, img_height = 256, 256

### 创建网络

img_input = Input(shape=(256, 256, 3))

x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)

x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)

x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)

# 块2

x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)

x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)

x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)

model = Model(input = img_input, output = x)

model.summary()

"""

_________________________________________________________________

层 (类型) 输出形状 参数数量

=================================================================

input_1 (InputLayer) (None, 256, 256, 3) 0

_________________________________________________________________

block1_conv1 (Conv2D) (None, 256, 256, 64) 1792

_________________________________________________________________

block1_conv2 (Conv2D) (None, 256, 256, 64) 36928

_________________________________________________________________

block1_pool (MaxPooling2D) (None, 128, 128, 64) 0

_________________________________________________________________

block2_conv1 (Conv2D) (None, 128, 128, 128) 73856

_________________________________________________________________

block2_conv2 (Conv2D) (None, 128, 128, 128) 147584

_________________________________________________________________

block2_pool (MaxPooling2D) (None, 64, 64, 128) 0

=================================================================

总参数:260,160.0

可训练参数:260,160.0

不可训练参数:0.0

"""

layer_dict = dict([(layer.name, layer) for layer in model.layers])

[layer.name for layer in model.layers]

"""

['input_1',

'block1_conv1',

'block1_conv2',

'block1_pool',

'block2_conv1',

'block2_conv2',

'block2_pool']

"""

import h5py

weights_path = 'vgg19_weights.h5'# ('https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels.h5)

f = h5py.File(weights_path)

list(f["model_weights"].keys())

"""

['block1_conv1',

'block1_conv2',

'block1_pool',

'block2_conv1',

'block2_conv2',

'block2_pool',

'block3_conv1',

'block3_conv2',

'block3_conv3',

'block3_conv4',

'block3_pool',

'block4_conv1',

'block4_conv2',

'block4_conv3',

'block4_conv4',

'block4_pool',

'block5_conv1',

'block5_conv2',

'block5_conv3',

'block5_conv4',

'block5_pool',

'dense_1',

'dense_2',

'dense_3',

'dropout_1',

'global_average_pooling2d_1',

'input_1']

"""

# 列出模型中的所有层的名称

layer_names = [layer.name for layer in model.layers]

"""

# 提取`.h5`文件中每层的模型权重

>>> f["model_weights"]["block1_conv1"].attrs["weight_names"]

array([b'block1_conv1/kernel:0', b'block1_conv1/bias:0'],

dtype='|S21')

# 将这一数组分配给weight_names

>>> f["model_weights"]["block1_conv1"]["block1_conv1/kernel:0]

# 列表推导(weights)储存层的权重和偏置

>>>layer_names.index("block1_conv1")

1

>>> model.layers[1].set_weights(weights)

# 为特定层设置权重。

使用for循环我们可以为整个网络设置权重。

"""

for i in layer_dict.keys():

weight_names = f["model_weights"][i].attrs["weight_names"]

weights = [f["model_weights"][i][j] for j in weight_names]

index = layer_names.index(i)

model.layers[index].set_weights(weights)

import cv2

import numpy as np

import pandas as pd

from tqdm import tqdm

import itertools

import glob

features = []

for i in tqdm(files_location):

im = cv2.imread(i)

im = cv2.resize(cv2.cvtColor(im, cv2.COLOR_BGR2RGB), (256, 256)).astype(np.float32) / 255.0

im = np.expand_dims(im, axis =0)

outcome = model_final.predict(im)

features.append(outcome)

## 收集这些特征,创建一个dataframe,在其上训练一个分类器

以上代码提取block2_pool特征。通常而言,由于这层有64 x 64 x 128特征,在其上训练一个分类器可能于事无补。我们可以加上一些全连接层,然后在其基础上训练神经网络

增加少量全连接层和一个输出层。

为靠前的层设置权重,然后冻结。

训练网络。

4. 新数据集很大,和原数据很不一样

由于你有一个很大的数据集,你可以设计你自己的网络,或者使用现有的网络。

你可以基于随机初始化权重或预训练网络权重初始化训练网络。一般选择后者。

你可以使用不同的网络,或者基于现有网络做些改动。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 机器学习
    +关注

    关注

    66

    文章

    8116

    浏览量

    130546
  • 深度学习
    +关注

    关注

    73

    文章

    5236

    浏览量

    119895

原文标题:基于Keras进行迁移学习

文章出处:【微信号:jqr_AI,微信公众号:论智】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    杨强教授:从机器学习迁移学习

    杨强教授认为,DeepMind把端到端的深度学习应用在强化学习上,使得强化学习能够应付大数据,因此能在围棋上把人类完全击倒,它做到这样是通过完全的自学习、自我修炼、自我改正,然后一个一
    发表于 04-29 14:44 6073次阅读

    什么是迁移学习迁移学习实现方法与工具分析

    向于不要求海量数据也能达到应用的精准要求,因此“小数据学习”正在成为新的热点,以迁移学习,强化学习为代表的小数据学习技术,更能体现人工智能的
    发表于 05-11 09:12 1.2w次阅读

    基于稀疏编码的迁移学习及其在行人检测中的应用

    一定进展,但大都需要大量的训练数据.针对这一问题,提出了一种基于迁移学习的半监督行人分类方法:首先基于稀疏编码,从任意的未标记样本中,学习到一个紧凑、有效的特征表示;然后通过迁移
    发表于 04-24 09:48

    迁移学习训练网络

    keras迁移学习,改变VGG16输出层,用imagenet权重retrain
    发表于 09-09 11:02

    【木棉花】学习笔记--分布式迁移

    迁移回原设备。创建工程同样的,我们还是创建一个java的工程,然后将工程命名为 MyMigrate。具体是怎么实现的就可以参考我的前两篇学习笔记:分布式数据库、轻量级偏好数据库学习
    发表于 09-05 10:49

    【木棉花】学习笔记--分布式迁移+回迁

    前言我又来啦,相信那些不了解分布式的童鞋,学习过我前几篇学习笔记了之后是不是会更加理解了一些呢。当然了,我这星期要整理到学习笔记中的也是和分布式能力相关的一个学习案例,那就是在上一期分
    发表于 09-07 20:09

    迁移学习

    神经网络训练方法卷积神经网络介绍经典网络结构介绍章节目标:深入了解神经网络的组成、训练和实现,掌握深度空间特征分布等关键概念,为深度迁移学习奠定知识基础 三、迁移
    发表于 04-21 15:15

    基于局部分类精度的多源在线迁移学习算法

    近年来,迁移学习得到越来越多的关注,现有的在线迁移学习算法一般从单个源领域迁移知识。然而,当源领域与目标领域相似度较低时,很难进行有效的
    发表于 12-25 11:04 0次下载

    吴恩达:将引领下一波机器学习技术”的迁移学习到底好在哪?

    两年前,吴恩达在 NIPS 2016 的 Tutorial上曾说“在监督学习后,迁移学习将引领下一波学习技术”。今天我们来分析一下迁移
    的头像 发表于 10-27 10:27 2597次阅读
    吴恩达:将引领下一波机器<b class='flag-5'>学习</b>技术”的<b class='flag-5'>迁移</b><b class='flag-5'>学习</b>到底好在哪?

    迁移学习与模型预训练:何去何从

    把我们当前要处理的NLP任务叫做T(T称为目标任务),迁移学习技术做的事是利用另一个任务S(S称为源任务)来提升任务T的效果,也即把S的信息迁移到T中。至于怎么迁移信息就有很多方法了,
    的头像 发表于 07-18 11:29 7489次阅读
    <b class='flag-5'>迁移</b><b class='flag-5'>学习</b>与模型预训练:何去何从

    基于迁移学习与图像增强的夜间航拍车辆识别

    为了对夜间航拍图片中的车辆进行有效识别,提出基于二次迁移学习和 Retinex算法的图像处理方法,仅利用小规模的数据集训练网络,采用基于 Faster r-CNN的深度学习算法即可实现
    发表于 06-21 14:59 16次下载

    基于迁移深度学习的雷达信号分选识别

    基于迁移深度学习的雷达信号分选识别   来源:《软件学报》 ,作者王功明等   摘要:  针对当前雷达信号分选识别算法普遍存在的低信噪比下识别能力差、特征参数提取困难、分类器模型参数复杂等问题,提出
    发表于 03-02 17:35 989次阅读

    迁移学习Finetune的四种类型招式

    迁移学习广泛地应用于NLP、CV等各种领域,通过在源域数据上学习知识,再迁移到下游其他目标任务上,提升目标任务上的效果。其中,Pretrain-Finetune(预训练+精调)模式是最
    的头像 发表于 04-02 17:35 2590次阅读

    一文详解迁移学习

    迁移学习需要将预训练好的模型适应新的下游任务。然而,作者观察到,当前的迁移学习方法通常无法关注与任务相关的特征。在这项工作中,作者探索了重新聚焦模型注意力以进行
    的头像 发表于 08-11 16:56 3597次阅读
    一文详解<b class='flag-5'>迁移</b><b class='flag-5'>学习</b>

    视觉深度学习迁移学习训练框架Torchvision介绍

    Torchvision是基于Pytorch的视觉深度学习迁移学习训练框架,当前支持的图像分类、对象检测、实例分割、语义分割、姿态评估模型的迁移学习
    的头像 发表于 09-22 09:49 448次阅读
    视觉深度<b class='flag-5'>学习</b><b class='flag-5'>迁移</b><b class='flag-5'>学习</b>训练框架Torchvision介绍