码迷,mamicode.com
首页 > 其他好文 > 详细

使用预训练的卷积神经网络__keras实现VGG16

时间:2018-11-14 22:42:36      阅读:766      评论:0      收藏:0      [点我收藏+]

标签:mod   nta   width   图形   连接   bubuko   NPU   text   sum   

VGG16内置于Keras,可以通过keras.applications模块中导入。

--------------------------------------------------------将VGG16 卷积实例化:-------------------------------------------------------------------------------------------------------------------------------------

1 from keras.applications import VGG16
2 
3 conv_base = VGG16(weights = imagenet,#指定模型初始化的权重检查点
4                   include_top = False,
5                   input_shape = (150,150,30))                        

weights:指定模型初始化的权重检查点、

include_top: 指定模型最后是否包含密集连接分类器。默认情况下,这个密集连接分类器对应于ImageNet的100个类别。如果打算使用自己的密集连接分类器,可以不适用它,置为False。

input_shape: 是输入到网络中的图像张量的形状。这个参数完全是可选的,如果不传入这个参数,那么网络能够处理任意形状的输入。

 

--------------------------------------------------------查看VGG详细架构:conv_base.summary()----------------------------------------------------------------------------------------------------------

                                                         技术分享图片

最后一特征图形状为(4,4,512),我们将在这个特征上添加一个密集连接分类器,有两种方式:

在你的数据集上运行卷积基,将输出保存为numpy数组,然后用这个数据做输入,输入到独立的密集连接分类器中。这种方法速度快,计算代价低,因为对于每个输入图像只需运行一次卷积基,而卷积基是日前流程中计算代价最高的。但这种方法不允许使用数据增强。

在顶部添加Dense层来扩展已有模型,并在输入数据上端到端地运行整个模型。这样你可以使用数据增强,因为每个输入图像进入模型时都会经过卷积基。但这种方法的计算代价比第一种要高很多。

 

#方法一:不使用数据增强的快速特征提取
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator

base_dir = cats_dogs_images

train_dir = os.path.join(base_dir,train)
validation_dir = os.path.join(base_dir,validation)
test_dir = os.path.join(base_dir,test)

datagen = ImageDataGenerator(rescale = 1./255)#将所有图像乘以1/255缩放
batch_size = 20

def extract_features(directory,sample_count):
    features = np.zeros(shape=(sample_count,4,4,512))
    labels = np.zeros(shape=(sample_count))
# 通过.flow或.flow_from_directory(directory)方法实例化一个针对图像batch的生成器,这些生成器
# 可以被用作keras模型相关方法的输入,如fit_generator,evaluate_generator和predict_generator
    generator = datagen.flow_from_directory(  
        cats_dogs_images/train,
        target_size = (150,150),
        batch_size = batch_size,
        class_mode = binary)
    i = 0
    for inputs_batch,labels_batch in generator:
        features_batch = conv_base.predict(inputs_batch)
        features[i * batch_size:(i+1) * batch_size] = features_batch
        labels[i * batch_size:(i+1)*batch_size] = labels_batch
        i += 1
        if i * batch_size >= sample_count:
            break
    return features,labels


train_features,train_labels = extract_features(train_dir,2000)
validation_features,validation_labels = extract_features(validataion_dir,1000)
test_features,test_labels = extract_features(test_dir,1000)

  # 要减特征(samples,4,4,512)输入密集连接分类器中,首先必须将其形状展平为(samples,8192)

train_features = np.reshape(train_features,(2000,4*4*512))
validation_features = np.reshape(validation_features,(2000,4*4*512))
test_features = np.reshape(test_features,(2000,4*4*512))

#定义并训练密集连接分类器
from keras import models
from keras import layers
from keras import optimizers

model = models.Sequential()
model.add(layers.Dense(256,activation=relu,input_dim=4*4*512))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1,activation=sigmoid))

model.compile(optimizers=optimizers.RMSprop(lr=2e-5),
              loss=binary_crossentropy,
              metrics = [acc])

history = model.fit(train_features,train_labels,
                    epochs=30,batch_size=20,
                    validation_data = (Validation_features,validation_labels) )

 

 

 

 
