GVCNN notes
思路总结与方法概括
GVCNN和MVCNN一样,也是一种基于多视图(multi-view)的、对三维物体进行识别分类的网络结构。
在MVCNN中,各个view的CNN特征通过一个view pooling层被整合成一个特征向量。这么做的缺憾在于,view pooling层并不能关注每个view的区分性。而实际上,在使用multi-view来对一个三维物体进行表示时,有些view之间的相似性可能会很高,而有些view之间的差别却比较大,挖掘出这些view之间的相互联系也许能够帮助网络更好地进行物体识别。
而GVCNN的核心思路便是基于上述的观测,它提出了一个c,用于对不同的view-level特征进行分组,并以组为单位对view-level特征进行聚合从而得到group-level的特征,最后通过一个学习到的权重来将group-level特征整合成一个全局特征描述子,以用于最终的分类。引入Grouping Module的好处在于,它考虑了view之间的组内相似性和组间区分性:相似度高的view被分到了同一组,组内特征对最终结果的影响因子是相同的;而不同的组间具有相对明显的区分性,因此每个组对最终结果的影响程度会不同。
具体结构
整体流程
- 表示一个三维物体的多个view首先被送入一个全卷积网络(Fully Convolutional Network)进行初步的特征提取,得到每个view的Raw View Descriptor,这里的FCN对于各个view而言是共享的。假设我们用 n 个view来表示一个三维物体,那么经过FCN,我们就会得到 N 个Raw View Descriptor。
- 提出得到的Raw View Descriptor接着被送入余下的CNN中进行进一步的特称提取,得到与每个view相对应的Final View Descriptor。类似地,这里的CNN也是view间共享的。相应地,这里我们也会得到 N 个Final View Descriptor
- 同时,由第1步提取得到的所有Raw View Descriptor还会被一起送入Grouping Module来进行组别的划分,并计算出各个组别的对应权重。Grouping Module有两个计算结果,分别是图中的Grouping Scheme和Grouping Weight。其中Grouping Scheme用来对view-level的特征进行分组。而Grouping Weight则是分配给各个组的权重,用于接下来的特征整合。Grouping Module的具体细节将会在下文讨论。
- 接着,由第2步得到的 N 个Final View Descriptor会根据第3步计算得出的结果来进行分组,分组的个数依赖于具体的数据,我们将分组个数记作 m 。
- 接下来,在各个组内进行view pooling操作(文章里使用的是average pooling),得到 M 个Group Descriptor。
- 根据第3步得出的Grouping Weight对第5步得到的Group Descriptor进行加权求和,得到最终的全局描述子shape descriptor。
- 使用一个全连接层对第6步得出的全局描述子进行分类。
Grouping Module
前面提到,Grouping Module的输出有两部分。一个是Grouping Scheme,用来确定如何划分组别。一个是Grouping Weight,是分配给每个组别的权重,权重表示每个组对最终的全局特征描述子的贡献度。
1. 计算区分度
在对各个view进行组别划分之前,先要得到每个view的区分度(Discrimination Scores),然后才能根据每个view的区分度来对其进行分组。Grouping Module的输入是 N 个Raw View Descriptor,这 N 个Raw View Descriptor首先被分别输入到一个共享的全连接层中,得到 N 个相应的输出值。假设输入的一组view为S = \{I_1,I_2,...,I_N\}, 对应的全连接层的输出值为\{O_{I_1},O_{I_2},...,O_{I_N}\},那么每个view的区分度的计算方式为:
\xi(I_i) = sigmoid(log(abs(O_{I_i})))
引入sigmoid函数,就使得区分度的取值落在0~1之间。注意到当sigmoid的输入高于5或小于-5时,其函数值便会趋向1或者0,这将不利于分组的进行。为了使得取值分布更加均匀,作者在sigmoid之前引入了abs和log函数。
2. 根据区分度进行分组
有了每个view的区分度,便可以对其进行分组了。分组的思路十分简单,具体如下:
首先将区间(0, 1)平均划分为 N 个子区间,接着依次查看每个view的区分度,区分度落在同一个子区间的view就被认为属于同一个组。最后便得到 M 个互不相交的分组 \{G_1, G_2,...,G_M\},并且有 1\le M \le N。
3. 计算每个分组的权重
分组的权重用于对Group Descriptor进行加权平均,已得到最后的shape descriptor。因此,权重的计算原则是:一个区分性高的组,应分配一个高的权重,反之则应该分配一个小的权重。权重的计算方式为:
\xi(G_j) = \frac{Ceil(\xi_{I_k} \times |G_j|)}{|G_j|}, \ \ \ \ I_k \in G_j
不过感觉论文这里应该漏了累加或者Max之类的操作符,因为单从公式上来看,并不知道I_k的具体取值。具体细节可能要去代码中查看了。。
实验
实验证明,GVCNN相对于MVCNN有2到3个百分点的提升。但有一部分的提升实际上是来自于GoogLeNet(GVCNN所使用的CNN baseline)相对于VGG-M(MVCNN所使用的CNN baseline)的优势。这样看来,Grouping Module所带来的实际性能提升其实只有一个百分点左右。
比起分类准确率的提高,论文中对Grouping Module的讨论和实验展示其实才是点睛之笔。
从展示的分组样例可以看出,Grouping Module对view的组别划分还是十分到位的。虽然最后的精度提升不是十分明显,但Grouping Module的作用仍值得肯定。