首页 > 其他分享 >揭开计算机视觉的神秘面纱,原来机器是这样“看图”的!

揭开计算机视觉的神秘面纱,原来机器是这样“看图”的!

时间:2024-10-23 18:45:55浏览次数:8  
标签:training 揭开 训练 images 面纱 tf 视觉 我们 神经元

上一篇:《教电脑“看”图片》

本篇序言: 本文介绍的计算机视觉,简单来说,是让计算机通过算法从图像中提取特征,并使用这些特征来表示图像中的各种元素及它们的相互关系,从而实现“看”的效果。这种方法在早期主要依赖于传统的机器学习(ML)技术,尤其是监督学习,在这种方法中,人类需要手动提供标注数据和设计特定的特征提取方式。

然而,自从Transformer模型和注意力机制的出现,尤其是自2017年谷歌发布的“Attention is All You Need”论文以来,无监督学习和自监督学习得到了极大的关注。这些方法可以在无需大量人工标注的情况下让模型自动学习特征,并通过对齐人类的感知方式来进行图像分析。这不仅显著提高了计算机视觉任务的准确性,还推动了该领域的前沿发展。如今,基于Transformer的模型,如Vision Transformers (ViT),在许多图像识别任务中已经能够超越人类的速度和精度。

本系列文章介绍的内容涵盖了人工智能领域的重要基础知识,掌握这些知识将帮助您更好地理解和设计AI技术。欢迎关注作者,期待与您一起探索更多AI的前沿内容!关注后,您的智慧将更上一层楼,不然就只能靠颜值取胜了哦! ^_^

用于视觉的神经元

在第一章中,你看到了一个非常简单的场景,机器被给了一组X和Y值,它学会了这些值之间的关系是Y = 2X - 1。这是通过一个非常简单的神经网络完成的,只有一层和一个神经元。

如果你将其可视化绘制出来,它可能看起来像图2-4。

我们的每张图像是一组784个值(28×28),这些值介于0到255之间。它们可以作为我们的X。我们知道数据集中有10种不同类型的图像,所以我们将它们视为我们的Y。现在我们想要学习一个函数的形式,在这个函数中,Y是X的函数。

图2-4 单个神经元学习线性关系

鉴于每张图像有784个X值,而我们的Y将在0到9之间,显然我们不能像之前那样简单地用Y = mX + c来解决问题。

但我们可以让多个神经元一起工作。每个神经元将学习参数,当我们把所有这些参数结合起来形成一个综合函数时,我们可以看看是否能够将该模式与我们期望的答案匹配(见图2-5)。

图2-5 为更复杂的例子扩展我们的模式

这个图表顶部的方框可以视为图像中的像素,或者说是我们的X值。当我们训练神经网络时,会将这些值加载到神经元层中——图2-5展示的是这些值仅被加载到第一个神经元中,但实际上它们会被加载到每个神经元中。每个神经元的权重和偏差(m 和 c)被随机初始化。然后,当我们将每个神经元的输出值相加时,我们会得到一个值。这将在输出层的每个神经元中进行,因此,神经元0会包含像素相加为标签0的概率值,神经元1对应标签1,依此类推。

随着时间的推移,我们希望将这个值与期望的输出匹配——在这个图像中,我们可以看到期望的输出是数字9,也就是图2-3中展示的短靴的标签。换句话说,这个神经元的值应该是所有输出神经元中最大的。考虑到有10个标签,随机初始化应能大约在10%的时间里得到正确答案。从这一点开始,损失函数和优化器将会逐个迭代地调整每个神经元的内部参数,以提高那10%的正确率。于是,随着时间的推移,计算机将学会“看出”一只鞋是鞋、一件连衣裙是连衣裙的特征。

设计神经网络

现在让我们看看这在代码中是如何实现的。首先,我们将观察图2-5中展示的神经网络的设计:

