resnet过拟合_重读经典:完全解析特征学习大杀器ResNet

公众号关注 “ML-CVer”

设为 “星标”,DLCV消息即可送达!

bcb68257d7a815da6833bcc780f6bc19.png

61f7c4adb1e5c05e0da547883523576f.png

作者丨刘昕宸@知乎来源丨https://zhuanlan.zhihu.com/p/268308900编辑丨极市平台

导读

 

通过堆叠神经网络层数(增加深度)可以非常有效地增强表征,提升特征学习效果,但是会出现深层网络的性能退化问题,ResNet的出现能够解决这个问题。本文用论文解读的方式展现了ResNet的实现方式、分类、目标检测等任务上相比SOTA更好的效果。

论文标题:Deep Residual Learning for Image Recognition

722ac0f60b8138e4838a473d723b48bf.png
32b53a59ffe50164fb69535ddd6f495a.png

1 motivation

通过总结前人的经验,我们常会得出这样的结论:通过堆叠神经网络层数(增加深度)可以非常有效地增强表征,提升特征学习效果。为什么深度的网络表征效果会好?
深度学习很不好解释,大概的解释可以是:网络的不同层可以提取不同抽象层次的特征,越深的层提取的特征越抽象。因此深度网络可以整合low-medium-high各种层次的特征,增强网络表征能力。那好,我们就直接增加网络深度吧!但是事情好像并没有那么简单!梯度优化问题:我们不禁发问:Is learning better networks as easy as stacking more layers?首先,深度网络优化是比较困难的,比如会出现梯度爆炸/梯度消失等问题。不过,这个问题已经被normalized initialization和batch normalization等措施解决得差不多了。退化问题:好,那就直接上deeper network吧!但是新问题又来了:deeper network收敛是收敛了,却出现了效果上的degradationdeeper network准确率饱和后,很快就退化了为什么会这样呢?网络更深了,参数更多了,应该拟合能力更强了才对啊!噢,一定是过拟合了。但似乎也不是过拟合的问题:
461c90eb47c02bf9e0387d44b924f299.png
因为56-layer网络(红线)的training error(左图)也比20-layer网络(黄线)要高,这就应该不是过拟合了啊!那么究竟是什么原因导致了deeper network degradation问题呢?现在,我们换一种思路来构建deeper network:the added layers are identity mapping, and the other layers are copied from the learned shallower model.(在原始的浅层网络基础上增加的层视为是identity mapping)也就是假设浅层网络已经可以得到一个不错的结果了,那我接下来新增加的层啥也不干,只是拟合一个identity mapping,输出就拟合输入,这样总可以吧。这样的话,我们觉得:这样构建的深层网络至少不应该比它对应的浅层training error要高。对吧。但是实验又无情地表明:这样却又不能得到(与浅层网络)一样好的结果,甚至还会比它差!看来,深度网络的优化并不容易的!总结一下:直觉上深度网络应该会有更好的表征能力,但是事实却是深度网络结果会变差,由此我们认为深度网络的优化部分出了问题,深度网络的参数空间变得更复杂提升了优化的难度。那么,ResNet来了。我们就想啊,与其直接拟合一个desired underlying mapping 307d8e88-ba36-eb11-8da9-e4434bdf6706.svg,不如让网络尝试拟合一个residual mapping 347d8e88-ba36-eb11-8da9-e4434bdf6706.svg。也就是:367d8e88-ba36-eb11-8da9-e4434bdf6706.svg原先的映射 307d8e88-ba36-eb11-8da9-e4434bdf6706.svg,被转换为了 387d8e88-ba36-eb11-8da9-e4434bdf6706.svg我们在这里假设优化残差映射(residual mapping) 347d8e88-ba36-eb11-8da9-e4434bdf6706.svg是比优化原映射 307d8e88-ba36-eb11-8da9-e4434bdf6706.svg要容易的。
比如如果现在恒等映射(identity mapping)是最优的,那么似乎通过堆叠一些非线性层的网络将残差映射为0,从而拟合这个恒等映射,最种做法是更容易的。3c3c735d257e35dc9ed9082574c0928d.png387d8e88-ba36-eb11-8da9-e4434bdf6706.svg可以通过如上图所示的短路连接(shortcut connection)结构来实现。shortcut就是设计的可以skip几层的结构,在ResNet中就是起到了相当于一个最最简单的identity mapping,其输出被加到了stacked layers的输出上。这样做既没有增加新的参数,也没有增加计算复杂性。ResNet的具体结构,后面会详细介绍。接下来,本文在ImageNet和CIFAR-10等数据集上做实验,主要是想验证2个问题:
  1. deep residual nets比它对应版本的plain nets更好优化,training error更低。

  2. deep residual nets能够从更深的网络中获得更好的表征,从而提升分类效果。

