news 2025/12/27 23:20:29

【论文精读(五)】DGCNN:让点云“动”起来,动态图卷积神经网络 (TOG 2019)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【论文精读(五)】DGCNN:让点云“动”起来,动态图卷积神经网络 (TOG 2019)

DGCNN:让点云“动”起来,动态图卷积神经网络 (TOG 2019)

博主导读
使用MLP处理点云虽然开创了点云深度学习的先河,但有一个致命缺陷:它把点云看作一盘散沙,每个点只顾自己(独立处理),完全忽略了局部几何信息
今天要讲的 DGCNN (Dynamic Graph CNN) 则是该领域的一次重要进化。它创造性地提出了EdgeConv模块,并且引入了“动态图” (Dynamic Graph)的概念——点与点的邻居关系不是固定的,而是随着网络层数加深,在特征空间中动态变化的。这使得网络不仅能学到几何形状,还能自动把“语义相似”的点(比如飞机的两个引擎)拉到一起。
本文将带你从图神经网络 (GCN)的视角,彻底拆解这篇经典之作。原文链接:Dynamic Graph CNN for Learning on Point Clouds


1. 核心痛点:PointNet 的孤独与静态

要理解 DGCNN,先要看看前人留下了什么遗憾。

1.1 孤独的点 (Lack of Local Structure)

PointNet系列的核心公式是f ( x 1 , . . . , x n ) ≈ g ( h ( x 1 ) , . . . , h ( x n ) ) f(x_1, ..., x_n) \approx g(h(x_1), ..., h(x_n))f(x1,...,xn)g(h(x1),...,h(xn))。注意看,h ( x i ) h(x_i)h(xi)只处理点x i x_ixi自己。这意味着网络没有提取“边”的特征,忽略了点与其邻居之间的几何关系。这就好比你在看一张图,你只盯着每个像素点看,却不看它和周围像素拼成了什么线条或形状。

1.2 静态的图 (Fixed Graph)

PointNet++ 或其他基于图的方法(如 Graph CNN),通常是在输入空间(XYZ坐标)构建好k kk-近邻图,然后从头用到尾。
缺陷:物理距离近的点,语义不一定相关;物理距离远的点(比如左机翼和右机翼),语义却应该是一样的。固定的图结构限制了网络捕捉长距离语义依赖的能力


2. DGCNN 的魔法:EdgeConv

作者提出了一种新的卷积操作:EdgeConv。它不再是处理孤立的点,而是处理**“点 + 边”** 。

2.1 数学原理

给定一个有向图G = ( V , E ) G=(V, E)G=(V,E),对于点x i x_ixi和它的邻居x j x_jxj,我们定义“边特征”e i j e_{ij}eij
e i j = h Θ ( x i , x j ) e_{ij} = h_\Theta(x_i, x_j)eij=hΘ(xi,xj)
其中h Θ h_\ThetahΘ是一个非线性函数。最后通过聚合操作(如 Max Pooling)得到x i x_ixi的新特征。

关键在于h Θ h_\ThetahΘ选什么?论文尝试了多种组合(如只用局部信息、只用全局信息等),最终选择了最强的一种非对称函数:
e i j ′ = ReLU ( θ ⋅ ( x j − x i ) + ϕ ⋅ x i ) e'_{ij} = \text{ReLU}(\theta \cdot (x_j - x_i) + \phi \cdot x_i)eij=ReLU(θ(xjxi)+ϕxi)
这里面蕴含了两个层面的信息:

  1. 全局信息 (x i x_ixi):保留点本身的绝对位置/特征,类似于 PointNet。
  2. 局部信息 (x j − x i x_j - x_ixjxi):捕获点与邻居的相对几何关系。

博主注
作者这一部分写的太复杂了,其实就是把邻居点和核心点拼接在一起,然后经过一个共享的MLP,并且所有的点的所有邻居都是一样的MLP,很耗显存!!!


3. 灵魂所在:动态图更新 (Dynamic Graph Update)

这是这篇论文最 Sexy 的地方,也是名字里“Dynamic”的由来。
在标准的 GCN 中,邻接矩阵A AA是固定的。但 DGCNN 中,每一层的图结构都是重新计算的