model = keras.Sequential([

keras.layers.Flatten(input_shape=(28, 28)),

keras.layers.Dense(128, activation=tf.nn.relu),

keras.layers.Dense(10, activation=tf.nn.softmax)

])

如果你还记得,在第1章中我们使用了Sequential模型来指定我们有多个层。当时只有一层,但在这里我们有多层。

首先,Flatten并不是一层神经元,而是一个输入层的规范。我们的输入是28×28的图像,但我们希望将它们视为一系列数值,就像图2-5顶部的灰色方块那样。Flatten会将这个“方形”值(即二维数组)转换成一条“线”(一维数组)。

接下来是Dense,它是一层神经元,并且我们指定了128个神经元。这是图2-5中间展示的那一层。你经常会听到这种层被称为隐藏层。处于输入和输出之间的层对调用者是不可见的,因此用“隐藏”来形容它们。我们要求128个神经元,并将它们的内部参数随机初始化。通常在这一点上,我会被问到“为什么是128个?”这完全是任意的——没有固定的规则规定应该使用多少个神经元。在设计层时,你需要选择合适的数量,以使模型能够真正学习。更多的神经元意味着模型运行得更慢,因为它需要学习更多的参数。更多的神经元还可能导致网络对训练数据表现很好,但对之前没见过的数据表现不佳(这被称为过拟合,我们将在本章稍后讨论)。另一方面,神经元太少可能会导致模型没有足够的参数来学习。

选择正确的值需要一些实验。这一过程通常称为超参数调优。在机器学习中,超参数是控制训练的值,而不是神经元内部的被训练/学习的值,这些内部值被称为参数。

你可能注意到在这一层还指定了一个激活函数。激活函数是在层中的每个神经元上执行的代码。TensorFlow支持许多激活函数,但在中间层中非常常见的一个是relu,它代表修正线性单元。它是一个简单的函数,只要返回大于0的值。在这种情况下,我们不希望负值传递到下一层,可能会影响求和函数,因此我们不需要写大量的if-then代码,只需通过relu激活该层即可。

最后是另一个Dense层,即输出层。这一层有10个神经元,因为我们有10个类别。每个神经元最终会输出一个概率值,表示输入的像素与该类别匹配的概率,因此我们的任务是确定哪个神经元的值最大。我们可以循环遍历这些神经元来选出那个值,但softmax激活函数为我们做了这件事。

现在,当我们训练神经网络时,目标是能够输入一个28×28像素的数组,中间层的神经元将具有权重和偏差(m和c值),当它们结合时,这些像素将被匹配到10个输出值之一。

完整代码

现在我们已经探讨了神经网络的架构,接下来让我们看看如何用Fashion MNIST数据集训练一个神经网络的完整代码:

import tensorflow as tf

data = tf.keras.datasets.fashion_mnist

(training_images, training_labels), (test_images, test_labels) = data.load_data()

training_images = training_images / 255.0

test_images = test_images / 255.0

model = tf.keras.models.Sequential([

tf.keras.layers.Flatten(input_shape=(28, 28)),

tf.keras.layers.Dense(128, activation=tf.nn.relu),

tf.keras.layers.Dense(10, activation=tf.nn.softmax)

])

model.compile(optimizer='adam',

loss='sparse_categorical_crossentropy',

metrics=['accuracy'])

model.fit(training_images, training_labels, epochs=5)

让我们逐步解析这一段代码。首先是一个方便的快捷方式来访问数据:

data = tf.keras.datasets.fashion_mnist

Keras 有许多内置的数据集,你可以通过这样一行代码访问它们。在这种情况下,你不必处理下载7万张图片、将它们划分为训练集和测试集等繁琐步骤——只需要一行代码。这种方法已经通过一个名为 TensorFlow Datasets 的 API 得到了改进,但为了减少你在这些早期章节中需要学习的新概念,我们仅使用 tf.keras.datasets。