2 solution

ResNet想做什么?learning residual functions with reference to the layer inputs, instead of learning unreferenced functions.理解不了没关系,接着往下看。

2.1 Residual Learning

前提:如果假设多个非线性层能够渐近一个复杂的函数,那么多个非线性层也一定可以渐近这个残差函数。令 307d8e88-ba36-eb11-8da9-e4434bdf6706.svg表示目标拟合函数。所以与其考虑拟合 307d8e88-ba36-eb11-8da9-e4434bdf6706.svg,不如考虑拟合其对应的残差函数 487d8e88-ba36-eb11-8da9-e4434bdf6706.svg.这两种拟合难度可能是不同的。回到上面的讨论,如果被增加层能够被构建成identity mapping,那么深层网络的性能至少不应该比其对应的浅层版本要差。这个表明:网络是在使用多层非线性网络趋近identity mapping做优化这里出了问题。残差学习的这种方式,使得“如果identity mapping是最优的,网络的优化器直接将残差学习为0”就可以了,这样做是比较简单的。但其实在真实情况下,identity mapping不一定是最优的映射啊!原文说这种设计仍有意义,这种设计help to precondition the problem.也就是如果optimal function更接近identity mapping的话,优化器应该能够比较容易找到残差,而不是重新学习一个新的。
8811c14d7570e1add426f53b369d3c8f.png
后面实验也表明了:残差网络各层输出的标准差是比较低的(如上图,后面会解释),这也验证了在identity mapping的基础上学习残差,确实是会更容易(identity mappings provide reasonable preconditioning.).这里解释得还是比较含糊,但总结来说就是作者想解释,训练学习残差会有效降低学习的难度,可能据此来解决深层网络的性能退化问题。

2.2 Identity Mapping by Shortcuts

3c3c735d257e35dc9ed9082574c0928d.png再回顾一下这个著名的残差块图片:identity mapping实现得非常之简单,直接就用了个shortcut形式化就是:4d7d8e88-ba36-eb11-8da9-e4434bdf6706.svg517d8e88-ba36-eb11-8da9-e4434bdf6706.svg表示residual mapping,比如上图,实际上就是2层网络,也就是 547d8e88-ba36-eb11-8da9-e4434bdf6706.svg然后直接将 567d8e88-ba36-eb11-8da9-e4434bdf6706.svg与 587d8e88-ba36-eb11-8da9-e4434bdf6706.svgelement-wise相加。最后,给 5c7d8e88-ba36-eb11-8da9-e4434bdf6706.svg套一个激活函数 5e7d8e88-ba36-eb11-8da9-e4434bdf6706.svg.这么设计(shortcut)有个巨大的好处,就是没有引入任何新的参数,也没有增加计算复杂度。下面还有2个小问题:问题1:关于 587d8e88-ba36-eb11-8da9-e4434bdf6706.svg因为 657d8e88-ba36-eb11-8da9-e4434bdf6706.svg是element-wise相加,那么如果 567d8e88-ba36-eb11-8da9-e4434bdf6706.svg和 587d8e88-ba36-eb11-8da9-e4434bdf6706.svg维度不一样怎么办?方案一:直接对 587d8e88-ba36-eb11-8da9-e4434bdf6706.svg补0.方案二:增加一个网络层(参数为 707d8e88-ba36-eb11-8da9-e4434bdf6706.svg),改变 587d8e88-ba36-eb11-8da9-e4434bdf6706.svg的维度。即:747d8e88-ba36-eb11-8da9-e4434bdf6706.svg事实上,每个shortcut我们都可以加一个映射层 707d8e88-ba36-eb11-8da9-e4434bdf6706.svg(实现起来可以就是个感知机)。不需要做维度转化时, 707d8e88-ba36-eb11-8da9-e4434bdf6706.svg就是个方阵。但是后面实验表明,直接shortcut就已经足够好了,不需要再加那么多参数浪费计算资源。问题2:关于 567d8e88-ba36-eb11-8da9-e4434bdf6706.svg567d8e88-ba36-eb11-8da9-e4434bdf6706.svg的结构应该是什么样的呢?567d8e88-ba36-eb11-8da9-e4434bdf6706.svg可以是2层或者3层,也可以是更多;但是不要是1层,效果会不好。最后,shortcut设计不仅针对全连接网络,卷积网络当然也是没问题的!

