1. 关于Application

  • Keras 的应用模块(keras.applications)提供了带有预训练权值的深度学习模型,这些模型可以用来进行预测、特征提取和微调(fine-tuning)。当你初始化一个预训练模型时,会自动下载权值到 ~/.keras/models/ 目录下。

2. keras内置的Model

  • 在 ImageNet 上预训练过的用于图像分类的模型:
VGG16
VGG19
Xception
ResNet50
InceptionV3
InceptionResNetV2
MobileNet
DenseNet
NASNet
  • 所有的这些模型(除了 Xception 和 MobileNet 外)都兼容Theano和Tensorflow,并会自动按照位于 ~/.keras/keras.json 的配置文件中设置的图像数据格式来构建模型。举个例子,如果你设置 image_data_format=channels_last,则加载的模型将按照 TensorFlow 的维度顺序来构造,即“高度-宽度-深度”(Height-Width-Depth)的顺序。
  • Xception 模型仅适用于 TensorFlow,因为它依赖于 SeparableConvolution 层。MobileNet 模型仅适用于 TensorFlow,因为它依赖于 DepthwiseConvolution 层。

3. 一些例子

  1. 使用 ResNet50 进行 ImageNet 分类

    from keras.applications.resnet50 import ResNet50
    from keras.preprocessing import image
    from keras.applications.resnet50 import preprocess_input, decode_predictions
    import numpy as np
    
    model = ResNet50(weights='imagenet')
    
    img_path = 'elephant.jpg'
    img = image.load_img(img_path, target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    
    preds = model.predict(x)
    # decode the results into a list of tuples (class, description, probability)
    # (one such list for each sample in the batch)
    print('Predicted:', decode_predictions(preds, top=3)[0])
    # Predicted: [(u'n02504013', u'Indian_elephant', 0.82658225), (u'n01871265', u'tusker', 0.1122357), (u'n02504458', u'African_elephant', 0.061040461)]
    
  2. 使用 VGG16 提取特征

    from keras.applications.vgg16 import VGG16
    from keras.preprocessing import image
    from keras.applications.vgg16 import preprocess_input
    import numpy as np
    
    model = VGG16(weights='imagenet', include_top=False)
    
    img_path = 'elephant.jpg'
    img = image.load_img(img_path, target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    
    features = model.predict(x)
    
  3. 从VGG19的任意中间层中抽取特征

    from keras.applications.vgg19 import VGG19
    from keras.preprocessing import image
    from keras.applications.vgg19 import preprocess_input
    from keras.models import Model
    import numpy as np
    
    base_model = VGG19(weights='imagenet')
    model = Model(inputs=base_model.input, outputs=base_model.get_layer('block4_pool').output) # 自定义用于输出中间层的Model
    
    img_path = 'elephant.jpg'
    img = image.load_img(img_path, target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    
    block4_pool_features = model.predict(x)
    
  4. 在新类上微调 InceptionV3

    from keras.applications.inception_v3 import InceptionV3
    from keras.preprocessing import image
    from keras.models import Model
    from keras.layers import Dense, GlobalAveragePooling2D
    from keras import backend as K
    
    # 构建不带分类器的预训练模型
    base_model = InceptionV3(weights='imagenet', include_top=False) # include_top ?
    
    # 添加全局平均池化层
    x = base_model.output
    x = GlobalAveragePooling2D()(x)
    
    # 添加一个全连接层
    x = Dense(1024, activation='relu')(x)
    
    # 添加一个分类器,假设我们有200个类
    predictions = Dense(200, activation='softmax')(x)
    
    # 构建我们需要训练的完整模型
    model = Model(inputs=base_model.input, outputs=predictions)
    
    # 首先,我们只训练顶部的几层(随机初始化的层)
    # 锁住所有 InceptionV3 的卷积层
    for layer in base_model.layers:
        layer.trainable = False
    
    # 编译模型(一定要在锁层以后操作)
    model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
    
    # 在新的数据集上训练几代
    model.fit_generator(...)
    
    # 现在顶层应该训练好了,让我们开始微调 Inception V3 的卷积层。
    # 我们会锁住 Inception V3 中底下的几层,然后训练其余的顶层。(因为底层都是低级语义,可共享)
    
    # 让我们看看每一层的名字和层号,看看我们应该锁多少层呢:
    for i, layer in enumerate(base_model.layers):
       print(i, layer.name)
    
    # 我们选择训练最上面的两个 Inception block
    # 也就是说锁住前面249层,然后放开之后的层。
    for layer in model.layers[:249]:
       layer.trainable = False
    for layer in model.layers[249:]:
       layer.trainable = True
    
    # 我们需要重新编译模型,才能使上面的修改生效
    # 让我们设置一个很低的学习率,使用 SGD 来微调
    from keras.optimizers import SGD
    model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy')
    
    # 我们继续训练模型,这次我们训练最后两个 Inception block
    # 和两个全连接层
    model.fit_generator(...)
    
  5. 通过自定义输入 tensor 构建 InceptionV3

    from keras.applications.inception_v3 import InceptionV3
    from keras.layers import Input
    
    # this could also be the output a different Keras model or layer
    input_tensor = Input(shape=(224, 224, 3))  # this assumes K.image_data_format() == 'channels_last'
    
    model = InceptionV3(input_tensor=input_tensor, weights='imagenet', include_top=True)
    

4. 内置模型的性能概览

模型 大小 Top-1 准确率 Top-5 准确率 参数数量 深度
Xception 88 MB 0.790 0.945 22,910,480 126
VGG16 528 MB 0.715 0.901 138,357,544 23
VGG19 549 MB 0.727 0.910 143,667,240 26
ResNet50 99 MB 0.759 0.929 25,636,712 168
InceptionV3 92 MB 0.788 0.944 23,851,784 159
InceptionResNetV2 215 MB 0.804 0.953 55,873,736 572
MobileNet 17 MB 0.665 0.871 4,253,864 88
DenseNet121 33 MB 0.745 0.918 8,062,504 121
DenseNet169 57 MB 0.759 0.928 14,307,880 169
DenseNet201 80 MB 0.770 0.933 20,242,984 201
  • Top-1 准确率和 Top-5 准确率都是在 ImageNet 验证集上的结果。

  • Xception:

    • ImageNet预训练的 Xception V1 模型
    • 注意,该模型目前仅能在 TensorFlow 后端使用,因为它依赖 SeparableConvolution 层,目前该层只支持 channels_last 的维度顺序(高度、宽度、通道)。模型默认图片输入尺寸是 299x299。
  • VGG16:

    • VGG16 模型,权值由 ImageNet 训练(不是预训练)而来。
    • 该模型在 TheanoTensorFlow 后端均可使用,并接受 channels_firstchannels_last 两种输入维度顺序(高度,宽度,通道)。模型默认输入尺寸是 224x224。
    • 预训练权值VGG at Oxford 发布的预训练权值移植而来,基于 Creative Commons Attribution License
  • VGG19:

    • VGG19 模型,权值由 **ImageNet ** 训练而来。
    • 该模型在 TheanoTensorFlow 后端均可使用,并接受 channels_firstchannels_last 两种输入维度顺序(高度,宽度,通道)。模型默认输入尺寸是 224x224。
    • 预训练权值由 VGG at Oxford 发布的预训练权值移植而来,基于 Creative Commons Attribution License
  • ResNet50:

    • ResNet50 模型,权值由 ImageNet 训练而来。
    • 该模型在 TheanoTensorFlow 后端均可使用,并接受 channels_firstchannels_last 两种输入维度顺序(高度,宽度,通道)。模型默认输入尺寸是 224x224。
    • 预训练权值由 Kaiming He 发布的预训练权值移植而来,基于 MIT license
  • InceptionV3:

    • nception V3 模型,权值由 ImageNet 训练而来。
    • 该模型在 TheanoTensorFlow 后端均可使用,并接受 channels_firstchannels_last 两种输入维度顺序(高度,宽度,通道)。模型默认输入尺寸是 299x299。
    • 预训练权值基于 Apache License
  • InceptionResNetV2:

    • Inception-ResNet V2 模型,权值由 ImageNet 训练而来。
    • 该模型在 TheanoTensorFlow 后端均可使用,并接受 channels_firstchannels_last 两种输入维度顺序(高度,宽度,通道)。模型默认输入尺寸是 299x299。
    • 预训练权值基于 Apache License
  • MobileNet:

    • 在 ImageNet 上预训练的 MobileNet 模型。

    • 注意,该模型目前仅能在 TensorFlow 后端使用,因为它依赖 SeparableConvolution 层,目前该层只支持 channels_last 的维度顺序(高度、宽度、通道)。要通过 load_model 载入 MobileNet 模型,你需要导入自定义对象 relu6DepthwiseConv2D 并通过 custom_objects 传参。模型默认输入尺寸是 224x224.

      model = load_model('mobilenet.h5', custom_objects={
                         'relu6': mobilenet.relu6,
                         'DepthwiseConv2D': mobilenet.DepthwiseConv2D})
      
    • 预训练权值基于 Apache License

  • DenseNet:

    • 可以选择载入在 ImageNet 上的预训练权值。如果你在使用 TensorFlow 为了发挥最佳性能,请在 ~/.keras/keras.json 的 Keras 配置文件中设置 image_data_format='channels_last'

      模型和权值兼容 TensorFlow、Theano 和 CNTK。可以在你的 Keras 配置文件中指定数据格式。

    • 预训练权值基于 BSD 3-clause License

  • NASNet:

    • 在 ImageNet 上预训练的神经结构搜索网络模型(NASNet)。
    • 注意,该模型目前仅能在 TensorFlow 后端使用,因此它只支持 channels_last 的维度顺序(高度、宽度、通道),可以在 ~/.keras/keras.json Keras 配置文件中设置。NASNetLarge 默认的输入尺寸是 331x331,NASNetMobile 默认的输入尺寸是 224x224。
    • 预训练权值基于 Apache License