TensorFlow深度学习实战(9)——构建VGG模型实现图像分类

发布于:2025-02-26 ⋅ 阅读:(16) ⋅ 点赞:(0)

0. 前言

VGG 模型是一种经典的深度卷积神经网络 (Convolutional Neural Network, CNN) 架构,该模型以其简单而有效的设计而著名,在图像分类任务中取得了优异成绩。VGG 模型的核心特点是采用了深层的网络结构,其中大部分层由卷积层和池化层组成,且卷积操作使用了尺寸较小的 3 x 3 卷积核,这使得网络能够捕捉到丰富的图像特征。

1. VGG 模型

1.1 VGG16 与 VGG19

VGG 是于 2014 年提出的图像识别模型,通过将网络层深度增加到 16-19 个,显著提高了网络性能。模型在 ImageNet ILSVRC-2012 数据集上对模型进行训练,数据集包含 1000 个类别的图像,分为三组:训练集 (130 万张图像)、验证集 (5 万张图像)和测试集( 10 万张图像)。每个图像为 224 x 224 像素,具有 3 个通道。VGG16 模型在 ILSVRC-2012 验证集上的 top-5 错误率为 7.5%,在 ILSVRC-2012 测试集上的 top-5 错误率为 7.4%
VGG19VGG16 的改进版本,具有更多的卷积和池化操作,VGG19 模型的体系结构如下:

VGG19

可以看到,上示的体系结构中具有更多的网络层以及更多的参数量。需要注意的是,VGG16VGG19 体系结构中的 1619 代表这些网络中的网络层数。

VGG19架构

1.2 ImageNet

ImageNet 竞赛的目标是利用一个大型手工标注的 ImageNet 数据集( 1000 万标记图像,描述了 10000 多个类别)的子集进行训练,算法需要预测图像中存在的对象的标签,以便对照片内容进行检索和自动标注。

2. 构建 VGG16 模型实现图像分类

2.1 模型构建

使用 tf.keras 能够预加载已经训练完成的 VGG 模型权重到 tf.keras 模型中使用:

import tensorflow as tf
from tensorflow.keras import layers, models
import cv2, numpy as np
import os

# define a VGG16 network
def VGG_16(weights_path=None):
    model = models.Sequential()
    model.add(layers.ZeroPadding2D((1,1),input_shape=(224,224, 3)))
    model.add(layers.Convolution2D(64, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(64, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2), strides=(2,2)))

    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(128, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(128, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2), strides=(2,2)))

    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(256, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(256, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(256, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2), strides=(2,2)))

    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(512, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(512, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(512, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2), strides=(2,2)))

    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(512, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(512, (3, 3), activation='relu'))
    model.add(layers.ZeroPadding2D((1,1)))
    model.add(layers.Convolution2D(512, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2), strides=(2,2)))

    model.add(layers.Flatten())

    #top layer of the VGG net
    model.add(layers.Dense(4096, activation='relu'))
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(4096, activation='relu'))
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(1000, activation='softmax'))

    if weights_path:
        model.load_weights(weights_path)

    return model

虽然我们可以使用 tf.keras.applications.vgg16 来直接获取模型及其权重,但为了展示 VGG16 的内部工作原理,我们使用 tf.keras 实现了一个 VGG16 网络,接下来,将使用该模型实现图像分类。

2.2 使用 VGG16 网络识别猫

使用预训练权重测试模型性能:

im = cv2.resize(cv2.imread('cat.jpg'), (224, 224)).astype(np.float32)
im = np.expand_dims(im, axis=0)

# Test pretrained model
path_file = os.path.join(os.path.expanduser("~"), '.keras/models/vgg16_weights_tf_dim_ordering_tf_kernels.h5')
model = VGG_16(path_file)
model.summary()
model.compile(optimizer='sgd', loss='categorical_crossentropy')
out = model.predict(im)
print(np.argmax(out))

测试图像

模型返回类别 281,对应于 tabby, tabby cat

测试结果

可以看到,我们所实现的 VGG16 网络能够成功识别猫的图像。

3. 使用 tf.Keras 内置的 VGG16 网络模块

tf.Keras.applications 包含预构建和预训练的深度学习模型。在实例化模型时,权重会自动下载并存储在 ~/.keras/models/ 中,使用模型预测小狗图像:

import tensorflow as tf
from tensorflow.keras.applications.vgg16 import VGG16
import matplotlib.pyplot as plt
import numpy as np
import cv2

# prebuild model with pre-trained weights on imagenet
model = VGG16(weights='imagenet', include_top=True)
model.compile(optimizer='sgd', loss='categorical_crossentropy')

# resize into VGG16 trained images' format
im = cv2.resize(cv2.imread('dog.jpg'), (224, 224))
im = np.expand_dims(im, axis=0)
im.astype(np.float32)

# predict
out = model.predict(im)
index = np.argmax(out)
print(index)

plt.plot(out.ravel())
plt.show()

测试图像

运行代码,模型返回结果 208,对应于 Labrador retriever,模型返回的其它类别置信度都非常小。

4. 利用预训练模型进行特征提取

当网络学习如何将图像分类到正确类别时,每一层都学会了识别执行最终分类所必需的特征。较低层识别低阶特征,如颜色和边缘,而较高层将这些低阶特征组合成形状或物体等高阶特征。因此,中间层具有提取图像重要特征的能力,这些特征能够用于模型执行分类任务。
可以使用深度卷积神经网络进行特征提取,本节中,我们以 VGG16 为例从特定层中提取图像特征。需要注意的是,由于顺序模型仅接受层进行构建,因此需要使用函数式 API

import tensorflow as tf
from tensorflow.keras.applications.vgg16 import VGG16 
from tensorflow.keras import models
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import preprocess_input
import numpy as np
import cv2

# prebuild model with pre-trained weights on imagenet
base_model = VGG16(weights='imagenet', include_top=True)
print (base_model)
for i, layer in enumerate(base_model.layers):
    print (i, layer.name, layer.output_shape)

# extract features from block4_pool block
model = models.Model(inputs=base_model.input, 
    outputs=base_model.get_layer('block4_pool').output)

img_path = 'cat.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

# get the features from this block
features = model.predict(x)
print(features)

使用预训练模型进行特征提取具有以下优点:

  • 可以重用公开的大规模训练模型,并将学习的特征应用到新任务
  • 可以节省大量的训练时间
  • 即使在没有大量训练样本的情况下,也可以得到合理的解决方案
  • 可以使用一个适合当前任务的初始网络结构,而不必从零开始构建模型

小结

通过使用小尺寸的卷积核和深层网络设计,VGG 能够有效地提取图像的特征,并在各种视觉任务中取得优异的表现。在实际应用中,可以通过迁移学习等方式,充分利用 VGG 的预训练模型,加速训练过程并提高分类效果。

系列链接

TensorFlow深度学习实战(1)——神经网络与模型训练过程详解
TensorFlow深度学习实战(2)——使用TensorFlow构建神经网络
TensorFlow深度学习实战(3)——深度学习中常用激活函数详解
TensorFlow深度学习实战(4)——正则化技术详解
TensorFlow深度学习实战(5)——神经网络性能优化技术详解
TensorFlow深度学习实战(6)——回归分析详解
TensorFlow深度学习实战(7)——分类任务详解
TensorFlow深度学习实战(8)——卷积神经网络


网站公告

今日签到

点亮在社区的每一天
去签到