Python深度学习读书笔记(四)(使用VGG16优化kaggle猫狗分类)

预训练网络:之前在大型数据集上训练好,保存好的网络。如果原始数据集足够大,足够通用,则预训练网络学到特征的空间层次结构可以有效的作为通用模型。

使用预训练网络的两种方法:

  1. 特征提取:对于卷积神经网络而言,特征提取就是取出之前训练好网络的卷积基(池化层和卷积层部分)。这部分学到的表示更加通用,更适合重复使用。

         卷积层提取表示的通用性取决于层中模型的深度,更靠近底部的是局部的高度通用的特征图,靠近顶部的是更加抽象的概念。

         在添加密集连接分类器时,有两种添加方式:

             1)先运行数据,将输出结果转为Numpy数组输入密集连接分类器。无法使用数据增强。

             2)直接为提取的卷积基添加添加密集连接分类器,再在完整的网络上训练。代价高,但可以设置数据增强。

from keras.applications import VGG16

#卷积基VGG16实例化
#参数(模型初始化的权重检查点,是否包含密集连接分类器,输入到网络中张量的形状(可选))
conv_base = VGG16(weights='imagenet',include_top=False,input_shape=(150,150,3))

#使用预训练的卷积基提取特征
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator

#此处对应笔记(三)中存放复制猫狗数据的根文件路径
base_dir='D:\\jupyter_code\\kaggle\\train1'
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)
batch_size=20

def extract_features(directory,sample_count):
    features=np.zeros(shape=(sample_count,4,4,512))
    labels=np.zeros(shape=sample_count)
    generator=datagen.flow_from_directory(
        directory,
        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(validation_dir,1000)
test_features,test_labels=extract_features(test_dir,1000)

#提取形状展平 ,便于输入到密集连接分类器
train_features=np.reshape(train_features,(2000,4*4*512))
validation_features=np.reshape(validation_features,(1000,4*4*512))
test_features=np.reshape(test_features,(1000,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(optimizer=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))

#采用数据增强的特征提取。拓展conv_base
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'))

#冻结卷积基,防止卷积基权重更新。导致之前所学的表示被破坏
conv_base.trainable=False

from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
#利用ImageDataGenerator设置数据增强
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_directory(
    train_dir,
    target_size=(150,150),
    batch_size=20,
    class_mode='binary'
)

validation_generator=test_datagen.flow_from_directory(
    validation_dir,
    target_size=(150,150),
    batch_size=20,
    class_mode='binary'
)

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

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

 

2.模型微调:将顶部几层解冻,对解冻的几层和新增加的Dense层进行联合训练,他只是略微调整了所复用模型中更加抽象的表示。

卷积基中更靠近底部的层编码是更加通用可复用特征,靠近顶部的层编码是更专业化的特征。

训练的参数越多,过拟合的风险越大。

 

使用预训练的卷积神经网络

特征提取

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

冻结基网络

训练所添加的部分

模型微调

解冻基网络中部分层

联合训练解冻层和添加层

#模型微调
#解冻直到某一层的所有层
#可通过conv_base.summary()查询卷积基的架构

conv_base.trainable=True

set_trainable=False
for layer in conv_base.layers:
    if layer.name=='block_conv1':
        set_trainable=True
    if set_trainable:
        layer.trainable=True
    else:
        layers.trainable=False
        
#微调模型
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)
print('test acc':test_acc)

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,实现识别任务需要进行迁移学习,使用预训练的VGG16模型可以帮助我们快速搭建一个高效的卷积神经网络。 以下是基本的实现步骤: 1. 导入相关库 ```python import os import numpy as np from keras.preprocessing.image import load_img, img_to_array from keras.applications.vgg16 import VGG16, preprocess_input from keras.models import Model from keras.layers import Dense, Dropout, Flatten from keras.optimizers import Adam from sklearn.model_selection import train_test_split ``` 2. 加载数据集 我们使用的数据集是Kaggle上的分类数据集,可以从以下链接下载:https://www.kaggle.com/c/dogs-vs-cats/data 数据集中包含25,000张大小不一的的图片,我们需要将其转换为模型可以处理的格式。 ```python # 定义数据集根目录 data_dir = 'path/to/data' # 定义图片大小和批次大小 img_size = (224, 224) batch_size = 32 # 加载数据集并将其转换为模型可以处理的格式 def load_dataset(): X = [] Y = [] for file in os.listdir(data_dir): if file.endswith('.jpg'): img = load_img(os.path.join(data_dir, file), target_size=img_size) img = img_to_array(img) X.append(img) if 'cat' in file: Y.append(0) else: Y.append(1) return np.array(X), np.array(Y) X, Y = load_dataset() ``` 3. 划分数据集 我们将数据集划分为训练集、验证集和测试集。训练集用于训练模型,验证集用于调整模型参数,测试集用于评估模型性能。 ```python # 划分数据集 X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42) X_train, X_val, Y_train, Y_val = train_test_split(X_train, Y_train, test_size=0.2, random_state=42) ``` 4. 加载预训练模型 我们使用Keras中已经训练好的VGG16模型作为特征提取器,将其载入并输出模型结构。 ```python # 加载预训练模型 base_model = VGG16(include_top=False, weights='imagenet', input_shape=img_size+(3,)) # 输出模型结构 for layer in base_model.layers: print(layer.name, layer.input_shape, layer.output_shape) ``` 5. 冻结模型权重 我们将模型的卷积层权重冻结,只训练新添加的全连接层的权重。 ```python # 冻结模型权重 for layer in base_model.layers: layer.trainable = False ``` 6. 构建模型 我们在VGG16模型的顶部添加了几个全连接层,用于分类任务。 ```python # 添加新的全连接层 x = base_model.output x = Flatten()(x) x = Dense(256, activation='relu')(x) x = Dropout(0.5)(x) x = Dense(1, activation='sigmoid')(x) # 构建新模型 model = Model(inputs=base_model.input, outputs=x) # 输出模型结构 model.summary() ``` 7. 训练模型 我们使用Adam优化器和二元交叉熵损失函数训练模型。 ```python # 编译模型 model.compile(optimizer=Adam(lr=0.001), loss='binary_crossentropy', metrics=['accuracy']) # 训练模型 history = model.fit( preprocess_input(X_train), Y_train, batch_size=batch_size, epochs=10, validation_data=(preprocess_input(X_val), Y_val), verbose=1 ) ``` 8. 评估模型 我们使用测试集评估模型性能。 ```python # 评估模型 score = model.evaluate(preprocess_input(X_test), Y_test, verbose=0) print('Test loss:', score[0]) print('Test accuracy:', score[1]) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值