(grounding) DINO 阅读笔记

DEtection with TRansformers 阅读笔记

DEtection with TRansformers 阅读笔记

模型结构

CNN Backbone

常规做法, 用来特征提取。输出一个 C * HW 的特征图。

Transformer

  • 多头注意力机制
  • pos_embed 给 sum 到 Encoder 的 query 和 key 里
  • Decoder 里固定查 N = 100 个 token

FFN

实际上就是 1*1 的卷积。

数据

COCO Dataset

训练

计算损失

由于产出 100 个检测结果,故而和事实做二分图匹配,跑个 Hungarian 算法即可获得匹配关系。

DINO 阅读笔记

Preliminaries

论文提到两个对它影响比较大的工作:

  • DAB-DETR 将 positional query 描述成 R^4 里的一个向量 (x, y, w, h)
  • DN-DETR 认为收敛缓慢可能是因为二分图匹配不够稳定,因此引入 denosing ,将带噪声的 label 和 box 送入 DETR
  • Deformable DETR 让 attention 关注 sampling points 周围的一小部份点。首先它引入了 query selection 技术(直接从 encoder 的输出提取 features 和 reference boxes);其次是它用了所谓梯度分离技术,这里叫它 look forward once

Backbone

分别用 ResNet-50 和 SwinL 作为 backbone

模型

  • look forward twice: 一个类似 residual connection 的操作,用来减少梯度消失的风险
  • Mixed Query Selection: 选择 top-k 个 feature 传入 decoder

训练

  • Contrastive DeNoising Training (CDN) ,将 Ground Truth 内的作为正样本,外的作为负样本,可以避免重复预测。

Grounding DINO 阅读笔记

Preliminaries

提出一个范式:Backbone 用于 feature extraction, neck 用于 feature enchancement, head 用于 region refinement(box prediction)

模型

image 经过一个 Swin-T 作为 backbone, 而 text 则经过一个 BERT

然后是一个 Feature Enhance Layer, SAM 和它有点相似,都是 image 和 text (在 SAM 里是 prompt) 各经过一个 self-attention / deformable self-attention 以后做一个双向的 cross-attention, 然后各 FFN 以后输出。

接着是 Language-Guided Query Selection, 这个部分首先将 image 和 text 的 feature 沿第三维卷积,取 max 作为 img feat,最后取 topk 返回。

接着是 Cross-Modality Decoder, 将 Query 经过 self-attention 以后,取 Q 分别和 Image Features, Text Features 的 K, V 做 Cross-Attention ,再过一个 FFN 以后输出。

输入

处理 Text Prompt: 以往采用两种 text prompt, 作者称之为 Sentence Level 和 Word Level; 在这里则使用了 Sub-sentence Level

训练

  • 类似 DETR, 仍然是先二分图匹配再计算损失

Ablations

消融实验认为 Encoder fusion 是最重要的部份

Segment Anything Model 阅读笔记

Segment Anything Model(SAM) 阅读笔记

模型架构

模型主要由三个部份组成,一个笨重的 image encoder ,用于将图像 embedding;一个轻量级的 prompt encoder 和一个轻量级的 mask decoder,

Image Encoder

Vision Transformer(ViT)

这个部份采用了 NLP 领域常用的 Transformer 思想。

输入图片首先经过 PatchEmbed 模块。在这里,将图片切割成 16 * 16 个 patch, 每个 patch 的维度是 768.

然后,如果启用 absolute positional embeddings, 也就是位置信息,那么直接将它 sum 到 patch embedding 上。

接下来通过一组 depth 个的 transformer blocks. 这里使用了 Multihead Attention,然后再经过一个激活函数是 GeLU 的 MLP 。 这里它使用了 Window Attention ,也就是每次自注意力只关注一个局部。论文称它使用了 14 * 14 的 Window。同时还加上了 relative positional embeddings。

Reduce Channel Dimension

