伯禹公益AI《动手学深度学习PyTorch版》Task 09 学习笔记
伯禹公益AI《动手学深度学习PyTorch版》Task 09 学习笔记
Task 09:目标检测基础;图像风格迁移;图像分类案例1
微信昵称:WarmIce
目标检测基础
无言以对,哪个臭Sb写的文档,来,你给我念一遍:
假设输入图像高为 ,宽为。我们分别以图像的每个像素为中心生成不同形状的锚框。设大小为且宽高比为,那么锚框的宽和高将分别为和。
你特么确定锚框的宽和高是这个?我来告诉你,根据你的代码,锚框的宽和高分别是和。
而且这样才讲得通,宁要是不想写文档的话,求宁别误人子弟行吗?
在每个像素处构造不同大小与宽高比的锚框,这样就能生成可多了的锚框。将锚框变量y
的形状变为(图像高,图像宽,以相同像素为中心的锚框个数,4)后,我们就可以通过指定像素位置来获取所有以该像素为中心的锚框了。
后面又讲了个吓人的名词,什么Jaccard系数,丫的就是交并比,整的那么玄乎。
下面的知识点还是比较重要的,主要就是讲解了一下,我们现在生成了这么多的锚框,里面哪些是有效的,是需要我们回归出来的,另外,我预设的锚框和实际锚框之间肯定有偏移,这个偏移量该怎么计算,算出来又该怎么处理来让回归变得容易一些。
在训练集中,我们将每个锚框视为一个训练样本。为了训练目标检测模型,我们需要为每个锚框标注两类标签:一是锚框所含目标的类别,简称类别;二是真实边界框相对锚框的偏移量,简称偏移量(offset)。在目标检测时,我们首先生成多个锚框,然后为每个锚框预测类别以及偏移量,接着根据预测的偏移量调整锚框位置从而得到预测边界框,最后筛选需要输出的预测边界框。
我们知道,在目标检测的训练集中,每个图像已标注了真实边界框的位置以及所含目标的类别。在生成锚框之后,我们主要依据与锚框相似的真实边界框的位置和类别信息为锚框标注。那么,该如何为锚框分配与其相似的真实边界框呢?
假设图像中锚框分别为,真实边界框分别为,且。定义矩阵,其中第行第列的元素为锚框与真实边界框的交并比。
首先,我们找出矩阵中最大元素,并将该元素的行索引与列索引分别记为。我们为锚框分配真实边界框。显然,锚框和真实边界框在所有的“锚框—真实边界框”的配对中相似度最高。接下来,将矩阵中第行和第列上的所有元素丢弃。找出矩阵中剩余的最大元素,并将该元素的行索引与列索引分别记为。我们为锚框分配真实边界框,再将矩阵中第行和第列上的所有元素丢弃。此时矩阵中已有两行两列的元素被丢弃。
依此类推,直到矩阵中所有列元素全部被丢弃。这个时候,我们已为个锚框各分配了一个真实边界框。
接下来,我们只遍历剩余的个锚框:给定其中的锚框,根据矩阵的第行找到与交并比最大的真实边界框,且只有当该交并比大于预先设定的阈值时,才为锚框分配真实边界框。如图9.3(左)所示,假设矩阵中最大值为,我们将为锚框分配真实边界框。然后,丢弃矩阵中第2行和第3列的所有元素,找出剩余阴影部分的最大元素,为锚框分配真实边界框。接着如图9.3(中)所示,丢弃矩阵中第7行和第1列的所有元素,找出剩余阴影部分的最大元素,为锚框分配真实边界框。最后如图9.3(右)所示,丢弃矩阵中第5行和第4列的所有元素,找出剩余阴影部分的最大元素,为锚框分配真实边界框。之后,我们只需遍历除去的剩余锚框,并根据阈值判断是否为剩余锚框分配真实边界框。
现在我们可以标注锚框的类别和偏移量了。如果一个锚框被分配了真实边界框,将锚框的类别设为的类别,并根据和的中心坐标的相对位置以及两个框的相对大小为锚框标注偏移量。由于数据集中各个框的位置和大小各异,因此这些相对位置和相对大小通常需要一些特殊变换,才能使偏移量的分布更均匀从而更容易拟合。设锚框及其被分配的真实边界框的中心坐标分别为和,和的宽分别为和,高分别为和,一个常用的技巧是将的偏移量标注为
其中常数的默认值为。如果一个锚框没有被分配真实边界框,我们只需将该锚框的类别设为背景。类别为背景的锚框通常被称为负类锚框,其余则被称为正类锚框。
以上这一段写得是没有问题的,可喜可贺。后面就是拉取一个batch数据的时候如何操作,对背景类别生成mask等,无需多言。
接下来讲了对于网络的输出如何处理的问题。也就是我们经常提到的NMS(非极大值机制)。
在模型预测阶段,我们先为图像生成多个锚框,并为这些锚框一一预测类别和偏移量。随后,我们根据锚框及其预测偏移量得到预测边界框。当锚框数量较多时,同一个目标上可能会输出较多相似的预测边界框。为了使结果更加简洁,我们可以移除相似的预测边界框。常用的方法叫作非极大值抑制(non-maximum suppression,NMS)。
我们来描述一下非极大值抑制的工作原理。对于一个预测边界框,模型会计算各个类别的预测概率。设其中最大的预测概率为,该概率所对应的类别即的预测类别。我们也将称为预测边界框的置信度。在同一图像上,我们将预测类别非背景的预测边界框按置信度从高到低排序,得到列表。从中选取置信度最高的预测边界框作为基准,将所有与的交并比大于某阈值的非基准预测边界框从中移除。这里的阈值是预先设定的超参数。此时,保留了置信度最高的预测边界框并移除了与其相似的其他预测边界框。
接下来,从中选取置信度第二高的预测边界框作为基准,将所有与的交并比大于某阈值的非基准预测边界框从中移除。重复这一过程,直到中所有的预测边界框都曾作为基准。此时中任意一对预测边界框的交并比都小于阈值。最终,输出列表中的所有预测边界框。
这个方法其实挺无脑的,预测出来的框框,每个框取其得到的分类结果中概率最大的为其预测分类,把所有的框框按照预测分类的置信度排序,以其为标准,删掉和它交并比大于某一阈值的框框。大于说明什么,说明有的框跟它靠的近,但是你虽然靠的近,可你的预测分类的置信度没我高啊,所以,删掉。
这个肯定有问题,所以也有论文想办法解决。但是这是个本质上极其丑陋的方法。
最后提了一下多尺度目标检测,其实前面说的方法一看就很暴力,对于每个像素都生成预设锚框实在有点过犹不及的感觉,因此,就有了多尺度检测的方法,最典型的,比如YOLO,对于不同尺度的物体,划分了不同大小的grid,为不同尺度的grid分别预设了不同长宽比的锚框。
图像风格迁移
大开眼界!
在我没有看这个讲解视频之前,我觉得,卧槽,这个风格迁移贼NB了,肯定很难。在我看了10分钟视频的时候,我心里想,害,什么破逼玩意儿,就这?在我看完视频的时候,我震惊了,尼玛还能这样???
我主要开了三个眼界。
第一,风格迁移需要内容和样式两个信息,这两个信息怎么来,从哪儿来。
深度卷积神经网络凭借多个层逐级抽取图像的特征。我们可以选择其中某些层的输出作为内容特征或样式特征。以下图为例,这里选取的预训练的神经网络含有3个卷积层,其中第二层输出图像的内容特征,而第一层和第三层的输出被作为图像的样式特征。接下来,我们通过正向传播(实线箭头方向)计算样式迁移的损失函数,并通过反向传播(虚线箭头方向)迭代模型参数,即不断更新合成图像。样式迁移常用的损失函数由3部分组成:内容损失(content loss)使合成图像与内容图像在内容特征上接近,样式损失(style loss)令合成图像与样式图像在样式特征上接近,而总变差损失(total variation loss)则有助于减少合成图像中的噪点。最后,当模型训练结束时,我们输出样式迁移的模型参数,即得到最终的合成图像。
可见,内容信息与样式信息都是从一个预训练好的模型中提取的,提取的时候有讲究,内容信息稍微远一点、深一点,样式信息稍微多一点、局部和全局的都来一些。
第二,干他娘的,我知道这一点的时候人都傻了,风格迁移网络的参数竟然是图像本身。而且,只有图像本身。
换句话说,提取特征信息的预训练网络你动都不用动,锁死即可。上面这些加粗的字怎么理解呢。你就这样想,网络的输入是一个nn.Parameter(),那么它就是可以被更新的,在经过后面的卷积运算后,得到输出,我们计算损失,损失回传的时候,梯度信息一样会影响到这个输入(因为它本身就是权重)。这样就等于更新了输入,其实就是我们所要的合成图像。
第三,损失的计算。内容特征的损失就是均方差,值得一说的是样式损失和总变差损失。
样式损失也一样通过平方误差函数衡量合成图像与样式图像在样式上的差异。为了表达样式层输出的样式,我们先通过
extract_features
函数计算样式层的输出。假设该输出的样本数为1,通道数为,高和宽分别为和,我们可以把输出变换成行列的矩阵。矩阵可以看作是由个长度为的向量组成的。其中向量代表了通道上的样式特征。这些向量的格拉姆矩阵(Gram matrix)中行列的元素即向量与的内积,它表达了通道和通道上样式特征的相关性。我们用这样的格拉姆矩阵表达样式层输出的样式。需要注意的是,当的值较大时,格拉姆矩阵中的元素容易出现较大的值。此外,格拉姆矩阵的高和宽皆为通道数。为了让样式损失不受这些值的大小影响,下面定义的gram
函数将格拉姆矩阵除以了矩阵中元素的个数,即。
有时候,我们学到的合成图像里面有大量高频噪点,即有特别亮或者特别暗的颗粒像素。一种常用的降噪方法是总变差降噪(total variation denoising)。假设表示坐标为的像素值,降低总变差损失
能够尽可能使邻近的像素值相似。
图像分类案例1
比较简单,都是前面学习过的内容,不多赘述了。
以上。