深度学习-使用预设计的模型预测

时间:2022-07-25
本文章向大家介绍深度学习-使用预设计的模型预测,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

使用预设计的模型预测

概述

通常对于神经网络来说,如果自己训练将会非常的费时间,有一种方法就是用别人在大样本上训练好的数据,然后使用在自己的网络上,比如,我们的分类目标是猫和狗的分类,如果存在一种大数据的动物分类器,那么就可以实现我们猫和狗分类的目的 有两种方式实现

  • 特征提取
  • 微调模型

特征提取

特征提取是使用之前网络学到的特征来从新样本中提取出需要的特征 神经网络由卷积核和最后的分类器组成,一般特征提取使用的是训练好的卷积核

from keras.applications import VGG16
# VGG16是一个网络框架
conv_base = VGG16(weights='imagenet',#指定模型初始化的权重检查点。
                    include_top=False,#指定模型最后是否包含密集连接分类器
                    input_shape=(150, 150, 3))# 输入图片的张量,长宽和深度
conv_base.summary()# 查看生成的模型
Using TensorFlow backend.


Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
58892288/58889256 [==============================] - 25s 0us/step
Model: "vgg16"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input_1 (InputLayer)         (None, 150, 150, 3)       0
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 150, 150, 64)      1792
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 150, 150, 64)      36928
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 75, 75, 64)        0
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 75, 75, 128)       73856
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 75, 75, 128)       147584
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 37, 37, 128)       0
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 37, 37, 256)       295168
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 37, 37, 256)       590080
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 37, 37, 256)       590080
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 18, 18, 256)       0
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 18, 18, 512)       1180160
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 18, 18, 512)       2359808
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 18, 18, 512)       2359808
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 9, 9, 512)         0
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 9, 9, 512)         2359808
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 9, 9, 512)         2359808
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 9, 9, 512)         2359808
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 4, 4, 512)         0
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________

可以看出模型由多个卷积层和池化层组成

