Transformer在文本、图像和点云数据中的应用——经典工作梳理

摘要

最近在整一些3D检测和分割的任务,接触了一下ptv3,在之前梳理的工作owlv2中用到了vit,去年年假阅读《多模态大模型:算法、应用与微调》(刘兆峰)时学习了Transformer网络架构及其在文本数据中的应用,细数下来,似乎各方面都多多少少了解和应用过一些,但是直到昨天跟别人讨论起Transformer在多模态数据中的应用,发现自己了解的不太系统,基于这个大背景,我希望借助闲暇时间梳理一下相关的代表性工作,后面如果有机会,也会做一些实践记录,希望自己学会的同时也可以帮助到一些有需要的小伙伴。

Transformer基础知识

网络架构

Transformer在nlp中的应用

Transformer在image处理中的应用

Transformer在point clouds处理中的应用

20250820:因为最近在整一些3d相关的工作,所以从该部分开始梳理。如果大家对pointnet系列的点云分割工作感兴趣的话,可以去看一下我之前整理的这篇文章3D分割系列论文梳理,欢迎一起讨论。

PT

参考链接:https://zhuanlan.zhihu.com/p/681682833

贡献

We design a highly expressive Point Transformer layer for point cloud processing. The layer is invariant to permutation and cardinality and is thus inherently suited to point cloud processing.

在pointnet中有提到,3d点云实际上是一种集合,在点云网络结构的设计中,由于点云是无序的,所以设计与点云排序和点数量无关的网络至关重要。而transformer的自注意力机制天生具有排序和点个数不变性,使得它非常适合用来提取点集的特征。

而本文也是聚焦在对点云局部特征提取结构的改造,将自注意力机制应用在了局部特征提取上。

Based on the Point Transformer layer, we construct high-performing Point Transformer networks for classification and dense prediction on point clouds. These networks can serve as general backbones for 3D scene understanding.

We report extensive experiments over multiple domains and datasets. We conduct controlled studies to examine specific choices in the Point Transformer design and set the new state of the art on multiple highly competitive benchmarks, outperforming long lines of prior work.

相关工作梳理

第一类,将不规则点云转换成规则表示:

Projection-based networks

将点云投影成图片,利用2D CNN进行处理,最后利用多视角特征融合构建最终的输出特征表示。

在基于投影的框架中,点云中的几何信息会在投影阶段被压缩。这些方法在投影平面上构建密集像素网格时,可能未能充分利用点云的稀疏特性。投影平面的选择会显著影响识别性能,而三维场景中的遮挡现象也可能导致精度下降。

Voxel-based networks

3D体素+3D 卷积

该类方法,如果直接简单粗暴的使用3D卷积的话,计算量和内存占用会随着分辨率增加导致体素块数量呈三次方增长而增加,解决方式是使用稀疏卷积或者非平衡八叉树结构,一定程度上减少计算量和内存占用。此外,由于体素网格上的量化处理,仍可能丢失部分几何细节。

第二类,直接操作不规则点云

Point-based networks.

研究人员没有将不规则点云投影或量化到二维或三维的规则网格上,而是设计了深度网络结构,直接将点云作为嵌入连续空间的集合来吸收。(pointnet/pointnet++)

许多方法将点集连接成一个图,并在此图上进行信息传递。(此类目前了解的比较少)

许多方法基于直接应用于三维点集的连续卷积,而无需量化。(此类目前了解的比较少)

本文的研究灵感

在序列处理和二维图像任务中,Transformer和自注意力网络的表现可与卷积网络相媲美甚至更胜一筹。自注意力机制在本研究中具有特殊意义,因其本质上属于集合运算:位置信息作为元素属性被处理为集合形式。由于三维点云本质上是具有空间属性的点集,这种机制特别适合此类数据类型。为此,开发了专门针对三维点云的点变换器层,实现了自注意力机制的应用。

Point Transformer

background

