Python 深度学习--学习笔记(八)

使用预训练的卷积神经网络学习猫狗分类

        在Python 深度学习–学习笔记(七)中,我们从零构建模型并进行学习。增加了增强学习,训练了100轮后,准确率还是没到80%。这很大程度上因为学习的数据不够多。所以,今天我们使用预训练的神经网络。预训练网络(pretrained network)是一个保存好的网络,之前已在大型数据集(通常是大规模图
像分类任务)上训练好。
        本次采用的训练神经网络已在ImageNet上训练了140万标记图片,1000个不同的类别。

我们将使用VGG16架构。

  • 首先,我们先导入架构
    这里注意,我们只需要VGG16中的卷积层
from keras.applications import VGG16

conv_base = VGG16(weights='imagenet',
                  include_top=False,
                  #指定模型最后是否包含密集连接分类器,默认情况下,这个密集连接分类器对应于 ImageNet 的 1000 个类别
                  input_shape=(150,150,3))
                  #规定网络处理的输入大小
conv_base.summary()

密集层分类器输出的是1000个类别,而我们只需要猫狗分类,所以,我们不要VGG16 的密集连接分类器,而需要自己定义。
1
VGG16的结构是:
输入层 -> 两次卷积一次池化 -> 两次卷积一次池化 -> 三次卷积一次池化 -> 三次卷积一次池化 -> 三次卷积一次池化
VGG结构基于 3x3的小型卷积核的卷积层运算,卷积层重叠2次到4次,再通过池化层将大小减半,最后经由全连接层输出结果.

不使用数据增强的快速特征提取

思路:分两步。
第一步,将数据经过VGG16的卷积层后提取输出。
第二步,再在自己定义的模型下学习,分类。

import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator

base_dir = './cats_and_dogs_small'
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))
    #卷积最后一层输出大小为(none,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
#获得从VGG16最后的卷积层输出的数据

  • 准备好提取器后,开始提取处理数据
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))
                                            #或input_shape=(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))

2
可以看出,在训练模型下,准确度达到0.9,得到质的飞跃!

  • 数据可视化(省略代码)
    3
使用数据增强的特诊提取

思路,直接嵌入自己定义的模型底层,将数据输入,从端到端的学习。
缺点:学习速度慢,计算代价高。

  • 导入模型
from keras.applications import VGG16

conv_base = VGG16(weights='imagenet',
                  include_top=False,
                  #指定模型最后是否包含密集连接分类器,默认情况下,这个密集连接分类器对应于 ImageNet 的 1000 个类别
                  input_shape=(150,150,3))
                  #规定网络处理的输入大小
conv_base.trainable = False

特别注意,在编译和训练模型之前,一定要“冻结”卷积基(conv_base.trainable = False)。
解释:冻结一个或多个层是指在训练过程中保持其权重不变。
原因:如果不这么做,那么卷积基之前学到的表示将会在训练过程中被修改。因为其上添加的 Dense 层是随机初始化的,所以非常大的权重更新将会在网络中传播,对之前学到的表示造成很大破坏。

  • 定义模型
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()

4

  • 创建数据增强器
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
import os

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


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')

# Note that the validation data should not be augmented!
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=20,
        # Since we use binary_crossentropy loss, we need binary labels
        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)

model.save('cats_and_dogs_small_3.h5')

5
这种方法的准确率与第一种方法的变化不大,但第二种方法的增强学习能有效抑制过拟合
训练的模型相当久!博主用CPU训练了整整10小时!!!
本方法计算代价很高,只在有 GPU 的情况下才能尝试运行。它在 CPU 上是绝对难以运行的。如果你无法在 GPU 上运行代码,那么就采用第一种方法。

  • 最后数据可视化(省略代码)
    6
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值