我们可以调用它的 load_data 方法来返回我们的训练集和测试集,如下所示:

(training_images, training_labels),

(test_images, test_labels) = data.load_data()

Fashion MNIST 设计为包含6万张训练图像和1万张测试图像。因此,data.load_data 返回的是一个包含6万张28×28像素图像的数组,名为 training_images,以及一个包含6万个值(0-9)的数组,名为 training_labels。类似地,test_images 数组将包含1万张28×28像素的图像,而 test_labels 数组将包含1万个值,范围在0到9之间。

我们的任务是将训练图像与训练标签相匹配,类似于我们在第1章中将 Y 与 X 相匹配的方式。

我们将保留测试图像和测试标签,这样网络在训练时不会看到它们。这些数据将用于测试网络在面对未见过的数据时的效果。

接下来的代码可能看起来有点不寻常:

training_images = training_images / 255.0

test_images = test_images / 255.0

Python 允许你通过这种符号对整个数组进行操作。请回想一下,我们的图像中的所有像素都是灰度值,范围在0到255之间。除以255确保每个像素都用0到1之间的数值表示。这一过程称为图像归一化。

为什么归一化的数据对训练神经网络更好,这里的数学原理超出了本书的范围,但请记住,在 TensorFlow 中训练神经网络时,归一化会提高性能。当处理未归一化的数据时,你的网络往往无法学习,并且会出现巨大的误差。在第1章的 Y = 2X – 1 例子中,我们不需要归一化数据,因为它非常简单,但出于好奇,你可以尝试用更大的 X 和 Y 值来训练它,你会看到它很快就会失败!

接下来我们定义构成模型的神经网络,正如前面讨论的那样:

model = tf.keras.models.Sequential([

tf.keras.layers.Flatten(input_shape=(28, 28)),

tf.keras.layers.Dense(128, activation=tf.nn.relu),

tf.keras.layers.Dense(10, activation=tf.nn.softmax)

])

当我们编译模型时,像之前一样指定损失函数和优化器:

model.compile(optimizer='adam',

loss='sparse_categorical_crossentropy',

metrics=['accuracy'])

在这种情况下,损失函数称为稀疏分类交叉熵,这是 TensorFlow 内置的众多损失函数之一。选择哪个损失函数本身就是一门艺术,随着时间的推移,你会学会在不同的场景中使用哪个最合适。与我们在第1章中创建的模型的主要区别在于,这次我们不是预测一个单一的数值,而是选择一个类别。我们的服装物品将属于10种类别之一,因此使用分类损失函数是最合适的选择,稀疏分类交叉熵就是一个很好的选择。

同样,选择优化器也是如此。adam 优化器是我们在第1章中使用的随机梯度下降(sgd)优化器的进化版,它被证明更快、更高效。由于我们要处理60,000张训练图像,任何性能的提升都会有所帮助,因此这里选择了它。

你可能会注意到代码中还指定了一个新的行,说明了我们想要报告的指标。在这里,我们希望在训练时报告网络的准确性。在第1章的简单示例中,我们只报告了损失,通过观察损失的减少来推断网络在学习。而在本例中,观察网络的学习过程,通过准确性来反馈,显然对我们更有帮助——它将返回网络正确匹配输入像素和输出标签的频率。

接下来,我们将通过将训练图像与训练标签匹配,进行五个周期的训练:

model.fit(training_images, training_labels, epochs=5)

最后,我们可以做一些新的操作——用一行代码评估模型。我们有一组1万张图像和标签用于测试,我们可以将它们传递给训练好的模型,让它预测每张图像是什么,比较预测结果与实际标签,并总结结果:

model.evaluate(test_images, test_labels)

训练神经网络

执行代码,你将看到网络逐个周期地进行训练。训练结束后,你会看到类似于以下的输出:

58016/60000 [=====>.] - ETA: 0s - loss: 0.2941 - accuracy: 0.8907

