第20章 如何加载和使用预训练的物体识别模型
卷积神经网络现在能够在某些计算机视觉任务上胜过人类,例如分类图像。也就是说,给定物体的照片,回答照片显示的1000个特定物体中的哪一个的问题。这项任务的竞赛获胜模型是牛津大学研究人员开发的VGG模型。除了能够对照片中的对象进行分类之外,该模型的重要之处在于模型权重可以免费获得,并且可以在您自己的模型和应用程序中加载和使用。在本教程中,您将了解用于图像分类的VGG卷积神经网络模型。完成本教程后,您将了解:
- 关于ImageNet数据集和竞赛以及VGG获奖模型。
- 如何在Keras中加载VGG模型并显示其结构。
- 如何使用加载的VGG模型对特定照片中的对象进行分类。让我们开始吧。
20.1 教程概述
本教程分为以下几部分:
- ImageNet
- 牛津VGG模型
- 在Keras中加载VGG模型
- 开发简单的照片分类器
注意,Keras使用Python Imaging Library或PIL库来处理图像。您系统上的安装可能有所不同。
20.2 ImageNet
ImageNet本来是一个项目,致力于开发带有注释的大型图像数据库,例如图像及其描述。自2010年以来,图像及其注释库一直是ImageNet大规模视觉识别挑战(ILSVRC)的图像分类挑战的基础,研究机构在预定义的数据集上展开了一场比赛,看谁的模型来能更好对图像中的对象进行分类。
ImageNet大规模视觉识别挑战是对数以百计的对象类别和数以百万计的图像进行对象类别分类和检测的基准,从2010年到现在每年都在进行挑战,吸引了来自50多个机构的参与。
— ImageNet Large Scale Visual Recognition Challenge, 2015.
对于分类任务,图像必须分为1,000个不同类别中的一个,在过去的几年里,几乎都是非常深的卷积神经网络模型最后获得胜出,在分析结果上已经超过了人类的表现。
图20.1:ILSVRC挑战赛中使用的ImageNet数据集的图像样本。ImageNet Large Scale Visual Recognition Challenge.
20.3 牛津VGG模型
牛津视觉几何组织(简称VGG)的研究人员参与了ILSVRC的挑战。2014年,VGG开发的卷积神经网络模型(CNN)赢得了图像分类任务。
图23。2:2014年ILSVRC对分类任务的结果。
比赛结束后,参与者在Very DeepConvolutional Networks for Large-Scale Image Recognition论文中写详细介绍了他们的模型,他们还在网上提供了他们的模型和学习的权重,这使得其他研究人员和开发人员可以在自己的工作和程序中使用最先进的图像分类模型,这有助于推动大量的转移学习工作,在这些工作中,通过对全新的预测建模任务使用使用预先训练的模型,进行少量修改,就可以利用已验证模型的最先进地特征提取能力。
......我们提出了更加精确的ConvNet架构,它不仅可以实现ILSVRC分类和定位任务的最好精度,而且还适用于其他图像识别数据集,即使在用作相对简单的管道的一部分也取得了不错的表现(例如,通过线性SVM分类的深度特征,而不进行微调)。我们发布了两个表现最佳的模型,以促进进一步的研究。
Very Deep Convolutional Networks for Large-Scale Image Recognition, 2014.
VGG发布了两种不同的CNN模型,16层模型和19层模型。有关这些型号的完整详细信息,请参阅该文章。VGG模型不再仅仅是几个百分点的最新技术。然而,它们是非常强大的模型,既可用作图像分类器,也可用作使用图像输入的新模型的基础。在下一节中,我们将看到如何在Keras中直接使用VGG模型。
20.4 在Keras中加载VGG模型
可以在Keras深度学习库中加载和使用VGG模型。Keras提供了一个用于加载和使用预训练模型的应用程序界面。使用此界面,您可以使用牛津集团提供的预训练权重创建VGG模型,并将其用作您自己模型中的起点,或者将其用作模型直接用于分类图像。在本教程中,我们将重点介绍使用VGG模型对新图像进行分类的用例。Keras通过VGG16和VGG19类提供16层和19层版本。让我们关注VGG16模型。可以按如下方式创建模型:
from keras.applications.vgg16 import VGG16
model = VGG16()
代码清单20.1:在Keras中创建VGG16模型
而已。第一次运行此示例时, Keras 将从 Internet 下载权重文件并将它们存储在/.keras/models目录中。请注意,权∼重约为528兆字节,因此下载可能需要几分钟,具体取决于Internet连接的速度。
权重仅下载一次。下次运行示例时,权重将在本地加载,模型应该可以在几秒钟内使用。我们可以使用标准的Keras工具来检查模型结构。例如,您可以按如下方式打印网络层的摘要:
from keras.applications.vgg16 import VGG16
model = VGG16()
model.summary()
代码清单20.2:创建和总结VGG16模型
你可以看到模型很大。您还可以看到,默认情况下,模型要求图像作为输入,大小为224*224像素,带有3个通道(例如颜色)。
Layer (type) Output Shape Param #
=================================================================
input_5 (InputLayer) (None, 224, 224, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
_________________________________________________________________
predictions (Dense) (None, 1000) 4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________
代码清单20.3:VGG16模型的输出摘要我们还可以在VGG
我们还可以创建VGG模型中的层的图,如下所示:
from keras.applications.vgg16 import VGG16
from keras.utils.vis_utils import plot_model
model = VGG16()
plot_model(model, to_file= 'vgg.png' )
代码清单20.4:创建并绘制VGG16模型的图形。
同样,因为模型很大,所以图有点太大,可能无法阅读。但是,下文提供了这份文件:
图20.3:VGG模型中的图层图。
VGG()类接受一些参数,如果您希望在自己的项目中使用该模型,例如用于转移学习,那么这些参数可能只会引起您的兴趣。例如:
- Include_top(True):是否包含模型的输出图层。如果您根据自己的问题拟合模型,则不需要这些。
- weight('imagenet'):要加载的权重。如果您有兴趣从头开始训练模型,则可以指定“无”以不加载预训练的权重。
- Input_tensor(None):如果您打算在不同大小的新数据上拟合模型,则为新输入层。
- input shape(None):如果更改输入图层,模型应采用的图像大小。
- pooling(None):训练一组新输出图层时要使用的池类型。
- classes(1000):模型的类数(例如输出向量的大小)。
接下来,让我们看一下使用加载的VGG模型对特定照片进行分类。
20.5 开发简单的照片分类器
让我们开发一个简单的图像分类脚本。
20.5.1 获取示例图像
首先,我们需要一个可以分类的图像。您可以从Flickr下载咖啡杯的随机照片。
图20.4:咖啡杯。照片来自jfanaian,保留一些权利。
下载图像并使用文件名mug.jpg将其保存到当前工作目录。20.5.2 加载VGG模型
加载VGG-16型号的权重,就像我们在上一节中所做的那样。
from keras.applications.vgg16 import VGG16
# load the model
model = VGG16()
代码清单20.5:创建VGG16模型
20.5.3 加载和准备图像
接下来,我们可以将图像作为像素数据加载并准备将其呈现给网络。Keras提供了一些工具来帮助完成此步骤。首先,我们可以使用load_img()函数加载图像并将其大小调整为所需
from keras.preprocessing.image import load_img
# load an image from file
image = load_img( 'mug.jpg' , target_size=(224, 224))
代码清单20.6:加载并调整图像大小
接下来,我们可以将像素转换为NumPy数组,以便我们可以在Keras中使用它。我们可以使用img_to_array()函数。
from keras.preprocessing.image import img_to_array
# convert the image pixels to a NumPy array
image = img_to_array(image)
代码清单20.7:将图像像素转换为NumPy数组
网络期望一个或多个图像作为输入;这意味着输入数组需要是4维的:样本,行,列和通道。我们只有一个样本(一个图像)。我们可以通过调用reshape()并添加额外的维度来
# reshape data for the model
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
代码清单20.8:重塑NumPy像素数组
接下来,需要以与准备ImageNet训练数据相同的方式准备图像像素。具体来说,从论文:
我们唯一的预处理是从每个像素中减去在训练集上计算的平均RGB值。
- Very Deep Convolutional Networks for Large-Scale Image Recognition, 2014.
Keras提供了一种称为preprocess_input()的函数,用于为网络准备新的输入。
from keras.applications.vgg16 import preprocess_input
# prepare the image for the VGG model
image = preprocess_input(image)
代码清单20.9:预处理模型的像素数据
我们现在准备对我们加载和准备好的图像进行预测。
20.5.4 做一个预测
我们可以在模型上调用predict()函数,以便预测属于1000种已知对象类型中的每一种的图像的概率。
# predict the probability across all output classes
yhat = model.predict(image)
代码清单20.10:使用VGG16模型对图像进行分类。
几乎在那里,现在我们需要解释概率。
20.5.5 解释预测
Keras提供了decode predictions()的解释分类概率的函数,它可以返回类的列表及其概率,但是您可能只想呈现照片中的前3个分类对象,本例只反馈第一个最可能的对象。
from keras.applications.vgg16 import decode_predictions
# convert the probabilities to class labels
label = decode_predictions(yhat)
# retrieve the most likely result, e.g. highest probability
label = label[0][0]
# print the classification
print( ' %s (%.2f%%) ' % (label[1], label[2]*100))
代码清单20.11:解释预测概率
就是这样。
20.5.6 完整的例子
将所有这些结合在一起,下面列出了完整的示例:
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.applications.vgg16 import preprocess_input
from keras.applications.vgg16 import decode_predictions
from keras.applications.vgg16 import VGG16
# load the model
model = VGG16()
# load an image from file
image = load_img( 'mug.jpg' , target_size=(224, 224))
# convert the image pixels to a numpy array
image = img_to_array(image)
# reshape data for the model
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
# prepare the image for the VGG model
image = preprocess_input(image)
# predict the probability across all output classes
yhat = model.predict(image)
# convert the probabilities to class labels
label = decode_predictions(yhat)
# retrieve the most likely result, e.g. highest probability
label = label[0][0]
# print the classification
print( ' %s (%.2f%%) ' % (label[1], label[2]*100))
代码清单20.12:使用VGG模型对图像进行分类的完整示例
运行该示例,我们可以看到图像被正确分类为具有75%可能性的咖啡杯。
注意:鉴于神经网络的随机性,您的具体结果可能会有所不同。考虑运行几次示例。
coffee_mug (70.70%)
代码清单20.13:对图像进行预测的示例输出
0 条 查看最新 评论
没有评论