卷积神经网络现在在某些计算机视觉任务(例如图像分类)中能够超越人类的表现。
也就是说,给定一张物体的照片,回答这张照片显示的是1000个特定物体中的哪一个。
牛津大学研究人员开发的VGG模型是这项任务中赢得比赛的模型。这个模型除了能够对照片中的物体进行分类之外,其重要性在于模型权重是免费提供的,可以加载并用于您自己的模型和应用程序。
在本教程中,您将了解用于图像分类的VGG卷积神经网络模型。
完成本教程后,您将了解:
- 关于ImageNet数据集和竞赛以及VGG获胜模型。
- 如何在Keras中加载VGG模型并总结其结构。
- 如何使用加载的VGG模型对即时照片中的物体进行分类。
我的新书《使用Python进行深度学习》将助您启动项目,其中包括分步教程和所有示例的Python源代码文件。
让我们开始吧。
教程概述
本教程分为4个部分,它们是:
- ImageNet
- 牛津VGG模型
- 在Keras中加载VGG模型
- 开发一个简单的照片分类器
ImageNet
ImageNet是一个研究项目,旨在开发一个包含标注(例如图像及其描述)的大型图像数据库。
自2010年以来,这些图像及其标注一直是名为ImageNet大规模视觉识别挑战赛(ILSVRC)的图像分类挑战的基础。结果是,研究机构在预定义的数据集上进行竞争,以找出谁拥有最佳的图像物体分类模型。
ImageNet大规模视觉识别挑战赛是在数百个物体类别和数百万张图像上进行物体类别分类和检测的基准。这项挑战自2010年至今每年举办一次,吸引了五十多个机构的参与。
——ImageNet 大规模视觉识别挑战赛,2015。
对于分类任务,图像必须被分类到1000个不同类别中的一个。
过去几年,非常深的卷积神经网络模型被用于赢得这些挑战,并且任务结果已经超越了人类的表现。

ILSVRC挑战赛中使用的ImageNet数据集中的图像样本
摘自“ImageNet大规模视觉识别挑战赛”,2015年。
牛津VGG模型
来自牛津视觉几何组(简称VGG)的研究人员参加了ILSVRC挑战赛。
2014年,VGG开发的卷积神经网络模型(CNN)赢得了图像分类任务。

