Arxiv: https://arxiv.org/abs/2106.14855
Github: https://github.com/ZwwWayne/K-Net/
语义、实例和全景分割之间尽管存在潜在联系,但是它们使用不同的和特定的框架来解决各自任务。这个工作为这些任务提供了一个统一、简单且有效的框架,即 K-Net。它通过一组可学习的 kernels 来分割实例和语义类别,其中每个 kernel 负责为潜在实例或 stuff 类别生成 mask。为了解决区分不同实例的困难,论文提出一种 kernel update 策略,改策略使每个 kernel 能够动态并以输入图像中意义组为条件。K-Net 可以通过二分匹配进行端到端的训练,其中训练和推理是不需要 NMS 和 矩形框的。
在传统的语义分割中,每个 convolutinal kernel 对应一个语义类。我们的框架扩展了这个概念,是每个 kernel 对应一个潜在的实例或者一个语义类。
在本文中,我们首次尝试制定一个统一且有效的框架,通过 kernels 的概念来连接看似不同的图像分割任务(语义、实例和全景)。我们的方法被称为 K-Net(“K”代表内核)。它从一组随机初始化的卷积核开始,并根据现有的分割目标学习 kernels,即用于语义类别的 semantic kernels 和用于实例身份的 instance kernels(图1b))。semantic kernels 和 instance kernels 的简单组合可以自然地进行全景分割(图1c)。在前向传递中,kernels 对图像特征进行卷积以获得相应的分割预测。
K-Net 的多功能性和简单性是通过两种设计实现的。首先,我们制定了 K-Net,以便它动态更新 kernels,使它们以它们在图像上的激活为条件。这种内容感知(content-aware)机制对于确保每个 kernel(尤其是 instance kernel)准确响应图像中的不同对象至关重要。通过迭代应用这种自适应 kernel 更新策略,K-Net 显着提高了 kernels 的判别能力并提升了最终的分割性能。值得注意的是,这种策略普遍适用于所有分割任务的 kernels 。
其次,受目标检测 DETR 最新进展的启发,我们采用二分匹配策略为每个内核分配学习目标。这种训练方法有利于传统的训练策略,因为它在图像中的 kernels 和实例之间建立了一对一的映射。因此,它解决了处理图像中不同数量的实例的问题。此外,它是纯 mask 驱动的,不涉及 boxes。因此,K-Net 自然是无 NMS 和无框的,这对实时应用很有吸引力。
尽管“有意义的组”有不同的定义,但所有分割任务本质都将每个像素分配给一个预定义的有意义的组。由于通常假设图片中的组数是有限的,因此我们可以将分割任务的最大组设置为 N。例如,有 N 个预定义的语义类用于语义分割,或者图像中最多有 N 个目标用于实例分割。对于全景分割,N 是图像中 stuff 类和 objects 的总数。因此,我们可以使用 N 个内核将图像划分为 N 个组,其中每个 kernel 负责找到属于期对应组的像素。具体来说,给定由深度神经网络生成的 B 副图像的输入特征图 \(F \in R^{B \times C \times H \times W}\),我们只需要 N 个内核 \(K \in R^{N \times C}\) 与 \(F\) 进行卷积即可获得相应的分割预测 \(M \in R^{B \times N \times H \times W}\) 为
\[M = \sigma (K \ast F),\]
其中 C,H 和 W 分别是特征图的通道数、高度和宽度。如果我们只想将每个像素分配给一个 kernel(通常用于语义分割),则激活函数 \(\sigma\) 可以是 softmax 函数。如果我们允许一个像素属于多个 mask,则 Sigmoid 函数也可以用作激活函数,通过在激活图上设置一个阈值(如 0.5)(通常用于实例分割),这会产生 N 个二进制 masks。
这个公式已经主导了语义分割多年。在语义分割中,每个 kernel 负责在图像中找到相似类别的所有像素。而在实例分割中,每个像素组对应一个对象。然而,以前的方法通过额外的步骤而不是 kernel 来分离实例。
本文是第一个探讨语义分割中的 kernel 概念是否同样适用于实例分割,以及更普遍的全景分割的研究。为了通过内核分离实例,K-Net 中的每个内核最多只能分割图像中的一个对象(图 1b)。通过这种方式,K-Net 区分实例并同时进行分割,无需额外步骤即可一次性实现实例分割。为简单起见,我们在本文中将这些内核称为 semantic kernel 和 instance kernels,分别用于语义和实例分割。实例内核和语义内核的简单组合可以自然地执行全景分割,将像素分配给 an instance ID 或 a class of stuff(图1c))。
尽管 K-Net 很简单,但直接通过内核分离实例并非易事。因为实例 kernels 需要区分图像内和图像间尺度和外观不同的 objects。没有像语义类别这样的共同和明确的特征,instance kernels 需要比 static kernels 更强的判别能力。
为了克服这一挑战,我们提供了一种方法,通过 kernel update head 使 kernel 以相应的像素组为条件,如图2所示。Kernel update head \(f_i\) 包含三个关键步骤:组特征组装(group feture assembling)、自适应内核更新(adaptive kernel update),和内核交互(kernel interaction)。首先,使用 mask 预测 \(M_{i-1}\) 组装每个像素组的 group feature \(F^K\)????。由于是每个组的上下文将它们彼此区分开来,因此使用 \(F^K\) 自适应地更新其对应的内核 \(K_{i-1}\)。之后,内核相互交互,对图像上下文进行全面建模。 最后,获得的 group-aware kernels \(K_i\) 对特征图 \(F\) 进行卷积以获得更准确的 mask 预测 \(M_i\)。 如图3所示,这个过程可以迭代地进行,因为更精细的分区通常会降低组特征中的噪声,从而产生更具辨别力的内核。这个过程被表述为
\[K_i, M_i = f_i(M_{i-1},K_{i-1},F)。\]
一组 learned kernels 首先与特征图 \(F\) 进行卷积以预测 mask \(M_0\)。然后这个 kernel update head 将 mask 预测 \(M_0\)、learned kernels \(K_0\) 和 特征图 \(F\) 作为输入,并生成类预测、group-aware (dynamic) kenrels 和 mask 预测。生成的 mask 预测、dynamic kernels 和特征图 \(F\) 被发送到下一个 kernel update head。迭代执行此过程以逐步细化 kernel 和 mask 预测。
值得注意的是,具有迭代细化的 kernel update head 是通用的,因为它不依赖于 kernel 的特性。因此,它不仅可以增强 instance kernels,还可以增强 semantic kernels。
表4a表明 adaptive kernel update 和 kernel interaction 是高性能的必要条件。从表4b中可以看出,positional information 是有益的,positional encoding 略好于 coordinate convolution。但是两者组合没有进一步提升性能,因此在此框架中进使用了 positional enconding。表4c表明 kernel update 的轮数在第4轮的时候,性能接近饱和。最后,在 instance kernels 的数量实验中,增加 N 的数量可以提升性能,但是当 N 较大时,提升幅度变缓。
Kernels 的总体分布。我们通过分析 val split 中 5000 个图像中 100 个实例内核的掩码激活平均值,仔细分析了在 K-Net 中学习到的实例内核的属性。所有 masks 都调整大小以具有类似的 \(200 \times 200\) 分辨率以进行分析。如图 4a 所示,学习到的 kernels 是有意义的。不同的 kernels 专注于图像的不同区域和不同大小的对象,而每个 kernel 关注图像中靠近位置的相似大小的对象。
通过 Kernel Update 优化的 Masks。我们进一步分析了如何通过图 4b 中的 kernel update 来改进 kernel 的 mask 预测。在这里,我们采用 K-Net 进行全景分割,以彻底分析语义和实例掩码。static kernels 生成的 masks 是不完整的,例如,河流和建筑物的掩码缺失。内核更新后,分割掩码完全覆盖了内容,尽管掩码的边界仍然不理想。更多内核更新后,边界得到了细化。内核更新后实例的分类置信度也会增加。
本文探讨了可以在分割过程中学习分离实例的实例内核。因此,以前辅助实例分割的额外组件可以被实例内核替换,包括边界框、嵌入生成和手工制作的后处理,如 NMS、内核融合和像素分组。这种尝试首次允许通过统一的框架处理不同的图像分割任务。该框架被称为 K-Net,首先通过学习的静态内核将图像划分为不同的组,然后通过从划分组中组装的特征迭代地细化这些内核及其对图像的划分。K-Net 在全景和语义分割基准上获得了新的SOTA的单模型性能,并在最近的实例分割框架中以最快的推理速度超越了成熟的 Cascade Mask R-CNN。我们希望 K-Net 和分析能够为未来统一图像分割框架的研究铺平道路。
]]>Arxiv: https://arxiv.org/abs/2108.06747
Github: https://github.com/easton-cau/SOTR
最近 tansformer-based 模型在视觉任务上表现出令人印象深刻的性能,甚至超过了卷积神经网络。在这项工作中,作者提出了一种新颖、灵活且有效的 tranformer-based 模型用于高质量的实例分割。所提出的模型,即 Segmenting Objects with TRansformers (SOTR),简化了分割的pipeline,具有2个并行的子任务:(1)通过 transformer 预测每个实例类别,(2)使用多层级上采样模块动态生成 segmentation mask。SOTR 可以分别通过特征金字塔(FPN)和 twin transformer 有效地提取较低级别的特征表示(lower-level feature representations)并不惑远程上下文依赖关系(long-range context dependencies)。同时,与原始的 tranformer 相比,多提出的 twin transformer 在时间和资源上都是有效的,因为只涉及行和列注意力(a row and a column attention )来编码像素。此外,SOTR 很容易与各种 CNN backbones 和 transformer 模型变体结合,从而显著提高分割精度和收敛性。
现代实例分割方法通常建立在 CNN 之上并遵循先检测后分割范式,该范式由一个用于识别和定位所有目标的检测器和一个用于生成分割掩码的掩码分支组成。这这种分割方法的成功归功于以下优点,即平移和位置不变性(tanslation equivariance and location),但面临以下障碍:1)由于感受野受限,CNN 在高级视觉语义信息中相对缺少特征的连贯性(features' coherence)来关联实例,导致对大目标的次优结果;2)分割质量和推理速度都严重依赖目标检测器,在复杂场景中性能较差。
为了克服这些缺点,提出了一些 Bottom-up 的策略。Bottom-up 的方法的主要缺点是在不同场景的数据集上不稳定的聚类(例如,)和较差的泛化能力。SOTR有效学习了位置敏感特征和动态生成实例分割结果,不需要后处理聚合,不受限于边界框位置和尺寸。我们提出了一种创新的自下而上模型 SOTR,它巧妙地结合了 CNN 和 Transformer 的优势。
Twin attention. self-attention 是 transformer 模型的关键组件,它内在地在输入序列上的每个元素之间捕获了全图的上下文信息并且学习到了长距离的交互。然而,self-attention 具有二次时间和内存复杂性,在高维维度序列(如图像)上产生更高的计算成本,并阻碍了不同设置下的模型可扩展性。
为了解决这个问题,本文提出了 twin attention 机制使用稀疏表示简化了注意力矩阵。这个策略主要将感受野限制为固定步幅的设计块模式。它首先计算每列内的注意力,同时保持不同列中的元素独立。该策略可以在水平尺度上聚合元素之间的上下文信息(如图3(1)所示)。然后,在每一行内执行类似的注意力,以充分利用垂直尺度的特征交互(如图3(2)所示)。两个尺度中的注意力一次连接到最后一个,它具有全局感受野,覆盖了两个维度上的信息。
FPN的第i层特征定义为 \(F_i \in \mathbb{R}^{H \times W \times C}\),SOTR 首先将这个特征图切分成 \({N \ast N}\) 个 patches \({P_i \in \mathbb{R}^{N \times N \times C}}\) ,然后将它们沿垂直和水平方向堆叠成固定的 blocks。Position embeddings 被添加到这些 blocks 中以保留位置信息,这意味着列和行的 position embedding 空间是 \(1 \ast N \ast C\) 和 \(N \ast 1 \ast C\)。两个注意力层都采用了 multi-head attention 机制。为了便于多层连接和后处理,在 twin attention 中所有子层都会产生 \(N \times N \times C\) 的输出。Twin attention 机制可以有效地将内存和计算复杂度从标准的 \(O((H \times W)^2)\) 降低到 \(O(H \times W^2 + W \times H^2)\)。
Transformer Layer. 在本节中,我们介绍3个不同的基于编码器的 transformer 层作为我们的基本构建块,如图3所示。原始的 transformer 层类似于 NLP 中使用的编码器,如图3a所示,它包括2个部分:1)经过 a layer normalization 后的 a multi-head self-attention 机制,以及 2)在 a layer normalization 之后的 a multi-layer perception。除此之外,使用残差连接来连接这两个部分。最后,可以得到一个多维序列特征作为这些 transformer 层的 K 个串联的输出,用于不同功能 heads 的后续预测。
为了在计算成本和特征提取效果之间做出最佳权衡,我们遵循原来的 Transformer 层设计,仅在纯 Twin Transformer 层中用 twin attention 代替 multi-head attention ,如图3b所示。为了进一步提升 twin tranformer 的性能,我们还设计了图 3c 所示的 hybrid twin transformer。它将两个 \(3 \times 3\) 卷积层通过 Leaky ReLU 层连接到每个 twin attention 模块。 假设添加的卷积操作可以作为注意力机制的有效的补充,更好地捕获局部信息并增强特征表示。
Functional heads. 来自 transformer 模块的特征图被输入到不同的功能 heads 以进行后续预测。class head 包括 a single linear layer 来输出一个 \(N \times N \times M\) 的分类结果,其中 \(M\) 是类别的数量。由于每个 patch 只为中心落入这个 patch 的单个目标分配一个类别,如 YOLO,我们利用多级预测并在不同特征级别共享这些 heads,以进一步提高模型在不同尺度对象上的性能和效率。 Kernel head 也由 a linear layer 组成,与 class head 并行输出一个 \({N \times N \times D}\) 的张量用于后续的 mask 生成,其中张量表示具有D个参数的 \(N \times N\) 个卷积核。在训练期间,Focal Loss 应用于分类,而对这些卷积核的所有监督都来自最终的 mask 损失。
为 instance-aware 和 position-sensitive 分割构建 mask 特征表示,一种直接的方式是对不同尺度的特征图进行预测。但是,这会增加时间和资源。收 Panoptic FPN 的启发,我们呢设计了 multi-level upsampling 模块,将每个 FPN 层级和 transformer 的特征合并为统一的 mask 特征。首先,从 transformer 模块中获取具有位置信息的相对低分辨率特征图 P5,并与 FPN 中的 P2-P4 结合执行融合。对于每个尺度的特征图,执行 \(3 \times 3\) Conv,Group Norm 和 ReLU 操作。然后 P3-P5 被双线性上采样 2x、4x、8x,分别为(H4,W4)分辨率。最后,将处理后的 P2-P5 相加后,执行逐点卷积和上采样以创建最终统一的 \(H \times W\) 特征图。
对于实例掩膜预测,SOTR 通过对上述统一特征图执行动态卷积操作,为每个 patch 生成 mask。给定来自 kernel head 的预测卷积核 \(k \in RN \times N \times D\),每个 kernel 负责对应的 patch 中实例 mask 的生成。具体操作可以表示如下:
\[Z^{H \times W \times N^2} = F^{H \times W \times C} \ast K^{N \times N \times D}\]
其中 \(\ast\) 表示卷积操作,\(Z\) 是最终生成的 mask,维度为 \(H \times W \times N^2\)。其中,\(D\) 的取值取决于卷积核的形状,也就是说,D等于 \(\lambda 2 C\),其中 \(\lambda\) 的 kernel 大小。最终的实例分割 mask 可以由 Matrix NMS[37] 生成,每个 mask 由 Dice Loss 独立监督。
用于特征编码的 Transformer。我们用三种不同的 transformers 来衡量我们模型的性能。这些变体的结果如表 2 所示。我们提出的 pure and hybrid twin transformers 在所有指标上都大大超过了 original transformer,这意味着 twin transformer 架构不仅成功地捕获了垂直和水平维度上的远程依赖关系,而且是更适合与 CNN 主干结合来学习图像的特征和表示。对于 pure and twin transformers,后者效果更好。我们假设原因是 \(3 \ast 3\) Conv 可以提取局部信息并改进特征表达以增强 twin transformer 的合理性。
我们展示了掩码特征的可视化。对于每一行,左边是原始图片,右边是与其对应的 positional-sensitive mask。
我们将我们方法的分割结果与 Mask R-CNN 、Blendmask 和 SOLOv2 进行比较。代码和训练好的模型由原作者提供。 所有模型都使用 ResNet-101-FPN 作为主干,并且基于 Pytorch 和 Detectron2。 我们的 Mask 质量更好。
动态卷积。对于 mask 生成,我们有两种选择:以静态卷积方式直接输出实例 mask 或通过动态卷积操作连续分割对象。前者不需要额外的 functional head 来预测卷积核,而后者包括卷积核以在融合特征的帮助下生成最终 mask。 我们在表 5 中比较了这两种模式。如图所示,没有 twin transformer 的 SOTR 实现了 39.7% 的 AP,表明 twin transformer 带来了 0.5% 的增益。 此外,动态卷积策略可以将性能提高近 1.5% AP。 原因是:一方面,由于非线性,动态卷积显着提高了表示能力。另一方面,动态卷积比静态卷积有助于更好更快地收敛。
]]>Code:暂未开源
最近提出的端到端 transformer 检测器 (例如 DETR 和 Deformable DETR)有一个堆叠的 6 个解码器层的级联结构,以用来迭代更新 object queries,否则它们的性能会严重下降。在这篇论文中,作者研究了 object containers 的随机初始化,object containers 包含 object queries 和 reference points,用于负责多次迭代的要求。基于这个发现,作者提出 Efficient DETR,一种用于端到端目标检测的简单高效的流程。通过同时利用密集检测(dense detection)和稀疏集合检测(sparse set detection),Efficient DETR 在初始化 object containers 利用密集先验,并且弥补了 1 层 decoder 结构和 6 层 decoder 结构的性能差异。在 MS COCO 上进行的实验表明,该的方法只有 3 encoder layers 和 1 decoder layer,与 state-of-the-art 目标检测方法相比,性能具有竞争力。 Efficient DETR 在拥挤的场景中也很强大,它在 CrowdHuman 数据集上大大优于当前的目标检测器。
最近,DETR 提出一种基于 encoder-decoder transformer 架构和二部图匹配构建的端到端框架,改框架可以直接预测一组边界框,而无需后处理(NMS)。然而,DETR 需要比当前主流检测器 10 到 20 倍训练的 epoch 才能收敛,并且在检测小目标方面表现出相对较低的性能。
DETR 的检测流程可以抽象成 Fig.1(a)。我们首先定义 object container 作为一种结构信息的容器,它可以包含不同种的目标特征。object queries 和 reference points 都属于 object container,因为 object queries 和 reference points 可以表示抽象的特征和目标的位置信息。一组随机初始化的 object containers 被送入特征精练器(feature refiner)中,用于和从图像提取的特征做交互作用。具体来说,具有 cross-attention 模块的 6 decoder layers 扮演了 cascade feature refiner的角色,它迭代的更新 object containers。这个精练之后的 object containers 有助于 DETR最后的预测。此外,图片的特征是通过 feature extractor 提取到的,在 DETR 中的 feature extractor 包括 a CNN backbone 和 6 encoder layer。总之,图像和随机初始化的 object containers 通过 feature extractor 和 cascade feature refiner 得到最终的结果。在这个流程中,DETR 和 Deformable DETR 都具有 6-encoder 和 6-decoder transformer 架构。我们假设这种结构是 DETR 系列 实现目标检测高精度的关键。
在这篇论文中,作者研究了 DETR 的各个组成部分,并且了解其机制。作者通过大量实验发现具有额外辅助损失的 decoder layer 对性能的贡献最大。transformer decoders 迭代地用特征图与 object containers 进行交互。作者探索了 DETR 中 object containers 随机初始化和多次修正的要求导致了收敛缓慢。
然而,很难直接分析 object queries,因为它们只是一组抽象特征。Deformable DETR 为 object queries 提出了 reference points。Reference points 是一个2维张量,表示猜想的框的中心点。通过可视化训练模型的参考点,作者发现它们被证明仅用作基于锚点的方法中的 anchor points。 此外,作者报告了 1-decoder 结构的 reference points 的不同初始化导致巨大性能差异。 问题来了:对于端到端检测器中的 object containers,哪种初始化更好?
Encoder and decoder. DETR 系列方法是在一个 encoder-decoder transformer 架构上。encoder 和 decoder 都级联了 6 个相同的层。An encoder layer 由 a mullti-head self-attention 和 a feed-forward network (FFN) 组成,而 a decoder layer 有一个额外的 multi-head cross attention layer。encoder layer 起到了与卷积类似的作用,并且从具有 multi-head self-attention 的 CNN backbone 上提取上线文特征。在 decoders 中,一组 256 维的 object queries 与整个图像的 encoder features 进行交互,并通过 multi-head cross attention 聚合信息。辅助二分匹配损失应用于每一个 decoder layer。表 1 说明 DETR 对 decoder layer 的数量更加的敏感,这意味着 decoder 比 encoder 对于 DETR 来说更加的重要。特别是,采用具有 3-encoders 和 3-decoders 的 DETR 作为我们的 baseline。如果在 decoder 中移除 2 层 layer,AP 可以减少约 9.3。相比之下,删除 encoder 中的 2 层 layer,仅导致 1.7 AP 的下降。
为什么 decoder 比 encoder 更加的重要? 它们都是在一个级联的框架下,但是 decoder 的每个相同的层上都有 一个额外的辅助损失。在表 1 中,我们发现这个辅助的解码损失是 DETR 对 decoder layer 数量敏感的主要原因。在没有辅助损失的情况下,encoder 和 decoder 的行为趋于相同。我们指出辅助解码损失在更新 query feature 时引入了强监督,这使得 decoder 更高效。decoder 级联结构通过逐层的辅助损失来精练特征。迭代次数越多,辅助解码监督越有效。
为了进一步套索 decoder 的级联结构,作者尝试了不同数量的 decoder layer。表 2 显示,随着级联次数的减少,性能显著降低。6-layer decoder 和 1-layer decoder 存在 10.3 AP 的巨大下降。值得注意的是,在 decoder 中每次迭代后,仅仅 object queries 得到了更新。Object queries 与性能密切相关,因为最终的预测是来自 object queries 并由检测头预测。然而,object queries 在训练开始时是随机初始化的。我们假设这种随机初始化不能提供良好的初始状态,这可能是 DETR 需要 6 次迭代的级联结构来实现竞争性能的原因。
基于前面的分析,object queries 的初始是值得研究的。object query 属于object container 中的特征信息。object query 被定义为可学习的位置嵌入,它是一个 256 维的抽象张量,因此很难分析。然而,我们观察到 DETR 中的每个 object query 都学会了专注于具有多种操作模式的特定区域和框的大小。我们假设研究 object query 的空间投影可能有助于直观的理解。
Deformable DETR 引入了一个新的组件,即与 object queries 相关的 reference point。Reference points 是表示框中心预测的 2 维张量,属于 object container 的位置信息。此外,参考点是通过线性投影从 256 维 object queries 中预测的。它们可以作为 object query 在 2D 空间中的投影,并提供 object query 中位置信息的直观表示。Reference point 和 object query 在 decoder 迭代期间更新,并作用到最终结果。
考虑到 reference points 直观地表示 object queries 中的位置信息,开始对其进行研究。在传递到 decoder layers 之前,reference points 试试通过随机初始化的 object queries 的线性投影生成的,如图 3(a)所示。我们称这个过程为参考点的初始化。图 2 展示了模型收敛之后的参考点。初始阶段的参考点均匀分布在图像上,覆盖整个图像区域。这种初始化类似于 anchor-based detectors 的 anchor points 的生成。随着迭代阶段的增加,reference points 逐渐聚集到前景的中心,最终在最后阶段几乎覆盖了所有的前景。直观的说,reference points 充当定位前景的 anchor points,并使得注意力模块专注于前景周围的一小组关键采样点。
在研究了 reference points 的更新之后,我们开始探索它们的初始化,这就是参考点的生成方式。对于剩下的部分,我们将 reference points 和 object queries 的初始化称为 object containers 的初始化。
Reference Point 不同的初始化。 在 anchor-based detectors 中,anchors 的生成对模型的性能有一个较大的影响。anchors 在每一个滑动窗口的位置生成,并且为目标可能出现的位置提供了一个合适的初始化。在 reference points 的初始化中,它的作用类似于 anchor points,可能对 Deformable DETR 的性能有影响。作者针对级联(6-decoder)和非级联(1-decoder)结构尝试了不同的初始化,并且比较它们的性能。如表 3 所示,不同的初始化在非级联结构上表现确实不同。相反,在级联结构上它们有一个相似的性能。与推测一致,网格(grid)初始化是在滑动窗口的中心生成 reference points,它的结果类似于可学习的初始化。然而,另外两种初始化,中心(center)和边界(border),在没有迭代的情况下,导致了准确率的巨大下降。为了更好的分析,我们再几个阶段可视化了不同初始化的 reference points,如图 4 所示。随着迭代的增加,它们的 reference points 往往处于相同的分布,并且在最终的阶段以相似的模式定位前景。总之,reference points 的不同初始化导致模型在非级联结构中性能的巨大差异,而级联结构通过多次迭代带来了它们的差距。 从另一个角度来看,更好的 reference points 初始化可能会提高非级联结构的性能。
我们能否通过更好的初始化来弥补 1-decoder 结构和 6-decoder 结构的差距?
基于以上的发现,reference points 更好的初始化可以提升性能,尤其对 1-decoder 结构。考虑到 reference points 类似于 anchor points,我们假设在主流检测器中 anchor 的先验可以帮助解决这个问题。在当前的 two-stage 检测器中,region proposals 通过 RPN 以一个滑窗的操作生成的,它可以针对前景提供一组类比无关的候选区域。
RPN 使用 dense 的先验生成前景的粗糙的边界框。如图 3(b) 所示,我们将 RPN 层添加到从 encoder 出来的 dense feature 上。RPN head 共享 encoder 的特征,并且为每一个 anchor 预测 objectness score 和 偏移。得分较高的边界框被选择作为 region proposals。然后,我们再非级联的结构中使用这些 region proposals 的中心作为 reference points 的初始化。表 3 表明了这种方式带来的较大的性能提升。图 5 可视化了这个方法,这里 reference points 作为初始化阶段得到了与其他方法最后阶段相似的分布。Region proposals 以一种更合理的分布初始化了 reference points,提升了非级联结构的 Deformable DETR 的准确性。
如表 4 所示,使用 dense 先验作为 reference point 的初始化,使得它达到了一个更好的初始化状态,并且在 1-decoder 结构中带来了显著的性能提升。然而,reference point 仅仅是 object query 的空间映射,object query 包含额外的抽象信息。因此,怎么同时使用 dense 先验初始化 256-d 的 object feature呢?
直观上,对于 proposal 初始化中的每个 reference point,我们从特征图中选择其对应的特征,即来自 encoder 的 256-d 张量,作为其 object query 的初始化。我们的方法如图 3(c) 所示。 在表 4 中,我们的方法将 1-decoder 结构进一步改进了 3 AP。此外,仅使用 dense 先验初始化 object query 并使用没有reference point 的原始 decoder 也可以显着改善 baseline。
这些结果表明 object container 的初始状态,包括 Deformable DETR 中的 reference point 和 object query,与非级联结构的性能高度相关。RPN 中的 proposals 信息提供了更好的初始化,有可能通过 dense 先验提高性能。基于我们的研究,我们提出了 Efficient DETR,它能够缩小 1-decoder 结构和 6-decoder 结构之间的性能差距。
Efficient DETR 包含 3 encoder layers 和仅仅 1 decoder layer,并且在 decoder 中没有级联结构。这个框架如图 5 所示。Efficient DETR 包含两个部分:dense 和 sparse。Dense 部分在来自 encoder 的 dense 特征上做预测。它从 dense 的预测结果中选择 top-k proposals。这个 4-d proposals 和它对应的 256-d feature 作为 reference points 和 object queries 的初始化。在 sparse 部分,object containers(包含 reference points 和 object queries )使用 dense 先验作为初始化,并且送入到 1-layer decoder,使其与 encoder feature 做信息交互更新特征。最终的预测结果来自于这个更新之后的 object containers。
Code:https://github.com/fundamentalvision/Deformable-DETR
最近提出的 DETR 消除了目标检测中很多手工设计的组件,然而降低了精度。除此之外,由于受到 Tranformer attention 模块在处理图片特征的限制,导致它收敛很慢,并且限制了特征空间分辨率。
为了解决上述问题,论文提出了 Deformable DETR,它的 attention 模块仅仅关注 参考点 附近的一组关键采样点。Deformable DETR 可以获得比 DETR 更好的性能(尤其是在小物体上),并且训练次数减少了 10 倍。
DETR存在的两个问题:(1)比起现存的目标检测器,它的收敛要求太长时间的训练周期。例如,在COCO数据集上,DETR 需要 500 epochs 才能收敛,而这大约比 Faster RCNN 慢了 10~20 倍。(2)DETR 在检测小目标上存在较低的性能。当前的检测器通常利用多尺度特征,这这些特征上小目标可以从高分辨率特征上被检测。然而,高分辨率的特征图给 DETR 带来的严重的计算代价。 上述问题主要归因于 Transformer 组件在处理图像特征图方面的不足。在初始化的时候,attention modules 将几乎统一的注意力权重投射到特征图中的所有像素。让学习注意力权重专注于稀疏有意义的位置,长时间的训练周期是必要的。 另一方面,Transformer 编码器中的注意力权重计算是像素数的平方计算量。 因此,处理高分辨率特征图具有非常高的计算和内存复杂性。
在图片领域,deformable 卷积是一种强有力且高效的关注稀疏空间位置的机制。它可以天然的避免上述提到的问题。然而它缺乏元素关系建模机制,这是DETR成功的关键。
在这篇论文中,作者提出 Deformable DETR,它缓解了 DETR 收敛慢和高计算复杂性的问题。它组合了 deformable 卷积的稀疏空间采样特性和 Transformer 的相关性的建模能力。论文提出的 deformable attention 模块将一小组采样位置作为所有特征图像素中重要的关键元素的预过滤器。
由于其快速收敛以及计算和内存效率,Deformable DETR 为我们开辟了利用端到端对象检测器变体的可能性。 作者探索了一种简单有效的迭代边界框细化(iterative bounding box refinement)机制来提高检测性能。 论文还尝试了一个 two-stage Deformable DETR,其中 region proposal 也是由 Deformable DETR 的变体生成的,它们被进一步输入 decoder 以进行 iterative bounding box refinement。
Transformers 是针对机器翻译任务设计的一种基于注意力机制的网络结构。给一个 query 元素(例如,在一个输出句子中的一个目标单词)和一组 key 元素(例如,在输入句子中的原单词),multi-head attention 模块根据注意力权重自适应地汇聚关键信息,这个注意力权重可以测量 query-key 对 质检的一致性。为了允许让模型从不同表示子空间和不同位置中关注信息,不同 attention heads 的输出是使用学到的权重线性聚合的结果。Multi-head attention 特征可以计算为:
\[\operatorname{MultiHeadAttn}\left(\boldsymbol{z}_{q}, \boldsymbol{x}\right)=\sum_{m=1}^{M} \boldsymbol{W}_{m}\left[\sum_{k \in \Omega_{k}} A_{m q k} \cdot \boldsymbol{W}_{m}^{\prime} \boldsymbol{x}_{k}\right]\]
\(q \in \Omega_{q}\) 表示 一个 query 元素的索引,其特征表示为 \(z_q \in \mathbb{R}^{C}\)
\(k \in \Omega_{k}\) 表示一个 key 元素的索引,其特征表示为 \(x_k \in \mathbb{R}^C\)
\(C\) 特征的维度
\(M\) attention head 的数量,\(m\) 是 attention head 的索引
\(\mathbf{W}_{m}^{\prime} \in \mathbb{R}^{C_{v}\times C}\) 和 \(\mathbf{W}_{m} \in \mathbb{R}^{C_{v}\times C}\) 是可学习的权重,并且 \(C_{v} = C/M\)
\(A_{m q k} \propto \exp \left\{\frac{\mathbf{z}_{q}^{T} \mathbf{U}_{m}^{T} \mathbf{V}_{m} \mathbf{x}_{k}}{\sqrt{C_{v}}}\right\}\) 是 attention 权重,它被归一化,并且 \(\sum_{k\in \Omega_{k}} A_{mqk}=1\) 其中 \(\mathbf{U}_{m}\) 和 \(\mathbf{V}_{m}\) 也是可学习的权重。
为了消除不同空间位置的歧义,表示特征 \(x_q\) 和 \(x_k\) 通常是和 positional embedding 的串联/求和。
对于 DETR 中的 Transformer encoder,query 和 key 元素都是特征图中的像素。输入是 ResNet 特征图(带有编码的 positional embeddings)。让 \(H\) 和 \(W\) 分别表示特征图的高度和宽度。 self-attention 的计算复杂度为 \(O(H^2 W^2 C)\) ,随空间大小呈二次方增长。
对于 DETR 中的 Transformer dncoder,输入包括来自 encoder 的特征图和 由可学习位置嵌入(例如,N = 100)表示的 N object queries。decoder 中有两种注意力模块,即 cross-attention 和 self-attention 模块。在 cross-attention 模块中,object query 从特征图中提取特征。query 元素属于object queries,key 元素属于encoder 的输出特征图。其中,\(N_q = N\),\(N_k = H \times W\),交叉注意力的复杂度为 \(O(HWC^2 + NHWC)\)。复杂性随着特征图的空间大小线性增长。在 self-attention 模块中,object queries 相互交互,以捕获它们的关系。 query 和 key 元素都是 object queries。 其中,\(N_q = N_k = N\),self-attention 模块的复杂度为 \(O(2NC^2 +N^2 C)\)。 中等数量的对象查询的复杂性是可以接受的。
这主要是因为处理图像特征的注意力模块很难训练。 例如,在初始化时,cross-attention 模块几乎对整个特征图具有平均注意力。而在训练结束时,attention maps 被学习到非常稀疏,只关注对象的外轮廓(extremities)。 似乎 DETR 需要很长的训练才能学习注意力图的如此显着的变化。
\[\operatorname{DeformAttn}\left(\boldsymbol{z}_{q}, \boldsymbol{p}_{q}, \boldsymbol{x}\right)=\sum_{m=1}^{M} \boldsymbol{W}_{m}\left[\sum_{k=1}^{K} A_{m q k} \cdot \boldsymbol{W}_{m}^{\prime} \boldsymbol{x}\left(\boldsymbol{p}_{q}+\Delta \boldsymbol{p}_{m q k}\right)\right]\]
这里 \(m\) attention head 的索引,\(k\) 采样 keys 的索引,\(K\) 是总采样的 key 的数量 \((K \ll HW)\)。\(\Delta p_{mqk}\) 和 \(A_{mqk}\) 是采样的偏置和在 \(m^{th}\) attention head 上的 \(k^{th}\) 采样点的 attention weight。
\[\operatorname{MSDeformAttn}\left(\boldsymbol{z}_{q}, \hat{\boldsymbol{p}}_{q},\left\{\boldsymbol{x}^{l}\right\}_{l=1}^{L}\right)=\sum_{m=1}^{M} \boldsymbol{W}_{m}\left[\sum_{l=1}^{L} \sum_{k=1}^{K} A_{m l q k} \cdot \boldsymbol{W}_{m}^{\prime} \boldsymbol{x}^{l}\left(\phi_{l}\left(\hat{\boldsymbol{p}}_{q}\right)+\Delta \boldsymbol{p}_{m l q k}\right)\right]\]
由于提出的 multi-scale deformable attention 可以再不同多尺度特征层上交换信息,所以没有使用 FPN 结构。
在 encoder 中 multi-scale deformable attention 模块的应用中,输出是与输入具有相同分辨率的多尺度特征图。key 和 query 元素都是来自多尺度特征图的像素。对于每一个 query 像素,这个参考点(reference point)就是它自己。为了识别每个 query 像素位于哪个特征级别,除了 positional embedding 之外,我们还向特征表示中添加了 a scale-level embedding,表示为 \(e_l\)。与固定编码的 positional embedding 不同,scale-level embedding \(\{e_l\}^L_l=1\) 是随机初始化并与网络联合训练。
decoder 中有 cross-attention 和 self-attention 模块。这两种注意力模块的 query 元素都是 object queries。在 cross-attention 模块中,object queries 从特征图中提取特征,其中 key 元素是来自 encoder 的输出特征图。在 self-attention 模块中,object queries 相互交互,其中 key 元素是 object queries。由于我们提出的 deformable attantion 模块是为处理卷积特征图作为 key 元素而设计的,因此我们仅将每个 cross-attention 模块替换为 multi-scale deformable attention 模块,而保持 self-attention 模块不变。对于每个 object query,参考点 \(\hat p_q\) 的二维归一化坐标是从其 object query embedding 中通过可学习的线性投影和 \(\mathrm{sigmoid}\) 函数预测的。
因为 multi-scale deformable attention 模块提取参考点(reference point)周围的图像特征,我们让检测头将边界框预测为相对偏移,也就是参考点进一步降低优化难度。 参考点用作框中心的初始猜测。检测头预测相对偏移,也就是参考点。这样,学习到的 decoder attention 将与预测的边界框有很强的相关性,这也加速了训练收敛。
通过在 DETR 中用 deformable attention 模块替换 Transformer attention 模块,我们建立了一个高效且快速收敛的检测系统,称为 Deformable DETR。
Iterative Bounding Box Refinemen
Two-Stage Deformable DETR
由上图可以看出,Deformable DETR 明显提升了训练速度。
1 | # 首先安装 beancount |
Fava 是复式簿记软件 Beancount 的 Web 界面,侧重于功能和可用性,使用非常友好。
我们可以先使用 bean-exampl
生成一个 Beancount
文件,文件的后缀名可以自己定义,一般用.bean
或.beancount
:
1 | (base) XX@XX:~$ mkdir MyBean |
运行 Beancount: 1
2(base) XX@XX:~/MyBean$ fava example.bean
Running Fava on http://localhost:5000
在浏览器上打开 http://localhost:5000 ,就可以看到运行界面,如下:
复式记账的最基本的特点就是以账户为核心,Beancount的系统整体上就是围绕账户来实现的。之前提到的会计恒等式中有资产、负债和权益三大部分,现在我们再增加两个类别,分别是收入和支出。Beancount系统中预定义了五个分类:
1 | ;; -*- mode: org; mode: beancount; -*- |
Beancount 文件中注释使用;
作为标记。
这里定义了项目的名词:Example Beancount file
,和使用的货币种类:美元 USD
。我们如果想使用人民币,可以同时添加 CNY
,例如:
1 | option "operating_currency" "CNY" |
顾名思义,Asserts 就相当于我们的存放 资产的账户,如果启用一个账户就使用 open
命令。
第一列是账户启用时间,第二列是命令,第三列是资产(Assets)名,最后一列是使用的货币种类。
1 | * Assets |
我的命名规则是:资产:账户类型:国别:(银行缩写:银行卡号)/(账户名)
这里定义我们的 收入来源,同样如果启用一个收入来源就使用 open
命令。
第一列是启用时间,第二列是命令,第三列是收入来源,最后一列是使用的货币种类。
1 | * Income |
这里我们定义 花费支出,我根据自己的花销,把花费支出定义为 5 大组类,分别是:Food,Transport,Life,Fun,Health,Home,其中每个大类又有若干子类。
1 | * Expenses |
最后我们记录的花销就会以下图呈现出来:
负债这里我开启了一张信用卡。
1 | * Liabilities |
目前我只设置了一个 Equity 账户 Equity:Opening-Balances,用来平衡初始资产、负债账户时的会计恒等式。
1 | * Equity |
复式记账法是以资产与权益平衡关系作为记账基础,对于每一笔经济业务,都要以相等的金额在两个或两个以上相互联系的账户中进行登记,系统地反映资金运动变化结果的一种记账方法。
复式记账是对每一项经济业务通过两个或两个以上有关账户相互联系起来进行登记的一种专门方法。任何一项经济活动都会引起资金的增减变动或财务收支的变动。
以上内容来自百度百科。
当前账本的交易记录主要分为三种:记录收益,记录支出,结余调整。下面分别展开进行介绍。
我们首先记录一下收入情况,我们将公司CompanyA
和公司CompanyB
的薪水转移到资产Assets:Bank:China:CCB:CardXXX1
中,这个资产定义的是我的银行卡。双引号中间的内容是注释性说明。要确保转移数值平衡,即相加为 0 。
1 | 2019-06-21 * "CompanyA" "Salary" |
以上内容可以直接写到.bean
文件中。
记录消费情况和记录收益情况类似,但是要注意资产转移的方向,即数值的正负号。
1 | 2019-04-17 * "储蓄卡" "餐饮(储蓄卡)" |
以上内容也可以直接写到.bean
文件中。
我们并不能完全记录每一笔收入和支出情况,所以会造成账本资产情况和实际资产情况数值不符。但是对于小数额的差值,我们可以使用结余调整。这样就把差值的资产补回来了。例如:
1 | 2019-01-01 * "结余调整" |
上边的意思是,从账户 Equity:Opening-Balances
转给账户 Assets:Bank:China:CCB:CardXXX1
。Beancount的规范是使用 Equity:Opening-Balances
。Equity:Opening-Balances
是权益类别下面的账户,可以表示没有记录来源的资产。
本人认为按照时间顺序记录账本的方法比较方便,所以我目前使用的目录结构如下; 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15~/Documents/MyBean
├── data
│ ├── 2017.bean
│ ├── 2018.bean
│ └── 2017.bean
├── documents.tmp/
├── Importers
│ ├── __init__.py
│ ├── regexp.py // 原来在位于 beancount/experiments/ingest/regexp.py
│ └── alipay.py
├── configs
│ ├── alipay.config
│ └── wechat.config
├── main.bean
└── strip_blank.py
include
命令包含其他账本文件(.bean
);.bean
);.csv
);当然也有其他的目录结构,如 blog 中提到的:
1 | ~/Documents/accounting |
在上个章节--Beancount 项目目录结构--中,我们按照时间顺序存放收入和交易记录的账本文件(.bean
),例如:2017.bean,2018.bean,2019.bean,那我们如何在主文件中导入这些子文件呢?可以使用 include
命令,如下:
1 | * Include |
如果我们想把工资收入情况做单独的记录,那么可以单独建立一个 Income.bean
文件,然后在使用 include
命令包含进来。
1 | include "Income/Income.bean" |
.bean
文件我们时间和精力有限,所以并不能手工记录每一次交易情况。为了方便生成交易账单,我们可以下载支付宝、微信、银行等交易记录,并且使用程序将他们转化为账单文件(.bean
)。这样节省了很多时间,并且记录准确。
bean-extract
命令: 从每个文件中提取交易和日期。这会生成一些 Beancount 输入文本,这些文本(.bean
)文件移动到您的输入文件中;
1 | bean-extract blais.config ~/Downloads |
可以参考 blog。
在使用 pandas 将 xls 转换为 utf-8 格式的 csv; 1
2
3import pandas as pd
data_xls = pd.read_excel('alipay_record_20190712_2003_1.xls', index_col=0)
data_xls.to_csv('alipay_tmp.csv', encoding='utf-8')
使用 strip_blank.py 删除文件中的所有多余空格; 1
python strip_blank.py alipay_tmp.csv > alipay.csv
使用bean-extract提取beancount数据。 1
bean-extract my_alipay.config alipay.csv > data_alipay.beancount
如果你使用 Atom 打开 beancount,可以安装 language-beancount,这个库可以高亮 beancount 的语法。
https://beancount.github.io/fava/index.html
web端使用fava,可以远程访问。
可以使用如下命令,指定IP和端口号: https://github.com/beancount/fava/blob/master/contrib/deployment.rst 1
fava --host localhost --port 5000 --prefix /fava /path/to/your/main.beancount
Fava 是 Beancount 的 web 界面,非常友好。
byvoid blog 该博客介绍的非常系统
Beancount使用经验 该博客介绍了通过Beancount导入支付宝csv账单的方法
lidongchao/BeancountSample 这里包含一些代码,可以用于导入 csv 账单到 Beancount 中。
这篇语义分割的文章提出使用 \(L_2\) Normalization layers。问题提出的结构如下图所示:
如图3所示,当我们需要组合两个或者更多的特征向量时,它们通常有不同的尺度和范数。简单的级联特征导致较差的性能,因为比较大的特征会主导较小的特征。虽然在训练期间,权重可能会相应调整,但需要非常仔细地调整参数,并且依赖于数据集,因此违背了稳健原则。我们发现,通过首先规范每个单独的特征,并学习以不同尺度进行放缩,这使得训练更加稳定,并且可以提高性能。
\(L_2\) 范数层不仅在特征组合的时候使用。如上所述,在某些情况下,后期融合也同样有效,但仅在L2归一化的帮助下。例如,如果我们想使用底层的特征去学习分类器,如图3所示,一些特征可能有很大的范数。在没有只是的权重初始化和参数调整的情况下,这非常困难。关于这个策略的一个工作就是使用一个附加的卷积层,并且使用多级微调,例如底层使用更小的学习率。这违反了简单和鲁棒的原则。在这篇论文的工作中,对分类之前的特征的每个通道,作者使用了\(L_2\)-norm并且学习了缩放参数,这导致了更加稳定的训练。
对于一个d维的输入 \(\mathbf{x}=(x_1, ..., x_d)\),我们使用 \(L_2\)-norm 规范它,即 \(\hat{x}=\frac{x}{\lVert x \rVert_2}\),其中 \(\lVert x \rVert_2=(\sum_{i=1}^{d} {\lvert x_i \rvert}^2)^{1/2}\) 是 \(\mathbf{x}\) 的 \(L_2\) 范数。
请注意,如果我们不相应地缩放它,只简单地规范化层的每个输入会改变层的尺度,将会减慢学习速度。例如,我们尝试规范化功能 s.t. \(L_2\)-norm 是1,但我们很难训练网络,因为特征变得非常小。 但是,如果我们将其规范化为,例如 10 或 20,网络开始较好的学习。在 batch normalization 和 PReLU 的推动下,我们为每个通道引入缩放参数 \(\gamma_i\),它缩放了归一化的值 \(y_i=\gamma_i \hat{x}_i\)。
额外参数的数量等于通道的总数,并且可以忽略不计,并且可以通过反向传播来学习。 实际上,通过设置 \(\gamma_i={\lVert x_i \rVert}^2\),我们可以恢复 \(L_2\) 归一化的特征。这很容易实现,因为规范化和缩放参数学习仅依赖于每个输入特征向量,并且不需要像批量规范化那样聚合来自其他样本的信息。在训练期间,我们使用反向传播和链规则来计算关于缩放银子 \(\gamma\) 和输入数据 \(\mathbf{x}\) 的导数。
1 | import torch.nn.functional as F |
1 | import torch |
导入所需要的包。 1
2
3In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: import matplotlib.pyplot as plt
通过传递一个列表创建 Series
,让pandas创建一个默认的整型索引: 1
2
3
4
5
6
7
8
9
10
11In [4]: s = pd.Series([1,3,5,np.nan,6,8])
In [5]: s
Out[5]:
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
通过传递一个Numpy
数组创建一个DataFrame
数据,用时间和有标签的列作为索引: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19In [6]: dates = pd.date_range('20130101', periods=6)
In [7]: dates
Out[7]:
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
'2013-01-05', '2013-01-06'],
dtype='datetime64[ns]', freq='D')
In [8]: df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
In [9]: df
Out[9]:
A B C D
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
2013-01-06 -0.673690 0.113648 -1.478427 0.524988
通过传递一个序列对象的字典创建DataFrame
。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15In [10]: df2 = pd.DataFrame({ 'A' : 1.,
....: 'B' : pd.Timestamp('20130102'),
....: 'C' : pd.Series(1,index=list(range(4)),dtype='float32'),
....: 'D' : np.array([3] * 4,dtype='int32'),
....: 'E' : pd.Categorical(["test","train","test","train"]),
....: 'F' : 'foo' })
....:
In [11]: df2
Out[11]:
A B C D E F
0 1.0 2013-01-02 1.0 3 test foo
1 1.0 2013-01-02 1.0 3 train foo
2 1.0 2013-01-02 1.0 3 test foo
3 1.0 2013-01-02 1.0 3 train foo
得到的DataFrame
的列有不同的类型: 1
2
3
4
5
6
7
8
9In [12]: df2.dtypes
Out[12]:
A float64
B datetime64[ns]
C float32
D int32
E category
F object
dtype: object
可以看基本章节。
这里我们查看一下frame的前几行和后几行: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15In [14]: df.head()
Out[14]:
A B C D
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
In [15]: df.tail(3)
Out[15]:
A B C D
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
2013-01-06 -0.673690 0.113648 -1.478427 0.524988
显示索引和列,并且显示隐含的NumPy数据: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17In [16]: df.index
Out[16]:
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
'2013-01-05', '2013-01-06'],
dtype='datetime64[ns]', freq='D')
In [17]: df.columns
Out[17]: Index(['A', 'B', 'C', 'D'], dtype='object')
In [18]: df.values
Out[18]:
array([[ 0.4691, -0.2829, -1.5091, -1.1356],
[ 1.2121, -0.1732, 0.1192, -1.0442],
[-0.8618, -2.1046, -0.4949, 1.0718],
[ 0.7216, -0.7068, -1.0396, 0.2719],
[-0.425 , 0.567 , 0.2762, -1.0874],
[-0.6737, 0.1136, -1.4784, 0.525 ]])
describe()显示一个快速的你的数据的统计信息: 1
2
3
4
5
6
7
8
9
10
11In [19]: df.describe()
Out[19]:
A B C D
count 6.000000 6.000000 6.000000 6.000000
mean 0.073711 -0.431125 -0.687758 -0.233103
std 0.843157 0.922818 0.779887 0.973118
min -0.861849 -2.104569 -1.509059 -1.135632
25% -0.611510 -0.600794 -1.368714 -1.076610
50% 0.022070 -0.228039 -0.767252 -0.386188
75% 0.658444 0.041933 -0.034326 0.461706
max 1.212112 0.567020 0.276232 1.071804
转置你的数据: 1
2
3
4
5
6
7In [20]: df.T
Out[20]:
2013-01-01 2013-01-02 2013-01-03 2013-01-04 2013-01-05 2013-01-06
A 0.469112 1.212112 -0.861849 0.721555 -0.424972 -0.673690
B -0.282863 -0.173215 -2.104569 -0.706771 0.567020 0.113648
C -1.509059 0.119209 -0.494929 -1.039575 0.276232 -1.478427
D -1.135632 -1.044236 1.071804 0.271860 -1.087401 0.524988
通过一个维度进行排序: 1
2
3
4
5
6
7
8
9In [21]: df.sort_index(axis=1, ascending=False)
Out[21]:
D C B A
2013-01-01 -1.135632 -1.509059 -0.282863 0.469112
2013-01-02 -1.044236 0.119209 -0.173215 1.212112
2013-01-03 1.071804 -0.494929 -2.104569 -0.861849
2013-01-04 0.271860 -1.039575 -0.706771 0.721555
2013-01-05 -1.087401 0.276232 0.567020 -0.424972
2013-01-06 0.524988 -1.478427 0.113648 -0.673690
通过数值排序: 1
2
3
4
5
6
7
8
9In [22]: df.sort_values(by='B')
Out[22]:
A B C D
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-06 -0.673690 0.113648 -1.478427 0.524988
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
选择一个列,这会产生一个Series
, 等同于df.A
: 1
2
3
4
5
6
7
8
9In [23]: df['A']
Out[23]:
2013-01-01 0.469112
2013-01-02 1.212112
2013-01-03 -0.861849
2013-01-04 0.721555
2013-01-05 -0.424972
2013-01-06 -0.673690
Freq: D, Name: A, dtype: float64
通过[]
进行选择,这可以切开行: 1
2
3
4
5
6
7
8
9
10
11
12
13In [24]: df[0:3]
Out[24]:
A B C D
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
In [25]: df['20130102':'20130104']
Out[25]:
A B C D
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
更多请看here。
使用标签获得一个截面: 1
2
3
4
5
6
7In [26]: df.loc[dates[0]]
Out[26]:
A 0.469112
B -0.282863
C -1.509059
D -1.135632
Name: 2013-01-01 00:00:00, dtype: float64
通过标签选择多个轴线: 1
2
3
4
5
6
7
8
9In [27]: df.loc[:,['A','B']]
Out[27]:
A B
2013-01-01 0.469112 -0.282863
2013-01-02 1.212112 -0.173215
2013-01-03 -0.861849 -2.104569
2013-01-04 0.721555 -0.706771
2013-01-05 -0.424972 0.567020
2013-01-06 -0.673690 0.113648
显示一个标签切片,并且也包括结束点: 1
2
3
4
5
6In [28]: df.loc['20130102':'20130104',['A','B']]
Out[28]:
A B
2013-01-02 1.212112 -0.173215
2013-01-03 -0.861849 -2.104569
2013-01-04 0.721555 -0.706771
1 | In [2]: ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)) |
1 | In [15]: plt.figure(); |
1 | In [17]: df2 = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd']) |
1 | In [21]: df4 = pd.DataFrame({'a': np.random.randn(1000) + 1, 'b': np.random.randn(1000), |
1 | In [24]: plt.figure(); |
1 | In [28]: plt.figure(); |
1 | In [30]: plt.figure() |
1 | In [32]: data = pd.Series(np.random.randn(1000)) |
何帆,男,现任北京大学汇丰商学院经济学教授,兼熵一资本首席经济学家。曾任中国社会科学院世界经济与政治研究所副所长,在政策研究领域研究已经超过20年 [3] ,发表学术论文100多篇,出版专著10余部,如《变量》《何帆大局观》等 。现被厦门大学EMBA管理学院特聘为EMBA讲师,同陆磊教授一同讲授EMBA课程-《宏观经济理论与实践》。同时,何帆是得到App《何帆大局观》《何帆的读书俱乐部》《何帆报告》课程主理人。
作者简介来自百度百科
2018年是一个新的开端。生活在2018年的人感受到的是中国经济遇到的各种冲击:中美贸易战、经济增长回落、股市下跌。他们会感到焦虑和担忧。旧路标已经消失,新秩序尚未出现。未来30年出现的一系列变化将挑战我们的认知,但历史从来都是一位“魔术师”,未来会出现意想不到的变化。在这一章,我会讲述如何像细致地观察一棵树一样观察历史,怎样从每年长出的“嫩芽”去判断中国文明这棵大树的生命力。我还会告诉你两个重要的概念:慢变量和小趋势。感知历史,就要会从慢变量中寻找小趋势。
2018年,关于技术发展路径的讨论引起全民关注。中国到底是应该集中全力补上“核心技术”,还是应该扬己所长发展“应用技术”呢?我将带你回顾美国在工业革命时期的经验,并试图发现中国在信息化时代的最佳战略。我找到的第二个变量是:技术赋能。在创新阶段,寻找新技术的应用场景更重要,在边缘地带更容易找到新技术的应用场景,技术必须与市场需求匹配。我们会到新疆去看无人机,而你很可能会在酒店里邂逅机器人。中国革命的成功靠的是“群众路线”,中国经济的崛起也要走“群众路线”。
2018年,谁是新兴产业,谁是传统产业?哪个更胜一筹?在过去几年,互联网大军就好像当年来自中亚大草原的游牧民族,兵强马壮,来去如风。在互联网大军的攻势下,传统产业的护城河形同虚设。到了2018年,这股“为跨不破”,精于“降维打击”的大军,却在一座城堡前久攻不下。这就是工业化的代表————已经有上百年历史的汽车行业。2018年,我发现的第三个变量是:老兵不死。我要带你到传统制造业的腹地,看看他们是如何抵御互联网行业的迅猛攻势。在这里,你会看到,传统行业的老兵早已经悄悄穿上了新的军装,而新兴的产业正在积极地想传统产业学习。新兴产业和传统产业的边界,也许并没有你想象的那般泾渭分明。
2018年,人们最关心的是房价是否会出现拐点,但从长时间来看更值得关注的是城市化的拐点。自上而下的城市化已不可持续。我观察到的第四个变量是:自下而上的力量浮出水面。城市化的进程不会停止,未来会有更多的城市圈,但这些都市圈是放大了的城市,还是一种新的城市物种呢?未来的城市不一定都能扩张,假如城市不得不“收缩”,该怎样才能像瘦身一样,瘦了更健康?未来的城市将深受互联网影响,城市空间布局会跟过去有很大的不同。“位置、位置、位置”的传统房地产“金律”很可能不再适用。我们会看到,城市会爆发一场“颜值革命”。这场“颜值革命”来自哪里呢?归根到底,它来自人民群众自己创造美好生活的能量。
2018年,我们听到了很多负面的社会新闻:米脂杀人、衡阳装车、高铁霸座......这个社会变得越来越糟糕了吗?其中这是一种误解。虽然从表明上看,有些人只关心自我私利,但大家对集体生活的向往并没有泯灭。中国人已经意识到,只有重建集体生活,才能更好地发现自我。我看到的第五个变量就是:重建社群。有哪些地方的人们正在“凝结”起来,形成新的社群?这些新的社群只是孤岛,还是将成为群岛?培养孩子也需要一个社群。我会带你到一所偏僻的农村小学看看。2018年,我找到的中国教育理念最先进的小学不是北京或上海名校,而是山区里的一所农村小学。你不必吃惊,社会发展的剧情经常会有令人意想不到的转变。
]]>CSP: Center and Scale Prediction
1 | def calc_gt_center(C, img_data,r=2, down=4,scale='h',offset=True): |
seman_map有三个位面,第一个是高斯值mask,第二个是学习权重,第三个是目标中心点的位置。
1 | def nn_p3p4p5(img_input=None, offset=True, num_scale=1, trainable=False): |
1 | def cls_center(y_true, y_pred): |
High-Resolution Net (HRNet)
这篇论文解决人体姿态估计问题,重点关注学习高分辨率表示。大多数现有的方法通过一个由高到低分辨率的网络,从一个低分辨率的表示中恢复高分辨率的表示。相反,本论文提出的网络自始至终都保持了高分辨率的表示。
作者从高分辨率子网作为第一个阶段,逐渐添加 高->低 分辨率的子网形成更多的阶段,并且并行连接这些多分辨率子网。作者多次进行多尺度融合,使得每一个高->低分辨率的表示可以从其他并行的表示中接收信息,从而生成丰富的高分辨率表示。因此,预测的关键点热图可以更准确,空间更精确。作者在COCO关键点检测数据集和MPII Human Pose数据集上进行了验证。
该方法并行级联高->低分辨率子网,而不是以序列的方式。因此,该方法保持了高分辨率,而不是从低分辨率中恢复高分辨率。所以预测的热图的空间上更准确。
现存的融合策略集成底层(low-level)和高层(high-level)的表示。 而该方法通过相似深度和相同层级的低分辨率表示的帮助,执行重复的多尺度融合提升高分率表示。
图1展示了提出的HRNet网络的结构。它包含并行的高->低分辨率的子网,重复的在不同分辨率子网之间的信息交换,即多尺度融合。水平和垂直方向分别对应于网络的深度和特征图的比例。
图2展示了其他方法的一些网络结构,这些方法都是依靠high-to-low和low-to-high框架的姿态估计网络结构。其中(a)表示Hourglass网络,(b)表示Cascaded pyramid networks,(c)表示SimpleBaseline网络:转置卷积(transposed convolutions)用于low-to-high过程。(d)组合空洞卷积(dilated convolutions)。
用\(N_{sr}\)表示子网络在第s个stage,r表示分辨率的序号,它的分辨率是第一个子网络分辨率的\(\frac{1}{r^{r-1}}\)倍。有S=4个stege的high-to-low网络可以表示为:
\[N_{11} \to N_{22} \to N_{33} \to N_{44}\]
我们从一个高分辨率子网络作为第一个stage起始,逐渐地增加high-to-low分辨率子网络,形成新的sgates,并且并行地连接多分辨率子网络。因此,后一阶段并行子网的分辨率包括前一阶段的分辨率和一个更低的分辨率。
这里给出一个网络结构的例子,包含4个并行的子网络,如下:
图3展示了交换单元(Exchange Unit)如何为高、中和底层融合信息的。右侧的注释表示:strided 3x3=stride 3x3卷积,up samp. 1x1=最近邻上采样和一个1x1卷积。
我们在不同的并行子网之间引入交换单元(exchange unit),这样每个子网可以重叠地从其他并行网络中接收信息。这里给出了一个交换信息框架的例子,如下图表示的结构。我们将第三个stage分成几个exchange blocks,并且每一个block有三个并行的卷积单元构成,一个交换单元在并行的卷积单元之间,如下:
其中,\(C^b_{sr}\)表示在第s个stage,第b个block的第r分辨率的卷积单元。\(\varepsilon^b_s\)是对应的交换的单元。
交换单元如图3所示。
我们简单地从最后一个交换单元(exhcange unit)输出的高分辨率表示中回归热图。损失函数(定义为均方误差)用于比较预测的热图和groundtruth热图。通过应用2D高斯生成的groundtruth热图,其中标准偏差为1像素,并以每个关键点的标注位置为中心。
实验中提出了两种网络,一个小网络HRNet-W32,一个大网络HRNet-W48,其中32和48分别表示在后3个sgate中的高分辨率子网络的宽度(C)。对于HRNet-W32,其他三个并行的子网络的宽度分别是64,128,256,对于HRNet-W48是96,192,384。
1 | def _make_fuse_layers(self): |
1 | class HighResolutionModule(nn.Module): |
这篇论文主要提出一个新颖的非极大值抑制(Non-Maximum Suppression, NMS)算法更好地改善检测器给出的检测框。本文主要贡献:
图1展示了不同阈值下的greedy-NMS的结果。蓝色的框表示丢失的目标,红色的框表示假正例(false positives)。(b)中的检测框是Faster R-CNN在NMS之前的检测结果。如图c,一个低的NMS阈值可能会移除正例(true positives)。如同d,一个高的NMS阈值可能会增加假正例(false positives)。
在本文中,作者提出了一种新的NMS算法,名为adaptive-NMS,它可以作为人群中行人检测的更有效的替代方案。直观地,高NMS阈值保持更多拥挤的实例,而低NMS阈值消除更多误报。因此,自适应NMS应用动态抑制策略,其中阈值随着实例聚集和相互遮挡而上升,并且当实例单独出现时衰减。为此,我们设计了一个辅助且可学习的子网络来预测每个实例的自适应NMS阈值。
当物体处于拥挤区域时,增加NMS的阈值可以保留高覆盖率。同样,在稀疏场景下,应该去掉重复度高的候选框,因为它们很可能是假正例。
\[d_i:= \max_{b_j \in \mathcal{G}, i \neq j} \mathrm{iou}(b_i, b_j)\]
目标\(i\)的密度被定义和在ground truth集合\(\mathcal{G}\)中的其他目标的最大紧致框的IoU的值。目标的密度表示拥挤遮挡的程度。
使用这个定义,我们提出更新下面策略中的移除步骤,
\[N_\mathcal{M} := \max(N_t, d_\mathcal{M})\]
\(N_t\)表示对于\(\mathcal{M}\)的adaptive NMS的阈值,\(d_{\mathcal{M}}\)表示目标\(\mathcal{M}\)覆盖的密度。
这个抑制策略有三个性质: 1. 当相邻的框远离\(\mathcal{M}\)时,即\(\mathrm{iou}(\mathcal{M}, b_i) < N_t\),它们与原始NMS保持一致。 2. 如果\(\mathcal{M}\)定位到拥挤的区域,即\(d_{\mathcal{M}} > N_t\),\(\mathcal{M}\)的密度被使用作为adaptive NMS的阈值。 3. 对与稀疏区域的目标,即\(d_{\mathcal{M}} \leq N_t\),NMS阈值\(N_\mathcal{M}\)和原始NMS阈值相等,非常接近的框被作为假正例所抑制。
这个算法具体步骤如图2所示。
作者把密度估计作为一个回归问题,目标密度值的计算根据它的定义,使用Smooth-L1损失函数作为训练损失。
一个天然的方式就是为这个回归在网络顶部添加一个并行的层,像分类和定位一样。然而,用于检测的特征仅仅包含目标自己的信息,比如外表、语义特征和位置。对于密度估计,使用独立目标的信息很难估计其密度,密度估计需要使用其周围目标的更多的线索。
为了解决这个,作者设计了一个额外的网络,它由三层卷积层构成,如图3所示。首选使用一个1x1的卷积层做特征维度降维,然后级联降维后的特征、用于RPN分类的特征和用于RPN回归的特征。最后使用一个大尺度的卷积核5x5作为最后的卷积层,为了把周围的信息送入网络。具体如图中Density subnet绿色框区域结构。
卷积神经网络(CNNs)的核心模块是卷积操作,这个操作使得网络能够通过每层的局部感受野融合空间和通道的信息,来构建有信息的特征。之前大量的工作已经研究了这种关系的空间组成部分,试图通过提高整个特征层次中空间编码的质量来增强CNN的表征能力。在这项工作中,作者将重点放在通道关系上,并且提出一个新的构架单元,成为“Squeeze-and-Excitation”(SE)块,通过明确地建模通道之间的相互依赖性来自适应地重新校准通道方面的特征响应。
来自https://github.com/moskomule/senet.pytorch/blob/master/senet/se_module.py的se_module.py文件
1 |
|
PIL(Python Image Library)是python的第三方图像处理库。其官方主页为:PIL。 PIL历史悠久,原来是只支持python2.x的版本的,后来出现了移植到python3的库pillow, pillow号称是friendly fork for PIL。
Pillow is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.
for Python2 Python Imaging Library (PIL)
for Python3 The Python Imaging Library Handbook
1 | from PIL import Image |
从一个文件加载图片,使用在Image
模块下的open()
函数。
1 | im = Image.open("lena.jpg") |
如果成功,这个函数会返回一个Image
目标。你可以使用实例属性去测试这个文件的内容:
1 | from __future__ import print_function |
JPEG (512, 512) RGB
format
属性判断图片的来源。如果一个图片不是从一个文件读入,它会被设置成None。size
属性是一个2元组,包含宽和高。mode
属性定义图片通道的数量和名字,以及像素类型和深度。通常的模式包含:“L”(luminance)表示灰度图像,”RGB“表示真彩色图像,”CMYK“表示印前(pre-press)图像
如果文件没有被打开,会给出IOError
。
一旦你有一个Image
类的实例,你可以使用这个类定义的方法取处理这个图片。例如,显示我们刚加载的图片:
1 | im.show() |
使用matplotlib进行可视化
1 | plt.imshow(im) |
<matplotlib.image.AxesImage at 0x7f1173b85518>
Image
类包含允许您操作图像中的区域的方法。要从图像中提取矩形区域,请使用crop()
方法。
1 | box = (100, 100, 400, 400) |
(300, 300)
这个区域使用一个4元组定义,它的坐标是(left, upper, right, lower)。Python Imaging Library在左上角使用(0, 0)的坐标系统。坐标表示像素之间的位置,因此上边例子中的区域是300x300像素。
1 | region = region.transpose(Image.ROTATE_180) |
<matplotlib.image.AxesImage at 0x7f11721e2518>
当把区域粘贴回去,区域的尺寸必须相同。除此之外,这个区域不能超越图像的边界。
1 | def roll(image, delta): |
1 | r, g, b = im.split() |
<matplotlib.image.AxesImage at 0x7f11721c9b38>
1 | im.save(r'out.jpg') |
1 | newIm= Image.new('RGB', (50, 50), 'red') |
<matplotlib.image.AxesImage at 0x7f1175c2d630>
1 | # 十六进制颜色 |
<matplotlib.image.AxesImage at 0x7f1175bfd8d0>
1 | # 传入元组形式的RGBA值或者RGB值 |
<matplotlib.image.AxesImage at 0x7f1175bd1be0>
1 | copyIm = im.copy() |
(512, 512)
1 | width, height = copyIm.size |
(512, 256)
1 | im = Image.open("lena.jpg") |
<matplotlib.image.AxesImage at 0x7f11721370b8>
1 | out = im.transpose(Image.FLIP_LEFT_RIGHT) |
<matplotlib.image.AxesImage at 0x7f1172111080>
1 | from PIL import Image |
L
1 | from PIL import ImageFilter |
<matplotlib.image.AxesImage at 0x7f1172073860>
1 | # 高斯模糊 |
<matplotlib.image.AxesImage at 0x7f117204f470>
1 | # 边缘增强 |
<matplotlib.image.AxesImage at 0x7f1171faf0b8>
1 | # 普通模糊 |
1 | # multiply each pixel by 1.2 |
1 | from PIL import ImageEnhance |
<matplotlib.image.AxesImage at 0x7f1171f906a0>
1 | from PIL import Image |
1 | plt.imshow(im) |
<matplotlib.image.AxesImage at 0x7f1171eec208>
1 | from PIL import ImageSequence |
1 | from PIL import Image |
%!PS-Adobe-3.0save/showpage { } def%%EndComments%%BeginDocument/S { show } bind def/P { moveto show } bind def/M { moveto } bind def/X { 0 rmoveto } bind def/Y { 0 exch rmoveto } bind def/E { findfont dup maxlength dict begin { 1 index /FID ne { def } { pop pop } ifelse } forall /Encoding exch def dup /FontName exch def currentdict end definefont pop} bind def/F { findfont exch scalefont dup setfont [ exch /setfont cvx ] cvx bind def} bind def/Vm { moveto } bind def/Va { newpath arcn stroke } bind def/Vl { moveto lineto stroke } bind def/Vc { newpath 0 360 arc closepath } bind def/Vr { exch dup 0 rlineto exch dup neg 0 exch rlineto exch neg 0 rlineto 0 exch rlineto 100 div setgray fill 0 setgray } bind def/Tm matrix def/Ve { Tm currentmatrix pop translate scale newpath 0 0 .5 0 360 arc closepath Tm setmatrix} bind def/Vf { currentgray exch setgray fill setgray } bind def%%EndProloggsave226.560000 370.560000 translate0.960000 0.960000 scalegsave10 dict begin/buf 384 string def128 128 scale128 128 8[128 0 0 -128 0 128]{ currentfile buf readhexstring pop } bindfalse 3 colorimage%%%%EndBinarygrestore endgrestore72 144 M 504 720 0 Vr/PSDraw-HelveticaNarrow-Bold ISOLatin1Encoding /HelveticaNarrow-Bold E/F0 36 /PSDraw-HelveticaNarrow-Bold F216 288 M (hopper) S%%EndDocumentrestore showpage%%End
1 | from PIL import Image |
<matplotlib.image.AxesImage at 0x7f1171d5a400>
1 | from PIL import Image |
1 | im = Image.open("lena.jpg") |
original = RGB (512, 512)draft = L (128, 128)
1 |
本文主要解决在one-stage的密集检测器中,大量前景和背景不平衡的问题。作者通过降低被很好分类样本的权重来解决类别不平衡的问题。Focal Loss集中于在稀疏难样本(hard examples)上的训练,并且在训练中防止大量的容易的反例(easy negatives)淹没检测器。
作者提出一个新的损失函数 Focal Loss, 该方法通过添加因子\((1-p_t)^\gamma\)到标准的交叉熵损失函数。设定\(\gamma>0\)会减少被很好分类样本(\(p>0.5\))的相对损失,更加关注于难和错误分类的样本。
图中显示了,RetinaNet检测器使用了focal loss,结果由于之前的one-stage和two-stage检测器。
在R-CNN这一类检测器中,类别不平衡问题通过two-stage级联和采样策略被解决。在候选区域提取阶段,Selective Search, EdgeBoxes, RPN等方法,缩小候选区域位置的数量到1~2k个,大量过滤掉了背景。在第二分类阶段,采样策略,例如固定前景背景比率(1:3),或者在线难样本挖掘(OHEM)方法被执行用于保持前景和背景的一个可控的平衡。
Focal Loss被设计用以解决one-state目标检测器训练中大量正反例样本不平衡的问题,通常是(1:1000)。我们首先介绍二值分类的交叉熵损失:
\[ CE(p, y)=\begin{cases}-log(p) & y=1\\-log(1-p) & otherwise.\end{cases} \]
一种通用的解决类别不平衡的方法是对类别1引入一个权重因子\(\alpha \in [0, 1]\),对类别class-1引入\(1-\alpha\)。我们写成\(\alpha-\)balanced CE loss:
\[CE(p_t)=-\alpha_t log(p_t)\]
试验中显示,在训练dense detectors是遭遇的大量类别不平衡会压倒交叉熵损失。容易分类的样本会占损失的大部分,并且主导梯度。尽管\(\alpha\)平衡了正负(positive/negative)样本的重要性,但是它没有区分易和难的样本(easy/hard)。相反,作者提出的更改过后的损失函数降低了容易样本的权重并且集中训练难反例样本。
我们定义focal loss:
\[FL(p_t)=-(1-p_t)^\gamma log(p_t)\]
Two-stage检测器通常没有使用\(\alpha-\)balancing 或者我们提出的loss。代替这些,他们使用了两个机制来解决类别不平衡问题:(1) 一个两级的级联,(2) 有偏置的小批量采样。第一级联阶段的候选区域提取机制减少了大量可能的候选位置。重要的是,这些选择的候选框不是随机的,而是选择更像前景的可能位置,这样就移除了大量的容易的难反例样本(easy negatives)。第二阶段,有偏置的采样通常使用1:3比率的正负样本构建小批量(minibatches)。这个采样率类似\(\alpha-\)balancing因子,并且通过采样来实现。作者提出的focal loss主要设计用于解决one-stage检测系统中的这些问题。
]]>@(工具学习记录)[Docker]
参考官网教程
1 | $ sudo apt-get remove docker docker-engine docker.iSET UP THE REPOSITORY |
SET UP THE REPOSITORY
1 | $ sudo apt-get update |
1 | $ sudo apt-get install \ |
1 | $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - |
1 | $ sudo apt-key fingerprint 0EBFCD88 |
x86_64/amd64 1
2
3
4$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
更新包的索引 1
$ sudo apt-get update
安装最新版本的Docker CE 1
$ sudo apt-get install docker-ce
安装特定版本Docker CE 1
2
3$ apt-cache madison docker-ce
docker-ce | 18.03.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
验证是否安装正确 1
$ sudo docker run hello-world
参考nvidia-docker nstalling version 2.0
Debian-based distributions 1
2
3
4
5
6curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
1 | sudo apt-get install nvidia-docker2 |
参考detectron install 1
2cd $DETECTRON/docker
docker build -t detectron:c2-cuda9-cudnn7 .
运行这个镜像 1
nvidia-docker run --rm -it detectron:c2-cuda9-cudnn7 python detectron/tests/test_batch_permutation_op.py
docker run :创建一个新的容器并运行一个命令 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。
docker run --name mynginx -d nginx:latest
使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。
docker run -P -d nginx:latest
使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。
docker run -p 80:80 -v /data:/data -d nginx:latest
绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.1 的 80 端口上。
$ docker run -p 127.0.0.1:80:8080/tcp ubuntu bash
使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
runoob@runoob:~$ docker run -it nginx:latest /bin/bash
root@b8573233d675:/#
docker rm :删除一个或多少容器
语法 1
docker rm [OPTIONS] CONTAINER [CONTAINER...]
OPTIONS说明:
-f :通过SIGKILL信号强制删除一个运行中的容器
-l :移除容器间的网络连接,而非容器本身
-v :-v 删除与容器关联的卷docker rm :删除一个或多少容器
语法 docker rm [OPTIONS] CONTAINER [CONTAINER...] OPTIONS说明:
-f :通过SIGKILL信号强制删除一个运行中的容器
-l :移除容器间的网络连接,而非容器本身
-v :-v 删除与容器关联的卷 1
2
3
4
5
6
7
8
9强制删除容器db01、db02
docker rm -f db01 db02
移除容器nginx01对容器db01的连接,连接名db
docker rm -l db
删除容器nginx01,并删除容器挂载的数据卷
docker rm -v nginx01
docker exec :在运行的容器中执行命令 1
2
3
4
5
6
7
8在容器mynginx中以交互模式执行容器内/root/runoob.sh脚本
runoob@runoob:~$ docker exec -it mynginx /bin/sh /root/runoob.sh
http://www.runoob.com/
在容器mynginx中开启一个交互模式的终端
runoob@runoob:~$ docker exec -i -t mynginx /bin/bash
root@b1a0703e41e7:/#
docker commit :从容器创建一个新的镜像。 - -a :提交的镜像作者; - -c :使用Dockerfile指令来创建镜像; - -m :提交时的说明文字; - -p :在commit时,将容器暂停。
将容器a404c6c174a2 保存为新的镜像,并添加提交人信息和说明信息。 1
2
3
4
5runoob@runoob:~$ docker commit -a "runoob.com" -m "my apache" a404c6c174a2 mymysql:v1
sha256:37af1236adef1544e8886be23010b66577647a40bc02c0885a6600b33ee28057
runoob@runoob:~$ docker images mymysql:v1
REPOSITORY TAG IMAGE ID CREATED SIZE
mymysql v1 37af1236adef 15 seconds ago 329 MB
1 | 将主机./RS-MapReduce目录拷贝到容器30026605dcfe的/home/cloudera目录下。 |
Python渐渐成为最流行的编程语言之一,在数据分析、机器学习和深度学习等方向Python语言更是主流。Python的版本比较多,并且它的库也非常广泛,同时库和库之间存在很多依赖关系,所以在库的安装和版本的管理上很麻烦。Conda是一个管理版本和Python环境的工具,它使用起来非常容易。
首先你需要安装Anconda软件,点击链接download。选择对应的系统和版本类型。
1 | # 创建一个名为python34的环境,指定Python版本是3.5(不用管是3.5.x,conda会为我们自动寻找3.5.x中的最新版本) |
1 | # 安装好后,使用activate激活某个环境 |
1 | # 如果想返回默认的python 2.7环境,运行 |
1 | # 删除一个已有的环境 |
用户安装的不同Python环境会放在~/anaconda/envs
目录下。查看当前系统中已经安装了哪些环境,使用conda info -e
。
1 | user@user-XPS-8920:~$ conda info -e |
为当前环境安装库 1
2
3# numpy
conda install numpy
# conda会从从远程搜索numpy的相关信息和依赖项目
### 查看已经安装的库
1 | # 查看已经安装的packages |
1 | # 查看某个指定环境的已安装包 |
1 | # 查找package信息 |
1 | Loading channels: done |
1 | # 安装package |
1 | # 更新package |
1 | # 删除package |
1 | # 更新conda,保持conda最新 |
1 | # 更新anaconda |
1 | # 更新python |
因为Anaconda.org的服务器在国外,所有有些库下载缓慢,可以使用清华Anaconda镜像源。
网站地址: 清华大学开源软件镜像站
Anaconda 安装包可以到 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 下载。
TUNA还提供了Anaconda仓库的镜像,运行以下命令: 1
2
3conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes
即可添加 Anaconda Python 免费仓库。
运行 conda install numpy
测试一下吧。
Miniconda 是一个 Anaconda 的轻量级替代,默认只包含了 python 和 conda,但是可以通过 pip 和 conda 来安装所需要的包。
Miniconda 安装包可以到 https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ 下载。
]]>本代码来自Machine Learning in Action。
想要了解更多的朋友可以参考此书。
\[\sigma(z) = \frac{1}{(1+e^{-z})}\]
1 | import numpy as np |
1 | z = np.linspace(-60, 60, 100) |
Sigmoid函数类似一个单位阶跃函数。当x=0时,Sigmoid函数值为0.5;随着x增大,Sigmoid函数值将逼近于1;随着x减小,Sigmoid函数将逼近于0。利用这个性质可以对它的输入做一个二分类。
为了实现Logistic回归分类器,我们可以在每个特征上都乘以一个回归系数,然后把它的所有的结果值相加,将这个总和带入Sigmoid函数中,进而得到一个范围在0~1之间是数值。当大于0.5的时候,将数据分类为1;当小于0.5的时候,将数据分类为0。
Sigmoid函数的输入记为z:
\[z=w_0x_0 + w_1x_1 + w_2x_2 + \cdot \cdot \cdot + w_n x_n\]
Sigmoid导数具体推导过程如下:
\[\begin{align} f^{\prime}(z) &= (\frac{1}{1+e^{-z}})^{\prime}\\\&=\frac{e^{-z}}{(1+e^{-z})^2}\\\&=\frac{1+e^{-z}-1}{(1+e^{-z})^2}\\\&=\frac{1}{(1+e^{-z})}(1-\frac{1}{(1+e^{-z})})\\\&=f(z)(1-f(z))\end{align}\]
梯度上升法:顾名思义就是利用梯度方向,寻找到某函数的最大值。
梯度上升算法迭代公式: \[w:=w+\alpha \nabla_w f(w)\]
梯度下降法:和梯度上升想法,利用梯度方法,寻找某个函数的最小值。 梯度下降算法迭代公式: \[w:=w-\alpha \nabla_w f(w)\]
梯度上升算法每次更新之后,都会重新估计移动的方法,即梯度。
1 | def loadDataSet(): |
1 | dataArray, labelMat = loadDataSet() |
('Total: ', 100)('The first sample: ', [1.0, -0.017612, 14.053064])('The second sample: ', [1.0, -1.395634, 4.662541])('Label: ', [0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0])
1 | def sigmoid(inX): |
1 | gradAscent(dataArray, labelMat) |
matrix([[ 4.12414349], [ 0.48007329], [-0.6168482 ]])
1 | def plotBestFit(weights): |
1 | weights = gradAscent(dataArray, labelMat) |
梯度上升算法在每次更新系数的时候都需要便利整个数据集,如果数据集的样本比较大,该方法的复杂度和计算代价就很高。有一种改进的方法叫做随机梯度上升方法。该方法的思想是选取一个样本,计算该样本的梯度,更新系数,再选取下一个样本。
1 | def stocGradAscent0(dataMatrix, classLabels): |
1 | weights = stocGradAscent0(np.array(dataArray), labelMat) |
上图之后遍历了一次数据集,这样的模型还处于欠拟合状态。需要多次遍历数据集才能优化好模型,接下来我们会运行200次迭代。
1 | def stocGradAscent0(dataMatrix, classLabels): |
1 | weights, X0, X1, X2 = stocGradAscent0(np.array(dataArray), labelMat) |
1 | fig, ax = plt.subplots(3, 1, figsize=(10, 5)) |
从上图可以看出,算法正在逐渐收敛。由于数据集并不是线性可分的,所以存在一些不能正确分类的样本点,每次更新权重引起了周期的变化。
1 | def stocGradAscent1(dataMatrix, classLabels, numIter=150): |
1 | weights, X0, X1, X2 = stocGradAscent1(np.array(dataArray), labelMat) |
1 | fig, ax = plt.subplots(3, 1, figsize=(10, 5)) |
1 | def classifyVector(inX, weights): |
1 | multiTest() |
/home/tianliang/anaconda2/lib/python2.7/site-packages/ipykernel_launcher.py:2: RuntimeWarning: overflow encountered in exp the error rate of this test is: 0.328358the error rate of this test is: 0.432836the error rate of this test is: 0.388060the error rate of this test is: 0.373134the error rate of this test is: 0.373134the error rate of this test is: 0.447761the error rate of this test is: 0.343284the error rate of this test is: 0.313433the error rate of this test is: 0.328358the error rate of this test is: 0.462687after 10 iterations the average error rate is: 0.379104
]]>CornerNet: Detection Objects as Paired Keypoints 这篇论文发表在ECCV2018,本人感觉非常有意思,所以和大家分享一下。
Arxiv: https://arxiv.org/abs/1808.01244 Github: https://github.com/umich-vl/
]]>本文档同步至github:here
Leotju/MGAN [ICCV-2019] Mask-Guided Attention Network for Occluded Pedestrian Detection [paper]
lw396285v/CSP-pedestrian-detection-in-pytorch 非官方实现 [CVPR-2019] High-level Semantic Feature Detection:A New Perspective for Pedestrian Detection [paper]
liuwei16/CSP [CVPR-2019] High-level Semantic Feature Detection:A New Perspective for Pedestrian Detection [paper]
liuwei16/ALFNet [ECCV-2018] Learning Efficient Single-stage Pedestrian Detectors by Asymptotic Localization Fitting
rainofmine/Bi-box_Regression 非官方实现 [ECCV-2018] Bi-box Regression for Pedestrian Detection and Occlusion Estimation
rainofmine/Repulsion_Loss 非官方实现 [CVPR-2018] Repulsion Loss: Detecting Pedestrians in a Crowd
garrickbrazil/SDS-RCNN [ICCV-2017] Illuminating Pedestrians via Simultaneous Detection & Segmentation
zhangliliang/RPN_BF [ECCV-2016] Is Faster R-CNN Doing Well for Pedestrian Detection?
- paper: https://arxiv.org/abs/1904.02948
- paper: https://arxiv.org/abs/1904.02948 - github: https://github.com/liuwei16/CSP
- paper: https://arxiv.org/abs/1902.09080v1
- paper: - project website: - slides: - github:
CityPersons数据集是在Cityscapes数据集基础上建立的,使用了Cityscapes数据集的数据,对一些类别进行了精确的标注。该数据集是在[CVPR-2017] CityPersons: A Diverse Dataset for Pedestrian Detection这篇论文中提出的,更多细节可以通过阅读该论文了解。
上图中左侧是行人标注,右侧是原始的CityScapes数据集。
文件格式
1 | #评测文件 |
注释文件格式 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24CityPersons annotations
(1) data structure:
one image per cell
in each cell, there are three fields: city_name; im_name; bbs (bounding box annotations)
(2) bounding box annotation format:
one object instance per row:
[class_label, x1,y1,w,h, instance_id, x1_vis, y1_vis, w_vis, h_vis]
(3) class label definition:
class_label =0: ignore regions (fake humans, e.g. people on posters, reflections etc.)
class_label =1: pedestrians
class_label =2: riders
class_label =3: sitting persons
class_label =4: other persons with unusual postures
class_label =5: group of people
(4) boxes:
visible boxes [x1_vis, y1_vis, w_vis, h_vis] are automatically generated from segmentation masks;
(x1,y1) is the upper left corner.
if class_label==1 or 2
[x1,y1,w,h] is a well-aligned bounding box to the full body ;
else
[x1,y1,w,h] = [x1_vis, y1_vis, w_vis, h_vis];
With over 238200 person instances manually labeled in over 47300 images, EuroCity Persons is nearly one order of magnitude larger than person datasets used previously for benchmarking. Diversity is gained by recording this dataset throughout Europe.
Object Class | # objects (day) | # objects (night) | # objects (sum) |
---|---|---|---|
Pedestrian | 183004 | 35309 | 218313 |
Rider | 18216 | 1564 | 19780 |
数据来自 CityPersons 官网。
Method | MR (Reasonable) | MR (Reasonable_small) | MR (Reasonable_occ=heavy) | MR (All) |
---|---|---|---|---|
YT-PedDet | 8.41% | 10.60% | 37.88% | 37.22% |
STNet | 9.78% | 10.95% | 36.16% | 31.36% |
DVRNet | 10.99% | 15.68% | 43.77% | 41.48% |
HBA-RCNN | 11.06% | 14.77% | 43.61% | 39.54% |
OR-CNN | 11.32% | 14.19% | 51.43% | 40.19% |
Repultion Loss | 11.48% | 15.67% | 52.59% | 39.17% |
Adapted FasterRCNN | 12.97% | 37.24% | 50.47% | 43.86% |
MS-CNN | 13.32% | 15.86% | 51.88% | 39.94% |
版本:0.0.1
作者:张天亮
邮箱:zhangtianliang13@mails.ucas.ac.cn
Github 加载 .ipynb 的速度较慢,建议在 Nbviewer 中查看该项目。
大部分内容来自keras项目中的examples