59552/60000 [=====>.] - ETA: 0s - loss: 0.2943 - accuracy: 0.8906

60000/60000 [] - 2s 34us/sample - loss: 0.2940 - accuracy: 0.8906

请注意,现在它正在报告准确性。在这种情况下,使用训练数据后,我们的模型经过五个周期后达到了约89%的准确性。

那么测试数据呢?使用 model.evaluate 对测试数据的结果可能会是这样的:

10000/1 [====] - 0s 30us/sample - loss: 0.2521 - accuracy: 0.8736

在这种情况下,模型在测试数据上的准确性为87.36%,考虑到我们只训练了五个周期,这已经算不错了。

你可能会想,为什么测试数据的准确性比训练数据低?这是非常常见的现象,而且仔细想想也是合理的:神经网络实际上只知道如何匹配它见过的输入数据与对应的输出值。我们希望通过足够的数据,它能从它见过的例子中进行泛化,“学习”到鞋子或连衣裙的外观。但总会有它没见过的足够不同的物品让它困惑的情况。

例如,如果你从小只见过运动鞋,运动鞋就是你眼中的鞋子,那么当你第一次看到高跟鞋时,可能会有点困惑。从你的经验来看,它可能是一双鞋,但你并不能百分之百确定。这就是类似的概念。

探索模型输出

现在模型已经训练完毕,并且我们通过测试集有了一个对其准确性的良好估计,让我们稍微探索一下:

classifications = model.predict(test_images)

print(classifications[0])

print(test_labels[0])

通过将测试图像传递给 model.predict,我们将得到一组分类结果。然后让我们看看打印出的第一个分类结果,并将其与测试标签进行比较:

[1.9177722e-05 1.9856788e-07 6.3756357e-07 7.1702580e-08 5.5287035e-07

1.2249852e-02 6.0708484e-05 7.3229447e-02 8.3050705e-05 9.1435629e-01]

你会注意到分类结果给我们返回了一组数值。这些数值是10个输出神经元的值。标签是该服装物品的实际标签,在这种情况下是9。看看这个数组——你会发现有些值非常小,而最后一个值(数组索引为9的那个)远远是最大的。这些是图像匹配某个特定索引标签的概率。因此,神经网络报告的是,这件服装有91.4%的可能性对应标签9。我们知道它的标签是9,所以它答对了。

尝试使用不同的值,看看是否能找到模型出错的地方。

更长时间的训练——发现过拟合

在本例中,我们只训练了五个周期。也就是说,我们对神经元的随机初始化、与其标签的对比、由损失函数测量性能、并由优化器更新参数的整个训练循环进行了五次。而我们得到的结果相当不错:训练集上的准确性为89%,测试集上为87%。那么如果我们训练更长时间会发生什么呢?

尝试将训练周期数改为50。在我的案例中,我得到了以下训练集的准确率:

58112/60000 [==>.] - ETA: 0s - loss: 0.0983 - accuracy: 0.9627

59520/60000 [==>.] - ETA: 0s - loss: 0.0987 - accuracy: 0.9627

60000/60000 [====] - 2s 35us/sample - loss: 0.0986 - accuracy: 0.9627

这是特别令人兴奋的,因为我们做得好多了:96.27%的准确性。测试集上达到了88.6%的准确率:

[====] - 0s 30us/sample - loss: 0.3870 - accuracy: 0.8860

所以,我们在训练集上有了很大的改进,测试集上也有所提升。这可能暗示着,训练网络更长时间会带来更好的结果——但这并不总是如此。网络在训练数据上表现得更好,但这并不意味着它是一个更好的模型。事实上,准确率数字的差异表明它已经过度专门化于训练数据,这一过程通常被称为过拟合。在构建更多神经网络时,这是一件需要注意的事情,在本书的后续章节中,你将学到一些避免这种情况的技术。