3.1 过程推演

  • Layer 1: 在输入空间 (XYZ) 计算k kk-NN,找到物理上最近的邻居,提取浅层几何特征。
  • Layer 2: 输入变成了 Layer 1 输出的特征向量。我们在特征空间中重新计算k kk-NN。
  • Layer N: 在深层特征空间计算k kk-NN。

3.2 为什么这么做?

在深层网络中,距离的定义发生了本质变化:

  • 输入空间:只有挨得近的点才是邻居。
  • 特征空间语义相似的点变成了邻居
    *例子:书架的层板、桌子的四条腿。它们在物理空间相距甚远,但在深层特征空间中,它们会聚在一起。DGCNN 通过动态构图,让信息得以在这些语义相似的点之间传播。

4. 网络架构深度拆解

DGCNN 的整体架构沿用了 PointNet 的 “MLP + Max Pooling” 骨架,但将 Point-wise MLP 替换成了 EdgeConv Block。

  1. Spatial Transform: 与 PointNet 一样,先对齐点云。
  2. EdgeConv Layers: 堆叠 4 层 EdgeConv。注意,每一层的k kk-NN 图都是新的。
  3. Feature Concatenation: 这是一个很棒的工程细节。作者不仅使用最后一层的特征,而是将所有 EdgeConv 层的输出特征拼在一起 (64+64+128+256 = 512 维)。
    • Insight: 这样既保留了浅层的几何细节,又包含了深层的语义信息。
  4. Global Pooling: 最后通过 Global Max Pooling 得到全局特征用于分类。

5. PyTorch 核心代码复现

Talk is cheap, show me the code.
DGCNN 的核心难点在于如何高效地在 GPU 上计算k kk-NN 并根据索引取值

5.1 k-NN 与 动态构图

importtorchimporttorch.nnasnnimporttorch.nn.functionalasFdefknn(x,k):""" Input: x: (Batch, C, N) 特征图 k: 邻居数量 Output: idx: (Batch, N, k) 最近邻的索引 """# 计算成对距离 ||x_i - x_j||^2 = ||x_i||^2 + ||x_j||^2 - 2*x_i*x_jinner=-2*torch.matmul(x.transpose(2,1),x)xx=torch.sum(x**2,dim=1,keepdim=True)pairwise_distance=-xx-inner-xx.transpose(2,1)# 取距离最近的 topk (topk返回的是最大值,所以上面取了负号)idx=pairwise_distance.topk(k=k,dim=-1)[1]# (batch_size, num_points, k)returnidxdefget_graph_feature(x,k=20,idx=None):""" 动态构图的核心:根据索引 idx 抓取邻居特征,并构建边特征 (x_j - x_i) """batch_size=x.size(0)num_points=x.size(2)x=x.view(batch_size,-1,num_points)# 1. 如果没传索引,就现算 (Dynamic Graph 的体现)ifidxisNone:idx=knn(x,k=k)# (batch_size, num_points, k)device=torch.device('cuda')iftorch.cuda.is_available()elsetorch.device('cpu')idx_base=torch.arange(0,batch_size,device=device).view(-1,1,1)*num_points idx=idx+idx_base idx=idx.view(-1)_,num_dims,_=x.size()# 2. 变换维度以便 gatherx=x.transpose(2,1).contiguous()# (batch_size, num_points, num_dims) -> (B*N, C)feature=x.view(batch_size*num_points,-1)[idx,:]feature=feature.view(batch_size,num_points,k,num_dims)# 3. 构造 EdgeConv 的输入: cat(x_i, x_j - x_i)x=x.view(batch_size,num_points,1,num_dims).repeat(1,1,k,1)# feature是 x_j (neighbors), x 是 x_i (center)# 输出形状: (Batch, 2*C, N, k)# 对应公式: concat(x_j - x_i, x_i)feature=torch.cat((feature-x,x),dim=3).permute(0,3,1,2).contiguous()returnfeature

5.2 EdgeConv 模块实现

