TowardsDataScience 博客中文翻译 2016~2018(一百六十)
图像分类挑战,使用迁移学习和深度学习工作室
Photo by Taylor Swayze on Unsplash.
图像分类的任务是识别图像上的对象或模式,并基于给定的类别/种类池来分配类别以对图像进行分类。有许多不同的子领域,如识别单个图像上的多个对象,甚至定位图像中的对象。
在这篇文章中,我想与你分享我参加第一次图像分类挑战赛以及使用深度学习工作室(DLS)平台的经历。DLS 在一个高抽象层次上提供了一个图形界面,以建立和训练基于后端的深度神经网络,如 keras / tensorflow / theano 等,免费用于桌面或云应用程序。
如果你从未听过或用过 DLS,去看看 这篇文章 由 Rajat 或在deep cognition . ai试用一下。
挑战
这项挑战被命名为汽水瓶识别挑战,由 DeepCognition.ai 直接主办,作为他们的第一场比赛,目标是在图像上识别不同种类的汽水瓶。 与其他竞赛类似,例如 Kaggle 上的竞赛,您会收到一个或多或少准备好的带有标签的图像数据集,以及一套关于如何评估结果的规则和信息,还有一个提交结果的流程。在这种情况下,由于需要使用深度学习工作室服务,数据集和提交过程是根据 DLS 的工作方式定制的,这使得获得 startet 和提交第一个模型变得非常容易。
在下面的帖子中,我试图描述我采取的步骤,我获得的经验和我犯的错误,我的最终模型得分为 93.75%,在比赛中获得了第 10 名。
数据集
提供的数据集由 6615 张图像组成,或多或少均匀地分成 8 类不同的汽水瓶。
Soda Bottle Dataset preview from DeepCognition.ai
正如你所看到的,图像已经基本上以类似的白色背景为中心,所以我决定我真的不需要任何更大的图像预处理步骤。人们应该注意到,并不是所有的图片都像这个数据集预览中显示的那样完美。通过手动滚动一些图像,您会注意到有许多不同角度的瓶子,以及瓶子躺着或被物体部分遮盖的图像。
Differently positioned bottles
原始图像大小为 640*480 像素,这不一定是一个巨大的图像处理,但肯定比大多数网络工作。因此,调整图像大小似乎是一个合理的决定,以查看哪些大小会产生最好的结果。
天真的第一种方法
我的第一个方法是简单地训练一个模型,用 DLS AutoML 特性生成,它将根据你的输入/输出设置为你生成一个完整的模型。
AutoML model for the Soda Bottle Challenge
正如你所看到的,生成的模型非常庞大,对于一个 6k 图像和 8 个类别的图像分类问题来说,可能是完全多余的,但我仍然继续尝试训练它。很快我就注意到,将图像保持在 640*480 像素的原始大小会立即填满我笔记本的 16GB RAM,并使训练过程崩溃。即使将尺寸缩小到原始图像的 1/4,这个 AutoML 模型对我的笔记本来说似乎还是太大了。
当然,DeepCognition 的云应用程序可以让你用相对较少的钱使用不同类型的 GPU,但我假设在这些条件下训练模型,将需要至少 4 个 GPU,这超出了我对这个项目的预算。
看起来简单的“魔棒”方法并没有让我走得更远,所以我考虑了其他可能的、资源更友好的解决方案。
迁移学习
迁移学习描述了一个相对宽泛的概念,即使用通过解决一组问题获得的知识来解决你当前问题的过程。
在我们的例子中,我们将使用一个已经成功训练的模型来识别图像上的某些对象,以识别不同的汽水瓶。乍一看,这可能没有意义。一个训练有素的模型如何区分猫和狗,能够告诉我们这个图像是包含露水还是胡椒博士瓶?
为了了解这可能是如何工作的,让我们非常简短地离题到图像分类模型是如何工作的。
特征抽出
几乎所有的图像分类模型都使用堆叠卷积层从图像中提取特征。这些特征在它们的第一层包含非常一般的信息,如边界或基本形状。使用预先训练的模型,我们可以利用模型的较低层的这些特征,因为它们将适用于几乎所有类型的图像数据。然后,我们只需要重新训练模型的最后几层,就可以学会识别我们的汽水瓶。
你可能想在这里 阅读关于卷积神经网络 的更深入的解释。
在讨论不同的模型选择之前,我们先来看看如何使用 DLS 实现预训练模型。
VGG16 as a pre-trained model
上面你可以看到一个非常基本的使用 DLS 图形编辑器的预训练 VGG16 模型的实现。有几件事需要考虑:
输入尺寸
我们的图像的输入尺寸显示在模型的第一个节点上(3,224,224),这意味着我们已经将图像的尺寸调整为 224*224 像素,这是 VGG16 模型的原始图像尺寸。
这可以在 DLS 的数据选项卡中轻松完成。
Resizing the input images
预训练模型
我们模型中的一个节点称为 VGG16,它实际上代表了压缩在单个节点中的整个 VGG16 模型架构。从预训练模型选项卡,DLS 提供了几个模型供选择。节点本身有一些关于如何加载预训练权重以及模型的哪个部分应该是可训练的选项。
VGG16 settings
正如你在右手边看到的,我们不包括 VGG16 模型的顶层,因为这些是一旦我们建立自己来分类 8 个汽水瓶类,而不是 1000 个类别的 imagenet 数据集,原始的 VGG16 模型被训练。
另一个重要参数是可训练值,它是我们希望在反向传播过程中包含的 VGG16 模型的百分比。由于前几层提取了相当一般化的特征,我们不想重新训练它们,而是保持它们原来的样子。实际上,在我的方法中,只重新训练 VGG16 模型的最后一个卷积块就足够了,它大约是模型的 25%。
通过这种设置,与 AutoML 模型相比,该模型需要的资源少得多,甚至可以在我配有 CPU 和 16GB RAM 的笔记本电脑上进行训练。然而,我只达到了大约 1 个样本/秒的处理速度,这将导致训练时间大约为。只有一个纪元的 76 分钟。这似乎是不可接受的,因为我想测试几种不同的方法,看看哪种模型表现最好。此外,整个比赛持续时间只有大约 3 周。
切换到云版本并使用 Telsa K80 以大约 1 美元/小时的速度运行,导致培训时间大约为。VGG16 型号每周期 74 秒,我尝试的一些其他型号甚至更快。
VGG16 / VGG19 / ResNet50
为了比较不同种类的预训练模型,我做了一个 10 个时期的小测试,每个时期都有与 VGG16 模型相同的设置。
VGG16
VGG16 training process
VGG16 模型在前 2 个时期后在验证集上仅实现了约 14%的准确度,并且似乎在最后 8 个时期都不被认可。在 8 类分类问题上 14%的准确率仅略高于随机猜测概率,后者约为 12.5%。这个结果对于迁移学习的前景来说并不是很鼓舞人心,但是让我们看看其他模型的得分如何。
VGG19
VGG19 training prcoess
VGG19 模型的架构与他的前任 VGG16 相似,但更深入,已经表现得更好,几乎达到 30%的精度。然而,训练曲线并没有给出通过进一步训练来提高准确度的希望。
ResNet50
ResNet50 training process
差别真大!这是我所希望的结果。如你所见,该模型在 3 个时期后几乎达到了 80%的准确率,并在整个训练过程中不断提高。除了在三款测试车型中表现最佳之外,它还拥有最快的训练速度。
估价
有几种方法可以评估模型的性能。首先,对您的数据进行适当的训练/测试分割对于创建一个对未来数据表现良好的模型是必不可少的。DLS 自动对您的数据执行训练/验证/测试分割,同时让您选择不同的分割比率。
DLS Dataset settup
在训练过程中,然后在每个时期之后使用验证集来计算验证损失和准确度,这与训练损失/准确度一起显示在训练图中。
在训练过程的最后,您可以对数据的测试分割进行推理。在我们的例子中,这意味着我们将使用我们训练过的模型来预测测试集的图像上显示的是哪一类汽水瓶。
DLS Dataset Inference
用我们训练过的模型在我们的测试分割上运行预测,可以让我们知道我们的模型能够多好地识别它以前没有见过的图像上的汽水瓶类别。
当然,这很大程度上取决于数据集内部的方差。在我们的案例中,提供的所有图像都是以非常相似的方式拍摄的,只有角度或旋转上的微小差异。因此,推理的表现和预期的一样好,这并不一定意味着它能够识别不同的图像。许多参赛者在提交他们的第一个模型进行评估后可能会注意到一个事实。
提交流程
在我们的私人数据集上创建了一个准确率约为 80%的模型后,我觉得自己已经准备好第一次提交参赛作品了。
本次比赛的提交过程相当简单。DLS 提供了一个以 zip 文件形式下载您的训练模型的功能,该文件包含您的. h5 模型文件以及一个配置文件和一个 test.py 脚本,可用于在测试映像上运行您的模型。这个压缩文件只需上传到比赛网站。
提交我的第一个模型,最终得分约为 40%。
相当令人失望,当我们预期分数约为 80%时。那么这种差异从何而来呢?
按照竞赛规则的规定,对参赛作品的评估是在个人的私有数据集上进行的,参赛者无法访问这些数据集。我们训练过的模型从未见过这些图像,因此 40%的准确率意味着该模型没有足够的泛化能力来识别它没有见过的图像上的汽水瓶。
数据扩充
提高模型性能的一种方法是数据扩充。数据扩充描述了仅使用来自我们的训练数据的信息来增加训练数据量的过程。对于我们的图像数据集,这意味着我们根据现有的图像创建更多具有不同特征的图像。例如,我们可以左右移动图像、旋转图像、上下翻转图像或执行剪切变换。
如果你有兴趣阅读更多关于数据增强的内容,请查看 瑞安·奥尔雷德 的 帖子 。
使用这些“新”图像,我们基本上在更大的数据集上训练我们的模型,并由此增加其鲁棒性,因为它不仅从原始图像中学习。因此,我们应该看到对私有评估数据集的预测也有所改善。
Data Augmentation in DLS
在 DLS,数据扩充可以像调整大小选项一样直接在输入图像的数据选项卡下使用。
使用如上所示的数据增强图像训练我们的 ResNet50 模型,得到了非常相似的训练曲线,在 10 个时期后峰值约为 90%。
ResNet50 training process with data augmentation
将这个模型提交给比赛给了我 57%的分数,这表明数据增强有助于提高模型的整体稳健性,正如我们预期的那样。
与我们在训练期间达到的 91%相比,57%看起来不是很好,但是不要忘记我们只训练了 10 个时期的模型。我认为有改进的余地。
超参数
机器学习中的超参数,描述我们的模型中在学习过程开始之前设置的那些参数。最常见的是你谈论的参数,如批量大小、时期数、优化器和损失函数。
阅读更多关于超参数的文章 本文 作者 丹尼尔·夏皮罗博士 。
这些也是 DLS 在超参数选项卡下为您提供的超参数。
据我所知,DLS 默认提供这些设置,基于 keras 中实现的默认值。因为这些是你最常用的设置,我继续使用 DLS 的默认设置。我只是调整了批量大小,以提高训练速度。
作为一个优化器,我们使用了 Adadelta,它有一个自适应的学习率,所以我们甚至不用费心去寻找正确的学习率。这对于快速获得好的结果是很棒的,但是也会导致一个小问题,我将在后面讨论。
如果你想深入了解不同的优化器,我建议你阅读本文Rinat Maksutov。
决赛成绩
为了提高分数,我尝试了很多不同的方法。最后,帕维尔·奥斯特亚科夫和阿列克谢·哈尔拉莫夫在他们的谈话中表达了一个想法,这个想法让我最终得出了大约 93%的准确率。
他们参加了一场图像分类挑战,这有点类似于汽水瓶识别挑战,但数据集要大得多。他们在训练中的方法是只在原始图像上开始训练,没有任何数据增强。然后,在训练收敛后,他们停下来,保存模型,并继续进行少量增强训练。他们多次重复这些步骤,一直训练到损失收敛,每次都增加数据增加量。
起初,在 DLS 建立这种行为是相当容易的,因为在开始训练过程时,有一个选项来加载上次跑步的重量。
DLS loading weights of previous runs
当我试图模仿上面提到的程序时,我的最终得分高达 80%,但在我看来,这主要是因为该模型的整体训练时间较长。
学习率
如前所述,我选择了具有自适应学习率的 Adadelta 优化器。它以较高的学习率开始,并在训练过程中逐渐降低。
由于我们已经多次开始和停止训练过程来调整数据扩充,所以学习率的调整并不真正有效,因为我在 DLS 找不到任何选项来保存或加载先前运行的学习率。
这就是为什么我决定尝试 Adam 优化器,它也有一个学习率衰减的参数,但从一个固定的学习率开始。因此,我在第一次运行时以 0.01 的标准学习率开始,然后在每次新的训练开始后手动调整学习率。
用这种新方法,我最终达到了 93.75%的最终分数,请注意,这是提交期的最后一天。
由于选择正确的学习速率是超参数调优中最棘手也是最重要的部分之一,我将推荐阅读 文章 作者Pavel Surmenok。
结论
总的来说,由于这是我第一次参加比赛,我对自己的成绩非常满意。DeepCognitions 竞赛极大地激励了人们去尝试不同的架构和方法,并在这样做的同时学到了很多东西,所有这些都不需要编写一行代码。
比赛的前两个位置实际上达到了完美的 100 分,所以对我来说肯定有改进的空间。
我希望你喜欢阅读我关于如何应对这一挑战的想法,甚至可能带走一些想法。请随时留下任何提示或建议,告诉我你会如何解决这个问题,以及我可以如何改进。
我总是很高兴认识新朋友并分享想法,所以如果你喜欢这篇文章,可以考虑在 LinkedIn 上加我。
使用 MNIST 数据集在 10 分钟内完成图像分类
深度学习案例研究
利用 TensorFlow 和 Keras |监督深度学习使用卷积神经网络来分类手写数字
如果你正在阅读这篇文章,我确信我们有着相似的兴趣,并且正在/将要从事相似的行业。所以还是通过 Linkedin 联系吧!请不要犹豫发送联系请求!Orhan g . yaln-Linkedin
MNIST Dataset and Number Classification by Katakoda
在开始这篇文章之前,我只想让你知道,如果你对深度学习感兴趣,我相信你也应该看看我的其他文章,比如:
1 — 使用深度卷积自动编码器在 10 分钟内降低图像噪声我们学习了如何构建用于图像去噪的自动编码器;
2 — 用递归神经网络预测明天的比特币(BTC)价格 我们用 RNN 预测 BTC 价格,因为它使用 API,所以结果总是最新的。
当你开始学习不同神经网络架构的深度学习时,你会意识到最强大的监督深度学习技术之一是卷积神经网络(缩写为“CNN”)。CNN 的最终结构实际上非常类似于常规神经网络(RegularNets ),其中存在具有权重和偏差的神经元。此外,就像在 RegularNets 中一样,我们在 CNNs [ CS231 ]中使用一个损失函数(例如 crossentropy 或 softmax)和一个优化器(例如 adam optimizer)。此外,在 CNN 中,还有卷积层、汇集层和平坦层。CNN 主要用于图像分类,尽管您可能会发现其他应用领域,如自然语言处理。
为什么选择卷积神经网络
正则网络的主要结构特征是所有的神经元都是相互连接的。例如,当我们有灰度为 28×28 像素的图像时,我们最终会在一个似乎易于管理的层中有 784(28×28×1)个神经元。然而,大多数图像有更多的像素,他们不是灰度。因此,假设我们有一组 4K 超高清彩色图像,我们将有 26,542,080 (4096 x 2160 x 3)个不同的神经元在第一层相互连接,这实际上是不可管理的。因此,我们可以说正则网对于图像分类是不可伸缩的。然而,特别是当涉及到图像时,两个单独的像素之间似乎几乎没有相关性或关系,除非它们彼此靠近。这就引出了卷积层和池层的概念。
CNN 中的层
我们能够在卷积神经网络中使用许多不同的层。但是,卷积、池化和全连接层是最重要的。因此,我将在实现它们之前快速介绍这些层。
卷积层
卷积层是我们从数据集中的图像中提取特征的第一层。由于像素仅与相邻和接近的像素相关,卷积允许我们保留图像不同部分之间的关系。卷积基本上是用较小的像素过滤器过滤图像,以减小图像的大小,而不丢失像素之间的关系。当我们通过使用具有 1x1 步幅(每步移动 1 个像素)的 3×3 滤波器将卷积应用于 5×5 图像时。我们最终将得到 3×3 的输出(复杂度降低了 64%)。
Figure 1: Convolution of 5 x 5 pixel image with 3 x 3 pixel filter (stride = 1 x 1 pixel)
汇集层
当构造 CNN 时,通常在每个卷积层之后插入汇集层,以减小表示的空间大小,从而减少参数计数,这降低了计算复杂度。此外,合并层也有助于解决过度拟合问题。基本上,我们通过选择这些像素内的最大值、平均值或和值来选择池大小以减少参数的数量。最大池化是最常见的池化技术之一,可演示如下:
Max Pooling by 2 x 2
一组完全连接的层
完全连接的网络是我们的规则网络,其中每个参数相互链接,以确定标签上每个参数的真实关系和效果。由于卷积和合并层大大降低了我们的时空复杂度,我们最终可以构建一个完全连通的网络来分类我们的图像。一组完全连接的层如下所示:
A fully connected layer with two hidden layers
既然您对我们将使用的各个层有了一些了解,我认为是时候分享一个完整的卷积神经网络的概览了。
A Convolutional Neural Network Example by Mathworks
现在你有了一个关于如何建立一个卷积神经网络的想法,你可以建立一个图像分类,我们可以得到最陈词滥调的分类数据集:MNIST 数据集,代表修改后的国家标准和技术研究所数据库。这是一个手写数字的大型数据库,通常用于训练各种图像处理系统。
下载 MNIST 数据集
MNIST 数据集是用于影像分类的最常用数据集之一,可从许多不同的来源访问。事实上,甚至 Tensorflow 和 Keras 也允许我们直接从它们的 API 导入和下载 MNIST 数据集。因此,我将从下面两行开始,在 Keras API 下导入 TensorFlow 和 MNIST 数据集。
MNIST 数据库包含 60,000 张训练图像和 10,000 张测试图像,取自美国人口普查局员工和美国高中生[ 维基百科 ]。因此,在第二行中,我将这两个组分为训练组和测试组,还将标签和图像分开。x_train 和 x_test 部分包含灰度 RGB 代码(从 0 到 255 ),而 y_train 和 y_test 部分包含从 0 到 9 的标签,表示它们实际上是哪个数字。为了可视化这些数字,我们可以从 matplotlib 获得帮助。
当我们运行上面的代码时,我们将得到 RGB 代码的灰度可视化,如下所示。
A visualization of the sample image at index 7777
我们还需要知道数据集的形状,以便将其导入卷积神经网络。因此,我将使用 NumPy 数组的“shape”属性,代码如下:
你会得到(60000,28,28)。您可能已经猜到,60000 表示训练数据集中的图像数量,而(28,28)表示图像的大小:28 x 28 像素。
重塑和标准化图像
为了能够在 Keras API 中使用数据集,我们需要 4 维 NumPy 数组。然而,正如我们在上面看到的,我们的数组是三维的。此外,我们必须规范化我们的数据,因为它在神经网络模型中总是需要的。我们可以通过将 RGB 代码分为 255(最大 RGB 代码减去最小 RGB 代码)来实现这一点。这可以通过下面的代码来完成:
构建卷积神经网络
我们将通过使用高级 Keras API 来构建我们的模型,该 API 在后端使用 TensorFlow 或 Theano。我想提一下,有几个高级 TensorFlow APIs,如 Layers、Keras 和 Estimators,可以帮助我们创建具有高级知识的神经网络。然而,这可能会导致混乱,因为它们的实现结构各不相同。所以,如果你看到同一个神经网络虽然都用 TensorFlow,但是代码完全不同,这就是为什么。我将使用最简单的 API,即 Keras。因此,我将从 Keras 导入顺序模型,并添加 Conv2D、MaxPooling、Flatten、Dropout 和 Dense 层。我已经谈到了 Conv2D、Maxpooling 和密集层。此外,丢弃层通过在训练时忽略一些神经元来对抗过度拟合,而展平层在构建完全连接的层之前将 2D 阵列展平为 1D 阵列。
对于第一致密层,我们可以用任何数目进行实验;然而,最终的密集层必须有 10 个神经元,因为我们有 10 个数字类(0,1,2,…,9)。你可以尝试内核大小、池大小、激活函数、退出率和第一密集层中的神经元数量,以获得更好的结果。
编译和拟合模型
使用上面的代码,我们创建了一个非优化的空 CNN。现在是时候为优化器设置一个使用度量标准的给定损失函数了。然后,我们可以通过使用我们的训练数据来拟合模型。对于这些任务,我们将使用以下代码:
您可以试验优化器、损失函数、指标和时期。然而,我可以说,亚当优化器通常是优于其他优化器。我不确定你是否真的可以改变多类分类的损失函数。请在下面随意试验和评论。纪元编号可能看起来有点小。然而,您将达到 98–99%的测试准确度。由于 MNIST 数据集不需要强大的计算能力,您也可以轻松地试验纪元编号。
评估模型
最后,您可以使用一行代码通过 x_test 和 y_test 来评估定型模型:
对于 10 个时期和这样一个简单的模型来说,结果相当不错。
Evaluation shows 98.5% accuracy on test set!
我们用这样一个基本模型达到了 98.5%的准确率。坦率地说,在许多图像分类情况下(例如,对于自动驾驶汽车),我们甚至不能容忍 0.1%的误差,因为作为类比,它将在 1000 个情况中导致 1 个事故。然而,对于我们的第一个模型,我会说结果还是不错的。我们还可以使用以下代码进行单独的预测:
我们的模型将图像分类为“9 ”,以下是图像的视觉效果:
Our model correctly classifies this image as a 9 (Nine)
虽然这不是一个很好的数字 9 的笔迹,但我们的模型能够将其归类为 9。
恭喜你!
你已经用 Tensorflow 的 Keras API 成功构建了一个卷积神经网络来对手写数字进行分类。你已经达到了超过 98%的准确率,现在你甚至可以保存这个模型&创建一个数字分类器应用程序!如果你对保存你的模型感兴趣,我会指引你去查看 Keras 文档。毕竟,为了能够有效地使用 API,必须学习如何阅读和使用文档。
订阅邮件列表获取完整代码
如果你想在 Google Colab 上获得完整的代码,并获得我的最新内容,请订阅邮件列表:✉️
喜欢这篇文章
如果你喜欢这篇文章,可以考虑看看我的其他类似文章:
在时尚 MNIST 的帮助下,使用深度卷积自动编码器清洁(或去噪)有噪声的图像
towardsdatascience.com](/image-noise-reduction-in-10-minutes-with-convolutional-autoencoders-d16219d2956a) [## 利用生成性对抗网络在 10 分钟内生成图像
使用无监督深度学习生成手写数字与深度卷积甘斯使用张量流和…
towardsdatascience.com](/image-generation-in-10-minutes-with-generative-adversarial-networks-c2afc56bfa3b) [## 使用递归神经网络预测比特币(BTC)价格
如果你能以某种方式预测明天的比特币(BTC)价格,这不是很棒吗?加密货币市场有…
towardsdatascience.com](/using-recurrent-neural-networks-to-predict-bitcoin-btc-prices-c4ff70f9f3e4) [## TensorFlow Hub & Magenta 在 5 分钟内实现快速神经风格转换
利用 Magenta 的任意图像风格化网络和深度学习,将梵高的独特风格转移到照片中
towardsdatascience.com](/fast-neural-style-transfer-in-5-minutes-with-tensorflow-hub-magenta-110b60431dcc)
图片分类 Keras 教程:Kaggle 犬种挑战赛
Golden Retriever image taken from unsplash.com
识别狗的品种是一个有趣的计算机视觉问题,因为细微的差异在视觉上将狗的品种彼此分开。本文旨在为那些刚刚开始使用卷积神经网络进行图像分类并希望了解如何试验网络架构、超参数、数据扩充以及如何处理加载自定义数据以进行测试和训练的人提供一个教程。
所有代码都用 Python 和 Keras 编写,托管在 Github 上:https://Github . com/CShorten/KaggleDogBreedChallenge/blob/master/dog breed _ binary classification . ipynb
我们使用的数据集来自 Kaggle.com 的狗品种鉴定挑战赛。Kaggle 竞赛是提升你的机器学习技能的一个很好的方式,本教程将帮助你熟悉网站上图像数据的格式。
Kaggle 上列出的这项挑战有 1286 个不同的团队参加。最大的挑战是在 120 个不同的种类中识别狗的品种。
120 个类是一个非常大的多输出分类问题,伴随着各种各样的挑战,例如如何对类标签进行编码。例如,对标签进行一次热编码将需要每个类别非常稀疏的向量,例如:[0,0,…,0,1,0,0,…,0]。
本教程随机选择了两个类,金毛寻回犬和设得兰牧羊犬,并侧重于二元分类的任务。
编程和数据科学新手可能会遇到的另一个挑战是 Kaggle 的数据格式。Kaggle 提供了一个由“id”而不是“Golden-Retriever-1”标记的图像的训练目录,以及一个带有 id →狗品种映射的 CSV 文件。我发现了 python 字符串函数。split('delimiter ')是我解析这些 CSV 文件的最好朋友,我将在教程中向您展示这是如何工作的。
本教程的第一部分将向您展示如何解析这些数据并将其格式化以输入到 Keras 模型中。然后我们将关注问题的一个部分,金毛寻回犬与设得兰牧羊犬,(任意选择)。
本教程的第二部分将向您展示如何将自定义数据加载到 Keras 中,并构建一个卷积神经网络来对它们进行分类。
本教程的第三部分将讨论偏差-方差权衡,并研究不同的架构、漏失层和数据扩充,以在测试集上获得更好的分数。
第 1 部分:格式化定制图像数据以输入到 Keras 模型
from PIL import Image # used for loading images
import numpy as np
import os # used for navigating to image path
import imageio # used for writing imagesnaimg_dict = {} # id: breed
f = open("labels.csv", "r")
fileContents = f.read()
fileContents = fileContents.split('\n')
for i in range(len(fileContents)-1):
fileContents[i] = fileContents[i].split(',')
naming_dict[fileContents[i][0]] = fileContents[i][1]
现在我们有了一个 python 字典 naming_dict,它包含了从 id 到 breed 的映射。现在,我们需要为每个品种建立一个计数字典,以便为图像分配标签,如“Golden_Retriever-1”、“Golden_Retriever-2”、“Golden_Retriever-67”。
breeds = naming_dict.values()
breed_set = set(breeds)
counting_dict = {}
for i in breed_set:
counting_dict[i] = 0
I .我们循环浏览当前命名为“id.jpg”的图像
二。剥去。来自他们的 jpg
三。将它们与命名词典中的品种相匹配。
四。然后我们会根据我们已经统计的数量给它们命名
动词 (verb 的缩写)最后,用这个新实例增加计数。
for img in os.listdir('./raw_data'):
imgName = img.split('.')[0] # converts '0913209.jpg' --> '0913209'
label = naming_dict[str(imgName)]
counting_dict[label] += 1
path = os.path.join('./raw_data', img)
saveName = './labeled_train/' + label + '-' + str(counting_dict[label]) + '.jpg'
image_data = np.array(Image.open(path))
imageio.imwrite(saveName, image_data)
现在,训练目录中的所有图像都被格式化为‘Breed-#’。jpg。非常有用的加载到 CNN 和分配一个热点矢量类标签使用图像命名。
将数据加载到 Keras 模型
关于训练-测试分割的说明:在本教程中,我决定使用训练集和测试集来代替交叉验证。这是因为我在我的 CPU 上运行这些 CNN,因此它们需要大约 10-15 分钟来训练,因此 5 重交叉验证将需要大约一个小时。我希望这项研究的重点是如何用不同的方法来改变你的模型结构,以达到更好的结果,因此快速迭代是很重要的。此外,我进行了大约 2/3–1/3 的训练/测试分割,这比通常的测试实例多一点,但是,这不是一个非常大的数据集。
def label_img(name):
word_label = name.split('-')[0]
if word_label == 'golden_retriever' : return np.array([1, 0])
elif word_label == 'shetland_sheepdog' : return np.array([0, 1])
这被称为一键矢量编码,它比用“0”或“1”编码每个标签产生更好的结果。就神经网络结构而言,这意味着输出层中有 2 个神经元,而不是 1 个,您将在下面 CNN 代码的最后一行中看到这一点:
更新(4/22/19): 这仅在多标签分类的情况下成立,而不是二进制分类。在二进制分类中,输出被视为 0 或 1,并且只有一个输出神经元,keras 将在编译期间纠正这一错误。
model.add(Dense(2, activation = 'softmax'))
调整图像大小
当我们格式化要输入到 Keras 模型的图像时,我们必须指定输入尺寸。许多学术数据集,如 CIFAR-10 或 MNIST,都有相同的大小(分别为 32x32x3 和 28x28x1)。然而,在 ImageNet 数据集和这个狗品种挑战数据集中,我们有许多不同大小的图像。首先,我们将编写一些代码来循环遍历这些图像,并收集一些关于狗图像的最大、平均和最小高度和宽度的描述性统计数据。
def get_size_statistics(DIR):
heights = []
widths = []
for img in os.listdir(DIR):
path = os.path.join(DIR, img)
data = np.array(Image.open(path)) #PIL Image library
heights.append(data.shape[0])
widths.append(data.shape[1])
avg_height = sum(heights) / len(heights)
avg_width = sum(widths) / len(widths) print("Average Height: " + str(avg_height))
print("Max Height: " + str(max(heights)))
print("Min Height: " + str(min(heights)))
print('\n')
print("Average Width: " + str(avg_width))
print("Max Width: " + str(max(widths)))
print("Min Width: " + str(min(widths)))
结果:平均身高= 388.34,最大身高=914,最小身高= 150
平均宽度= 459.12,最大宽度= 800,最小宽度= 200
加载图像
IMG_SIZE = 300def load_training_data():
train_data = []
for img in os.listdir(DIR)
label = label_img(img)
path = os.path.join(DIR, img)
img = Image.open(path)
img = img.convert('L')
img = img.resize((IMG_SIZE, IMG_SIZE), Image.ANTIALIAS)
train_data.append([np.array(img), label]) # Basic Data Augmentation - Horizontal Flipping
flip_img = Image.open(path)
flip_img = flip_img.convert('L')
flip_img = flip_img.resize((IMG_SIZE, IMG_SIZE), Image.ANTIALIAS)
flip_img = np.array(flip_img)
flip_img = np.fliplr(flip_img)
train_data.append([flip_img, label]) shuffle(train_data)
return train_data
测试图像加载以确保其正常工作
train_data = load_training_data()
plt.imshow(train_data[43][0], cmap = 'gist_gray')
第 2 部分:简单的 CNN
model = Sequential()
model.add(Conv2D(32, kernel_size = (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 1)))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())model.add(Conv2D(96, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())model.add(Conv2D(32, kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(BatchNormalization())
model.add(Dropout(0.2))model.add(Flatten())
model.add(Dense(128, activation='relu'))
#model.add(Dropout(0.3))
model.add(Dense(2, activation = 'softmax'))
此模型的培训日志:
评估模型时使用:
loss, acc = model.evaluate(testImages, testLabels, verbose = 0)
print(acc * 100)
初始模型= 72.09%的准确度
第 3 部分:改进模型
我认为有 5 种策略可以最有效地提高测试准确度:
I .增加更多辍学层
正如我们从训练报告中看到的,该模型在训练集上达到了 100%的准确率。从训练中的 100%到测试中的 72%表明了过度拟合的明显问题。过拟合可以通过增加漏失层或简化网络架构来解决(la 偏差-方差权衡)。然而,这与其说是一门科学,不如说是一门艺术,如果没有反复试验,很难准确计算出如何减少过拟合。
二。卷积网络参数
我们可以尝试删除或添加卷积层,改变滤波器大小,甚至改变激活函数。
三。改变网络末端的多层前馈神经网络
卷积网络的工作原理是对图像进行卷积,创建一个新的表示,然后将该表示压缩成一个向量,该向量被输入到一个经典的多层前馈神经网络中。我们可以尝试添加更多的隐藏层,或者改变每个隐藏层中神经元的数量。
四。数据扩充
在本教程中,我们只是用水平翻转来增强图像。但是您可以尝试其他方法,如随机裁剪、翻译、色阶转换等等。如果你雄心勃勃,你也可以尝试神经类型转移或生成对抗网络来增强数据。
动词 (verb 的缩写)狗对象检测裁剪
当我浏览这个数据集时,很明显,这些图像中有许多噪声,可能会混淆卷积神经网络。因此,改善这个网络的一个很好的策略是训练一个对象识别模型来检测狗的图片,并裁剪掉图像的其余部分,这样你就只对狗本身进行分类,而不是对狗和背景中的其他一切进行分类。
如果您对改进图像识别模型的更多细节感兴趣,请查看这篇文章:
建立模型后提高图像识别准确性的后续步骤。
towardsdatascience.com](/hacking-your-image-recognition-model-909ad4176247)
结论
希望本文能帮助您加载数据,熟悉 Kaggle 图像数据的格式,并了解更多关于图像分类和卷积神经网络的知识。这是我第一次尝试做一个完整的编程教程,请在评论中留下你的任何建议或问题。另外,如果这篇文章对你有帮助,请留下你的掌声,谢谢你的阅读!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对深度学习和软件工程感兴趣。
基于 MNIST 数据集的卷积神经网络图像分类。
这篇文章是为那些对机器学习感兴趣并且正在寻找一个不太复杂的来源的人准备的。
我是犹他大学的一名研究生,在我短暂的课程工作中,我对机器学习和人工智能产生了兴趣。我喜欢研究不同的数据集,并做笔记,然后发布到网上,这样那些觉得难以理解深度研究论文的人就可以从更简单、更容易理解的角度来看待人工智能和人工智能。
如果我必须向一个五年级学生解释什么是机器学习,我会说,你迈出的每一小步都会产生一个结果,让你知道什么是有利的,什么是不利的。这是机器学习的基础。类似地,当我们在大型数据集上训练计算机系统时,我们在给它们提供什么是有利的,什么是不利的信息。例如,当狗和猫的图片被提供给系统时,系统根据该信息训练自己,并且基于该信息,系统现在能够识别什么是猫,什么是狗。如何训练一个计算机系统来完成这样的魔法,我们将在本文的后面部分找到答案。
MNIST 手写的图像:
这是一个数据集,由从 0 到 9 的手写数字图像组成。每个图像都是单色的,28 * 28 像素。请参见下面的示例:
Source: www.tensorflow.org/tutorials/l…
目标:
训练计算机系统首先理解什么是数字的手写图像,然后测试该系统以正确预测新的手写图像。我们将向我们的系统提供 MNIST 数据集,并用随机图像对其进行测试,以检查其预测的准确性。
先决条件:
- python 脚本基础知识,Python 3.6。
- 关于什么是机器学习和张量流的概念。
- 学习新事物的活力。
如何做:
导入张量流和 MNIST 数据:
import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
占位符:
占位符不同于变量。它们是为保存训练数据而创建的参数,在这种情况下,它们是训练图像。MNIST 图像的形状为(28*28)。这些将被展平成(None *784)形状张量。“无”表示它可以是任何大小。
x = tf.placeholder(tf.float32, [None, 784])
权重和偏差:
权重和偏差的初始值被设置为零,因为当计算发生时它将被改变。因此,初始值是什么并不重要。因为存在 784 个特征和 10 个输出,所以 w’是(784 * 10)形状。“b”的形状是 10,因为从 0 到 9(数字)有 10 个输出。
w = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
预测模型:
x 和 w 是相乘并加到偏差上的矩阵。softmax 函数接受值并使总和为 1。这样,它可以用作概率值,使得判断哪个数字(0 -9)被预测的机会更高变得一致。
y = tf.nn.softmax(tf.matmul(x,w) + b)
#training our model
y_ = tf.placeholder(tf.float32, [None,10])
交叉熵函数:
交叉熵函数是成本或损失函数。它将真实值与预测值进行比较。目标是使损失最小化。
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
梯度下降优化器:
当使用交叉熵函数形成模型图时,我们希望找到损失最小的点。这是使用梯度下降优化器完成的。它向图中值较小的部分移动。可以手动设置步数或学习率。如果设定一个非常小的学习率,如 0.001,系统将永远需要达到损失最小的点,但它将更加精确。如果学习率设置得很高,则系统可能会产生快速但错误的结果。
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
训练模式:
在这里,我们正在训练我们的模型,以 100 个为一批来学习 MNIST 数据。
y_ = tf.placeholder(tf.float32, [None,10])cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
评估和测试模型:
在这里,模型以 0.8916 的精度被评估和测试。tf.argmax 给出一个轴中的最高值。所以,y_ 是正确值,y 是预测值。tf.equal 用于判断它们是否相等。
prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
多卷积层:
在这里,我们使用更多的层、权重和偏差来改进我们的模型并提高准确性。
我们的第一个卷积层对于每个 5*5 的面片有 32 个特征。它的权重张量将是[5,5,1,32]的形状。前两个维度是面片大小,接下来是输入通道,最后一个数字是输出通道。
为了应用卷积层,x 被整形为 4D 张量。28*28 是图像的宽度和高度,最后一个维度是颜色通道的数量。
然后应用 ReLU 函数使负值为 0,并保持正值不变。最大池将图像大小缩小到 14*14。
第二卷积层对于每个 5*5 的面片具有 64 个特征。
现在,图像大小已经减少到 7*7,我们添加一个具有 1024 个神经元的全连接层。
漏失和读出层:
为了减少过度拟合,我们会随机丢弃一些数据。因此,下降层有助于提高预测的准确性。下一层用于读取数据。
最终精度:
0.9919
完整的 Python 代码:
在 GitHub 上创建一个帐户,为 rajitnikhare/MNIST 的发展做出贡献。
github.com](github.com/rajitnikhar…)
参考文献:
- https://www . tensor flow . org/versions/r 1.0/get _ started/Mn ist/pros
- https://code labs . developers . Google . com/code labs/cloud-tensor flow-mnist/# 2
图像分类:完整的工作流程
I .定义问题并获取数据
机器学习模型一般分为两类,分类和回归模型。然而,分类模型之间还有一些额外的变化。例如,您可以预测一个二进制输出,如猫对狗,或许多输出,如 CIFAR-10 数据集,还有许多其他方法来映射分类器的输出,这将反映在网络的最终层。
一旦你定义了你的问题,你就应该开始考虑如何获得你的数据。最流行的方法之一是开发一种网络抓取算法,从网站上的标签中抓取图像。你也可以使用机械土耳其人外包你的数据收集需求。我通常只是通过简单地在网上截图并改变截图的默认存储位置来开始项目,以便通过这种方式收集数据。这个过程显然是非常艰巨的,但是,我发现它可以很好地获得项目的快速原型。
此外,一旦您收集了大量数据,您将需要考虑替代的数据存储方法,如云。
二。卷积架构,目标是增加复杂性
一旦你收集了足够的数据开始,你将建立你的卷积网络。这对于 TFlearn、Keras 或 PyTorch APIs 来说非常容易。下面的文章将为您提供入门代码,您可以轻松地将其复制并粘贴到您的项目中,从而创建一个非常简单的 CNN 架构。
[## Python:如何构建卷积网络分类器:耐克 vs 阿迪达斯鞋子
我为#100DaysOfMLCode 做的一个实验是建立一个图像分类器来区分 Nike…
towardsdatascience.com](/how-to-build-a-convolutional-network-classifier-81eef880715e)
渐进复杂性:当你在试验你的卷积网络时,最好从一个简单的结构开始,比如 1-4 个卷积层。当您添加更多数据时,或者如果您的初始结果不令人满意,您可能希望添加更多图层。当您试验您的网络架构时,为测试模型保留一个数据集是很重要的。通过这种方式,您可以使用这种性能作为控制来试验您的模型复杂性。
三。数据扩充
提高模型性能和稳健性的最简单方法之一是向数据集添加合成数据。添加更多数据的最简单方法是简单地水平翻转你的图像(如果与你的问题相关,也可以垂直翻转)。另一种流行的方法是随机生成与图像大小相同的噪声,然后将这种噪声添加到图像中。最后,如果你喜欢冒险,有很多关于使用生成对抗网络(GANs)来添加有意义的数据的研究。
四。解释结果,混淆矩阵
这是最重要的步骤之一,尽管经常被忽视。这一步被忽略的原因主要是因为数据昂贵且难以获得。因此,将一部分数据单独放在一边进行测试似乎是愚蠢的。然而,这对于建立您的绩效基准非常重要。
然而,除了要优化的相关性能变量之外,您还可以使用混淆矩阵可视化来深入了解您的数据。通过可视化错误分类的实例,您可以深入了解在描述整体类时哪些类型的图像未被充分代表。
动词 (verb 的缩写)数据采集和自动化改进
一旦您的模型被部署到某种应用程序中。您通常可以找到收集更多数据的方法,从而提高模型的性能和概化能力。
提高图像识别模型性能的最佳方法之一是添加更多数据进行训练!一些最…
towardsdatascience.com](/automatic-data-collection-to-improve-image-classifiers-232c2f0b2070)
结论
我相信这个工作流程是构建图像分类模型的一系列步骤。如果您想获得关于改进图像识别模型的更多提示,请点击此处。感谢您的阅读!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对计算机视觉、深度学习和软件工程感兴趣。
人工智能的图像数据集
在人工智能领域,数据就是力量。
人工智能算法以及它们如何相互融合是一门艺术,通过大学课程、在线培训以及观看 YouTube 视频的人逐渐了解这门艺术。人工智能是开源的,应该是。为了保护你的公司免受竞争,你可以做的是建立专有数据集。
有大量的数据集向公众开放。例如, Kaggle ,以及其他企业或学术数据集,以及众多联邦和市级数据源。我们在很多项目中使用这些,但是其他人也可以。你要的是造一些我没有的“特别”。例如,你不能在搜索方面打败谷歌,因为他们知道人们搜索什么,而你不知道。优势在于其数据集的规模和深度,而不仅仅是市场份额。
我们经常遇到构建人工智能解决方案的需求,在这种情况下,客户需要一个图像数据集来继续前进。客户端通常没有图像数据集来开始。他们不能简单地使用现成的解决方案或 API,因为现成卷积网络中典型的 1000 个对象并不像人们希望的那样广泛,而且区分两个类的分类器可能比有 1000 个的分类器更强大。当“输出类”(系统可以看到的事物类型)的数量很小时,做出错误预测的机会就很少,因此这些专门的模型往往工作得很好。
今天我想向大家介绍的是我们构建这些自定义图像数据集的一种方法。先说只有 2 类的情况:染病叶片和健康叶片。这个想法是用人工智能来区分某处田地里健康和病态的叶子。
首先,我们安装了 images-scraper 和 nodejs,我们将抓取的图像限制为非 https URLs。我们确保网址有。jpg '结尾,这通常是格式良好的。我们接下来需要的是一组关键字,所以我们使用下面的关键字列表开始:
keywordList = ['healthy', 'thriving', 'growing', 'living', 'beautiful','nourishing','tasty','green']baseKeyword = 'leaf'
从这里,我们生成关键字列表和基本关键字的组合。例如:
('healthy leaf', 'thriving leaf', 'growing leaf', 'living leaf', 'beautiful leaf')
接下来,我们将每个组合传递到一个单独的 nodejs 线程中。scraper 将抓取的图像收集到一个基本目录中,每个关键字组合都有子文件夹。然后,我们运行脚本来删除重复和空的文件。
这是一个完整的例子,我们如何刮图像感染的叶子。
keywordList = ['sick', 'damaged', 'infected', 'dying', 'bacteria','virus','sickly','wilting']
baseKeyword = 'leaf'import lemayScraper as lsls.scrapeImages(keywordList, baseKeyword)
在这一点上,我们有 2 个文件夹,一个包含数千张健康叶子的图片(和许多垃圾图片),另一个包含数千张感染叶子的图片(和更多垃圾图片)。接下来的任务是手动浏览图像,并删除与树叶无关的图像(一个拿着雨伞的婴儿),然后再次浏览图像,并删除类型错误的图像(树叶的绘图、树叶的 3D 渲染等)。最后,人类操作员梳理图像,并添加他们认为第一遍所需的尽可能多的努力。在后期阶段,我们可能会选择裁剪图像,或做其他图像清理。在这个阶段,目标只是确保坏数据不会过滤到训练数据中。
Collected image data for healthy leaves (left) and infected leaves (right).
此时,训练人工智能进行图像识别的项目可以开始了。我们已经看到了收集图像数据的许多其他要求,因此您的项目的解决方案可能会有所不同。有时,我们会寻找在感知哈希方面相似的图像,如下例所示:
3 images from a scrape
上面的图片都是醒目的红色。也许它们来自于对单词“红色”和“停止”的刮擦。我们可以通过下面的代码看到它们是多么相似:
结果如下:
ffe2c38f8983073d c3991c6e763899c3 ffe3c3c0c0c1c0ec
False
s1-s2 47
s1-s3 20
在结果的第一行,我们看到每个图像都有一个唯一的散列。英语停止标志(s3.jpg)和禁止标志(s3.jpg)之间的差异大于英语和法语停止标志(s3.jpg 和 s3.jpg)之间的差异。这太酷了!用数学它明白了停止标志是相似的!
因此,我们能够对刮下的图像进行后处理,在没有人工干预的情况下,将与其他东西相似的东西收集成堆(子类)。我们有很多其他的脚本来帮助清理 scraper 输出。一旦我们在分类器训练过程中看到一个好的分类结果(混淆矩阵),我们就停止胡闹。在这篇文章中讨论了这个图像刮刀的起源,以及一些关于如何使用它的疯狂想法。
至于使用来自 web 抓取的数据所需的许可,以及其他知识产权问题,那已经超出了本文的范围。
因此,总之,抓取图像形成一个数据集是完全可行的。我们都在关注快节奏的开发和尽早展示价值,抓取图像是构建定制图像识别解决方案的重要组成部分。
如果你喜欢这篇关于构建图像数据集的文章,可以看看我过去读过最多的文章,比如“如何为人工智能项目定价”和“如何聘请人工智能顾问”除了与业务相关的文章,我还准备了一些关于寻求采用深度机器学习的公司所面临的其他问题的文章,如“没有云和 API 的机器学习”
编码快乐!
-丹尼尔 丹尼尔@lemay.ai ←打个招呼。 LEMAY . AI 1(855)LEMAY-AI
您可能喜欢的其他文章:
keras 中从零开始的图像分类。初学者友好,中级刺激和专家刷新。
source: pixabay.com
上周末我在大声思考。
如果我有一个非常非常小的图像数据集,我自己捕获的,并想教计算机识别或区分一些特定的类别。
假设我有几千张图像,我想训练一个模型来自动检测一个类和另一个类。既然我只有这么少的数据,我能训练一个深度神经网络来成功地对这些图像进行分类吗?
嗯,在做了一些研究后,我发现必须用很少的数据训练深度神经网络是人们在计算机视觉领域遇到的常见情况。
Image source: pixabay.com
好吧,让我们面对现实吧,并不是每个人都可以像谷歌或人脸那样访问大数据,而且有些数据很难获得。
但是我也发现这个问题的解决方法很简单。所以今天我将带你训练一个卷积神经网络使用这一点点图像数据,你必须得到一个真正好的分类器,其准确率约为 81%。
在这篇的文章中,我介绍了一种叫做迁移学习的非常强大的技术,它帮助我们将准确率提高到大约 95%。
Image source: pixabay.com
好了,你可以出去开始收集数据了。
我将使用 K aggle 平台上现有的猫狗数据集。——是的,我很懒。我拿不到自己的数据。
kaggle.com
Kaggle 是全球数据科学和机器学习从业者的家园。他们举办了一些最大的数据科学竞赛,这是一个获得开源数据以及向获奖专家学习的好地方。
Yes i’m a Zindian. source: zindi.africa
我觉得我应该这么说。如果你来自非洲,我们有一个名为 Zindi 的新平台,它类似于 Kaggle ,但对非洲社会进行了微调。它包含从非洲企业和组织收集的数据集。这是防止 AI 偏见的一大步, Zindi 就是一个很棒的平台。
所以小心那些津迪亚人,我们来了。
好了,回到获取数据。我们前往 Kaggle 上的这个页面。这里我们有两个选择,我们可以下载数据并在我们的笔记本电脑上本地训练我们的模型,或者我们可以使用 Kaggle 内核,它为我们提供了更多的计算能力,访问 GPU,以及几乎所有预安装的用于机器学习和深度学习的库。
我不知道你怎么想,但我宁愿用 Kaggle 内核,除非我有 GPU。
source: pcmag.com
如果你买得起 GPU,或者你是一个游戏玩家,我完全虚构了这个词**,并且已经有了一个 GPU,并且你想在你的 PC 上训练你的模型,因为你太喜欢你的 PC 了,那么你可以按照这个 教程 或者这个one建立你自己的深度学习工作站。**********
对于其余懒惰或目前负担不起的 GP-us,让我们前往 K 阿格尔并启动这个引擎。
点击链接,我们传送到这里。
cats vs dogs kernel on kaggle
注意:当你访问一个 Kaggle 竞赛页面时,阅读数据描述通常是一个好主意。
接下来,点击内核**,然后点击右上角的蓝色新内核按钮,这将要求您选择内核类型。选择笔记本,这样我们可以做一些交互式编程。**
如果你不知道什么是笔记本或者需要刷新你的 notebooking 技能,这里的和这里的都是很棒的关于 Jupyter 笔记本的教程网站。
点击 Notebook 为你创建一个新的私有内核,并自动将 dogs vs cats 数据集添加到你的文件路径——云中的当然还有。****
给你的内核取个名字,并使用你的超级能力( GPU )来加快计算速度。
Your Notebook opens like this
现在我们的内核已经准备好了,让我们导入一些将要使用的库。键入下面的代码并按下 shift 回车 来运行单元格。
Import the following libraries
- cv2 cv2也叫OpenCV,是 Python 等多种高级编程语言中可用的图像和视频处理库。它用于各种图像和视频分析,如面部识别和检测、车牌读取、照片编辑、高级机器人视觉、光学字符识别等。在本教程中,我们将使用它来读取和调整我们的图像。****
- NumPy 是 Python 中最流行的数学库。它使大型多维数组和矩阵的工作和计算变得非常容易和快速。它有大量的高级数学函数来处理这些数组。
- PandasPandas 是一个为 Python 编程语言编写的用于数据操作和分析的软件库。特别是,它提供了数据结构和操作来操作数字表和时间序列。
- Matplotlib是 Python 的一个绘图库。它可以用来绘制线,条形图,图表,直方图,甚至显示图像。
- %matplotlib inline 是一个让我们的图出现在笔记本中的命令。
- 操作系统是一个内置的 python 包,用于访问你的计算机和文件系统。它可以用来显示目录中的内容,创建新的文件夹,甚至删除文件夹。
- random 将帮助我们创建随机数,这些随机数将在我们分割或打乱数据集时使用。
- gc 垃圾收集器的简称,是手动清理和删除不必要变量的重要工具。我们将在 Kaggle 内核上积极使用它,因为由于我们正在处理图像数据集,分配给我们的空闲内存可能会变满。
导入必要的库后,我们将图像读入内存。数据以 Zip 文件的形式存储在我们的内核中。
Our data
我们可以看到三个文件:
- sample submission.csv 这是一个 csv(逗号分隔值)文件,用于在训练您的模型并在给您的测试文件上进行测试后进行提交。由于本次比赛已经结束,我们不能提交,所以我们将忽略此文件。
- test.zip 该文件包含我们将在训练后测试我们的模型的图像,以了解我们的模型是否已经学会区分狗和猫。
- 这是我们模特的食物。它包含了我们将要用来教我们的模型一只狗或一只猫长什么样的数据。
现在,为了访问我们的训练图像,我们将使用我们之前导入的操作系统包。****
注意:kaggle 上的所有数据文件路径都以根目录 开始../输入。例如,这个内核中训练数据的文件路径将是../输入/训练
import our Images
- 在这里,我们为我们的训练和测试数据创建一个文件路径
- **这里我们创建两个变量 train_dogs 和 train_cats 。一个用于所有的狗图像,另一个用于猫图像。我们编写一个列表理解,使用命令 os.listdir() 获取列车数据 zip 文件中的所有图像,并检索名称中带有狗的所有图像。 我们对猫的图像也是如此。
- 我们也得到我们的测试图像。
- 训练数据集总共包含 25,000 幅图像,但由于我们正在试验使用一个小数据集,并且我们显然只能使用很少的计算能力,因此我们将从两个类中仅提取 2000 幅图像。 ** 2000 张狗图像和 2000 张猫图像,制作 4000 张图像的训练数据集。 所以我们从 train_dogs 和 train_cats 中抓取前 2000 个图像,然后将它们连接成一个名为 train_imgs 的训练集。
- 非常重要! 我们随机洗牌 train_imgs。
- 在这里,我们做一些清洁。你可能已经注意到了,我们现在有 train_imgs 意为 train_dogs 和 train_cats 变量是无用的,并且占用了不必要的空间。如果我们不删除它们,当我们开始训练我们的模型时,我们可能会耗尽内存。
好的,让我们来看看 train_imgs 中的一些图片。
lets view some cute dogs
- 从 matplotlib 导入图像绘图模块
- 运行 for 循环来绘制 train_imgs 中的前三幅图像
请记住这是一个随机列表,但幸运的是,当我运行代码时,前三个图像是由两只狗和一只猫组成的,请注意它们有不同的尺寸。
The last two images of plot
在下一个代码块中,我们将使用 cv2 模块来调整图像的大小。 首先让我们声明我们想要使用的新维度。在这里,我使用 150 乘 150 的高度和宽度和 3 个通道。
declare some important variables
彩色图像由 3 个通道组成,即红色、绿色和蓝色像素值的 3 个阵列。我们可以使用 1 个通道来读取灰度格式(黑白)的图像。
现在,让我们写一个小函数,它也有助于阅读,然后调整我们的图像到上面提到的高度和宽度。
helper function
- 创建一个新变量 X ,它将保存新的训练集,而 y 将保存我们的训练标签。(如果图像是狗,则为 1;如果图像是猫,则为 0)
- 我们一个接一个地读取我们的图像,并用 cv2 命令调整它们的大小。
- 如果图像是一只狗,我们将 1 添加到 y 中,如果图像是一只猫,我们将 0 添加到图像中。
现在,让我们调用我们的函数并处理图像。
*****X, y = read_and_process_image(train_imgs)*****
x 现在是图像像素值的数组,y 是标签的列表。我们来预览一下 x 中的第一张图片。
Yea, that’s what your computer calls a dog
我的朋友是一只狗。或者我们可以说我们的电脑称之为狗。等等!我怎么知道它是一只狗?好吧,让我们看看标签列表 y 中的对应值。
remember 1 for dog and 0 for cat
嗯,记得我们说过让 1 和 0 分别代表狗和猫。
还是不相信我。然后,让我们绘制 X 的前 5 个数组。我们不能用上面的matplotlib . image*的 mpimg 模块绘制 X 中的图像,因为这些现在是像素数组,而不是原始的 jpg 文件。所以我们应该使用 imshow ()命令。*****
plot the first five images
现在,我们确信我们的训练集包含了适当的狗和猫的图像,让我们看看我们的标签。记住我们总共有 4000 张图片(2000 只狗和 2000 只猫),因此我们的标签列表 y 应该包含 2000 张 1 和 2000 张 0。让我们画出这个并确认。
- 我们导入了 seaborn 包,这是另一个构建在 matplotlib 之上的绘图包,它给出了非常漂亮的绘图。
- 记住,我们是爱整洁的人,我们不会等着清洁工来为我们打扫卫生。所以我们删除了 train_imgs ,因为它已经被转换为一个数组并保存在 X. 中
- x 和 y 目前是 list 类型(python 数组的列表),我们将把它们转换成 numpy 数组,这样我们就可以把它输入到我们的模型中。
- 绘制一个彩色图表来确认我们的 y 标签变量中的类的数量
bar count of labels
太好了!我们有 2000 个狗和猫的班级。我们继续吧。
接下来让我们检查数据的形状。总是检查和确认你的数据的形状,这是非常重要的。
shape of our data
我们可以看到,我们的图像是一个秩为 4 的张量,或者我们可以说是一个 4 维数组,其尺寸为 4000 x 150 x 150 x 3,分别对应于批次大小、高度、宽度和通道。
我们的图像数组的形状对于我们将要构建的 keras 模型非常重要。该模型将(高度、宽度、通道)的数组作为输入
现在我们的数据已经准备好了(X,y ),我们可以开始训练,但是首先我们必须做一些非常重要的事情,那就是将我们的数据分成训练集和验证集。这是开始训练模型之前要做的最重要的事情之一。
对于拆分,我们将使用 python 中一个流行的机器学习包中的一个方便的函数,名为 sklearn 。
- 从 sklearn 导入 train_test_split
- 我们告诉函数,我们希望将 20%的数据分配给验证集,而将另外 80%的数据分配给训练集。
- 这里我们打印了新的训练和验证集的形状
接下来,我们将声明在训练我们的模型时将使用的一些重要变量。
- 是的,我们还在打扫。
- 获取训练集和验证集的长度。
wheeeeew…现在是时候创建我们的模型了。
我们将使用卷积神经网络(convnet)来训练我们的模型。当涉及到计算机视觉问题时,Convets 是当前的标准。在任何图像问题上,它们总是胜过其他类型的神经网络。
刚接触 convnets?在这篇文章的最后,有一些很好的网站链接,你可以在那里了解它们。
在创建我们的模型时,我们将使用 KERAS 。
根据维基百科…
Keras 是用 Python 编写的开源神经网络库。它能够在 TensorFlow、微软认知工具包或 Theano 上运行。旨在实现深度神经网络的快速实验,它专注于用户友好、模块化和可扩展。
首先,让我们导入将要使用的必要的 keras 模块
- *****这里我们导入 keras 图层 模块 其中包含深度学习中使用的不同类型的图层,例如: **卷积层(主要用于计算机视觉) **池层(也用于计算机视觉) **递归层(主要用于序列和时间序列建模) *嵌入层(主要用于自然语言处理) 规范化层 等等
- *****这里我们导入 keras 模型 ,它包含两种类型:
- *我们将在本教程中使用的顺序模型和
- 带有函数式 API 的模型****
- 这里我们导入 kerasoptimizer,一个模块* 包含不同类型的反向传播算法用于训练我们的模型。这些优化器包括:
**sgd(随机梯度下降)
**rmsprop(均方根传播)
-
- Adams
-
- Adagrad
-
- Adadelta*****
-
- 这里我们导入一个最重要的函数( ImageDataGenerator ),在处理小数据集时使用。以下是更多相关信息。
现在让我们创建我们的网络架构。我们将遵循一个流行、有效和简单的架构,叫做 VGGnet
slide from Elsever
网络架构只是我们排列卷积层的方式
我们将使用一个小的 vggnet,但你可以在下面看到,我们的过滤器大小随着我们向下分层而增加。
32 → 64 →128 →512 —最后一层是 1
- 这里我们创建一个序列模型。这告诉 keras 按顺序堆叠所有层。
- 这里我们通过调用来创建第一层。在我们创建的模型上添加()函数,并传递我们想要的图层类型——一个 Conv2D 图层。这第一层被称为输入层,有一些我们需要设置的重要参数。 ****** 滤波器大小 [ 32 ]:这是输出维度的大小(即卷积中输出滤波器的数量) *** kernel _ size[3,3]: 这指定了 2D 卷积窗口的高度和宽度。 **激活 [' relu ']:我们选择一个激活函数,也称为非线性,供我们的神经网络使用。R eLU (整流线性单位)是当今最常用的激活函数,其他变体还有ReLU*和 eLU 。 输入形状[150,150,3]: 还记得我们调整图像的尺寸吗?150 乘 150 对吗?我们在这里通过,包括通道 3。 我们不传递第一个维度 4000,因为这是批量维度。**
- 这里我们添加一个maxpool 2d图层。它的功能是减少输入特征的空间大小,因此有助于减少网络中的参数和计算的数量,从而有助于减少过拟合。
过拟合发生在我们的模型记忆训练数据的时候。该模型在训练时表现出色,但在测试时会失败。
- 这里我们添加一个展平层。conv2D 图层提取并学习空间要素,然后在展平后将其传递给密集图层。这是展平层的工作。
- 这里我们添加一个值为 0.5 的下降层。Dropout 随机丢弃神经网络中的一些层,然后使用简化的网络进行学习。通过这种方式,网络学会在单个层上独立而不可靠。底线是,它有助于过度拟合。 0.5 表示随机掉一半的图层。
- 最后一层的输出大小为 1,激活函数称为 sigmoid。 这是因为我们试图检测一张图片是狗还是猫。也就是说,我们希望模型输出图像是狗而不是猫的概率,这意味着我们需要一个概率分数,其中较高的值意味着分类器认为图像是狗,较低的值意味着它是猫。 sigmoid 非常适合这种情况,因为它接受一组数字,并返回 0 到 1 范围内的概率分布。
我们可以通过调用 Keras 函数来预览我们的 convnet 的排列和参数大小。模型对象上的 summary() 。****
我们可以看到我们想要训练的参数的数量(300 多万)和不同层的一般排列。
下一步是编译我们的模型。
我们向 model.compile()命令传递三个参数
- lOSS[' binary _ cross entropy ']:我们指定一个损失函数,我们的优化器将最小化它。在这种情况下,因为我们正在处理两类问题,所以我们使用 二进制交叉熵损失 。
- 还记得我们之前定义的 优化器 吗?我们将使用其中一个名为 rmsprop 的。这不是一个固定的选择,这是一个叫做 超参数调整 的过程的一部分,这可能就是世界级模型和幼稚模型的区别。
- ****在这里,我们指定在训练后测量模型性能时要使用的指标。我们想知道我们的模型做得好不好。 既然我们在做分类问题,那么精度指标 (acc) 是个不错的选择。 注:您用来衡量模型性能的指标将取决于您正在处理的问题的类型。
最后,在我们开始训练我们的模型之前,我们需要执行一些规范化。即缩放我们的图像像素值,使其具有单位标准偏差和平均值 0。
我们将使用 Keras 中一个名为imagedata generator的重要模块,当我们在训练期间将图像输入模型时,它会执行一些重要的功能。******
但是……但是什么是图像数据生成器呢?
根据 Keras 的创建者 Fran ois Chollet的说法,Keras ImageDataGenerator()让我们可以快速设置 python 生成器,自动将图像文件转换为预处理张量,可以在训练期间直接输入到模型中。它很容易为我们执行以下功能: 1 .将 JPEG 内容解码为像素的 RGB 网格。 2。把这些转换成浮点张量。 3。将像素值(在 0 和 255 之间)重新缩放到[0,1]区间(神经网络在规格化数据时表现更好)。 4。它帮助我们轻松地增强图像。(这是我们将使用的一个重要特性,因为我们是在一个小数据集上进行训练的)。
好了,让我们创建我们的 ImageDataGenerator 对象。我们将创建两个生成器,一个用于训练集,另一个用于验证集。
- 我们将 rescale 选项传递给 ImageDataGenerator 对象。 重新标度=1。/255选项是一个非常重要的参数。它将图像像素值标准化为平均值为零,标准偏差为 1。它有助于您的模型有效地学习和更新其参数。****
- 第二组选项是图像增强。他们告诉 ImageDataGenerator 对图像随机应用一些变换。这将有助于扩大我们的数据集,提高泛化能力。
- 这里我们还为我们的验证集创建了一个 ImageDataGenerator 对象。注意:我们这里不做数据扩充。我们只执行 重新调整 。
既然我们有了 ImageDataGenerator 对象,让我们通过传递我们的训练和验证集从它们创建 python 生成器。
- 我们称之为 。我们在上面创建的数据生成器上的 flow( ) 方法传递数据和标签集。 X_train 和 y_train 用于训练,然后 X_val 和 y_val 用于验证。 批次大小告诉数据生成器一次仅获取指定批次(在我们的例子中为 32)的图像。
- 现在我们通过调用来训练我们的网络。在模型**上拟合()方法并传递一些参数。第一个参数是训练集imagedata generatorobject[train _ generator]。****
- 这里我们指定每个时期 的 步数。这告诉我们的模型,在对我们的损失函数进行梯度更新之前,我们想要处理多少图像。 总共 3200 张图像除以 32 的批量大小将得到 100 个步骤。这意味着我们将在整个训练集中一次对我们的模型进行总共 100 次梯度更新。
- 一个历元是整个训练集的一个完整周期或一遍。在我们的例子中,当我们按照我们的 steps_per_epoch 参数的指定进行 100 次梯度更新时,就达到了一个 epoch。 E pochs = 64 ,意味着我们要检查我们的训练数据 64 次,每次我们将进行 100 次梯度更新。
- 我们传递我们的验证数据生成器。
- 我们也在这里设置步长。我将使用与上述相同的步长。
运行细胞开始训练…这需要一段时间。去推特上打扰某人吧…
仅仅过了 64 个时期,我就获得了大约 80%的准确率。
screenshot of model training
对于一个我们用很少的数据从零开始训练的模型来说,这已经不错了。
也许增加历元的数量和使用一些超参数,如批量大小和优化器,将有助于提高这个分数。
我将把那留给你去探索。
接下来,我们保存我们的模型,使用下面显示的简单的 Keras 函数,这样我们可以随时重用它,而不是在重新运行我们的笔记本时再次训练。
****#Save the modelmodel.save_weights('model_wieghts.h5')
model.save('model_keras.h5')****
我们将绘制一些训练集和验证集中的准确性和损失的图表,看看我们是否可以获得一些见解。
- 在训练一个 Keras 模型之后,它总是计算并保存我们在一个名为 history 的变量中编译我们的模型时指定的指标。我们可以提取这些值并绘制出来。 注:历史对象包含训练过程中发生的所有更新。
- 这里我们简单的从' acc' 列表中的数值个数得到我们 epoch 的大小。
- 这里我们绘制了精度与历元大小的关系。
- 这里我们绘制了损失与历元大小的关系。
Plot of accuracy against epochs
那么我们能从这个情节中学到什么呢?
- 首先要注意的是,我们没有过度拟合,因为训练和验证准确性非常接近,并且相互跟随。
- 我们还可以注意到,精度随着历元的增加而不断增加,这给我们一种直觉,即增加历元大小可能会给我们带来更高的精度。
Plot of loss against epochs
我们仍然没有过度拟合,因为训练和验证损失都呈下降趋势,就像上面的准确度图一样,如果我们增加历元大小,损失可能会更低..
所以,你已经有了一些直觉。现在尝试增加历元大小,并使用一些超参数。
在我结束本教程之前,我们将在测试集中的一些图像上测试我们的模型。
code to pre-process the test Images
我们在训练和验证集上执行相同的预处理。
- 我们读取测试集中的前 10 幅图像,并将其转换为数组列表。 注: y_test 将为空,因为测试集没有标签。
- 我们将数组列表转换成一个大的 numpy 数组。
- 我们创建了一个测试 ImageDataGenerator ,并且只执行标准化。 注意:我们不扩充测试集。
现在我们将创建一个简单的 for 循环,它遍历来自生成器的图像来进行预测。然后我们将绘制结果。
- 创建一个列表来保存我们将要生成的标签。
- 我们设置将要绘制的图像的图形大小。
- 这里我们通过调用对 ImageDataGenerator 提供的特定图像进行预测。predict( ) 方法在我们训练好的模型上。
- pred 变量是模型确定当前图像是狗的概率。 因为我们给狗的标签是 1,所以高概率——至少大于平均 0.5——意味着我们的模型非常确信图像是狗,否则就是猫。 因此,我们简单地创建一个 if -else 语句,如果概率大于 0.5,该语句将字符串“ Dog ”追加到 text_label。我们这样做是为了在绘图时给图像添加一个标题。
- 这里我们添加了一个支线剧情,这样我们就可以绘制多个图像。
- 这里,我们将预测的类作为标题添加到图像绘图中。
- 我们最终绘制出图像。
让我们看看我们的模型在以前看不到的图像上表现如何。
嗯…我们的模型从五幅图像中得到一个错误。我没说它处于最佳状态…至少现在还没有。
wheeew…这是一个很长的帖子,但我想这是值得的。在这个 下一个教程中,我们通过使用一个 预训练的网络,改进了我们的模型,达到了大约 95%的准确率。 一个过程叫做 转移学习。
source: pixabay.com
好了,再见了,祝你编码愉快。
CNN 和 Keras 上一些惊人的帖子和文章。
- 用于视觉识别的 CS231n 卷积神经网络。
- Keras 的创造者 Francois Chollet 用 python 进行深度学习。
- 卷积神经网络基础知识。
- CNN 上一篇很棒的媒体文章。
- CNN 直观指南 |中帖。
- Keras 教程。
欢迎提问、评论和投稿。
在 推特 上跟我连线。
在insta gram上跟我连线。
图像处理类别(EGBE443) #1.2 —数字图像
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。如果我犯了什么错误,请纠正我。谢谢你。
上一篇文章是关于构建图像的最简单的方法。在这篇文章中,我将谈论什么是数字图像和每种文件格式的区别。
如果您还没有阅读上一篇文章,您可以点击下面的链接轻松找到它。:)
大家好!我叫皮查亚·西普克汉姆。我是玛希隆生物医学工程系四年级学生…
towardsdatascience.com](/image-processing-class-egbe443-0-1-image-aquisition-7e80cc89de84)
什么是数字图像?
D 数字图像是以计算机可以存储的形式(即以数字的形式)呈现的图像。这种形式易于操作,适用于图像处理。
制作“数码快照”的方法有以下几个必要步骤:
- **空间采样:**将连续信号转化为离散表示。这一步被称为图像的“空间采样”,它取决于传感器和采集设备的几何形状。
- 时间采样:该过程通过定期测量入射到每个单独传感器元件上的光量来执行。
- **像素值的量化:**所有的像素值都被转换成一个范围内的整数值,例如 8 位= 256 或 12 位= 4096。但是在某些情况下,使用浮点值。(例如,医学图像处理)
数字图像的坐标系统
尺寸为 M x N(列 x 行)的图像表示为图像矩阵 I。每个像素由它们所在的行和列表示,原点坐标在图像的左上角(u = 0,v =0)。所以最大列和最大行分别是 M-1 和 N-1。
在现实世界中,每次测量的像素数量;例如,每英寸点数或每英寸线条数被称为图像的*'**'。*
每个像素的值取决于数据类型,该数据类型总是长度为 k (k 为 2 的幂)的二进制值,因此像素值可以是该范围内的任何值。k 值被称为图像的“比特深度”。
图像处理中你应该知道的另一个重要话题是‘图像文件格式’。**
图像文件格式
任何图像都存储在内存中,光栅图像包含按规则矩阵排列的像素值。相反,矢量图像使用连续坐标表示几何对象。如果放大光栅图像,图像的分辨率将会丢失,但在矢量图像中不会发生这种情况。
Raster image and Vector image
- 标记图像文件格式(TIFF)
TIFF 旨在满足不同领域的专业需求。这种格式支持各种类型的图像,也支持灰度和真彩色图像。TIFF 提供了多种不同的压缩方法(LZW、ZIP、CCITT 和 JPEG ),它可以在单个 TIFF 文件中存储多种不同大小和表现形式的图像。
典型 TIFF 文件的结构由标题和图像对象的链接列表组成。每个图像对象都由一个“标签”列表组成,其对应的条目后跟一个指向实际图像数据的指针。
The structure of a typical TIFF file for three image object.
2。图形交换格式(GIF)
GIF 格式支持多位深度索引颜色,并可以通过在单个文件中存储大量图像并按顺序显示它们来编码简单的动画。这种格式设计用于灰度和彩色图像,最大深度为 8 位,不支持真彩色。
3。便携式网络图形(PNG)
PNG 是作为 GIF 格式的替代而开发的。PNG 支持三种不同类型的图像:
- 真彩色(3 x 16 位/像素)
- 灰度(16 位/像素)
- 索引(256 色)
PNG 为透明度提供了最大深度为 16 位的 alpha 通道。该通道只有一位深,并且该格式仅支持在一个文件中具有 2 行的最大 30 次方和 2 列的最大 30 次方的单个图像。
3。Windows 位图(BMP)
BMP 只是在 Windows 下使用,它支持灰度、真彩色和索引图像以及二进制图像,但每个像素都用一个完整的字节存储。
4。可移植位图格式(PBM)
PBM 格式将图像存储在人类可读的文本中,可以使用文本编辑器进行阅读和编辑。
Example of BPM file format read from text editor program.
5。JPEG
JPEG 是一种广泛使用的文件格式。JPEG 标准压缩方法取决于应用。在 RGB 图像的情况下,有三个主要步骤:
- ***颜色转换和下采样:*将颜色转换到 YCbCr 空间。y 和 C 分别是亮度分量和颜色分量。
- ***频率空间中的余弦变换和量化:*图像被分成 8 个块的网格,对于每个块,使用离散余弦变换来计算频谱。然后,将每个块的 64 个频谱系数量化到量化表中。
- ***无损压缩:*用无损方法压缩数据。
The process of JPEG compression method in RGB image.
实际上,JPEG 不是一种文件格式,而是一种压缩方法。Eric Hamilton 和 IJG 开发了一种关于 JPEG 压缩方法的文件格式,称为“JPEG 文件交换格式”或 JFIF。此外,还有一种称为可交换图像文件格式(EXIF)的文件格式,它是 JPEG(JFIF)的变体,也可以将图像存储在数码相机上。
希望你对数字世界中的图像有更清楚的了解。课程的下一个主题是关于应用和修改数字图像。你可以通过点击下面的链接很容易地找到下一篇文章。
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
medium.com](medium.com/@ptchaya.p/…)*
图像处理 1.1 级—图像采集
大家好!我叫皮查亚。我是玛希隆大学生物医学工程系的四年级学生。
我写这篇文章的目的是总结我在医学图像处理课程或 EGBE443 中学到的经验。如果我犯了什么错误,请纠正我。谢谢你。
先说第一个题目, 图像采集 。
Image from NOPO Pinhole Camera
什么是图像采集过程?
图像采集是构建图像的过程。有一个执行这个过程的简单模型叫做 【针孔摄像机模型】 。
针孔摄像机型号
室内摄像机是生成图像的最简单的工具。它很容易制作,因为它的组件只是由一个漆黑的房间,一个叫做“针孔”的小洞和一个场景组成。为了形成图像,光线穿过针孔,入射到场景中。这会使图像变小并反转。
针孔摄像机的几何属性非常简单,如下图所示。
Geometric properties of the image from pinhole camera
从图中可以看出,物体位于离 针孔水平距离 Z 处,离光轴垂直距离 Y 处。f 是针孔和场景之间的距离。我们通过相似三角形原理找到了物体坐标 X,Y,Z 和图像坐标 X,Y,焦距 f 之间的关系。
The relationship between object coordinate and image coordinate.
然而,针孔照相机并不像预期的那样实用。较小的孔产生更清晰的图像,并且伴随着更长的曝光时间。所以使用 光学镜头型号 就是因为这些原因。为了使用,我们需要用薄透镜代替针孔。我们假设它无限薄。所以图像的几何形状类似于针孔摄像机的图像。薄透镜模型的几何特性如图所示。
The geometric properties of thin lens model
这个视频将向您展示如何制作针孔摄像机以及图像采集过程的结果。
我和我组里的朋友制作了一个针孔相机,并在不同的距离和快门速度下测试了第一个原型。这些是每个标准的结果。
- 与物体的距离= 1 米。速度快门= 5 秒
- 距离物体 1 米,快门速度 10 秒
- 距离物体 2 米,速度快门 5 秒
- 距离物体 2 米,快门 10 秒
如你所见,很容易制作!让我们开始吧,享受你的相机!:)
无论如何,可调整的图像必须是数字图像。所以在下一章,我会解释这个话题。它让你明白它是如何适合这种形式的修改。
下面是下一篇文章。请点击它前往:)
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
medium.com](medium.com/@ptchaya.p/…)
图像处理类别# 2-直方图
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
这篇文章是关于基本的图像处理。如果你是这个领域的新手,你可以点击下面的链接阅读我的第一篇文章。:)
大家好!我叫皮查亚·西普克汉姆。我是玛希隆生物医学工程系四年级学生…
towardsdatascience.com](/image-processing-class-egbe443-0-1-image-aquisition-7e80cc89de84)
在之前的帖子中,我已经谈到了数字图像。在这篇文章中,你会了解到 直方图 ,这是一个必要的话题。
什么是直方图?
H istogram 是图像中强度值的频率分布。直方图条目取决于图像的比特深度(k)。例如,8 比特灰度图像包含 2⁸ = 256 的强度,强度在 0 到 255 的范围内。每个直方图条目被定义为 h(i)
h(i) =强度值为 I 的图像中像素值的数量
最小强度值 0 指的是颜色为黑色的像素,最大强度值 255 指的是颜色为白色的像素。
图像的直方图只提供统计信息,不提供空间信息。这是给出相同强度分布的两幅图像的例子。
Two different pictures, a. and b., provide the same histogram due to the equal number of the intensities.
计算直方图
在本节中,直方图是通过 python 编程代码(Python 3.6)的实现来计算的。
对于 python 3.6,有很多常用的图像处理模块,如 Pillow、Numpy、OpenCV 等。但是在这个程序中使用了 Pillow 和 Numpy 模块。
要从您的计算机导入图像,请使用此代码并更改您的路径,这是您的图像的位置。
img = Image.open('/PATH/')
下一步,您需要将图像转换为灰度,并将变量类型转换为 numpy 数组,以便轻松计算直方图。
img = img.convert("L") #Convert photo to gray scale
img = np.asarray(img) #Convert variable type to numpy array
现在,图像准备计算直方图。用这个代码算算吧!
h = [0]*256
for x in range(img.shape[0]):
for y in range(img.shape[1]):
i = img[x,y]
h[i] = h[i]+1
最后一步,变量 h 包含每个强度值的个数。我们可以使用 matplotlib 模块绘制直方图。这是我程序结果的一个例子。
The example image (.jpeg) and the plot of histogram
下一章,主题是关于直方图的点操作和均衡化。这可能有助于提高图像质量。点击下面的链接,你可以很容易地找到下一篇文章。
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
medium.com](medium.com/@ptchaya.p/…)
图像处理等级#3 —点操作
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
这篇文章是关于基本的图像处理。如果你是这个领域的新手,你可以点击下面的链接阅读我的第一篇文章。:)
大家好!我叫皮查亚·西普克汉姆。我是玛希隆生物医学工程系四年级学生…
towardsdatascience.com](/image-processing-class-egbe443-0-1-image-aquisition-7e80cc89de84)
有时,相机拍出的照片质量可能很差。它们是当时可怕光线的结果。因此,图像处理中提高图像质量的一个基本方法就是点运算。
概述
- 点运算
- 自动对比度调整
- 改进的自动对比度
- 直方图均衡
- 直方图规定化
什么是点操作?
点操作是在不改变图像的大小、几何形状和局部结构的情况下修改像素值。新的像素值仅取决于先前的值。它们由函数 f(a)映射
如果函数 f()不依赖于坐标,则称之为"全局或"齐次"运算。另一种叫做非齐次点运算,如果依赖于坐标的话。非均匀点操作用于补偿图像采集期间的不均匀光照。
同质操作的常见示例包括:
- 修改对比度和亮度
- 通过夹紧限制结果
- 反转图像
- 阈值操作
点操作的实现对直方图的影响。提高亮度会将直方图向右移动,提高图像的对比度会扩展直方图。这些点操作通过包含常数的映射函数来映射强度,该常数是图像内容,例如最高强度和最低强度。
自动对比度调整
自动对比度调整是将图像中的最低强度和最高强度分别映射到全强度范围的最小和最大强度的方法(对于 8 位灰度图像,全范围为 0–255)。自动对比度调整的映射函数定义为
从等式中,a 最小值、a 最大值、a 低值和 a 高值分别是范围内的最小值强度、最大值强度、最低强度和最高强度。在 8 位图像的情况下,最小值=0,最大值=255,因此映射函数定义为
修改自动对比度
最高强度和最低强度可能是图像的噪声,我们通过使用分位数使图像的强度饱和来排除这些噪声。它可以通过下面的等式计算出来。
映射方程定义为
直方图均衡化
执行此任务是为了使两幅图像之间的差异更易于比较并在印刷出版物中使用。其原理是将图像直方图映射成近似均匀分布。映射函数定义为:
其中 H(a)是像素值 a 的累积直方图,K 是最大强度值,MN 是最近的累积强度。
您可以使用 OpenCV 模块将其应用到您的 python 代码中
equ = cv2.equalizeHist(img)
这是直方图均衡化的结果。
直方图规定化
该任务类似于直方图均衡化,但是该过程的目的是将直方图的分布函数映射到参考分布。为了独立于图像大小,图像强度需要归一化到范围 0-1。归一化直方图被解释为随机过程的概率密度函数。其中 p(i)是像素值 I 的概率,h(i)是所有强度值的总和。所以所有概率函数的和等于 1。
H(i)定义为累积直方图,H(i)的统计对应部分是离散分布函数 P()。这也称为累积分布函数(cdf)。
直方图规定化原理
如图所示,我们需要将图像 A 的 pdf 映射到参考图像 r。我们获得新的像素值 A ’,如下所示
因此,映射函数定义为
确保参考图像 R 的 pdf 是可逆的(具有 b =[0,1]的现有值)。
然而,修改图像的方法不仅仅是点操作,还有另一种方法,叫做 【滤镜】 。我将在下一章向你介绍更多的信息。回头见!
现在,下一章出版了。你可以点击下面的链接阅读。:D
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
medium.com](medium.com/@ptchaya.p/…)
图像处理类别#4 —过滤器
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
这一章是关于过滤图像。为了更容易理解,你可以通过下面的链接阅读上一章关于点操作的内容。
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
towardsdatascience.com](/image-processing-class-egbe443-3-point-operation-477ad38334f5)
如果你是图像处理的新手,你可以点击下面的链接阅读我的第一篇文章。:)
大家好!我叫皮查亚·西普克汉姆。我是玛希隆生物医学工程系四年级学生…
towardsdatascience.com](/image-processing-class-egbe443-0-1-image-aquisition-7e80cc89de84)
轮廓
- 过滤
- 线性过滤器
- 线性滤波器的属性
- 非线性滤波器
什么是过滤器?
对图像应用滤镜是修改图像的另一种方式。与点操作的不同之处在于滤波器使用一个以上的像素来产生新的像素值。例如,平滑滤波器,其通过其相邻像素值的平均值来替换像素值。滤波器分为两种, 线性滤波器和非线性滤波器 。
线性滤波器
L 线性滤波器是以线性方式(即,作为加权求和)操作支持区域中的像素值的滤波器。支持区域由 【滤波矩阵】 指定,由表示为 H(i,j) 。H 的大小称为“过滤区域”,过滤矩阵有自己的坐标系,I 是列索引,j 是行索引。它的中心是原点位置,它被称为“热点”。
Applying weight median filter to the image I, a hotspot location is at the orange shade (center of the filter matrix H)
应用滤镜
要对图像应用滤镜,请遵循以下步骤。
- 在图像上移动滤波器矩阵 I 和 H(0,0)必须跟随当前图像位置(u,v)
- 将每个滤波器系数 H(i,j)乘以相应的图像元素 I(u+i,v+j)
- 对上一步的所有结果进行平均,这就是当前位置 I(u,v)的结果
所有步骤都可以用下面的等式来描述
线性滤波器的类型
- 平滑滤镜 (这个滤镜只有正整数。)
- 箱式过滤器。 这个过滤器的所有成员都是一样的。
- 高斯滤波器。 过滤构件的重量取决于构件的位置。过滤器的中心承受最大的重量,随着与中心的距离增加而减少。
2。不同的过滤器
- 拉普拉斯或墨西哥帽状滤波器。 此过滤器的某些成员是负过滤器,它可以通过正成员和负成员的求和来计算。
3D structure, 2D structure and example of filter (a) Box filter (b) Gaussian filter and (c) Laplace filter
线性滤波器的特性
首先,我将介绍一个与线性滤波器相关的操作。这个操作叫做 “线性卷积”。 对于二维函数 I 和 H,卷积运算定义为等式
其中*是卷积运算。看看这个等式,你会发现这个操作提供了与线性滤波器相似的结果,该线性滤波器具有在水平和垂直轴上都反映的滤波器功能。卷积矩阵 H 可以称为 核 。
线性卷积的性质
- 交换性
- 线性
- 结合性
- 可分离性:核 H 可以表示为多个核的卷积,并且可以在二维核 x 和 y 中分离。
注意 :在线性特性中,在与核进行卷积之前,将标量值 b 加到图像 I 上,不等于将标量值 b 加到图像与核之间的卷积结果上。
非线性滤波器
使用平滑滤波器(一种线性滤波器)去除噪声,使图像结构、线条和边缘变得模糊。非线性滤波器用于解决这个问题,它以非线性方式工作。
非线性滤波器的类型
- 最小和最大滤波: 原始图像的运动区域 R 中的最小值和最大值分别是最小和最大滤波的结果。这些过滤器被定义为
The equation of minimum and maximum filter
- 中值滤波器: 结果的计算方法与最小值和最大值滤波器相同。移动区域 R 中所有值的中值是中值滤波的结果。这种滤波器通常用于消除图像中的椒盐噪声。该过滤器被定义为
下图显示了中值滤波器的工作原理
python 3 中过滤器的实现非常简单。对于盒子、高斯和中值滤波,可以使用cv2.boxFilter()、cv2.GaussianBlur()和cv2.medianBlur()。
这是这个项目的结果
Applying Box filter, Gaussian filter and Median filter to remove salt pepper noise in the image
在这篇文章中,你已经知道了滤镜的类型以及如何将它们应用到图像中。这有助于提高图像质量(例如,去除噪声)。下一次,我将利用过滤器来检测边缘和锐化图像。
现在你可以点击下面的链接进入下一章。:)
** [## 图像处理类(EGBE443) #5 —边缘和轮廓
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
medium.com](medium.com/@ptchaya.p/…)**
图像处理类别#5 —边缘和轮廓
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
这篇文章是关于基本的图像处理。如果你是这个领域的新手,你可以点击下面的链接阅读我的第一篇文章。:)
大家好!我叫皮查亚·西普克汉姆。我是玛希隆生物医学工程系四年级学生…
towardsdatascience.com](/image-processing-class-egbe443-0-1-image-aquisition-7e80cc89de84)
边缘和轮廓在人类视觉系统中起着重要的作用。边缘是由沿着特定方向的强度的局部变化引起的。这篇文章是关于边缘检测的各种方法。
轮廓
- 基于梯度边缘检测
- 边缘算子
- 二阶导数边缘检测
- 边缘锐化
基于梯度边缘检测
这种边缘检测方法从沿着一条图像线的强度变化或强度轮廓检测边缘。因为基本上,它是由一阶导数计算出来的。在图像中,一阶导数函数需要估计,可以表示为它在位置 u 处切线的斜率。
多维函数沿一个轴的导数称为**【偏导数】**。因此,图像函数 I(u,v)沿 u 轴和 v 轴的偏导数表现为以下函数。
该函数被称为**“梯度向量”**,梯度的大小可以通过下式计算
沿着 x 和 y 轴的一阶导数函数可以实现为具有系数矩阵的线性滤波器
边缘算子
很多边缘算子的基本原理都是来自于一阶导数函数。它们的不同之处仅在于过滤器中组件的组合方式。
- 普-索二氏手术
这些方法使用在 3 个相邻行和列上延伸的线性滤波器。对于 Prewitt 算子,沿 x 和 y 轴的滤波器 H 的形式为
和 Sobel 算子,滤波器 H 沿 x 和 y 轴的形式为
通过对 Prewitt 算子和 Sobel 算子进行适当的缩放,我们可以得到估计的局部梯度分量。
对图像应用梯度滤波器,给出 x 和 y 轴的两个梯度图像,Dx 和 d y
Dx 和 Dy 用于计算每个图像位置(u,v)的边缘奇异值 E 和方向。
总之,这些过滤器的过程如下所示
罗伯茨算子
这也是最简单的方法。两个尺寸为 2×2 的小滤波器用于边缘检测。
这些是这两个小过滤器的结果。
罗盘操作员
该方法不仅开发了单对滤波器,还开发了八个方向上 45 度方向的滤波器:
边缘强度和方向也需要被计算,但是它们以不同的方式被计算。边缘强度由来自八个滤波器的梯度图像的最大值来定义。
并且局部边缘方向被定义为
二阶导数边缘检测
这个想法就是这么简单。边缘位于一阶导数结果的最大值和最小值上。但是在二阶导数中,边缘位于过零点,如下图所示。
这种算子的一个常见例子是将高斯平滑滤波器和二阶导数(拉普拉斯)滤波器结合在一起的**“拉普拉斯-高斯”(LoG)** 算子。
边缘锐化
该任务通常用于解决扫描或缩放后图像锐度损失的问题。想法是放大图像分量的高频。这些过程显示了如何锐化图像的边缘。
- **用拉普拉斯滤波器锐化边缘(二阶导数):**通过减去二阶导数的某个分数 w 来锐化边缘。
- **反锐化掩模:**该方法包括两个主要步骤:
1.通过用内核 H(平滑滤波器)减去图像 I 的平滑版本来生成掩模 M。
2.将因子 a 加权到掩模 M 上,并添加到原始图像 I 上
我用 Python 3 实现了边缘检测,这是结果
这是我学到的边缘检测的基础,边缘检测是灵活的,它取决于你的应用。所以在下一章,可能是我图像处理的最后一章,我会描述 形态滤波器。再见:)
现在,下一章在这里!请点击下面的链接。
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
medium.com](medium.com/@ptchaya.p/…)
图像处理类#6 —形态滤波器
这篇文章是为了总结我在医学图像处理课上(EGBE443)学到的经验。
这篇文章是关于基本的图像处理。如果你是这个领域的新手,你可以点击下面的链接阅读我的第一篇文章。:)
大家好!我叫皮查亚·西普克汉姆。我是玛希隆生物医学工程系四年级学生…
towardsdatascience.com](/image-processing-class-egbe443-0-1-image-aquisition-7e80cc89de84)
在前一章中,我已经谈到了一种使用中值滤波器去除噪声的方法。中值滤波使图像结构发生了很大变化。下图显示了对二值图像应用中值滤波的结果。移除小结构、单线和点,并填充小尺寸孔。
所以在这一章中,我将介绍一个克服这个问题的想法。它被称为“”。
Shrink and grow process
形态滤波器
形态滤波器的思想是收缩和放任生长的过程。单词“收缩”意味着使用中值滤波器来圆化大的结构并移除小的结构,并且在生长过程中,剩余的结构以相同的量生长回来。
首先描述二值图像的形态学操作,并且将在下面的概述中讨论。
概述
- 二元滤波器的结构元素
- 膨胀和侵蚀
- 复合操作
结构化元素
在形态滤波器中,矩阵中的每个元素称为“结构元素”,而不是线性滤波器中的系数矩阵。结构化元素只包含值 0 和 1。并且过滤器的热点是深色遮光元件。
二进制图像被描述为多组二维坐标点。这叫做 “点集” Q,点集由所有前景像素的坐标对 p = (u,v)组成。点集的一些操作类似于其他图像中的操作。对二值图像求逆运算是补码运算,对两个二值图像求并运算。通过将向量 d 加到点 p,将二进制图像 I 移动某个坐标向量 d,或者将二进制图像 I 的反射乘以-1 到点 p。
膨胀和侵蚀
- 膨胀 是一个形态学操作符,它适用于我之前提到的生长过程。该算子的方程定义为
- 侵蚀 是一个形态学操作符,也适用于我之前提到的收缩过程,等式定义为
膨胀和侵蚀的特性
- 可交换的:仅在膨胀中
- 联想:仅在膨胀中
注意: 中的侵蚀与膨胀相反,不具有交换性。
此外,腐蚀和膨胀是 对决 ,因为前景的膨胀可以通过背景的腐蚀来完成,随后的结果是两种不同性质但工作相似
复合操作
在形态学过程中,膨胀和腐蚀共同作用于复合运算。有常用的方法来表示这两种操作的顺序,打开和关闭。开放表示侵蚀,随后以相反的方式膨胀和关闭。
Opening and Closing process respectively
在打开前景等于关闭背景的意义上,打开和关闭也是双重的。
形态滤波器也可以应用于灰度图像,但在不同的定义。它是最小和最大运算符的推广。我将在下面的大纲中描述。
轮廓
- 结构化元素
- 膨胀和侵蚀
- 打开和关闭
结构化元素
在灰度形态学中,结构元素被定义为实值 2D 函数,而不是点集
H 中的值可以是负值或零值。但与线性卷积不同,它使用零元素来计算结果。如果您不想在某个位置使用元素,您可以在该位置不放置元素。
膨胀和侵蚀
灰度形态学中膨胀和腐蚀的结果是由最大值和最小值运算贡献的。
对于膨胀,结果是 H 中的值的最大值加到当前子图像。
对于侵蚀,结果是差值的最小值。
这些操作会造成负值,所以我们需要对计算后的结果进行箝位。
Example of dilation in gray-scale morphology
打开和关闭
灰度形态学中的打开和关闭与二值形态学中的工作方式相同。区别只是膨胀和侵蚀中的操作符。
对于使用 OpenCV 模块在 Python 3 中的实现,可以使用函数cv2.erode(input,size)和cv2.dilate(input,size)
这是程序的结果,侵蚀和扩张,打开和关闭。
The result of erosion and dilation of the program.
The result of opening and closing from the program.
这是我关于图像处理的最后一篇文章。感谢您阅读并关注我的帖子。继续享受 图像处理 !我很快就回来,祝你好运。:)
路上的图像识别
当谷歌宣布他们开源其内部物体检测系统 Tensorflow 物体检测 API 时,我知道必须尝试一下。在图像中检测物体是一个长期的挑战,由于深度学习的一系列研究,近年来已经取得了巨大的进展。这是一种非常适合深度学习的任务:易于描述和直观掌握,但很难正式解决。
谷歌的 API 提供了五种最先进的 Tensorflow 模型,可以识别和定位图像中的多个对象。这些型号涵盖了从轻量级(用于在手机上实时工作)到重型(计算成本更高但更精确)的所有型号。他们还在 COCO 数据集上对每个模型进行了预训练,这样它们就可以检测出 90 种现成的常见物体类别。还包括一个 Jupyter 笔记本,演示如何使用他们预先训练好的模型。
我设法拍了一些南湾交通路口的照片。对于检测通过十字路口的机动车、骑自行车的人和行人,有几个有前途的应用:基于观察到的汽车数量的更智能的交通灯信号定时,通过提醒司机注意迎面而来的车辆来预防事故,以及识别经常发生交通堵塞的区域。
由于要在十字路口检测的对象属于 COCO 的常见类别,所以我能够使用预先训练的模型。这意味着我不必忍受收集带标签的数据集和旋转 GPU 时钟周期来训练的单调乏味。下面是(相当粒状)原始图像。
而这里是运行最精确模型后的输出,faster _ rcnn _ inception _ resnet _ v2 _ atrous _ coco。
Box colors and their classifications: {Light green: car, Purple: truck, Neon green: person, Pink: vase, White: motorcycle, Darker Green: traffic light}
结果给我留下了深刻的印象!它克服了几个障碍:低分辨率、重影、遮挡和缺乏颜色,但仍能识别每辆汽车、摩托车和骑摩托车的人。它还发现人行道上有一名行人。它确实犯了把树干归类为花瓶的错误(粉色方框)。
总而言之,Tensorflow 对象检测 API 是一个用于对象检测和定位的优秀系统。它对较差的图像质量很鲁棒,并且使用简单。
图像分割:Kaggle 体验
今天我在 Kaggle 上获得了我的第一枚金牌,参加了空中客车船舶探测挑战赛。我们的 3 人团队(奥列格·亚罗舍夫斯基、德米特里·达涅夫斯基和弗拉德·什米赫洛)在卫星图像上分割船只的任务中获得了 884 名中的第 4 名。之前,我们的团队在地震图像上分割盐层的类似比赛中获得了 3234 名中的第 30 名( TGS 盐识别挑战赛)。我决定这是一个分享我参加竞争性机器学习的经验的好机会。
重要的是要强调,虽然我们在这些比赛之前在计算机视觉和深度学习方面有一些经验,但我们从未做过任何与语义或实例分割相关的高级东西。为了取得好成绩,我们必须学习很多东西,并以非常快的速度工作。下面是分割问题的概述和我们解决方案的更详细的概要。
什么是图像分割?这是一项非常常见的计算机视觉任务,要求您为图像中的每个像素分配一些标签,描述这个特定像素是属于某个对象(例如船只)还是属于某个背景(例如水或地面)。有许多不同的技术可以解决图像分割问题,但在本文中,我想重点关注近年来利用的方法,尤其是基于深度学习的方法。
Photo taken from satellite and corresponding segmentation mask
这个想法是训练一个神经网络,在给定原始图像数据的情况下,给图像中的每个像素分配一个标签,特别适合这个问题的架构是 U-Net 。U-Net 是一种卷积神经网络,最初设计用于执行医学图像分割,但它在各种各样的任务中工作得很好,从分割显微镜图像上的细胞到检测卫星照片上的船只或房屋。
U-Net 由编码器和解码器网络组成。编码器网络负责构建从简单的特征(如边缘和形状)到复杂的特征(如船只、人脸、汽车等)的层次结构。解码器负责将细粒度的低级特征与粗粒度的高级特征合并,逐渐恢复位置信息,以实现精确的逐像素分割。
U-Net architecture (source: arxiv.org/abs/1505.04…)
你可以对默认的 U-Net 架构做很多调整,以提高它在特定情况下的性能。对于计算机视觉任务,使用迁移学习几乎总是一个好主意。你需要做的是将在不同任务上训练的网络参数用于你的问题。这是可行的,因为对于网络来说,当它已经有了关于边缘和形状的知识时,学习相关特征要比从头开始容易得多。这就是为什么我们使用 ImageNet 上预训练的 SE-ResNeXt-50 网络作为我们的编码器。至于解码器,我们从 AlbuNet 获得了灵感,它使用的架构与最初 U-Net 论文中描述的略有不同。
这将我们带到对默认 U-Net-ResNet 架构的第一个重要调整。默认情况下,为了减少计算成本,ResNet 的第一层(以及许多其他为图像分类设计的神经网络)应用 7×7 步距 2 卷积,有人可能会认为应用步距 2 卷积可能会丢失精确的逐像素分割所需的许多重要信息,经过一些简化,我们可以说,将步距 2 conv 应用于 256×256 图像类似于将步距 1 conv 应用于 128×128 图像,这意味着我们试图预测两倍于网络“看到”的图像大小的掩模。这对于在照片和其他任务中分割人的大多数情况是可以的,在这些情况下,我们主要处理大型对象,网络可以从上下文中恢复大部分信息,但在分割非常小的船只(20-30 个正像素)的情况下,这可能是至关重要的,因此我们在 ResNet 的第一层中从步幅 2 移动到步幅 1 卷积,并观察到分数的良好提升。缺点之一是,这种调整增加了巨大的计算开销,因为网络中的每个特征地图现在都是原来的两倍大。这大大减少了批量大小,降低了网络速度,但一个时期的训练时间仍然在足够的时间内,因为我们是在随机的 256 乘 256 作物上训练的,这将我们带到下一点。
为了降低计算成本,加快训练速度并增加批量大小,我们对随机的 256 乘 256 的作物进行了训练,这种方法的问题是,训练集中只有一小部分图像实际上至少有一些积极的标签,其中大多数只是空的,随机作物的情况甚至更糟,因为这些作物几乎总是根本没有船只。这导致了巨大的类别不平衡,这是图像分割中普遍面临的问题。
为什么这不好?这是不好的,因为为多数类计算的损失超过为少数类计算的损失,导致非常低的误差信号。有许多解决方案可以克服这个问题,这些解决方案在特定情况下有效,其中大多数是关于选择正确的损失函数(如焦点损失、骰子损失、平衡交叉熵)或重采样数据集以获得更好的类分布。
一个非常巧妙的技术被设计用来克服阶级不平衡,这个技术非常有效。这个想法是随机裁剪图像的一部分,这样至少有一些积极的像素出现在裁剪中,这大大提高了分数,在我看来,这是一个关键的设计决策,使我们比其他参与者更有优势。
在进行人工故障分析时,我们观察到两个问题:大船检测和对小物体(例如石油平台)的误报。我们认为假阳性的问题可能与智能作物逻辑有关,但没有时间来检查这是否是真的。
为了克服假阳性问题,我们决定训练一个额外的基于 CNN 的二元空/非空分类器。人们可能会认为 U-Net 擅长空/非空分类,但在实践中它容易犯分类错误。另一方面,专用分类器明确地最小化了错误分类率,并且由于它没有解码器,所以训练起来要快得多。如果我们考虑到数据集中有大约 80%的空图像,假阳性问题会变得更加严重。利用非空图像的过采样在所有可用图像上训练分类器,以克服类别不平衡。我们认为性能良好的二进制分类器对本次比赛至关重要,我们认为这是我们从公共排行榜的第 26 位跃升至私人排行榜第 4 位的主要原因之一。一个单独的分类模型也导致了更快的推断:我们没有用慢速 U-Net 模型预测所有 15k 图像,而是只预测了大约 3k,因为其余的已经被分类器作为空图像丢弃了。
大型船只的问题没有假阳性那么严重,但是我们仍然对我们的模型进行了一些修改,以更好地捕捉这些大型实例。也就是说,我们在 U-Net 模型的底部增加了一个额外的卷积层,由于计算成本增加,我们在开始时将其丢弃。这个简单的技巧增加了我们模型的感受域,使它们能够捕捉更多的全球背景。
同样重要的是要提到,这项任务是一种称为实例分割的图像分割。在实例分割中,您不仅必须标记图像中的每个像素,还必须为唯一的对象分隔分割遮罩。这意味着我们必须有一种方法来区分哪些像素属于一艘船,哪些属于另一艘船。我们使用了一种叫做分水岭的方法来将蒙版分成实例。
在本教程的第 2 部分,我将更多地关注我们的方法和我们尝试的东西的技术细节,我还将分享这次比赛的源代码,敬请期待!
在 Tensorflow 中使用各种自动编码器进行图像分割
GIF from this website
我想我需要练习表演分段,因此我发了这个帖子。我也想探索自动编码器的世界。下面是我想探究的案例。
情况 1)普通全卷积自动编码器 情况 2)多损耗自动编码器 情况 3)重复全卷积自动编码器 情况 4)全卷积 变分自动编码器
情况 1)普通全卷积自动编码器
蓝框 →卷积层 红框 →转置卷积层
现在,上述网络具有最简单的结构,其中输入是彩色图像,输出是分段的掩蔽图像。现在让我们看看这个网络的结果。
总的来说,网络在检测图像中的物体方面做得不错,正如上面测试图像的结果所示。它实际上做了一个很好的基础网络,下面是为结果创建的 gif。
左图 Gif →为一段时间内的训练图像生成的遮罩 右图 Gif →为一段时间内的测试图像生成的遮罩 右图 →训练期间的一段时间内的成本
情况 2)多损耗自动编码器
Image from this paper
这次我的灵感来自于论文“用于由粗到细的密集语义图像标注的门控反馈细化网络”,论文作者不仅引入了多损失函数,还引入了门控网络。在这里,我将只看到多重损失函数的影响。
**
对于具有多重损失函数的网络,看起来图像的某些部分比基本网络更清晰。这个网络做得很好,特别是粉红色花的形象。
左图 Gif →生成的训练图像随时间变化的蒙版 右图 Gif →生成的测试图像随时间变化的蒙版 右图 →训练期间的成本随时间变化
情况 3)重复全卷积自动编码器
**
蓝框 →卷积层 红框 →普通重复和卷积层
现在,这个网络的架构与之前的完全相同,但我只是想看看如果我们不使用转置卷积运算会发生什么。而只是天真地重复像素值两次,并执行卷积?
**
如上所述,当我们仅使用卷积运算并天真地重复像素来执行上采样时,生成的遮罩是位清晰和平滑的。但是,我们可以在生成的蒙版中观察到一些随机的黑点。
左图 Gif →为一段时间内的训练图像生成的遮罩 右图 Gif →为一段时间内的测试图像生成的遮罩 右图 →训练期间的一段时间内的成本
情况 4)全卷积 变分自动编码器
我从未见过任何用于分段目的的自动编码器的变化。(如果有人知道论文的名字请告诉我!)但我想使用它,下面是生成的面具。关于这个网络生成的掩码,我注意到的一件事是掩码中存在的噪声量,这可能是因为我们在训练期间从正态分布中抽取样本。
左图 Gif →为一段时间内的训练图像生成的遮罩 右图 Gif →为一段时间内的测试图像生成的遮罩 右图 →训练期间的一段时间内的成本
互动码
对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上复制一份。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!
要访问案例 a 的代码,请点击此处。 要访问案例 b 的代码,请点击此处。 要访问案例 c 的代码,请点击此处。 要访问案例 d 的代码,请点击此处。
最后的话
现在必须指出的是,所有这些模型都不能直接相互比较。超参数存在差异。但是我们仍然可以得到每个建筑的总体效果。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请点击这里查看我的网站。
同时,在我的推特这里关注我,并访问我的网站,或我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 pos t。
参考
- 图像调整:转换图像内容—浏览 v0.15.dev0 文档。(2018).Scikit-image.org。检索于 2018 年 7 月 9 日,来自http://sci kit-image . org/docs/dev/user _ guide/transforming _ image _ data . html
- 伊斯兰,m .,罗昌,m .,那霸,s .,布鲁斯,n .,,王,Y. (2018)。用于由粗到细的稠密语义图像标注的门控反馈细化网络。Arxiv.org。检索于 2018 年 7 月 9 日,来自arxiv.org/abs/1806.11…
- 直观地理解变分自动编码器-走向数据科学。(2018).走向数据科学。检索于 2018 年 7 月 9 日,来自https://towards data science . com/直觉-理解-变分-自动编码器-1bfe67eb5daf
- 图片|张量流。(2018).张量流。检索于 2018 年 7 月 9 日,来自www.tensorflow.org/api_guides/…
- tf.random_normal | TensorFlow。(2018).张量流。检索于 2018 年 7 月 9 日,来自www.tensorflow.org/api_docs/py…
使用自动编码器的图像相似性
计算机视觉项目中一个非常具有挑战性的任务是确定图像之间的相似性。像每个像素的平均差异这样的东西实际上只是测量图像之间颜色使用的差异,而不是图像的任何真正的语义特征。
自动编码器通过编码器和解码器网络工作。编码器获取输入图像,并通过一个或多个隐藏层对其进行映射,直到最终达到具有比原始图像低得多的维度的隐藏层表示,例如 2 或 5 个神经元。然后,解码器将低维层中神经元的输出映射回原始图像。原始图像和从编码器→解码器重建的图像之间的差异被称为重建损失,并用于训练网络。
这如何用于图像相似性?
我们可以获取两幅图像,将它们通过自动编码器,并检查低维表示中的激活,以确定图像之间的相似性。
当表现为 2 或 3 维时,可视化这些激活很容易完成,但是对于更高维,我们需要使用聚类技术进行可视化,例如 t-SNE。T-SNE 聚类创建一个较低维度的映射,然后在较高维度中保持空间距离。我们可以利用这一点得出自动编码特征空间的可视化,从而得出图像之间的视觉差异。
我们可以通过在编码器中添加卷积层和在解码器中添加去卷积层来增强图像自动编码器的功能。解卷积层可以被认为类似于 DCGAN (深度卷积生成对抗网络)中的生成器网络。
视觉相似性的应用
视觉相似性度量有许多有趣的应用,例如图像推荐和搜索。然而,一个非常有趣的应用是数据聚类和标记未标记数据。许多深度学习项目有大量未标记的数据,很难找出如何标记这些数据。基于自动编码器的聚类是解决这个问题的好方法。感谢阅读!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对深度学习和软件工程感兴趣。
使用 OpenCV 进行图像拼接
如你所知,Google photos 应用程序具有令人惊叹的自动功能,如视频制作、全景拼接、拼贴制作、根据照片中人的存在整理照片等等。我一直想知道为什么这些都是可能的。但是有一天,我觉得自己做全景拼接非常酷。
当我要做一个图像拼接的项目时,我感到非常兴奋。当我终于成功地建立了我自己的图像拼接器时,那是一个灵光一现的时刻:)。我在Python——我一直最喜欢的语言和使用 OpenCV 3.1.0 中做的。
尽管互联网上有很多这方面的资源,但今天我想和代码一起展示我的工作。下面的代码和解释都是为了把两张图片拼接在一起。
首先,让我们导入必要的模块。
import cv2
import numpy as np
import matplotlib.pyplot as plt
from random import randrange
正如我们所知,我们正在拼接 2 幅图像,让我们来阅读它们。
left.jpg and right.jpg
img_ = cv2.imread(‘right.JPG’)
img1 = cv2.cvtColor(img_,cv2.COLOR_BGR2GRAY)img = cv2.imread(‘left.JPG’)
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.cvtColor 将输入的 RGB 图像转换成灰度形式。
对于图像拼接,我们遵循以下主要步骤:
- 计算两幅图像的 sift 关键点和描述符。
- 计算一幅图像中的每个描述符和另一幅图像中的每个描述符之间的距离。
- 为图像的每个描述符选择前“m”个匹配项。
- 运行 RANSAC 来估计单应性
- 缝合时要对齐的经线
- 现在把它们缝在一起
非常感谢…,
首先,我们必须找出两幅图像中匹配的特征。这些最匹配的特征充当缝合的基础。我们提取两幅图像的关键点和 sift 描述符,如下所示:
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
kp1 和 kp2 是关键点,des1 和 des2 是相应图像的描述符。
现在,在一幅图像中获得的描述符也将在该图像中被识别。我们的做法如下:
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
BFMatcher() 匹配更相似的特征。当我们设置参数 k=2 时,我们要求 knnMatcher 为每个描述符给出 2 个最佳匹配。
“匹配”是一个列表列表,其中每个子列表由“k”个对象组成。为了理解这一点,并更好地跟踪接下来的部分,请通过这个。
通常在图像中,这些特征很有可能存在于图像的许多地方。这可能会误导我们在实验中使用琐碎的特征。因此,我们从所有匹配中筛选出最佳匹配。因此,我们使用上面获得的前 2 个匹配来应用比率测试。如果下面定义的比率明显大于规定的比率,我们认为匹配。
# Apply ratio test
good = []
for m in matches:
if m[0].distance < 0.5*m[1].distance:
good.append(m)
matches = np.asarray(good)
现在是对齐图像的时候了。如您所知,执行转换需要单应矩阵,并且单应矩阵需要至少 4 个匹配,我们执行以下操作。点击了解更多。
if len(matches[:,0]) >= 4:
src = np.float32([ kp1[m.queryIdx].pt for m in matches[:,0] ]).reshape(-1,1,2)
dst = np.float32([ kp2[m.trainIdx].pt for m in matches[:,0] ]).reshape(-1,1,2)H, masked = cv2.findHomography(src, dst, cv2.RANSAC, 5.0)
#print H
else:
raise AssertionError(“Can’t find enough keypoints.”)
最后是最后一部分,图像的拼接。既然我们已经找到了变换的单应性,现在我们可以继续将它们扭曲并缝合在一起:
dst = cv2.warpPerspective(img_,H,(img.shape[1] + img_.shape[1], img.shape[0]))
plt.subplot(122),plt.imshow(dst),plt.title(‘Warped Image’)
plt.show()
plt.figure()
dst[0:img.shape[0], 0:img.shape[1]] = img
cv2.imwrite(‘output.jpg’,dst)
plt.imshow(dst)
plt.show()
我们使用 matplotlib 绘制扭曲的图像,以便很好地可视化扭曲。
结果如下:
TensorFlow 1.3 中使用 Keras 的图像标记
我们已经了解了如何通过 TensorFlow 使用 Scikit-learn,并大致讨论了 TensorFlow 的高级 API。TensorFlow 直接支持的另一个流行的高级 API 是 Keras。
TensorFlow 1.3 的发布让美国用户可以直接在 TensorFlow 中使用 Keras。 Keras 是一个高级 API 规范,由Fran ois Chollet积极构建,主要是为了降低开发机器学习模型的门槛,并提供一个单一的 API 来访问许多底层的机器学习工具包。Keras 的流行意味着许多模型的框架(代码+预处理)都是现成的,并且由社区很好地维护和改进。
Keras — supported ML toolkits [TensorFlow, Theano, MXNet and Cognitive Toolkit]
为什么对 TensorFlow 开发者很重要?
就提交、开发者和更新的数量而言,TensorFlow 是迄今为止开发最活跃的 ML 工具包。然而,随着的积极发展,API 也发生了变化。另一方面,Keras 为底层的 ML 工具包提供了更高层次的抽象。因此,原型快速 ML 框架的可行性是不可知的变化酝酿之下。
将 Keras 放在 TensorFlow 中还可以避免安装其他库。如果您以前使用过 Keras,在您的机器上安装 Keras 也意味着安装 Theano(直到最近才支持两个框架)。当只使用 TensorFlow 和 Keras 时,这是一个不必要的 Theano 安装,当您想要部署使用 Keras 开发的 ML 模型时,这也是一个需要关注的原因。
在过去的两篇博客中,我们一直在讨论如何从 Scikit-learn 迁移到 TensorFlow,以及如何将 TensorFlow 和 Scikit-learn 库结合起来开发我们的 ML 模型。将 Keras 集成到 TensorFlow 中带来了一个类似的特性,只是除了 TensorFlow 之外,不需要安装其他库。
为什么对 Keras 开发者很重要?
我们不得不承认,TensorFlow 正在成为集成新的 ML 函数和库的领导者。因此,在训练大型深度网络时,Keras 开发人员将极大地受益于 TensorFlow 的分布式训练。
Keras 开发者可以使用的另一个有趣的功能是 TensorFlow 的 TensorBoard 。TensorBoard 不仅提供了培训和评估的可视化,也是可视化嵌入的简洁实现。
Keras 开发人员还可以访问 TensorFlow Serving 和 Google Cloud ML ,它们允许部署 ML 模型来对生产环境中的新数据进行推理。
用 5 行深 CNN 标记图像
深度卷积神经网络已经证明在图像分类方面优于人类。虽然训练这种深度模型所需的 GPU 和 CPU 资源是昂贵的,但推理在计算上并不昂贵。因此,我们看看如何利用不同的艺术级图像分类模型,在少于五行代码中对图像进行推理。
并且,为了使这样的推论成为可能,我们使用 Keras 来使这成为可能。以下几行显示了我们如何在 TensorFlow 1.2 中使用 Keras 实现这一点:
img = image.load_img('niagara.jpeg', target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
正如所承诺的,我们处理图像并在 5 行代码中推断其内容(忽略导入,咄!)。在上面的代码中我们还没有定义的一件事是模型。有两个非常好的深度 CNN 模型,其性能优于人类。我们对用于执行分类的残差网络和 Inception v3 CNN 模型特别感兴趣。这两个模型都是深度网络,需要数周时间在 ImageNet 数据上进行训练。然而,我们将简单地站在巨人的肩膀上,下载这些模型并对我们的图像进行推理。我们如下初始化剩余网络(50 层深的 CNN ):
model = ResNet50(weights='imagenet')
我们可以类似地使用一个 Inception v3 模型来为我们的预测加载权重。我们如下初始化 Inception v3 模型:
model = InceptionV3(weights='imagenet')
我们对之前加载的图像进行推断,以获得我们预测的类别和概率,如下所示:
preds = model.predict(x)
我们可以如下解码来自模型的图像预测:
print('Predicted:', decode_predictions(preds, top=5)[0])
从图像加载到执行预测的端到端框架的笔记本可以在我的 GitHub 存储库中找到。《盗梦空间》v3 T1 和《T2》残网 T3 笔记本上市了。在我的 GitHub 上的 Keras 资源库中有一些更有趣的脚本,供那些想使用 Keras 探索其他 TensorFlow 应用程序的人使用。
在 TensorFlow 最近的更新中,使用最先进的深度 CNN 标记图像变得非常容易。Keras 作为高级 API,肯定降低了进入 ML 的门槛。查看我的 Keras ,了解更多使用 Keras 和 TensorFlow 构建的应用程序。
让我知道你想要建造什么。请在下一篇博文中留下您希望我讨论的内容!干杯!
公共/私人区块链中的不变性—第 1 部分
Photo by Donnie Rosie on Unsplash
不变性是区块链实现的核心价值。在公开和私下的区块链谈论这个问题的技术细节之前,退一步想想它意味着什么以及它为什么重要可能是有益的。
不变性是什么意思?
尽可能字面上的不变性是指某件事不能改变。好吧,这很简单,对吧?。有点…我们首先需要定义什么是真正的改变。
想象一下,现在你有一辆白色的汽车。现在你决定你想要一个红色的。你至少有两个选择:
- 把你现在的车涂成红色。
- 卖掉你现在的车,买一辆红色的。
前者,你可以说你的车变了,因为颜色是你车的一个属性。因为这个属性已经改变了,所以你可以放心地说你的车已经改变了。后者,你不能真的说你的车自从你买了另一辆车后就变了。
那么这有什么意义呢?。首先,在分析对象的可变性之前,我们必须弄清楚是什么定义了对象的身份。将这个想法发挥到极致,如果一个对象的身份被定义为它的所有属性,那么改变其中任何一个属性都意味着我们有了另一个对象,因此原始对象没有改变。
还有一个关于如何定义身份的哲学讨论。当然,这不是这篇文章的目的,但是如果你感兴趣的话,你可以看看太阳的船。
TL;DR:在考虑一个对象是否已经改变之前,我们应该首先对它的身份有一个清晰的定义。
为什么不变性很重要?
让我们考虑以下情况。你是一个房屋所有者,你居住的国家决定房屋所有权将由分类账中的记录来定义。
考虑以下索赔:
我是房子的主人,所以账本里有记录支持这个事实。
这种说法并不准确。以下说法是这个国家房屋所有权的正确表述:
账本上有记录,所以我是房主。
现在,这听起来很不一样。由于拥有自己的房子需要付出很多努力,你可能会开始考虑问以下问题:
- 如果账本被销毁了呢?
- 如果我房子的相关记录被删除了怎么办?
- 如果不知何故记录被更改,另一个人拥有我的房子怎么办?
- 账本查不到怎么办?
这些都是合理的问题,因为房子是非常高价值的资产。如果我们谈论的不是房子,而是糖果,你不介意在这些方面冒险。
前面的问题分析了分类账可能面临的不同风险,特别是,第二个问题听起来应该是不可改变的。第三个不是关于不变性,而是关于授权。
也许不可变这个词现在开始变得有意义了。但是,等等,房地产业务就是转让所有权,所以我们有突变。
现实在变,但历史不会变。
这才是重点。一个新的转让所有权的交易并不能改变一个事实,那就是在那之前的某个时候,我是那栋房子的主人。
如果我们使用分类账中的信息做出重要决策,我们希望这些信息是不可变的;我们需要建立因果关系,并保持它的永久性。更准确地说,把时间看作一个维度,考虑到时间是单行道,我们应该得出这样的结论:历史应该是不可改变的。
我们仍然没有讨论账本是否是数字的。它可以是基于纸张的分类账、关系数据库、区块链等;但是这是一个实现细节,无论如何都不会改变我们例子中不变性的重要性。不变性是一个设计决策。
在区块链的上下文中,不变性是什么意思?
作为复习,请记住以下几点:
- 区块链是分布式总账。
- 分布式部分指的是很多参与节点,特别是有一个账本的副本。
- 区块链共识算法负责所有节点最终汇聚到同一个账本。
- 区块链由有序的块组成,其中每个块包含前一个块的散列(这就是它被称为区块链的原因;块用散列来链接)。
- 区块链是只附加的数据结构。
区块链 as 分类帐实施用于对事务处理历史进行建模。一个交易发生如果是历史的一部分。正如我们前面提到的,历史是不变的,因此区块链也应该是不变的。
上面列表的最后一点提到区块链是只附加的数据结构;这是必不可少的,因为每个生成的块不能被改变以保持不变性。
如果我们有相同的事务有序历史记录,但在块中分组不同(例如,我们使用两倍大小的块),会怎么样?我们可以问,对于同一段历史,我们是否有多个区块链。这是一个更微妙的讨论,因为我们有两个相同历史的表述。在比特币的情况下,当生成一个块时,生成交易由矿工包含,其中包含奖励,如果相同的有序交易被不同地分组在块中,则历史会不同。
在区块链,打破不变性指的是说服大多数节点改变现有块的难度。如果这是可能的,我们将改变历史导致可能无法接受的后果。
在第 2 部分中,我将比较两种解决方案中这一设计目标的实现差异:
- 使用工作证明(PoW)共识机制的公共区块链,例如比特币。
- 一个私人的区块链,特别是 Hyperledger 面料。
我认为两者之间的对比非常有趣,因为链接块的核心思想在不变性中有非常不同的重要性。