到目前为止,我们在每种情况下都硬编码了训练的周期数。虽然这样可以工作,但我们可能希望训练直到达到期望的准确率,而不是反复尝试不同的周期数,进行训练和重新训练,直到得到我们想要的值。那么,比如说,我们想要训练直到模型在训练集上的准确率达到95%,而不知道需要多少个周期,该怎么办呢?

最简单的方法是使用回调函数。让我们看看使用回调函数的更新代码:

import tensorflow as tf

class myCallback(tf.keras.callbacks.Callback):

def on_epoch_end(self, epoch, logs={}):

if(logs.get('accuracy')>0.95):

print("\nReached 95% accuracy so cancelling training!")

self.model.stop_training = True

callbacks = myCallback()

mnist = tf.keras.datasets.fashion_mnist

(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

training_images = training_images / 255.0

test_images = test_images / 255.0

model = tf.keras.models.Sequential([

tf.keras.layers.Flatten(),

tf.keras.layers.Dense(128, activation=tf.nn.relu),

tf.keras.layers.Dense(10, activation=tf.nn.softmax)

])

model.compile(optimizer='adam',

loss='sparse_categorical_crossentropy',

metrics=['accuracy'])

model.fit(training_images, training_labels, epochs=50, callbacks=[callbacks])

让我们看看我们改变了什么。首先,我们创建了一个名为 myCallback 的新类。它以 tf.keras.callbacks.Callback 作为参数。在其中,我们定义了 on_epoch_end 函数,该函数将为我们提供该周期的日志信息。这些日志中有一个准确率值,因此我们只需查看该值是否大于0.95(即95%);如果是,我们可以通过设置 self.model.stop_training = True 来停止训练。

一旦我们指定了这一点,我们创建一个 callbacks 对象作为 myCallback 函数的实例。

现在看看 model.fit 语句。你会发现我将其更新为训练50个周期,然后添加了一个 callbacks 参数。在这里,我传递了 callbacks 对象。当进行训练时,在每个周期结束时,回调函数将被调用。所以在每个周期结束时你都会检查,经过大约34个周期后,你会看到训练结束,因为训练已经达到了95%的准确率(你的数字可能会因为初始的随机初始化而略有不同,但可能会接近34):

56896/60000 [====>..] - ETA: 0s - loss: 0.1309 - accuracy: 0.9500

58144/60000 [====>.] - ETA: 0s - loss: 0.1308 - accuracy: 0.9502

59424/60000 [====>.] - ETA: 0s - loss: 0.1308 - accuracy: 0.9502

Reached 95% accuracy so cancelling training!

总结

在第1章中,你学到了机器学习如何通过神经网络的复杂模式匹配将特征与标签相匹配。在本章中,你更进一步,超越了单个神经元,学会了如何创建你的第一个(非常基础的)计算机视觉神经网络。由于数据的限制,它有些局限。所有图像都是28×28的灰度图像,服装物品位于画面中央。这是一个很好的开始,但它是一个非常受控的场景。为了在视觉识别上做得更好,我们可能需要让计算机学习图像的特征,而不仅仅是原始像素。

我们可以通过卷积操作来实现这一点。在下一章中,你将学习如何定义卷积神经网络来理解“看懂”图片的内容。

标签:training,揭开,训练,images,面纱,tf,视觉,我们,神经元
From: https://blog.csdn.net/JellyAI/article/details/143140990

相关文章

  • 计算机视觉库supervision学习-day(1)-图像检测和标记
    supervision库是一款由roboflow开发的计算机视觉库提供了一系列方便的工具和功能,用于可视化和处理各种计算机视觉任务。它的目标是简化深度学习模型的可视化和后处理步骤,尤其适用于对象检测、图像分割、关键点检测等任务。一、下载supervision库1.在3.8版本及以上的python,使用pi......
  • 机器学习中的图像处理与计算机视觉
    引言在现代计算机科学中,图像处理和计算机视觉已成为最活跃的研究领域之一,这得益于机器学习和深度学习的发展。本文将深入探讨图像处理与计算机视觉的基础概念、常见应用、关键技术、常用工具,以及在这些领域中的代码示例。通过本篇文章,我们将了解如何从头开始构建一个简单的计......
  • 云渲染与3D视觉效果如何影响珠宝行业!
    3D渲染技术在珠宝行业的应用正迅速增长,2023年已带来数亿元收益,预计2024年将继续保持增长态势。珠宝品牌正越来越多地采用3D可视化技术来提升产品展示,以在激烈的市场竞争中占据优势。云渲染技术不仅提升了渲染效率,还降低了成本,同时保持输出质量。这种技术尤其在珠宝设计领域表现出......
  • 【数据结构】动态规划:揭开算法优化的秘密
    在算法世界中,动态规划(DynamicProgramming,DP)无疑是一个充满魅力的思想,特别是在解决复杂的优化问题时,它展现出了极大的威力。它不仅能优化问题的求解速度,还能通过减少重复计算来提高效率。然而,对于很多初学者来说,动态规划常常显得有些晦涩难懂。本文将通过浅显的例子,帮助你......
  • 泥石流山体滑坡监控AI视觉识别检测算法
    泥石流山体滑坡监控AI视觉识别检测算法基于AI视觉识别技术,泥石流山体滑坡监控AI视觉识别检测算法通过监控摄像头采集到的图像和视频流,利用先进的视觉识别算法分析和判断监控画面中是否出现泥石流和山体滑坡现象。泥石流山体滑坡监控AI视觉识别检测算法一旦系统识别到灾害事件的发......
  • MoH:融合混合专家机制的高效多头注意力模型及其在视觉语言任务中的应用
    在深度学习领域,多头注意力机制一直是Transformer模型的核心组成部分,在自然语言处理和计算机视觉任务中取得了巨大成功。然而,研究表明并非所有的注意力头都具有同等重要性,许多注意力头可以在不影响模型精度的情况下被剪枝。基于这一洞察,这篇论文提出了一种名为混合头注意力(Mi......
  • 小而强大!H2O.ai 发布新AI视觉模型 文档分析领域超越科技巨头
    近日,H2O.ai宣布推出两款新型视觉语言模型,旨在提升文档分析和光学字符识别(OCR)任务的效率。这两款模型分别是H2OVLMississippi-2B和H2OVL-Mississippi-0.8B,它们在性能上与大型科技公司的模型相比,展现出令人瞩目的竞争力,可能为处理文档繁重工作流的企业提供更为高效的解决......
  • 视觉之相机硬件选型
    硬件1)相机2D相机类型:线阵(一行一行成像,拼接成图),像素高,速度慢面阵(瞬间成像),像素低,速度快(市面常见)芯片:CCD(性能好)CMOS(价格低,主导)颜色模式:黑白相机、彩色相机(颜色识别、深度学习)传感器大小:单位英寸,常见尺寸有1、2/3、1/2、1/3、1/4英寸等。1英寸cmos传感器是16mm。这里的......
  • 机器的“眼睛“:计算机视觉技术背后的魔法
    计算机视觉,作为人工智能领域中的一颗璀璨明珠,正逐步改变着我们的生活方式。它赋予了机器“看”的能力,使得计算机能够从图像和视频中提取信息并进行分析,就像人类用眼睛和大脑来理解世界一样。本文将带你走进计算机视觉的世界,揭开这项技术背后的神奇魔法。1.什么是计算机视......
  • 计算机视觉——人像的分割与无缝融合
    1.概述新加坡现代汽车集团创新中心的一篇新论文提供了一种在计算机视觉中分离“融合”人像的方法——在这些情况下,对象识别框架发现一个人在某种程度上与另一个人“太接近”(例如例如“拥抱”动作或“站在后面”的姿势),并且无法区分所代表的两个人,将他们与一个人或一个实体......