2.3 网络架构

9a8fc63579ec64fc93baaf7f050cd62a.png
受VGGNet(左边)启发,设计了34层的plain network(中间),以及其对应的residual network版本(右边)。注意:中间plain network和右边residual network层数一致,网络参数也可以设计得完全一样(element-wise相加维度不match时直接补0就不会增加任何learnable parameters)。34-layer plain network设计原则(遵循VGGNet):
  1. for the same output feature map size, the layers have the same number of filters

  2. if the feature map size is halved, the number of filters is doubled so as to preserve the time complexity per layer

3 dataset and experiments

3.1 ImageNet on Classification3.1.1 与plain network的对比实验这个实验是核心,为了说明residual network能够非常完美地解决“深度增加带来的degradation”问题!!!
39bc20d31b6b163cc25b9bbc638e58b6.png
左边是plain network,右边是ResNet;细线是train error,加粗线是val errorPlain network会出现网络的层数增加,train error和val error都会升高什么原因呢???
首先排除过拟合,因为train error也会升高
其次排除梯度消失,网络中使用了batch normalization,并且作者也做实验验证了梯度的存在
事实上,34-layers plain network也是可以实现比较好的准确率的,这说明网络在一定程度上也是work了的。
作者猜测:We conjecture that the deep plain nets may have exponentially low convergence rates. 层数的提升会在一定程度上指数级别影响收敛速度。下面是Residual Network与plain network的量化对比:34eebf5eb98986fe1add0266588d0a6c.png观察上面两张图,我们可以得出结论:
  1. 而ResNet却真正实现了网络层数增加,train error和val error都降低了,证明了网络深度确实可以帮助提升网络的性能。degradation problem在一定程度上得到了解决。

  2. 相对于plain 34-layers,ResNet 34-layers的top-1 error rate也降低了3.5%。resnet实现了在没有增加任何参数的情况下,获得了更低error rate,网络更加高效。

  3. 从plain/residual 18-layers的比较来看,两者的error rate差不多,但是ResNet却能够收敛得更快。

总结来说就是,ResNet在不增加任何参数的情况下,仅使用shortcuts and zero-padding for matching dimensions结构,就实现了:解决了degradation problem,更高的准确率,更快的收敛速度简直太强了!!!

3.1.2 Identity v.s. Projection shortcuts

所谓projection shortcuts,就是:shortcuts包括了一个可学习参数(可以用来对齐维度,使得element-wise相加可以实现):747d8e88-ba36-eb11-8da9-e4434bdf6706.svg设计了A,B,C三种实验:A:单纯使用identity shortcuts:4d7d8e88-ba36-eb11-8da9-e4434bdf6706.svg维度不能对齐时使用zero padding来提升维度此方案没有增加任何参数B:仅仅在维度需要对齐时使用projection shortcuts,其余均使用parameter-free的identity shortcutsC:全部使用projection shortcuts下面是三种方案的实验结果:747cf32c10f0ae6b69d3fbfa6a07f309.pngABC三种方案均明显好于plain版本C虽然结果稍微优于B、C,但是却引入了大量的参数,增加了时空计算复杂度。作者认为:projection shortcuts are not essential for addressing the degradation problem.因此后面的实验仍然采用A或者B结构。