# 使用预设计的卷积核提取特征
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator# 导入生成器
# 定义路径
base_dir = '/home/sunqi/python_study/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))# 建立一个空矩阵存储特征
    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)
Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.
# 现在提取的特征为(n, 4, 4, 512)
# 将提取的特征进行展开
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))
Train on 2000 samples, validate on 1000 samples
Epoch 1/30
2000/2000 [==============================] - 1s 449us/step - loss: 0.6243 - acc: 0.6520 - val_loss: 0.4484 - val_acc: 0.8310
Epoch 2/30
2000/2000 [==============================] - 1s 350us/step - loss: 0.4355 - acc: 0.8050 - val_loss: 0.3676 - val_acc: 0.8560
Epoch 3/30
2000/2000 [==============================] - 1s 365us/step - loss: 0.3720 - acc: 0.8390 - val_loss: 0.3299 - val_acc: 0.8740
Epoch 4/30
2000/2000 [==============================] - 1s 375us/step - loss: 0.3248 - acc: 0.8645 - val_loss: 0.3068 - val_acc: 0.8840
Epoch 5/30
2000/2000 [==============================] - 1s 345us/step - loss: 0.2908 - acc: 0.8860 - val_loss: 0.2841 - val_acc: 0.8870
Epoch 6/30
2000/2000 [==============================] - 1s 350us/step - loss: 0.2700 - acc: 0.8935 - val_loss: 0.2775 - val_acc: 0.8940
Epoch 7/30
2000/2000 [==============================] - 1s 347us/step - loss: 0.2480 - acc: 0.9040 - val_loss: 0.2650 - val_acc: 0.8940
Epoch 8/30
2000/2000 [==============================] - 1s 350us/step - loss: 0.2287 - acc: 0.9145 - val_loss: 0.2694 - val_acc: 0.8910
Epoch 9/30
2000/2000 [==============================] - 1s 366us/step - loss: 0.2221 - acc: 0.9140 - val_loss: 0.2526 - val_acc: 0.9030
Epoch 10/30
2000/2000 [==============================] - 1s 356us/step - loss: 0.2195 - acc: 0.9180 - val_loss: 0.2489 - val_acc: 0.9020
Epoch 11/30
2000/2000 [==============================] - 1s 351us/step - loss: 0.2061 - acc: 0.9230 - val_loss: 0.2455 - val_acc: 0.9020
Epoch 12/30
2000/2000 [==============================] - 1s 352us/step - loss: 0.1967 - acc: 0.9245 - val_loss: 0.2446 - val_acc: 0.9020
Epoch 13/30
2000/2000 [==============================] - 1s 344us/step - loss: 0.1852 - acc: 0.9285 - val_loss: 0.2399 - val_acc: 0.9030
Epoch 14/30
2000/2000 [==============================] - 1s 348us/step - loss: 0.1794 - acc: 0.9375 - val_loss: 0.2385 - val_acc: 0.9050
Epoch 15/30
2000/2000 [==============================] - 1s 343us/step - loss: 0.1727 - acc: 0.9380 - val_loss: 0.2384 - val_acc: 0.9030
Epoch 16/30
2000/2000 [==============================] - 1s 355us/step - loss: 0.1650 - acc: 0.9410 - val_loss: 0.2370 - val_acc: 0.9060
Epoch 17/30
2000/2000 [==============================] - 1s 353us/step - loss: 0.1533 - acc: 0.9455 - val_loss: 0.2392 - val_acc: 0.9030
Epoch 18/30
2000/2000 [==============================] - 1s 365us/step - loss: 0.1484 - acc: 0.9470 - val_loss: 0.2343 - val_acc: 0.9050
Epoch 19/30
2000/2000 [==============================] - 1s 366us/step - loss: 0.1470 - acc: 0.9500 - val_loss: 0.2386 - val_acc: 0.9060
Epoch 20/30
2000/2000 [==============================] - 1s 368us/step - loss: 0.1374 - acc: 0.9540 - val_loss: 0.2345 - val_acc: 0.9030
Epoch 21/30
2000/2000 [==============================] - 1s 372us/step - loss: 0.1291 - acc: 0.9580 - val_loss: 0.2319 - val_acc: 0.9050
Epoch 22/30
2000/2000 [==============================] - 1s 390us/step - loss: 0.1339 - acc: 0.9535 - val_loss: 0.2454 - val_acc: 0.8990
Epoch 23/30
2000/2000 [==============================] - 1s 354us/step - loss: 0.1194 - acc: 0.9600 - val_loss: 0.2353 - val_acc: 0.9060
Epoch 24/30
2000/2000 [==============================] - 1s 349us/step - loss: 0.1166 - acc: 0.9615 - val_loss: 0.2354 - val_acc: 0.9070
Epoch 25/30
2000/2000 [==============================] - 1s 350us/step - loss: 0.1182 - acc: 0.9600 - val_loss: 0.2326 - val_acc: 0.9050
Epoch 26/30
2000/2000 [==============================] - 1s 352us/step - loss: 0.1112 - acc: 0.9635 - val_loss: 0.2325 - val_acc: 0.9040
Epoch 27/30
2000/2000 [==============================] - 1s 347us/step - loss: 0.1092 - acc: 0.9640 - val_loss: 0.2337 - val_acc: 0.9050
Epoch 28/30
2000/2000 [==============================] - 1s 348us/step - loss: 0.1020 - acc: 0.9670 - val_loss: 0.2373 - val_acc: 0.9040
Epoch 29/30
2000/2000 [==============================] - 1s 352us/step - loss: 0.0975 - acc: 0.9710 - val_loss: 0.2404 - val_acc: 0.9060
Epoch 30/30
2000/2000 [==============================] - 1s 347us/step - loss: 0.0956 - acc: 0.9690 - val_loss: 0.2377 - val_acc: 0.9030

因为只涉及后面的分类层,所以运算非常快

绘图

import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()

可以看出验证集的精确度达到了val_acc: 0.9030

微调模型

相比较特征提取,微调模型可以针对模型中个别层进行修改

conv_base.trainable = True #解冻
set_trainable = False
for layer in conv_base.layers:
    if layer.name == 'block5_conv1':#对block5_conv1开始进行解冻
        set_trainable = True
    if set_trainable:
        layer.trainable = True
    else:
        layer.trainable = False
## 最后通过训练模型达到微调训练的目的

结束语

对于卷积神经网络的内容基本就是这些,虽然学习来容易,但是用到自己的数据就会出问题,就这样吧

love&peace