2014年ILSVRC分类任务结果
比赛结束后,参与者在论文中撰写了他们的发现
- 用于大规模图像识别的超深度卷积网络, 2014.
他们还将其模型和学习到的权重在线提供。
这使得其他研究人员和开发人员能够在自己的工作和程序中使用最先进的图像分类模型。
这有助于推动一系列迁移学习工作,其中预训练模型经过少量修改后用于全新的预测建模任务,从而利用经过验证模型的最先进的特征提取能力。
……我们提出了显著更准确的ConvNet架构,它们不仅在ILSVRC分类和定位任务上达到了最先进的准确性,而且也适用于其他图像识别数据集,即使作为相对简单的管道(例如,由线性SVM分类的深度特征,无需微调)的一部分,它们也取得了出色的性能。我们已经发布了我们两个表现最佳的模型,以促进进一步研究。
— 用于大规模图像识别的非常深层卷积网络,2014年。
VGG发布了两种不同的CNN模型,分别是16层模型和19层模型。
有关这些模型的完整详细信息,请参阅论文。
VGG模型不再是最先进的,只差几个百分点。尽管如此,它们是非常强大的模型,既可以作为图像分类器,也可以作为使用图像输入的新模型的基础。
在下一节中,我们将看到如何在Keras中直接使用VGG模型。
在Keras中加载VGG模型
VGG模型可以在Keras深度学习库中加载和使用。
Keras提供了一个应用程序接口,用于加载和使用预训练模型。
使用此接口,您可以使用牛津团队提供的预训练权重创建VGG模型,并将其作为自己模型的起点,或直接将其用作分类图像的模型。
在本教程中,我们将重点介绍使用VGG模型对新图像进行分类的用例。
Keras通过VGG16和VGG19类提供16层和19层版本。让我们重点关注VGG16模型。
该模型可以按如下方式创建:
1 2 |
from keras.applications.vgg16 import VGG16 model = VGG16() |
就是这样。
首次运行此示例时,Keras将从互联网下载权重文件并将其存储在 ~/.keras/models 目录中。
注意,权重大约为528兆字节,因此下载可能需要几分钟,具体取决于您的互联网连接速度。
权重只会下载一次。下次运行示例时,权重将从本地加载,模型应在几秒钟内准备好使用。
我们可以使用标准的Keras工具检查模型结构。
例如,您可以按如下方式打印网络层的摘要:
1 2 3 |
from keras.applications.vgg16 import VGG16 model = VGG16() print(model.summary()) |
您可以看到模型非常庞大。
您还可以看到,默认情况下,模型期望的输入图像大小为224 x 224像素,具有3个通道(例如彩色)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
_________________________________________________________________ 层(类型) 输出形状 参数数量 ================================================================= input_1 (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 ================================================================= 总参数:138,357,544 可训练参数:138,357,544 不可训练参数: 0 _________________________________________________________________ |
我们还可以按如下方式创建VGG模型中各层的图:
1 2 3 4 |
from keras.applications.vgg16 import VGG16 from keras.utils.vis_utils import plot_model model = VGG16() plot_model(model, to_file='vgg.png') |
同样,由于模型很大,图也太大了,可能难以阅读。尽管如此,它还是在下面提供了。

VGG模型层图
VGG() 类接受一些参数,如果您希望在自己的项目中使用模型(例如,进行迁移学习),这些参数可能会引起您的兴趣。
例如
- include_top (True):是否包含模型的输出层。如果您在自己的问题上拟合模型,则不需要这些层。
- weights (‘imagenet‘):要加载的权重。如果您有兴趣从头开始训练模型,可以指定None以不加载预训练权重。
- input_tensor (None):如果您打算在新尺寸的不同数据上拟合模型,则这是一个新的输入层。
- input_shape (None):如果您更改输入层,模型预期接受的图像大小。
- pooling (None):当您训练一组新的输出层时要使用的池化类型。
- classes (1000):模型的类别数量(例如输出向量的大小)。
接下来,让我们看看如何使用加载的VGG模型对即时照片进行分类。
开发一个简单的照片分类器
让我们开发一个简单的图像分类脚本。
1. 获取示例图像
首先,我们需要一张可以分类的图像。
您可以从Flickr此处下载一张随机的咖啡杯照片。

咖啡杯
照片作者:jfanaian,保留部分权利。
下载图像并将其保存到您的当前工作目录,文件名为“ mug.jpg ”。
2. 加载VGG模型
加载VGG-16模型的权重,如上一节所述。
1 2 3 |
from keras.applications.vgg16 import VGG16 # 加载模型 model = VGG16() |
3. 加载和准备图像
接下来,我们可以将图像作为像素数据加载,并准备好将其呈现给网络。
Keras提供了一些工具来帮助完成此步骤。
首先,我们可以使用 load_img() 函数加载图像并将其调整为所需的224×224像素大小。
1 2 3 |
from keras.preprocessing.image import load_img # 从文件加载图像 image = load_img('mug.jpg', target_size=(224, 224)) |
接下来,我们可以将像素转换为NumPy数组,以便在Keras中使用它。我们可以使用 img_to_array() 函数来完成此操作。
1 2 3 |
from keras.preprocessing.image import img_to_array # 将图像像素转换为numpy数组 image = img_to_array(image) |
网络期望输入一个或多个图像;这意味着输入数组需要是4维的:样本、行、列和通道。
我们只有一个样本(一张图像)。我们可以通过调用 reshape() 并添加额外维度来重塑数组。
1 2 |
# 重塑数据以适应模型 image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2])) |
接下来,图像像素需要以与ImageNet训练数据相同的方式进行准备。具体来说,根据论文:
我们唯一做的预处理是从每个像素中减去在训练集上计算的平均RGB值。
— 用于大规模图像识别的非常深层卷积网络,2014年。
Keras提供了一个名为 preprocess_input() 的函数来为网络准备新输入。
1 2 3 |
from keras.applications.vgg16 import preprocess_input # 为VGG模型准备图像 image = preprocess_input(image) |
我们现在已经准备好对加载和准备好的图像进行预测。
4. 进行预测
我们可以调用模型上的 predict() 函数,以获取图像属于1000种已知物体类型中每一种的概率预测。
1 2 |
# 预测所有输出类别的概率 yhat = model.predict(image) |
差不多了,现在我们需要解释这些概率。
5. 解释预测
Keras提供了一个名为 decode_predictions() 的函数来解释这些概率。
它可以返回一个类别列表及其概率,以防您想展示照片中可能存在的排名前3的物体。
我们将只报告第一个最有可能的物体。
1 2 3 4 5 6 7 |
from keras.applications.vgg16 import decode_predictions # 将概率转换为类别标签 label = decode_predictions(yhat) # 检索最可能的結果,例如最高概率 label = label[0][0] # 打印分类结果 print('%s (%.2f%%)' % (label[1], label[2]*100)) |
就是这样。
完整示例
将所有这些联系起来,完整的示例如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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 # 加载模型 model = VGG16() # 从文件加载图像 image = load_img('mug.jpg', target_size=(224, 224)) # 将图像像素转换为numpy数组 image = img_to_array(image) # 重塑数据以适应模型 image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2])) # 为VGG模型准备图像 image = preprocess_input(image) # 预测所有输出类别的概率 yhat = model.predict(image) # 将概率转换为类别标签 label = decode_predictions(yhat) # 检索最可能的結果,例如最高概率 label = label[0][0] # 打印分类结果 print('%s (%.2f%%)' % (label[1], label[2]*100)) |
运行示例后,我们可以看到图像被正确分类为“ 咖啡杯 ”,可能性为75%。
1 |
咖啡杯 (75.27%) |
扩展
本节列出了一些您可能希望探索的扩展本教程的想法。
- 创建函数。更新示例并添加一个函数,该函数在给定图像文件名和已加载模型的情况下,将返回分类结果。
- 命令行工具。更新示例,使其在命令行上给定图像文件名时,程序将报告图像的分类。
- 报告多个类别。更新示例以报告给定图像的前5个最可能的类别及其概率。
进一步阅读
如果您想深入了解此主题,本节提供了更多资源。
- ImageNet
- 维基百科上的ImageNet
- 用于大规模图像识别的超深度卷积网络, 2015.
- 用于大规模视觉识别的非常深层卷积网络,牛津大学。
- 使用极少量数据构建强大的图像分类模型, 2016.
- Keras 应用程序 API
- Keras权重文件
总结
在本教程中,您了解了用于图像分类的VGG卷积神经网络模型。
具体来说,你学到了:
- 关于ImageNet数据集和竞赛以及VGG获胜模型。
- 如何在Keras中加载VGG模型并总结其结构。
- 如何使用加载的VGG模型对即时照片中的物体进行分类。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
谢谢你,Jason!
不客气。
你好,我是一名博士研究员,我想将这种方法应用于沙漠地区以检测沙丘,这可能吗?
也许可以。将模型作为起点(迁移学习),并为您的特定问题重新训练模型的分类后端。
在此处了解更多信息
https://machinelearning.org.cn/transfer-learning-for-deep-learning/
您好,我是这个领域的新手,我的硕士论文需要使用新的神经网络架构来检测植物叶片疾病,但是没有足够的代码,这是我的导师告诉我的,所以如果您能给我一些提示,因为我有点迷失。谢谢
“没有足够的代码”是什么意思?
嘿,Jason Brownlee,你能帮我做一个关于露骨内容检测的深度学习项目吗?
这是我的Twitter账号:wilson_exex
我真的需要帮助来完成这个项目
我没有能力加入你的项目,抱歉。
谢谢你,Jason。非常有趣的工作。
从这一点开始,我们继续我们的计算机视觉之旅?
如果可能的话,请在未来的工作中告诉我们关于感兴趣区域(Region of Interest)技术。对于初学者来说很难理解,但在实践中非常有用。
很好的建议,谢谢亚历山大。
在接下来的几个月里,重点将是自然语言处理,以及与我的新书相关的帖子。
我不想扫你的兴,但是…
http://www.bbc.com/news/technology-41845878
是的,我看到了。
我们仍在取得令人印象深刻的进展,并取得了十年前我们无法想象的惊人成果。
感谢Jason的精彩文章,您能推荐哪种预训练模型可以用于识别单个字母和数字吗?
好问题,我一下子也想不起来,也许可以尝试在谷歌上搜索一下。我预计会有这样的模型。
如果您发现了一些,请告诉我。
谢谢你,Jason。
有一天你能花时间写一篇关于训练VGG用于不属于原始1000个类别(Imagenet数据集)但完全是新的2000个类别的文章吗?我特别感兴趣的是从头开始训练的时间和微调的时间。没有顶层权值会大大减少训练时间吗?
再次感谢您的帖子
好建议,谢谢 Sam。我希望能做到。
是的,输出层之前的层确实包含有价值的信息!我已经在一些图像字幕示例中测试过这一点。
感谢Jason的精彩文章。我们真诚地希望您能发表一篇关于物体检测(如SSD(单发多盒检测器))的文章,用于标准数据和自定义数据,或者关于语义分割(如FCN或U-Net)的文章,那将非常棒。
谢谢 Adel!
非常感谢。
不客气。
我仍然很困惑,我可以更改图像数据集并用VGG训练它吗?
谢谢
抱歉,我没明白,您能重新陈述您的问题吗?
你好 Jason,
我现在正在学习深度学习,您的网站是一个宝库。
非常感谢。
我刚刚读完《如何使用预训练VGG模型对照片中的物体进行分类》,这非常有帮助。
Keras + VGG16在图像分类方面确实非常有帮助。
您的文章使学习变得容易。万分感谢。
我想知道我可以使用什么工具进行医学图像分析。
是否有任何特定的库可以帮助我分析医学图像?VGG不能。
您的回复将不胜感激。
抱歉,我没有这方面的经验。我无法给您具体的建议。
你能告诉我“mug.jpg”应该保存在哪里吗?
我试着把它保存到一些目录中,但它总是返回以下错误。
FileNotFoundError: [Errno 2] No such file or directory: ‘mug.jpg’
非常感谢!!
将文件保存在与代码文件相同的目录中,并从命令行运行代码,以避免IDE和笔记本带来的任何问题。
嗨,Jason,
感谢分享。我想知道VGG16模型能否识别图像中的不同物体,然后提取每个物体的特征,或者是否有通过Keras库实现此功能的方法?
它可以重新用于类似这样的应用程序。
请参阅这个接近的示例:
https://machinelearning.org.cn/develop-a-deep-learning-caption-generation-model-in-python/
你好 Jason,
R语言中有类似的包吗?
可能有一些,但我不太清楚,抱歉。
有没有办法使用不同于224×224的格式?
我找到的唯一示例在这里:https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.3-using-a-pretrained-convnet.ipynb
基本上,我们需要在模型顶部添加一个额外的层并使用自定义分类器。
我猜由于模型是针对224×224图像训练的,它不会直接适用于不同大小的图像,我说得对吗?
是的,你需要训练一个新的前端。
嗨,Jason,我正在尝试使用Keras的VGG16模型,但我遇到了一个严重的问题。每当我执行
Vgg_model = VGG16() 时,我的电脑就会带着这个警告冻结:
tensorflow/core/framework/allocator.cc.124 分配的449576960字节超过系统内存的10%
我目前使用的是64位,4GB内存的Linux Mint 18操作系统。
我无法访问任何GPU。
我认为这个问题与我有限的内存有关?
此致,Aditya
这可能与内存有限有关。
也许尝试在另一台机器上或EC2实例上运行?
简单但对我提供给这个程序的20个测试图像文件效果很好!干得漂亮!谢谢!
干得好!
如果您能指出如何将VGG16扩展为实际的Keras或Tensorflow代码,以便学习者可以自行修改代码进行训练、推理或迁移学习,我将不胜感激。
很好的建议,谢谢。
你好
我需要一个关于
包含一些图像数据集的CSV文件数据集的建议。
它有6列,每列的值为(1,0,-1)
我想使用VGG16并进行多级分类。
如何处理这个问题,任何想法、建议或论文都会非常有帮助。
提前感谢。
通常图像不以CSV格式存储,而是以JPEG或PNG等二进制图像格式存储。
哪些图像类别被输入到预测对象的VGG模型中?
我们如何查看?
好问题,可能有办法。
不假思索地说,一种方法是枚举decode_predictions()的所有输入。
嗨,Jason,
我有一个与Namrata类似的问题,如果我想用一些新的类别训练我的VGG模型,我该怎么做?
这里有一些谷歌搜索的解决方案
https://stackoverflow.com/questions/47474869/getting-a-list-of-all-known-classes-of-vgg-16-in-keras
@Jason,
您给出的链接显示了在VGG模型中训练的类别列表,我的问题是,我们能否编写自己的VGG模型并提供类别?
如果有任何链接或方法可以做到这一点,请告诉我
我没有这方面的链接。
也许您可以查看Keras代码并根据您的用例调整API中的现有示例?
感谢您所做的所有努力。您让研究人员的梦想成真 :)
谢谢。
感谢这篇精彩的文章。
我是深度学习新手。我有一个问题,模型能否提供对象的精确位置,以便我们可以在其上放置一个边界框?VGG16模型能否在一张图像中检测多个对象并给出它们的位置?
它可以,这被称为对象定位,并且需要的不仅仅是VGG类型的模型。抱歉,我没有一个可用的示例。
你好Yuri,
我正在处理与你相同的问题,你的研究有进展吗?
感谢您所有的精彩演示。但是,我想知道如何使用预训练的VGG网络来分类我的灰度图像,因为VGG网络的图像通道数是3,而不是1。我可以改变VGG网络图像的通道数吗?例如,2?
很好的问题!
也许可以切掉模型的输入层,然后训练新的输入层,使其期望1个通道。
太棒了,出色的工作!赞赏。
谢谢。我很高兴它有帮助。
谢谢老师的这个教程,请问我能否使用VGG16来分类属于特定领域且ImageNet数据库中不存在的图像?
好的,试试看吧。
先生,
我是您博客的忠实读者。我读过您的作品,很喜欢。此外,在您的这个例子中,我看到您将图片输入到网络中。我也是Adrian博士作品的粉丝,我正在阅读关于迁移学习的内容,其中我们移除了末尾的FC层,并在那里添加了一个逻辑回归来分类数据集(例如Caltech 101),我们获得了98%的准确率。VGG16是在Imagenet上训练的,但迁移学习允许我们将其用于Caltech 101。
感谢你们向我们凡人传授如此不可思议的东西。有一个请求,您能否展示一个使用预训练词嵌入(如GloVe或WordNet)进行迁移学习的类似示例,以检测电影评论中的情感。
谢谢。
我提供了重用词嵌入的示例,请在博客中搜索。或查看我的NLP书籍。
是的,我知道你已经在你的NLP书中包含了它们,使用CNN和词嵌入来分类情感,我也已经实现了。无论如何,谢谢回复。
此致,
Anirban Ghosh。
嘿,你好,
谢谢你的文章,但我有一个疑问,
网络中的最后一层是softmax层,在这个层之前,全连接层有1000个神经元,对吗?所以我们可以用它来分类1000个对象。
我的疑问是,这1000个神经元对于所有VGG网络来说都是固定的吗,即使我们只尝试分类少数(比如小于1000的100个)?或者这个数字(最后一层全连接层中的神经元数量)取决于我们尝试处理的分类数量。
预测是对1000个神经元进行的softmax。
它固定为1000,但如果您愿意,可以根据具有更多/更少类别的不同数据集重新拟合网络。
好的,那么正如我所说,如果我们要预测100个类别,我们仍然会有1000个神经元,但只有100个会用于分类。您是这个意思吗?如果是这样,那剩下的900个神经元会怎样呢,softmax层可以这样工作,只使用所有可用神经元中的一部分吗?
抱歉,如果这听起来很基础,我刚开始学习深度学习,这些事情让我有些困惑。谢谢
如果你有100个类别,你的输出层有100个节点,而不是1000个。
明白了!感谢回复
非常感谢Jason Brownlee先生!您做得非常出色!我一直在关注您的一些机器学习精通“如何…”、“入门…”系列。您处理、推广和推进一些深度学习“热门和趋势”话题的方式令我印象深刻……用简单的文本解释它们(包括基本的Python概念,当然还有Keras API、TensorFlow库等)。
对我来说,主要问题是您能够传达完整的解决方案,涵盖从问题开始的各个方面,包括数学或深度学习的直觉概念,接着是编程语言、所用库模块的操作思想、参考文献列表等。最后但同样重要的是,您提供了可操作的代码,让我们能够亲自实验您介绍的所有概念。
JG向您致以最诚挚的感谢,感谢您真正出色的精通之作!!
不客气,很高兴这些材料有帮助。
我想知道,如果我想训练我自己的数据集以基于VGG模型获取新的权重,并对新的权重进行预测,我该怎么做
保持整个VGG模型固定,只训练一些新的输出权重以与VGG输出进行交互。
嗨,您能帮我定位图像中的物体,比如车牌吗?我知道YOLO和Faster-RCNN可以用于此。但是我在使用锚框实现区域建议时遇到了问题。您能给我一些建议吗?
我希望将来能介绍YOLO。
Jason Brownlee先生,再次非常感谢您对VGG16 Keras应用程序的介绍,我认为您的代码和解释是完美的(至少对我目前的水平而言),在深入研究更深层次的问题,例如在Keras上构建自己的模型之前。我喜欢您在运行整个系统之前构建代码块的方式。我感谢您为我们所有人提供的“免费”工作。您为我们的机器学习社区做了许多值得赞赏的事情!!祝您在这方面取得长足发展!
谢谢,很高兴它有所帮助。
嗨,Jason,
您的博客是机器学习的最佳选择!
我有一个关于VGG性能的问题。
对于咖啡杯,它能精确检测到物体。
但是我尝试了一张非常明显的蛇的照片(https://reikiserpent.files.wordpress.com/2013/03/snakes-guam.jpg);然而结果并不那么令人满意
[[(‘n01833805’, ‘蜂鸟’, 0.22024027),
(‘n01665541’, ‘棱皮龟’, 0.10800469),
(‘n01664065’, ‘蠵龟’, 0.088614523),
(‘n02641379’, ‘雀鳝’, 0.083981715),
(‘n01496331’, ‘电鳐’, 0.061437886)]]
VGG表现非常好,有没有办法在不重新训练模型的情况下改善模型结果(也许进行一些微调)?
非常感谢,
也许试试VGG以外的模型?
我也试过ResNet,但结果仍然与现实相去甚远。
我想测试图像必须与用于训练模型的图像(例如ImageNet)非常相似。
嗨,先生,谢谢你的教程
我注意到有些地方使用VGG16,但它们输入的图像大小和宽高比不同,例如192×99或69×81等等,我不明白它们是如何获得输出的,VGG16可以在不调整大小的情况下接受224×224以外的图像吗?结果会是什么?谢谢。
也许调整图像大小?
也许改变网络的输入形状使其更大,并对较小的图像进行零填充?
你好,
我尝试将vgg16的类型更改为Sequential,但是,更改后它删除了输入层。
我不知道为什么。我该如何解决?
谢谢
为什么要把它改成Sequential?
嗨,Jason,
我非常喜欢它,想知道是否有关于VGG微调的后续内容?
谢谢。
很好的问题!
从小而衰减的学习率和早期停止开始会是一个好主意。
非常感谢这项伟大的工作。我想知道是否可以使用这个模型(VGG16)来分类日常活动。
怎么会呢?
谢谢你,Jason!我无言以对。
谢谢。我很高兴它有帮助。
你好,
我已经下载了vgg19.npy模型。是否可以直接从这个模型加载,而不必再次下载?
也许吧,我没有手动加载模型的示例,抱歉。
非常感谢这篇有价值的帖子。真的很有帮助。
我有一个问题,请问,
我如何检索前n个概率的索引位置?
例如,杯子的预测向量会生成一个1000*1的向量,其中包含每个类别的概率值。
假设概率为
[.1
.2
.3 (前1)
.001
.002
.25(前2)
.24 (前3)
.1
.01
…
…
..
等等}
我希望检索前3个概率所在的位置/索引。
在前面的例子中,我希望检索
.3 (前1)
和
.25(前2)
和.24 (前3) 的位置
即[2,5,6]
谢谢你。
好问题,你可以自己编写代码,或者numpy可能有一个函数。
也许argpartition可以做到?
https://docs.scipy.org.cn/doc/numpy/reference/generated/numpy.argpartition.html
非常感谢。
大家好,感谢这个很棒的教程。你们有没有关于如何用我们自己的图像(自定义分类器)进行训练的教程,使用你们现在遵循的任何架构。所以请告诉我。谢谢你们的帮助。
当然,您可以加载您的图像,并可能使用VGG模型作为起点进行迁移学习。
亲爱的 Jason,
非常有帮助的帖子。另外,我有一个问题,我想使用具有不同输入形状的预训练模型。例如,预训练模型的输入是 (None, 3661, 128),而我正在应用于预训练模型的新数据集的输入形状是 (None, 900, 165)。所以,我想知道如何为新数据集设置预训练模型的输入形状,因为我遇到了一个错误
“ValueError: “input_length”是3661,但收到的输入形状是 (None, 900, 165)”。
提前致谢
您可以在新的输入层之后添加一个新的隐藏层,并且只训练这个新层的权重。
或者调整输入大小以匹配旧模型。
亲爱的Jason,我想知道用于迁移学习的预训练模型是否也包含测试阶段,还是只包含训练阶段?换句话说,预训练模型是同时包含训练和测试阶段,还是只包含训练阶段?
提前感谢。
它们像任何其他模型一样使用,例如,微调/训练,然后测试/评估。
我不明白你的意思。请问你能再解释一下吗?谢谢你的回复。
哪一部分?
你好,Anam,这是对你问题的简要解释。该网络 (VGG16) 在部署为模型之前已经过训练和测试,因此,无需再次讨论训练和测试集。当你输入一张图片进行分类时,你所做的只是使用预训练模型进行分类。我希望这能有所帮助,否则,如果你需要进一步的澄清,请告诉我。@Jason Brownlee 做得很棒!!
解释得很棒。
@Busayo 不完全是。你可以使用 VGG16 进行以下任一操作:
1) 仅使用架构而不使用权重。在这种情况下,你在自己的数据集上训练模型。
2) 只保留一些初始层及其权重,并使用你的数据集训练后面的层。
3) 将完整的 VGG16 用作预训练模型,并仅将你的数据集用于测试目的。
总结得很好!
如何使用我自己的自定义训练数据集训练模型?
我在这里教授如何训练模型
https://machinelearning.org.cn/start-here/#deeplearning
我想如果我想用VGG人脸进行人脸识别,也是同样的原理,对吗?
也许吧,但人脸识别与简单的分类是截然不同的问题。
我目前正在使用Keras、ImageNet和VGG16开发一个应用程序。
我想知道是否可以检查图像是否属于植物、动物、食物等类别……而不是仅仅检查它是哪种植物或食物?
是的,也许模型的输出或分类器部分需要重新训练以适应更高阶的类标签?
先生您好,感谢您的教程,我正在使用预训练的VGG 16模型对照片中的对象进行微调分类,分为6个不属于imagenet模块的类别。当我运行我的代码时,我遇到了错误:ValueError:“decode_predictions”期望一批预测(即形状为(samples, 1000)的2D数组),但发现数组形状为(1, 6)。请问您能帮我解决这个问题吗?
您不能将解码预测与您自己的类别一起使用。您必须自己将整数映射到您的类别标签。
谢谢您的回复,先生,您能指导我使用上面的例子将整数映射到我自己的类标签的过程吗?我仍然是机器学习的新手
是的,你可以使用标签编码器
https://scikit-learn.cn/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html
我读了你的所有文章,但我不太明白在哪里以及如何训练数据集,以及如何使用上述代码进行预测,请详细说明一下,一步一步来。
因为我有一个图像数据集,所以我是不是需要为每个图像进行分类标注,以及如何训练数据集以及如何预测,请帮帮我
是的,每张图片都需要一个标签。
我希望很快能提供一个关于你所问内容的教程。
请问我想知道。你对一张图片——“mug.jpg”应用了这个算法,但如果我有像image1、image2、image3这样很多图片,那么如何编码?
也许你可以枚举目录中的所有图像并对每个图像进行预测?
能举个例子吗?
是的,我有很多,也许从这里开始
https://machinelearning.org.cn/start-here/#dlfcv
谢谢这篇解释清晰的教程。
谢谢,很高兴对您有帮助。
你好,
感谢本教程。是否可以使用VGG预训练网络进行时间序列回归?输入和输出层应该如何改变?
是的,但是将用于图像分类的模型用于时间序列预测是没有意义的。
谢谢您的回复。您知道有什么可以使用的预训练RNN吗?我已经在网上进行了广泛搜索,但找不到。
抱歉,我不知道有适用于时间序列的预训练模型。
我无法运行
from keras.applications.vgg16 import VGG16
model = VGG16()
spyder 中的以下命令。它显示了很多错误。
听到这个消息我很难过。
我建议从命令行运行代码示例。我在这里演示了如何操作
https://machinelearning.org.cn/faq/single-faq/how-do-i-run-a-script-from-the-command-line
先生,我如何将这个预训练模型与一些其他数据集一起使用?
我在上面的教程中演示了如何操作。
感谢您的回答。
抱歉,但在上面的教程中,它是在预训练的 IMAGENET 数据集上进行分类……但我希望使用其他数据集来训练 VGG 模型。请分享链接或代码,因为我已经为此困扰了几天。
谢谢你
这篇帖子展示了如何在另一个数据集上拟合模型。
https://machinelearning.org.cn/how-to-develop-a-convolutional-neural-network-to-classify-photos-of-dogs-and-cats/
名称 = decode_predictions(pre[0])
–>
—————————————————————————
ValueError 回溯 (最近一次调用)
in
—- > 1 名称 = decode_predictions(pre[0])
2 名称 = 名称[0][0]
~\Anaconda3\lib\site-packages\keras\applications\__init__.py 中的 wrapper(*args, **kwargs)
26 kwargs[‘models’] = models
27 kwargs[‘utils’] = utils
— > 28 返回 base_fun(*args, **kwargs)
29
30 返回 wrapper
~\Anaconda3\lib\site-packages\keras\applications\vgg16.py 中的 decode_predictions(*args, **kwargs)
14 @keras_modules_injection
15 定义 decode_predictions(*args, **kwargs)
— > 16 返回 vgg16.decode_predictions(*args, **kwargs)
17
18
~\Anaconda3\lib\site-packages\keras_applications\imagenet_utils.py 中的 decode_predictions(preds, top, **kwargs)
220 ‘一批预测 ‘
221 ‘(即形状为 (samples, 1000) 的二维数组)。 ‘
–> 222 ‘找到形状为 ‘ + str(preds.shape) 的数组)
223 如果 CLASS_INDEX 为 None
224 fpath = keras_utils.get_file(
ValueError: `decode_predictions` 期望一批预测(即形状为 (samples, 1000) 的二维数组)。找到形状为 (2,) 的数组
我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
Vgg-16模型能否用于10个人的人脸识别问题,并使用预训练权重?
不直接,模型需要针对新数据进行调整。
最好使用facenet或vggface
https://machinelearning.org.cn/how-to-develop-a-face-recognition-system-using-facenet-in-keras-and-an-svm-classifier/
感谢您的回复。这真的对我的工作很有帮助。如果我使用嵌入和SVC,模型可以识别我自己的数据集中的人脸。但我不想使用嵌入和SVC分类器进行识别。如果我在facenet模型的最后一层添加一个softmax,并用我自己的数据集图像微调模型的最后一层,它在训练时可以达到100%的准确率,但如果我测试一些随机图像,它就无法识别该人脸。我找不到原因。
是的,你需要 VGGFace 模型,而不是 VGG 模型,请看这里
https://machinelearning.org.cn/how-to-perform-face-recognition-with-vggface2-convolutional-neural-network-in-keras/
如何将VGG从conv5_3层提取的特征转换为SVC参数输入?
这些特征是一个向量(或可以通过 flatten() 转换为向量),可以用作任何你想要的模型的输入。
除了默认的VGG16权重,如何加载其他训练好的VGG16权重?
我相信你必须指定“weights”参数和文件名,例如 weights=’/imagenet.h5’
你可以在这里了解更多关于 API 的信息
https://keras.org.cn/applications/#vgg16
如何将VGG16预训练权重加载到我们的脚本中,并将其用作猫狗数据集的分类器?
这里有一个例子
https://machinelearning.org.cn/how-to-develop-a-convolutional-neural-network-to-classify-photos-of-dogs-and-cats/
谢谢!
不客气。
我正在使用 VGG16 和 VGG19 处理我自己的数据集。我将图像形状更改为 32X32。我的验证准确率没有变化……我的代码有什么问题……我被困住了……
我不想使用迁移学习方法……请帮忙……
第1个周期/共30个周期
52/52 [==============================] – 116秒 2秒/步 – 损失:nan – 准确率:0.2558 – val_loss:nan – val_acc:0.2540
第2个周期/共30个周期
52/52 [==============================] – 119秒 2秒/步 – 损失:nan – 准确率:0.2558 – val_loss:nan – val_acc:0.2540
第3个周期/共30个周期
52/52 [==============================] – 121秒 2秒/步 – 损失:nan – 准确率:0.2505 – val_loss:nan – val_acc:0.2540
第4个周期/共30个周期
52/52 [==============================] – 126秒 2秒/步 – 损失:nan – 准确率:0.2522 – val_loss:nan – val_acc:0.2540
第5个周期/共30个周期
52/52 [==============================] – 122秒 2秒/步 – 损失:nan – 准确率:0.2571 – val_loss:nan – val_acc:0.2540
第6个周期/共30个周期
52/52 [==============================] – 121秒 2秒/步 – 损失:nan – 准确率:0.2510 – val_loss:nan – val_acc:0.2540
我在这里有一些建议
https://machinelearning.org.cn/improve-deep-learning-performance/
谢谢你的回复.....
不客气。
感谢您出色的教程!
我对预测的父类别很感兴趣。
例如,如果模型预测是一只狗。我希望得到动物这个类别。
听起来是个有趣的项目!
先生,您可能会觉得这个问题很愚蠢,但请您帮我澄清一下我的疑惑。
1) 迁移学习 (VGG-16) 在我们拥有不同类别的数据时是否有效,这意味着模型没有在新类别上进行训练,或者说新数据不来自 Imagenet 数据集?
2) 先生,您能解释一下,如果我们将所有 VGG-16 层都设置为不可训练 (vgg.trainable = False),并且在其顶部添加了我们自定义的卷积层,那么迁移学习是如何工作的?(图像不是来自那 1000 个类别)?如果我们关闭这些层,我们如何从 VGG-16 获取信息到自定义层?
您可以将模型与 Imagenet 相同或不同的类别一起使用。如果使用不同的类别,您将不得不在您的新类别/数据集上训练新层。
它的工作原理是只训练您添加的新层,而保持所有其他层不变。现有层将从照片中提取特征,您的新层将解释这些特征并对其进行分类——这对我来说仍然很神奇!
Jason,关于预训练模型的精彩文章。您能告诉我哪种模型可以用于EEG信号处理以进行情绪检测吗?谢谢。
也许可以比较eMLP、CNN和LSTM,并将模型作为时间序列分类。
你可以从这里开始
https://machinelearning.org.cn/start-here/#deep_learning_time_series
嗨,Jason,
首先,非常感谢您所做的工作。这些教程非常好,每当我想搜索特定的机器学习/深度学习概念时,我总是会访问这个网站。然而,我对加载预训练模型并在其上进行预测感到困惑。我有一个从头开始训练的 VGG 模型,保存在 .h5 文件中。我可以使用以下方法加载它:
“””””””from keras.models import load_model
saved_model = load_model(“/content/vgglite.h5″)
saved_model.layers[0].input_shape #(None, 224, 224, 3)””””” 但当我尝试预测时,测试文件夹没有转换为数组,我得到了 [[[ IsADirectoryError: ]]]
我当时在使用 [[[[[ import os
from keras.preprocessing import image
import numpy as np
batch_holder = np.zeros((20, 224, 224, 3))
img_dir=’/content/drive/My Drive/COMPUTER VISION DOCS/imagenette_6class/test/’
for i,img in enumerate(os.listdir(img_dir))
img = image.load_img(os.path.join(img_dir,img), target_size=(224,224))
batch_holder[i, :] = img]]]]]]]]
请您解释一下如何加载预训练模型并使用测试集进行预测。提前致谢。
不客气。
也许可以从教程中的示例开始,确认它在您的工作站上运行正常,然后慢慢将其适应您的项目。
Jason,感谢您 enlightening 人们的出色工作。我真的很感激。我正在研究一个开发系统以区分假图像和原始图像的项目。我可以使用这个 VGG-16 模型来开发它吗?
不客气。
也许可以把它作为起点?
嗨,Jason,
感谢您的出色工作。我尝试了同样的图像(cup.jpg)示例。
我从您的原始图像中剪切并保存为“cup.jpg”的图像。在我按照您的代码使用VGG16模型后,我无法获得准确性,预测也错误。
模型输出为“mosquito_net”,准确率为1.7%。
请问,为什么我的预测在同一张图像上出错了?
也许确保您已正确加载图像并按照教程中的预期方式准备像素。
嗨,执行所有代码后我收到以下错误
无法导入 PIL.Image。使用 `load_img` 需要 PIL。
这将帮助您安装和测试 PIL/Pillow
https://machinelearning.org.cn/how-to-load-and-manipulate-images-for-deep-learning-in-python-with-pil-pillow/
谢谢Jason的这个教程,这个代码是针对一张图片的,你能告诉我如何为VGG16 CNN准备一个像FER2013这样的数据集吗?
你说的准备数据集是什么意思?
我的意思是,我如何才能像ImageNet训练数据那样,为VGG16 CNN调整一个像FER2013这样的数据集,因为我有一个关于面部表情识别的项目。
抱歉,我没有这方面的确切示例。
亲爱的 Jason
我如何从TL模型计算FP、TP和敏感度?
这将帮助您计算其他指标
https://machinelearning.org.cn/tour-of-evaluation-metrics-for-imbalanced-classification/
我可以在 TL 中实现 GAN 增强而不是常规增强吗?如何实现?
抱歉问这些基本问题,我是一个初学者。
是的,但我预计它不如常规图像数据增强有效。
你好 Jason,
我是辛辛那提大学的研究生。我想知道我是否可以在我的硕士论文中使用您帖子中的图片,并引用图片来源,即此帖子。
请告诉我。
谢谢你
Anusha
只要您清楚地引用并链接到来源即可
https://machinelearning.org.cn/faq/single-faq/how-do-i-reference-or-cite-a-book-or-blog-post
嗨,Jason,
如何用非方形矩阵图像(例如640*480)训练VGG16?我也需要改变卷积和池化过滤器的大小吗?
谢谢你。
不行。
嗨,Jason,
为什么VGG16在迁移学习和微调教程中比Resnet50更受欢迎,更常用于训练包含多个类的数据集?
这有什么关键的区别或原因吗?
谢谢你。
因为它简单、易于理解,并且对于许多应用程序来说已经足够好用。
我可以用VGG16处理癌症图像吗?还是应该选择Resnet/Alexnet/Inception_3或其他模型?
我建议测试一套模型作为迁移学习的起点,并发现最适合你特定数据集的模型。
我可以用VGG16处理其他图像数据集吗?
当然可以。
感谢您的出色工作,但当我使用VGG16数据集时,numpy数组的输入形状出现了错误。
您能对此有所启发吗?
代码片段
def test_on_whole_videos(train_data,train_labels,validation_data,validation_labels)
x = []
y = []
count = 0
output = 0
base_model = load_VGG16_model()
model = train_model(train_data,train_labels,validation_data,validation_labels)
i=0
count = 0
for filename in os.listdir(“./test_im/3”)
img=cv2.imread(“./test_im/3/”+filename,0)
x.append(img)
错误
x = np.array(x) in test_on_whole_videos(train_data, train_labels, validation_data, validation_labels)
17 x = np.array(x)
18 print(type(x))
—> 19 x_features = base_model.predict(x)
20 answer = model.predict(x_features)
21 print(answer)
ValueError: Input 0 of layer block1_conv1 is incompatible with the layer: expected ndim=4, found ndim=3. Full shape received: [None, 224, 224]
很抱歉您遇到了问题,也许这些技巧会有所帮助
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
嘿,Jason,看这一行
> image = preprocess_input(image)
看起来Keras的VGG preprocess_input实际上只是调用imagenet_utils.preprocess_input(x, data_format=data_format, mode=’caffe’),根据源代码
@keras_export(‘keras.applications.vgg16.preprocess_input’)
def preprocess_input(x, data_format=None)
return imagenet_utils.preprocess_input(
x, data_format=data_format, mode=’caffe’)
来源:https://tensorflowcn.cn/api_docs/python/tf/keras/applications/vgg16/preprocess_input
我理解这意味着它默认为'caffe'模式,根据文档
> caffe: 会将图像从RGB转换为BGR,然后对ImageNet数据集的每个颜色通道进行零中心化,不进行缩放。
零中心化是有道理的,因为它遵循了论文的预处理技术。但是将通道从RGB切换到BGR呢?
Keras的load_img()默认是'rgb'。所以我担心使用Keras的preprocess_input(image)会搞乱通道顺序。
我测试了一下
from tensorflow.keras.applications.vgg16 import preprocess_input
copied_data = np.copy(data)
prep_data = preprocess_input(copied_data)
from matplotlib import pyplot as plt
plt.imshow(data[0].astype(‘int’))
plt.show()
plt.imshow(prep_data[0].astype(‘int’))
plt.show()
果然,RGB通道被翻转了。原始图像中的黄色/红色变成了蓝色调。
那么,最好的解决方法是什么?从一开始就将数据加载为BGR吗?
哦,看来提问往往是通往启蒙的道路……我现在明白,将图像从RGB转换为BGR是必要的,因为Keras VGG16模型(带有“imagenet”权重)内部使用的是BGR通道顺序。
> 在Keras VGG16的链接中,提到:“这些权重是从牛津大学VGG发布的权重移植过来的。”因此VGG16和VGG19模型在Caffe中训练并移植到TensorFlow,因此这里的模式是“caffe”(范围从0到255,然后提取平均值[103.939, 116.779, 123.68])。
@ https://stackoverflow.com/questions/53092971/keras-vgg16-preprocess-input-modes
太棒了!
有趣,也许Keras在最新版本中搞砸了。
或许你可以为你的应用程序手动实现数据预处理。
为什么预训练模型能够准确分类常见物体,但在处理人脸图像时效果不佳,尽管Imagenet中有一个名为“person”的类别?
好问题。
该模型擅长对训练数据中的物体照片进行分类。该模型是在物体上训练的,而不是在人脸/人物上。
嗨,Jason,
感谢您写了一篇好文章。
您能指导我如何选择VGG16的正确TOP-1准确率吗?因为MobileNet的作者在他们的论文中写的是71.5%的top-1,keras应用表显示是71.3%,而
paperwithcodes在ImageNet基准测试下显示是74.4%。
谁报告的准确率是正确的?您能指导一下吗?
谢谢!
不客气。
通常,我建议您在自己的数据集上测试每个模型,并选择表现最好的模型。
如果你想比较报告的数字,或许你可以查阅论文,看看它们是否是同类比较,如果不是,或许可以在你预期使用它们的条件下自行评估模型。
嗨,Jason。
我有以下问题
1. 什么时候应该使用像VGG16这样带有迁移学习的预训练模型,而不是从头开始训练神经网络?这取决于分类任务吗?
2. 对于神经网络初学者,应该直接使用预训练模型吗?
预训练模型可以节省时间并获得良好的结果,如果它们是在类似的问题上训练的。当它们比从头开始训练的模型给出更好的结果时使用它们。
预训练模型是解决大多数问题的绝佳起点。
谢谢 Jason。
不客气。
嗨,Jason。
我按照您上面的教程使用VGG16,并对一些杂货商品图片(如茶叶、食用油等)进行了测试。结果预测效果非常差。那么现在我有什么选择?
用我现有的图片训练VGG16,然后再进行预测吗?
谢谢!
也许你可以尝试其他模型?
或者,你可以使用迁移学习来调整模型,使其更适合你的数据集?
谢谢Jason。选择替代的预训练模型有什么标准吗?您能分享一些关于如何使用给定预训练模型进行迁移学习的参考资料吗?
谢谢!!
选择一个对您的数据集表现良好或最佳的模型。
博客上有很多关于迁移学习的例子,您可以使用页面顶部的搜索框进行查找。
谢谢 Jason。
你好Jason,感谢您的信息!我对深度学习还非常陌生,我需要使用vgg16和resnet 50完成我的事故预测毕业设计,您能帮帮我吗????????请帮帮我
不客气!通常,我建议你自己完成作业和任务。
你选择了课程,甚至(也许)支付了学费。你选择通过自学投资自己。
为了最大程度地利用这项投资,你必须努力学习。
此外,你(可能)已经付钱给老师、讲师和支持人员来教你。利用这些资源,向他们寻求关于你作业或任务的帮助和澄清。从某种意义上说,他们为你工作,没有人比他们更了解你的作业或任务以及如何进行评估。
尽管如此,如果你仍然感到困惑,也许你可以把你的困难归结为一句话,然后联系我。
给我一些关于VGG19的建议。如何在实际生活中应用?给一些练习项目?
你好 Javed……以下内容可能对你有所帮助
https://medium.com/analytics-vidhya/python-based-project-covid-19-detector-with-vgg-19-convolutional-neural-network-f9602fc40b81