keras 迁移学习

加载VGG16前13层结构和权重,自己定义最后全连接层,然后冻结前13层,使用小数据集训练模型。

看似简单,中间遇到很多问题,说多了都是泪,就是因为纠结于网上给的例子,太死脑筋了。

csdn里面有一个帖子讲的很详细,我跑里面的例子一直报错:

https://blog.csdn.net/sinat_26917383/article/details/72861152#commentsedit

自定义全连接层:

base_model = VGG16(weights='imagenet', include_top=False)

top_model = Sequential()

top_model.add(Flatten(input_shape=base_model.output_shape[1:]))

top_model.add(Dense(256, activation='relu'))

top_model.add(Dropout(0.5))

top_model.add(Dense(2, activation='sigmoid'))

model = Model(inputs=base_model.input, outputs=top_model.output)

无论怎么改都报错,调用Model()的时候总是报错:

ValueError: Graph disconnected: cannot obtain value for tensor Tensor("flatten_1_input:0", shape=(?, 512, 7, 7), dtype=float32) at layer "flatten_1_input". The followingprevious layers were accessed without issue: []

修改如下:

(1)

base_model = VGG16(weights='imagenet', include_top=False,input_shape=(3, 224, 224))

x = base_model.output

x= Flatten()(x)

#x = GlobalAveragePooling2D()(x)

# let's add a fully-connected layer

x = Dense(4096, actication='relu',name= 'fc1')(x)

x = Dense(4096,activation='relu',name='fc2')(x)

x = Dense(2,actication='sigmoid')(x)

model = Model(inputs=base_model.input, outputs=predictions)
print(model.summary())

注意使用flatten的时候,需要指定输入图片大小,input_shape(3,224,224),否则会报错:

ValueError: The shape of the input to "Flatten" is not fully defined (got (512, None, None). Make sure to pass a complete "input_shape" or "batch_input_shape" argument to the first layer in your model.

打印的网络结构:

block5_pool (MaxPooling2D)   (None, 512, 7, 7)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
dense_1 (Dense)              (None, 2)                 8194    

(2)使用GlobalAveragePooling2D,代替Flatten层

base_model = VGG16(weights='imagenet', include_top=False)

x = base_model.output

#x= Flatten()(x)

x = GlobalAveragePooling2D()(x)

# let's add a fully-connected layer

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

predictions = Dense(2, activation='sigmoid')(x)

model = Model(inputs=base_model.input, outputs=predictions)

个人理解这里GlobalAveragePooling2D的作用其实相当于flatten层,都是把多维矩阵压平,并且不用指定input_shape()的大小,打印模型的结果如下:
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 512, 7, 7)         0         
_________________________________________________________________
global_average_pooling2d_1 ( (None, 512)               0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              2101248   
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
dense_1 (Dense)              (None, 2)                 8194   

(3)第三种写法最简单粗暴,但是不好理解

base_model = VGG16(weights = 'imagenet', include_top = False, pooling = 'avg')
predictions = Dense(2, activation='sigmoid')(base_model.output)
# 定义整个模型
model = Model(inputs=base_model.input, outputs=predictions)

打印模型结构:

block5_pool (MaxPooling2D)   (None, 512, 7, 7)         0         
_________________________________________________________________
global_average_pooling2d_1 ( (None, 512)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 2)                 1026   

 

 

if include_top:
    # Classification block
    x = layers.Flatten(name='flatten')(x)
    x = layers.Dense(4096, activation='relu', name='fc1')(x)
    x = layers.Dense(4096, activation='relu', name='fc2')(x)
    x = layers.Dense(2, activation='softmax', name='predictions')(x)
else:
    if pooling == 'avg':
        x = layers.GlobalAveragePooling2D()(x)
    elif pooling == 'max':
        x = layers.GlobalMaxPooling2D()(x)

 

’‘’看官方代码,这里添加参数pooling='avg',已经自动的使用GlobalAveragePooling2D,所以不需要压缩层,这里卡了很久,一度以为真的不需要平滑层

base_model = VGG16(weights = 'imagenet', include_top = False, pooling = 'avg')

# 构建网络的最后一层

predictions = Dense(2, activation='sigmoid')(base_model.output)

# 定义整个模型

model = Model(inputs=base_model.input, outputs=predictions)

 

三种改法殊途同归,折腾了将近一天,有任何问题欢迎交流讨论。

给出完整的代码:

from keras import applications
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Model
from keras.layers import Flatten, Dense,GlobalAveragePooling2D,Convolution2D,MaxPooling2D,ZeroPadding2D
import os
import h5py
from keras.applications.vgg16 import VGG16
from keras.models import load_model
from keras import backend as K
from keras.utils import to_categorical
K.set_image_dim_ordering('th')



img_width, img_height = 224, 224
train_data_dir = 'train1'
validation_data_dir = 'validation'
nb_train_samples = 2000
nb_validation_samples = 800
epochs = 10
batch_size = 16
nb_classes = 2

#model = VGG16(weights='imagenet', include_top=False)
base_model = VGG16(weights='imagenet',  include_top=False,input_shape=(3,224, 224))
x = base_model.output
x= Flatten(name='flatten')(x)
#x = GlobalAveragePooling2D()(x)
# let's add a fully-connected layer
x = Dense(4096, activation='relu',name='fc1')(x)
x = Dense(4096, activation='relu',name='fc2')(x)
x = Dense(nb_classes, activation='sigmoid')(x)

# add the model on top of the convolutional base
model = Model(inputs=base_model.inputs, outputs=x)
print(model.summary())

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

# compile the model with a SGD/momentum optimizer
# and a very slow learning rate.
model.compile(loss='binary_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1. / 255)

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),
    batch_size=batch_size,
    class_mode='categorical')
image_numbers = train_generator.samples
# fine-tune the model
model.fit_generator(
    train_generator,
    steps_per_epoch = image_numbers,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps = batch_size
    )
model.save('weights1.h5')

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值