3.1.3 Deeper Bottleneck Architectures.

为了探索更深层的网络,保证训练时间在可控范围内,作者重又设计了bottleneck版本的building blockc594c42653fecaedc166d875a5882fd5.png左边是原版本,右边是bottleneck版本bottleneck版本是将卷积核换成了1*1,3*3,1*1的size,虽然层数增加到了3层,但是降低了参数量。
作者在这里是想探索深度的真正瓶颈,而不是追求很低的error rate,因此在这里使用了更加精简的bottleneck building block50-layers:将34-layers的每个2-layer block换成了3-layers bottleneck block101-layers/152-layers:增加更多的3-layers bottleneck block网络具体参数可参考如下图:
2e06d7a44aeccc05eecd9a89fa2f3ae4.png
实验结果如下所示:2d421353440e5047d0e87acf5a1edfda.png网络越深,确实取得了更好的结果。Plain network的degradation problem似乎消失了。

3.2 CIFAR-10实验与分析

0330056ea91d9d2f0068a09110c30d74.png
实线是test error,虚线是train error左边是plain network,中间是ResNet,右边是ResNet with 110 layers and 1202 layers.结论基本与之前一致,但在1202层时,ResNet还是出现了degradation现象(结果比110层差),作者认为是过拟合。另外:Analysis of Layer Responses
3d140e1a5a3ecf45e45affb8f803d71c.png
关于response:The responses are the outputs of each 8f7d8e88-ba36-eb11-8da9-e4434bdf6706.svglayer, after BN and before other nonlinearity (ReLU/addition).从上图我们可以直接看出:ResNet较于plain network,一般来说response std更小。并且:deeper ResNet has smaller magni- tudes of responses这就说明了:
  1. residual functions(即 347d8e88-ba36-eb11-8da9-e4434bdf6706.svg ) might be generally closer to zero than the non-residual functions.

  2. When there are more layers, an individual layer of ResNets tends to modify the signal less.(也就是后面逐渐就接近identity mapping,要拟合的残差越来越小,离目标越来越近)

4 code review

ResNet实现非常简单,网上各种实现多如牛毛,这里仅随意找了个实现版本作为对照:代码基于CIFAR-10的:2层的BasicBlock:
class BasicBlock(nn.Module):
expansion = 1

def __init__(self, in_planes, planes, stride=1, option='A'):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(planes)