在这里它参照了Exploring Plain Vision Transformer Backbones for Object Detection,把输出先后通过 1 * 1, 256 channel 和 3 * 3, 256 channel 的卷积压缩。每次卷积后 LayerNorm 一次。

Prompt Encoder

将输入分成以下四种:

  • 一个点:将 positional encoding 和一个表示它是在前景还是背景的 embedding 相加。
  • 一个框:分别用两个 embedding 表示左上角和右下角。
  • mask:可能是用于训练,直接塞入 dense_prompt_embedding ,sparse 项置零。
  • 无输入:单独的 embedding,表示 no prompt.

分别传出两个部份 sparse_prompt_embeddingdense_prompt_embedding

Lightweight mask Decoder

传入的信息包括两个部份:

  • token:这里包括两个 Embedding :iou_tokenmask_token ,还有 prompt encoder 传出的 sparse_prompt_embedding ,将他们 concatenate 在一起。
  • src:这个部分将 image_embeddingdense_prompt_embedding sum 在一起。

接下来将 src 和 pos_src (分别代表 prompt 的信息和 image 的信息)放入 TwoWayTransformer 。分别用两个 cross attention 来处理 token 和 image 之间的相互关系。

一个 upscaling,然后生成 4 个 mask token ;同时预测一个 IoU (用来给结果质量排序)

Ambiguity-aware

这个部分主要问题是可能会把多个有效输出的 mask 给平均掉。「observe that」的处理方案是同时预测并输出三个 mask(代表整体,部份和子部份),同时预测一个 IoU 给结果排序,并且只考虑质量最好的 loss 来反向传播。

同时如果给出多个 prompt 的话只返回一个(多个 prompt 足以确认一个有效输出),为了不和前面混淆总共需要生成 4 个 mask。

数据

原文用了很大篇幅来解释数据的采样在种族,国家和生存环境上的多样性。

数据集生成

原始数据是从某个摄影公司处获取的,同时附有

大致分成三个步骤

  • Assisted-manual stage: 这个阶段主要由打标人在一个 web 端上用一些工具来打标
  • Semi-auto stage: 这个阶段标记出 confident masks,然后要求打标人给其他的对象打标
  • Fully-auto stage: 这个部份用一个 32 * 32 的 point 型 prompt 来生成一组 masks,然后根据预测的 IoU 来筛选

一些 trick

  • 只保留 confident mask ,也就是 IoU > 88.0
  • 去除覆盖超过 95% 的 mask,提升 mask 质量,同时处理掉过小(100像素)的 spurious holes 和 components

训练

Losses

用 focal loss 和 dice loss 的 20:1 的线性组合来监督 mask 用 mean-square-error loss 监督 IoU 预测,factor 是 1.0

Training Algorithm

等概率选择 foreground point 或者 bounding box,然后加一些扰动。

之后从误差区域里加入新的采样点作为 prompt

把前一代的 mask 作为 prompt 塞给后一代(这可能是前面 prompt encoder 中 mask 的作用)

由于 prompt encoder 和 mask decoder 的开销很小(不足 1% 相对 image encoder),所以可以支持多步迭代(这里选择了 1 次初始,8 次更新采样点,然后 2 次没有额外信息的迭代)

Zero-shot Text-to-Mask

The key observation here is that because CLIP’s image embeddings are trained to align with its text embeddings, we can train with image embeddings, but use textembeddings for inference. That is, at inference time we run text through CLIP’s text encoder and then give the resulting text embedding as a prompt to SAM.

用 CLIP 的 image embedding 做训练,用 text embeddings 作推理。很深刻。

知识图谱领域部份论文阅读笔记:TransE/H/R/D RotatE PairRE


知识图谱领域部份论文阅读笔记:TransEHRD RotatE PairRE

Trans E

Translating Embeddings

基本概念

将集合里的关系和实体各嵌入(embedding)成 中的一个向量。 Trans E 的合法性是基于下述假设:

设关系 嵌入为 ,实体 嵌入为向量

对于实体 和关系 ,关系 成立当且仅当 在向量空间成立

流程

input: 训练集 , 实体 , 关系 ,差额 , 图谱维度
//为何是 6?

loop:

  • //b 是集合大小
  • for each //在这里 h’ 和 t’ 表示二者之一随机替换成其他实体

这样训练的参量规模是 的。

SGD

上一节我们提到了 是损失函数。

其中 是:

其中表示 意义下的范数, 表示 范数,意义是对自己应用乘法以后开根号。上式可以理解为 的简单展开。

当然这里的加法和乘法(包括乘方)都是构成 的群操作和域操作。

Trans H

Translating Hyperplanes

基本概念

事实上, Trans E 的假设是建立在关系集合 中每一个单独的关系 对应的图的边的出入度都至少为 的基础上。

倘若任意关系 存在度数不为 的点,那么在把元素映射到线性空间时 就会迫使这个度数不为 的点相邻的点映射到相近的位置。尽管它们可能完全不同。

Trans H 为了解决这个问题做出如下假设:

设关系 嵌入为法向量为 维超平面及其上的向量 ,实体 嵌入为向量

则对于实体 和关系 ,关系 成立当且仅当 恒成立。

其中:

如果说 Trans E 是把关系集合里的每一张图都嵌入成 中的一个向量,那 Trans H 就是改为把这张图嵌入成 中的 维超平面及其上的一个向量。显然,听起来把一张图嵌入成一个平面比嵌入成一个向量科学很多。

损失函数

其中

其中 表示先后的情况。

这样训练的参量规模是 的。

 

Trans R

Translating Relations

基本概念

Trans H 把每个关系的那张图嵌入到一个平面中,而 Trans R 则认为每个关系是将原空间进行一次线性变换,然后线性变换之后,关系两端的向量会各自聚成一堆。因此,它做出如下假设:

设关系 可被看做 上的某种线性变换 和变换后的向量空间中的向量 ,实体 嵌入为向量

则关系 成立当且仅当 在向量空间成立。

 

损失函数

损失函数基本同上。

同样地有评分函数

损失函数也同理。

CTrans R

所谓 Cluster-based TransR ,基于聚类的 Trans R

基本思路是对映射后的实体对的差值做聚类。

对于每个聚类 得到评分函数:

显著缺点

Trans R 在性能上存在一个明显的缺点:线性变换需要一个 级别的矩阵,因此需要训练的参量规模是 级别的。这意味着,随着对拟合度要求的提高(即向量空间维数 的增加),参量规模会显著提升并迅速变得不可接受。

Trans D

Translating Dynamic Mapping Matrix

基本概念

Trans D 认为,前面的几种模型是建立在反对称的关系上的。但事实上,关系未必总是反对称(甚至可能是对称的)。所以,在一些特定的样本中,前述模型就会出现问题。

一个自然的想法就是区分头实体和尾实体。

Trans D 于是尝试将每个实体各自嵌入到两个向量:它的位置,和它作为头/尾实体时的调整。

它作出如下假设:

设关系 嵌入为 上的位置向量 和投影向量 ,实体 嵌入为位置向量 和投影向量

则关系 成立当且仅当 在向量空间成立。

其中:

这样处理,除了可以拟合非对称的关系以外还有一个优点就是它显著降低了参量规模。因为这里的线性变换矩阵 是通过投影向量实时(所谓的 Dynamic !)生成的,所以参量规模降低到了 。当然,这一定层度上会降低拟合效率。

损失函数

估价函数是:

RotatE

Rotate Embedding(大概)

基本概念

上述的模型都是将关系对映射到 的。自然地联想到,可以尝试将它映射到其他向量空间中。一个可以考虑的对象是

RotatE 上作出如下假设:

设关系 嵌入为 ,实体 嵌入为向量

关系 成立当且仅当 在向量空间成立。