#在卷积基上添加一个密集连接分类器

from keras import models
from keras import layers

model = models.Sequential()
model.add(conv_base)
model.add(layers.Flatten())
model.add(layers.Dense(256,activation=relu))
model.add(layers.Dense(1,activation=sigmoid))

model.summary()

技术分享图片如上图,VGG16的卷积基有14714688个参数,非常多。在其上添加的分类器有200万个参数。

在编译和训练模型之前,一定要“冻结”卷积基。

冻结? 指一个或多个层在训练过程中保持其权重不变

如果不这么做,那么卷积基之前学到的表示将会在训练过程中被修改。因为其上添加的Dense层是随机初始化的,所以非常大的权重更新将会在网络中传播,对之前学到的表示造成很大破坏。

在keras中,冻结网络的方法是将其trainable属性设置为False

eg. conv_base.trainable = False

 

#使用冻结的卷积基端到端地训练模型
from keras.preprocessing.image import ImageDataGenerator
from kera import optimizers

train_datagen = ImageDataGenerator(
    rescale = 1./255,
    rotation_range = 40,
    width_shift_range = 0.2,
    height_shift_range = 0.2,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True,
    fill_mode = nearest
)

test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_dirctory(
    train_dir,
    target_size = (150,150),
    batch_size = 20,
    class_mode = binary
)

validation_generator = test_datagen.flow_from_dirctory(
    validation,
    target_size = (150,150),
    batch_size = 20,
    class_mode = binary
)

model.compile(optimizer=optimizers.RMSprop(lr=2e-5),
             loss=binary_crossentropy,
             metrics = [acc])

history = model.fit_generator(
            train_generator,
            steps_per_epoch = 100,
            epochs = 30,
            validation_data = validation_generator,
            validation_steps=50
)

 

 

 

 

--------------------------------------------------------微调模型--------------------------------------------------------------------------------------------------------------------------------------------------------------

另外一种广泛使用的模型复用方法是模型微调,与特征提取互为补充。

对于用于特征提取的冻结的模型基,微调是指将其顶部的几层“解冻”,并将这解冻的几层和新增加的部分联合训练。之所以叫作微调,是因为他只是略微调整了所复用模型中更加抽象的表示,

以便让这些表示与手头的问题更加相关。

 

冻结VGG16的卷积基是为了能够在上面训练一个随机初始化的分类器。同理,只有上面的分类器训练好了,才能微调卷积基的顶部几层。如果分类器没有训练好,那么训练期间通过网络传播的

误差信号会特别大,微调的几层之前学到的表示都会被破坏。因此,微调网络的步骤如下:

(1)在已经训练好的基网络上添加自定义网络

(2)冻结基网络

(3)训练所添加的部分

(4)解冻基网络的一些层

(5)联合训练解冻的这些层和添加的部分

#微调模型
model.compile(loss=binary_crossentropy,
             optimizer = optimizers.RMSprop(lr=1e-5),
             metrics = [acc])
history = model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs = 100,
    validation_data = validation_generator,
    validation_steps = 50
)

test_generator = test_datagen.flow_from_directory(
    test_dir,
    target_size = (150,150),
    batch_size = 20,
    class_mode = binary
)

test_loss,test_acc = model.evaluate_generator(test_generator,steps=50)

 

 

 

 

为什么不微调更多层?为什么不微调整个卷积基?当然可以这么做,但需要先考虑以下几点:

(1)卷积基中更靠底部的层编码的是更加通用的可复用特征,而更靠顶部的层编码的是更专业化的特征。微调这些更专业化的特征更加有用,因为它们需要在你的新问题上改变用途。

微调更靠底部的层,得到的汇报会更少

(2)训练的参数越多,过拟合的风险越大。卷积基有1500万个参数,所以在你的小型数据集上训练这么多参数是有风险的。

 

使用预训练的卷积神经网络__keras实现VGG16

标签:mod   nta   width   图形   连接   bubuko   NPU   text   sum   

原文地址:https://www.cnblogs.com/nxf-rabbit75/p/9960277.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!