self.shortcut = nn.Sequential()
if stride != 1 or in_planes != planes:
if option == 'A':
"""
For CIFAR10 ResNet paper uses option A.
"""
self.shortcut = LambdaLayer(lambda x:
F.pad(x[:, :, ::2, ::2], (0, 0, 0, 0, planes//4, planes//4), "constant", 0))
elif option == 'B':
self.shortcut = nn.Sequential(
nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(self.expansion * planes)
)

def forward(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += self.shortcut(x)
out = F.relu(out)
return out
ResNet骨架:解释一下:forward函数中定义resnet骨架:
  1. 首:1层conv

  2. 身:由BasicBlock构成layer1、layer2、layer3,个数分别为 947d8e88-ba36-eb11-8da9-e4434bdf6706.svg ,因为每个BasicBlock有2层,所以总层数是 967d8e88-ba36-eb11-8da9-e4434bdf6706.svg

  3. 尾:1层fc

所以总共有 977d8e88-ba36-eb11-8da9-e4434bdf6706.svg层!layer1, layer2, layer3输出维度分别是16,32,64
class ResNet(nn.Module):
def __init__(self, block, num_blocks, num_classes=10):
super(ResNet, self).__init__()
self.in_planes = 16

self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(16)
self.layer1 = self._make_layer(block, 16, num_blocks[0], stride=1)
self.layer2 = self._make_layer(block, 32, num_blocks[1], stride=2)
self.layer3 = self._make_layer(block, 64, num_blocks[2], stride=2)
self.linear = nn.Linear(64, num_classes)

self.apply(_weights_init)

def _make_layer(self, block, planes, num_blocks, stride):
strides = [stride] + [1]*(num_blocks-1)
layers = []
for stride in strides:
layers.append(block(self.in_planes, planes, stride))
self.in_planes = planes * block.expansion

return nn.Sequential(*layers)

def forward(self, x):
out = F.relu(self.bn1(self.conv1(x)))
out = self.layer1(out)
out = self.layer2(out)
out = self.layer3(out)
out = F.avg_pool2d(out, out.size()[3])
out = out.view(out.size(0), -1)
out = self.linear(out)
return out
最后,像堆积木一样,通过设置layer1、layer2、layer3的BasicBlock个数来堆出不同层的ResNet:
def resnet20():
return ResNet(BasicBlock, [3, 3, 3])


def resnet32():
return ResNet(BasicBlock, [5, 5, 5])


def resnet44():
return ResNet(BasicBlock, [7, 7, 7])


def resnet56():
return ResNet(BasicBlock, [9, 9, 9])


def resnet110():
return ResNet(BasicBlock, [18, 18, 18])


def resnet1202():
return ResNet(BasicBlock, [200, 200, 200])

5 conclusion

ResNet核心就是residual learning和shortcut identity mapping,实现方式极其简单,却取得了极其好的效果,在分类、目标检测等任务上均是大比分领先SOTA,这种非常general的创新是非常不容易的,这也是ResNet备受推崇的原因吧!另外给我的启示就是:不仅仅是"talk is cheap, show me the code"了,而是"code is also relatively cheap, show me ur sense and thinking"!

推荐阅读:

推荐!CV预训练模型全集!

国内外优秀的计算机视觉团队汇总|最新版

YOLOv4中的数据增强

a7312afa9bd2f48521ced636d26a85ca.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java开发笔记(二十三)数组工具Arrays

数组作为一种组合形式的数据类型,必然要求提供一些处理数组的简便办法,包括数组比较、数组复制、数组排序等等。为此Java专门设计了Arrays工具,该工具包含了几个常用方法,方便程序员对数组进行加工操作。Arrays工具的方法说明如下…

生成对抗网络gan原理_必读!TOP10生成对抗网络GAN论文(附链接)

来源:新智元本文约2200字,建议阅读7分钟。本文所选论文提供了一个易读的对GAN的介绍,帮助你理解GAN技术的基础。[ 导读 ]生成对抗网络 (GAN) 是深度学习中最有趣、最受欢迎的应用之一。本文列出了 10 篇关于 GAN 的论文,这些论文将…

visudo精确用户赋权(sudo)

原文BLOG:http://iminmin.blog.51cto.com/689308/455992sudo” 是 Unix/Linux 平台上的一个非常有用的工具,允许为非根用户赋予一些合理的 “ 权利 ” ,让他们执行一些只有根用户或特许用户才能完成的任务,从而减少根用户的登陆次…

es6中的类及es5类的实现

目录 类的特点类的特点 1.类只能通过new得到 在es6中类的使用只能是通过new,如果你将它作为一个函数执行,将会报错。 //es6的写法 class Child {constructor() {this.name 1;} } let child new Child(); console.log(child.name)//1 //如果直接…

python高阶函数filter_Python进阶系列连载(13)——Python内置高阶函数filter(上)...

前言进阶部分连载继续~如果还没看过我的入门连载部分,先看:当然,小编的免费入门课程已经有咯,看过连载的朋友可以看看视频再快速梳理一遍~前文传送门:filterfilter是什么意思呢?我们百度看看:百…

javaone_JavaOne 2012:观察与印象

javaone我正坐在旧金山国际机场等待登上一架飞机,然后又一次满意但累人的JavaOne(2012)体验,开始撰写这篇特别的博客文章。 自上周日的主题演讲以来,在会议上狂热地撰写了约30篇博客文章之后,再写另一篇博客…

CSDN转载博客的方法

前言 对于喜欢逛CSDN的人来说,看别人的博客确实能够对自己有不小的提高,有时候看到特别好的博客想转载下载,但是不能一个字一个字的敲了,这时候我们就想快速转载别人的博客,把别人的博客移到自己的空间里面&#xff0c…

linux 服务器账号及安全杂谈

1、useradd zhangsan,添加zhangsan用户后,不能交互式登陆该账号。 原因是:/etc/shadow中内容是 zhangsan:!!:16804:0:99998:7::: 其中,两个!!表示出于安全角度,不能登陆。给zhangsan设置密码后,就可以登陆…

mysql-9索引

mysql索引的建立对于mysql的高效运行是很重要的,索引可以大大提高mysql的检索速度。 索引分为单列索引和组合索引。 单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。 组合索引,即一个索…

带有AWS Lambda和Java的无服务器FaaS

什么是无服务器架构? 无服务器架构在由第三方完全管理的临时容器中运行自定义代码。 自定义代码通常只是完整应用程序的一小部分。 也称为函数 。 这为无服务器架构提供了另一个名称,即功能即服务 (FaaS)。 该容器是短暂的&#x…

python 查找算法_七大查找算法(Python)

查找算法 -- 简介查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素。查找表(Search Table):由同一类型的数据元素构成的集合关键字(Key):数据元素中某个数据项的值,又称为键值主键(Primary K…

traceroute命令的用法实例

ceroute命令的用法实例traceroute 跟踪数据包到达网络主机所经过的路由工具;traceroute 是用来发出数据包的主机到目标主机之间所经过的网关的工具。traceroute 的原理是试图以最小的TTL发出探测包来跟踪数据包到达目标主机所经过的网关,然后监听一个来自…

去除div最后一个逗号_去除重复值、统计数量,这个公式可以直接套用!

点击上方蓝字关注星标★不迷路本文作者:拉登 Dony来源:拉小登(ID:ladengchupin)本文编辑:小叮、竺兰前段时间遇到这样一个问题,让我很头疼。头疼的原因有 3 点:❶ 问题描述不清晰,理解起来困难&…

spring shell_Spring Shell项目发布

spring shellSpring Source昨天发布了Spring Shell 。 Spring Shell是一个交互式Shell,可以使用基于Spring的编程模型轻松地通过命令进行扩展。 它是通过删除OSGi依赖项从Spring Roo项目中提取的,并变成了一个独立项目。 这使得那些只希望使用交互式外壳…

Word报告自动生成(例如 导出数据库结构)

将很早之前写的一个小组件重新整理优化一下,做成一个通用的功能。适用于导出数据库的结构(表、字段等)到Word或将体检数据自动生成Word版的体检报告等。代码:Github 一、主要需要完成功能: 1. 灵活的配置规则及word样式设置&#…

马尔科夫随机场

1、相关概念 马尔科夫随机过程:在已知当前状态的情况下,未来的状态只与当前状态有关,与过去状态无关。这种已知“现在”的条件下,“未来”和“过去”彼此独立的特性叫做马尔科夫性,具有这种特性的随机过程叫做马尔科夫…

php上传文件详解

上传文件功能由两个部分组成&#xff0c;HTML页面和PHP处理部分。HTML页面主要是让用户选择所要上传的文件&#xff0c;php部分让我们可以把文件存储到服务器的指定目录。 一&#xff0e;HTML部分 upload.html [html] view plaincopy<html> <head> &…

pythonwhile循环love_input和while循环——Python编程从入门到实践

PythonPython开发Python语言input和while循环——Python编程从入门到实践input( )input()函数&#xff1a;让程序运行暂停&#xff0c;等待用户输入。message input(Tell me something, and I will repeat it back to you:)print(message)运行结果&#xff1a;Tell me somethi…

phpstudy添加redis扩展

操作系统 windows&#xff1b; 直接贴步骤记录下 一. 划重点&#xff0c;运行phpinfo(), 观察第四行 x86 好了记住这个 x86 三. http://pecl.php.net/package/redis php官方redis扩展下载地址&#xff1b; 我需要的是3.1的版本 之前记住的 x86 当然并不是所有人…

高阶图匹配

一、基于结构特征的相似性度量 将特征看作向量空间中的点&#xff0c;通过计算两个点或者两个点组之间的距离来度量他们是否相似。 一阶度量&#xff1a;minkowsky距离、马氏距离 二阶度量&#xff1a;特征点本身有相关性&#xff0c;所以将特征点对之间的关系加入到相似性度量…