其中 表示 Hadamard 积,而非作用在 上的那个域的乘法(内积)。

那么有距离函数:

这里的范数是内积意义上的。(显然, Hadamard 积不能导出范数)

RotatE 相比与 Trans E 的一大优势是它良好地解决了对称关系的问题:如果 的每一个分量都是 的话,它就代表一个对称关系。

最优化方案

最优化的核心仍然是设计损失函数。 RotatE 采用了一种被称为「负采样」的损失函数设计方式:

其中 Sigmoid 函数,即 是各自将其第 个分量替换以后得到的向量。 是负样本集合规模。

自对抗采样

设计权值函数

其中 是一个「温度」参量。这个权重将替换上文的 而作为每个样本的权重。

这是因为作者认为不同的负样本在学习的时候能够提供不同的启发性。如果一个负样本的估值函数很正,说明它还没有被良好地和正样本区分开,那它就需要加上更多的权重;反之,它就已经被良好地区分开了,于是就不必特别考虑它的影响。这种方法可以有效提升训练效率。

PairRE

Paired Relation Embedding

基本概念

上述的模型常常遇到一个问题,就是无法同时优质拟合多对多、 对多、多对 的关系。就是说,它对度数分布比较复杂的关系拟合可能会出现问题。因为误差参量(margin) 是个固定值。

PairRERotatE 的基础上做了一些改良。它结合了 Trans D 的思想,作出如下假设:

设关系 嵌入为 ,实体 嵌入为向量

关系 成立当且仅当 在向量空间成立。

其中 表示Hadamard 积。

另外, PairRE 还做到了较好的拟合子关系:

若存在子关系对 ,使得 ,则施加如下约束:

这样就能推导出前者。证明是显然的。

PairRE 的另一个特点是区分了多对多、 对多、多对 的关系。类似于 Trans D ,它通过区分每个关系向量和头实体的相关与其和尾实体的相关,得到了j较好的拟合性。

中间有一些精妙的数学推导,详见论文。

最优化

估价函数:

同样是进行了负采样和自对抗采样。

论文打包下载地址:http://SmokeyDays.top/wordpress/wp-content/uploads/2022/04/KGE-References-TransEHRD-RotatE-PairRE.zip

PyTorch 环境配置踩坑记录 – 1

首先配好 Anaconda

参照https://blog.csdn.net/weixin_47525457/article/details/115287373

1.5G的包始终装不上

用镜像。如清华提供的镜像:

 https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
 https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/

CUDA 不匹配

典型报错:

The current PyTorch install supports CUDA capabilities sm_37 sm_50 sm_60 sm_61 sm_70 sm_75 compute_37.
If you want to use the GeForce RTX 3060 Laptop GPU GPU with PyTorch, please check the instructions at https://pytorch.org/get-started/locally/

在NVIDIA的控制面板里查看CUDA版本,我是11.6.58,故而在下载Pytorch的时候应当使用这样的指令:

conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch

OSError: [WinError 1455] 页面文件太小,无法完成操作。

往往体现在。

Error loading “\site-packages\torch\lib\caffe2_detectron_ops_gpu.dll“ or one of its dependencies.

首先需要在控制面板-查看高级系统设置中,给Python的安装盘(我是D盘)配置额外的虚拟内存。

参见https://www.cnblogs.com/blue-lin/p/14982097.html

同时调小 BATCH_SIZE 和 num_workers。

之所以调小后者,可参见:

https://github.com/ultralytics/yolov3/issues/1643#issuecomment-985652432

这个comment讲得鞭辟入里。

具体来说就是,它会载入一个dll文件,尽管这个dll文件里的绝大部分都用不到;windows系统会给它预留非常充分的内存;而多线程运行的时候每次 import torch 都会载入一遍,这就无端占据了巨额的内存,以至于怎么分配都不足够。

无论如何,总算跑起来了!

(希望不会有下一个踩坑记录)