classEdgeConv(nn.Module):def__init__(self,in_channels,out_channels,k=20):super(EdgeConv,self).__init__()self.k=k# 这里的输入维度是 in_channels * 2,因为拼接了 (x_j - x_i) 和 x_iself.conv=nn.Sequential(nn.Conv2d(in_channels*2,out_channels,kernel_size=1,bias=False),nn.BatchNorm2d(out_channels),nn.LeakyReLU(negative_slope=0.2))defforward(self,x):# x: (Batch, C, N)# 1. 构建动态图,获取边特征 (Batch, 2C, N, k)x=get_graph_feature(x,k=self.k)# 2. 在边上进行卷积 (MLP)x=self.conv(x)# 3. 对 k 个邻居进行 Max Pooling (Aggregation)# 对应论文中的 channel-wise symmetric aggregation# (Batch, C', N, k) -> (Batch, C', N)x=x.max(dim=-1,keepdim=False)[0]returnx

6. 进阶深度解析:性能与复杂度的博弈

6.1 性能怪兽 (Performance)

DGCNN 在 ModelNet40 分类任务上达到了92.9%的准确率,相比 PointNet (89.2%) 和 PointNet++ (90.7%) 有了显著提升。特别是在部分点缺失(Dropout)的情况下,实验表明即使丢失了一半的点,模型依然能保持合理的识别结果,这得益于图结构带来的鲁棒性。

6.2 计算代价 (Cost)

天下没有免费的午餐。DGCNN 的性能提升是拿计算量换的。

  • 显存占用:每一层都要算一个( N , N ) (N, N)(N,N)的距离矩阵,或者维护( N , k ) (N, k)(N,k)的邻接表。
  • 时间复杂度:动态k kk-NN 是非常耗时的操作。PointNet++ 只需要做一次 Ball Query,而 DGCNN 每一层都要重新做k kk-NN。

💡 总结
DGCNN 是点云深度学习中“图方法”的集大成者。它证明了:Local Geometry (局部几何)Semantic Grouping (语义分组)对 3D 识别至关重要。虽然计算量偏大,但其EdgeConv的思想被后续无数工作(如 Point Transformer 等)所借鉴。


📚 参考文献

[1] Wang, Y., et al. “Dynamic Graph CNN for Learning on Point Clouds.” ACM Trans. Graph. 2019.
[2] 官方代码仓库: https://github.com/WangYueFt/dgcnn.


📚 附录:MLP点云网络系列导航

本专栏致力于用“人话”解读 3D 点云领域的硬核论文,从原理到代码逐行拆解。
🔥 欢迎订阅专栏:【点云特征分析_顶会论文硬核拆解】持续更新中…


本文为 CSDN 专栏【深度学习-论文讲解】原创内容,转载请注明出处。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/18 0:55:41

解决AMD GPU在ROCm环境下无法被ComfyUI识别的完整指南

解决AMD GPU在ROCm环境下无法被ComfyUI识别的完整指南 【免费下载链接】ROCm AMD ROCm™ Software - GitHub Home 项目地址: https://gitcode.com/GitHub_Trending/ro/ROCm 你是否在Ubuntu系统中安装了ROCm环境,却发现ComfyUI提示"No HIP GPUs are avai…

作者头像 李华
网站建设 2025/12/25 22:10:05

Zen Browser翻译功能终极指南:多语言支持与效率提升实操技巧

Zen Browser翻译功能终极指南:多语言支持与效率提升实操技巧 【免费下载链接】desktop 🌀 Experience tranquillity while browsing the web without people tracking you! 项目地址: https://gitcode.com/GitHub_Trending/desktop70/desktop Zen…

作者头像 李华
网站建设 2025/12/18 0:55:07

1094 The Largest Generation

#include<iostream> #include<vector> using namespace std; vector<int>v[100];//邻接表&#xff0c;存储树结构 int book[100]{0};//记录每层节点数 //dfs,统计每层节点数 void dfs(int index,int level){book[level];for(int i0;i<v[index].size();i){…

作者头像 李华
网站建设 2025/12/21 0:23:40

显卡驱动彻底清理神器:DDU一键解决驱动冲突与蓝屏问题

显卡驱动彻底清理神器&#xff1a;DDU一键解决驱动冲突与蓝屏问题 【免费下载链接】display-drivers-uninstaller Display Driver Uninstaller (DDU) a driver removal utility / cleaner utility 项目地址: https://gitcode.com/gh_mirrors/di/display-drivers-uninstaller …

作者头像 李华