Self-attention operators can be classified into two types: scalar attention [39] and vector attention [54]. 此处文章中公式很清晰,如果还是看不懂的话,可以问问豆包,并让它给举个例子,很清晰。

Point Transformer layer

数学运算:

在局部邻域应用vector self-attention,对特征所做的数学运算见上图公式(3),对应的网络架构见下图。(确定提局部邻域特征的运算是关键,后续搭建网络是水到渠成的事情)

Position Encoding

Network Architecture

Backbone structure

The feature encoder in point transformer networks for semantic segmentation and classification has five stages that operate on progressively downsampled point sets. The downsampling rates for the stages are [1, 4, 4, 4, 4], thus the cardinality of the point set produced by each stage is [N, N/4, N/16, N/64, N/256], where N is the number of input points.

Transition down

见网络架构图

Transition up

见网络架构图

Output head

见网络架构图

问题及解答

问题1:TransitionDown与PointTransformerLayer都是做局部特征提取的,它俩有什么不同?并且两个块之间的数据是怎么流动的?

参考了openpoints库中的代码:

python 复制代码
class TransitionDown(nn.Module):
    def __init__(self, in_planes, out_planes, stride=1, nsample=16):
        super().__init__()
        self.stride, self.nsample = stride, nsample
        if stride != 1:
            self.linear = nn.Linear(3 + in_planes, out_planes, bias=False)
            self.pool = nn.MaxPool1d(nsample)
        else:
            self.linear = nn.Linear(in_planes, out_planes, bias=False)
        self.bn = nn.BatchNorm1d(out_planes)
        self.relu = nn.ReLU(inplace=True)

    # 如果self.stride != 1会减少点数,通过最大池化获取每个分组的全局特征。
    def forward(self, pxo):
        p, x, o = pxo  # (n, 3), (n, c), (b)
        if self.stride != 1:
            n_o, count = [o[0].item() // self.stride], o[0].item() // self.stride
            for i in range(1, o.shape[0]):
                count += (o[i].item() - o[i - 1].item()) // self.stride
                n_o.append(count)
            n_o = torch.cuda.IntTensor(n_o)
            # print(n_o.device, p.device)
            idx = pointops.furthestsampling(p, o, n_o)  # (m)
            n_p = p[idx.long(), :]  # (m, 3)
            x = pointops.queryandgroup(self.nsample, p, n_p, x, None, o, n_o, use_xyz=True)  # (m, nsample,3+c)
            x = self.relu(self.bn(self.linear(x).transpose(1, 2).contiguous()))  # (m, out_planes, nsample)
            x = self.pool(x).squeeze(-1)  # (m, out_planes)
            p, o = n_p, n_o
        else:
            x = self.relu(self.bn(self.linear(x)))  # (n, out_planes)
        return [p, x, o]

class PointTransformerLayer(nn.Module):
    def __init__(self, in_planes, out_planes, share_planes=8, nsample=16):
        super().__init__()
        self.mid_planes = mid_planes = out_planes // 1
        self.out_planes = out_planes
        self.share_planes = share_planes
        self.nsample = nsample
        self.linear_q = nn.Linear(in_planes, mid_planes)
        self.linear_k = nn.Linear(in_planes, mid_planes)
        self.linear_v = nn.Linear(in_planes, out_planes)
        self.linear_p = nn.Sequential(nn.Linear(3, 3), nn.BatchNorm1d(3), nn.ReLU(inplace=True),
                                      nn.Linear(3, out_planes))
        self.linear_w = nn.Sequential(nn.BatchNorm1d(mid_planes), nn.ReLU(inplace=True),
                                      nn.Linear(mid_planes, mid_planes // share_planes),
                                      nn.BatchNorm1d(mid_planes // share_planes), nn.ReLU(inplace=True),
                                      nn.Linear(out_planes // share_planes, out_planes // share_planes))
        self.softmax = nn.Softmax(dim=1)

    # 不会减少点数,只是会对每个点,计算其邻域的self-attention
    def forward(self, pxo) -> torch.Tensor:
        p, x, o = pxo  # (n, 3), (n, c), (b)
        # 点特征分别经过三个线性层,获得q,k,v
        x_q, x_k, x_v = self.linear_q(x), self.linear_k(x), self.linear_v(x)  # (n, c)
        # 查找最近邻
        x_k = pointops.queryandgroup(self.nsample, p, p, x_k, None, o, o, use_xyz=True)  # (n, nsample, 3+c)
        x_v = pointops.queryandgroup(self.nsample, p, p, x_v, None, o, o, use_xyz=False)  # (n, nsample, c)
        p_r, x_k = x_k[:, :, 0:3], x_k[:, :, 3:]
        for i, layer in enumerate(self.linear_p): p_r = layer(p_r.transpose(1, 2).contiguous()).transpose(1,
                                                                                                          2).contiguous() if i == 1 else layer(
            p_r)  # (n, nsample, c)
        w = x_k - x_q.unsqueeze(1) + p_r.view(p_r.shape[0], p_r.shape[1], self.out_planes // self.mid_planes,
                                              self.mid_planes).sum(2)  # (n, nsample, c)
        for i, layer in enumerate(self.linear_w): w = layer(w.transpose(1, 2).contiguous()).transpose(1,
                                                                                                      2).contiguous() if i % 3 == 0 else layer(
            w)
        w = self.softmax(w)  # (n, nsample, c)
        n, nsample, c = x_v.shape
        s = self.share_planes
        # w.unsqueeze(2)广播机制
        x = ((x_v + p_r).view(n, nsample, s, c // s) * w.unsqueeze(2)).sum(1).view(n, c)  # (n, out_planes)
        return x

由上述开源代码可以看出来,TransitionDown是对输入点集进行最远点采样,分组,逐点特征提取以及组内最大池化后输出各个邻域的特征。

而PointTransformerLayer是对输入的点集中的每一个点查找k近邻,然后对每个邻域做自注意力,获得每个点的聚合特征,并不会减少点的数量。(自注意力机制的核心是 "同一组数据内部元素之间的注意力交互"(即查询、键、值均来自同一组输入)。)

PTV2

贡献

网络架构

问题及解答

PTV3

相关推荐
Ginkgo_Lo4 分钟前
【LLM越狱】AI大模型DRA攻击解读与复现
人工智能·安全·ai·语言模型
凯子坚持 c12 分钟前
AI 赋能云端运维:基于 MCP 协议深度集成 Codebuddy CLI 与腾讯云 Lighthouse 的实战全解
运维·人工智能·腾讯云·腾讯轻量云ai创想家
胖达不服输12 分钟前
「日拱一码」087 机器学习——SPARROW
人工智能·python·机器学习·sparrow
minhuan39 分钟前
构建AI智能体:三十一、AI医疗场景实践:医学知识精准问答+临床智能辅助决策CDSS
人工智能·医学知识问答·临床辅助决策·cdss·医学模型
大千AI助手1 小时前
线性预热机制(Linear Warmup):深度学习训练稳定性的关键策略
人工智能·深度学习·大模型·模型训练·学习率·warmup·线性预热机制
七牛云行业应用1 小时前
企业级AI大模型选型指南:从评估部署到安全实践
大数据·人工智能·安全
진영_1 小时前
深度学习打卡第N6周:中文文本分类-Pytorch实现
人工智能·深度学习
龙亘川1 小时前
智慧城市SaaS平台之智慧城管十大核心功能(六):业务指导系统
人工智能·智慧城市
龙亘川1 小时前
智慧城市SaaS平台之智慧城管十大核心功能(七):后台支撑系统
服务器·人工智能·系统架构·智慧城市·运维开发·智慧城市saas平台
cms小程序插件【官方】1 小时前
pbootcms版AI自动发文插件升级到2.0版,支持AI配图、自动提取关键词
人工智能