文章目录
2020年第44周学习小结:
本文为10月26日~11月1日的学习小结。
本周主要学习了BSP-Net网络细节以及训练方法,其中目标函数的构建中有几个地方值得注意,理解推导需要花费一点时间。
预备知识
自动编码器
自动编码器(Autoencoder,AE)是一种人工神经网络,它能够以无监督学习的方式对数据进行编码。自动编码器通常用于数据的降维,同时也用于重构。
自动编码器由两个主要部分组成:将输入数据转换为特征的编码器,以及将特征映射到原始结构的解码器。它能够学习将输入复制到输出。AE为非监督学习模式,输入数据时不需要包含对应的label。
超平面
超平面是n维欧氏空间中余维度等于一的线性子空间,也就是必须是(n-1)维度。
超平面将线性空间分割为两个部分。若空间是2维的,那么超平面就是(2-1)维,即一条直线,将平面空间分割为两个部分;若空间是3维的,那么超平面为(3-1)维,即平面,它将三维空间分割为两个部分。
二叉空间分割
二叉空间分割(BSP)为一种空间分割算法,不断通过超平面对空间进行划分。
在三维空间中,一个平面可以将空间分为内、外两个子空间,对于每个子空间,同样可以使用一个平面将子空间分割为更小的两个空间,就像二叉树的每个节点又可以分为左子树与右子树。
如下图,现有一个空间P被L1分割为了P1与P2两个部分。
由P得到的子空间P2又被L2分割为了P3与P4两部分
若继续对其进行划分,经过若干次划分后,空间P被分为了5个区域,此时若知道一个点与L1,L2,L3,L4的关系就可以得知该点在哪个区域。
BSP-Net的原理就是用一个个的平面将三维空间划分为小的子空间,用该空间表示目标形状的一部分(零件),最终组合这些部分就形成了生成的形状。如一个桌子就可以分为桌面,桌腿这几个部分,一个方形的桌面就可以由上下两个平面以及周围四个平面包起来的区域表示。
需要注意的一点是BSP只能将空间划分为“凸集”,凸集的定义如下:
在凸几何中,凸集(convex set)是在凸组合下闭合的仿射空间的子集。更具体地说,在欧氏空间中,凸集是对于集合内的每一对点,连接该对点的直线段上的每个点也在该集合内。例如,立方体是凸集,但是任何中空的或具有凹痕的例如月牙形都不是凸集。
因此在三维空间中,分割得到的结果只可能是一个个凸多边体,这就意味着一些包含凹形的形状只能通过其他方式得到。如一个杯子的杯壁部分就无法直接使用二叉空间分割得到,只能将其分解为一些小的三维形状(凸),这种表示方式就不够简洁,且大大增加了处理难度。
论文阅读 BSP-Net: Generating Compact Meshes via Binary Space Partitioning
BSP-Net网络与前面介绍的自动编码器的结构相似,编码器部分对输入数据进行特征提取,以得到特征向量,如在二维图像中使用ResNet生成图像特征或针对体素使用3D CNN生成三维图像特征。
接下来解释BSP-Net的解码器部分,即生成网络的结构。
生成网络
- L0:超平面提取
网络首先对输入数据,即编码器部分得到的特征向量 f f f,应用MLP生成平面参数矩阵 P = P ω ( f ) P= P\omega(f) P=Pω(f)。该矩阵( P p × 4 P_{p\times4} Pp×4)定义了 p p p个空间平面方程的参数(如平面方程 A x + B y + C z + D = 0 Ax+By+Cz+D=0 Ax+By+Cz+D=0中的四个参数 A , B , C , D A,B,C,D A,B,C,D)
- L1:计算点到平面距离
x n × 4 x_{n\times4} xn×4为坐标矩阵,保存了 n n n个点的坐标信息 ( x , y , z , 1 ) (x,y,z,1) (x,y,z,1),将坐标矩阵 x x x与平面参数矩阵的转置 P T P^T PT相乘就得到距离矩阵 D n × p D_{n\times p} Dn×p, D D D中记录了每个点到 p p p个平面的有符号距离,当距离为负时表明点在平面内侧,距离为正说明点在平面外侧。
- L2:组合平面
使用了BSP的思想,将空间划分为凸集,定义了一个二值矩阵
T
p
×
c
T_{p\times c}
Tp×c,用于组合
p
p
p个平面,由最大池化操作聚合为
c
c
c个凸集,即凸多边体空间。
注意:图中并没有使用最大池化操作,具体原因会在下一部分解释。
- L3:组合平面
前面提到过BSP分割得到的空间都是凸集,无法直接生成非凸的形状。因此这一层的目的就是将L2中生成的形状(零件)组合拼接为目标形状。该层定义了一个权重
W
W
W用于形状的生成,通过最小池化或加权求和将这些零件组合为生成形状。
注意:图中的
S
n
×
1
+
S^+_{n\times1}
Sn×1+与
S
n
×
1
∗
S^*_{n\times1}
Sn×1∗分别为最小池化与加权求和得到的目标形状,二者的区别见下一部分。
平面到凸集
首先看一下凸集是如何组合的,如下图,给定9个平面
p
p
p,矩阵T取值如下:
T
T
=
∣
1
0
1
1
0
0
1
0
0
0
1
0
0
0
1
0
0
1
0
0
0
1
0
0
1
1
0
∣
T^T=\begin{vmatrix} 1 & 0 & 1 & 1 & 0 & 0 & 1 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 & 1 & 0 & 0 & 1\\ 0 & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 0 \end{vmatrix}
TT=∣∣∣∣∣∣100010100101000010101001010∣∣∣∣∣∣
有了矩阵
T
T
T就可以将平面组合为凸集,如下图中第二层的黑色正方形就是由编号为1,3,4,7的平面组合而成的。
那么如何确定点在形状的内部还是外部呢?文章中使用了最大池化操作来获取点与凸集的位置关系:
我们已经知道一个点到平面的距离是有符号的,当取值为正的时候说明点在平面外部,反之在内部。那么凸集内部的点一定满足条件:
该点在所有组成凸集的平面的内部。
图中正方形是由第1,3,4,7个平面组合得到的,因此正方形内部的点到这4个平面的距离一定为负值。当点到所有组成凸集的平面距离最大值都小于0时,求得最大值仍小于0,说明点在凸集内部。如果此时有一个点到1,3,4个平面的距离都为负值,到平面7的距离为正值(对应正方形上方的一小块白色区域),那么通过max操作得到的结果也是大于0的,说明该点在正方形的外部。
可以看出使用max操作的
C
j
∗
(
x
)
C^*_{j}(x)
Cj∗(x)能够很好的指示点与凸集的位置关系。但是文中却没有使用
C
j
∗
C^*_{j}
Cj∗,这是因为最大池化在反向传播时会丢失梯度。下图为二维图像处理中max pooling操作的具体过程:
图片来源:
https://blog.csdn.net/qq_21190081/article/details/72871704
可以看到梯度在反向传播时只会流经最大的那个值,因此使用式(1)进行训练时,梯度同样只会经过一个平面(距离点最近的平面)。
为了解决这个问题,文章中使用了线性整流函数(ReLU)来解决梯度问题,见下式:
其中ReLU函数形式如下:
当引入了ReLU函数后,当点在平面内部时,无论距离平面有多远,取值都为0,同时当且仅当点在所有平面内部时,
C
j
+
(
x
)
C^+_{j}(x)
Cj+(x)的取值才为0,和
C
j
∗
(
x
)
C^*_{j}(x)
Cj∗(x)具有相同的指示作用。
凸集的组合
为了得到目标形状,需要将得到的凸集进行组合,如下图:
文章中使用了最小池化来实现:
在式(3)中只要有一项
C
j
+
(
x
)
C^+_{j}(x)
Cj+(x)是的取值为0,那么对应的
S
∗
(
x
)
S^*(x)
S∗(x)取值也为0,以上图的形状为例,凸集
C
1
C_1
C1中只有正方形部分取值为0,其余地方取值为正,
C
2
C_2
C2中的三角形区域同理。经过min操作后,生成的形状
S
S
S的对应空间部分取值都取最小值(即0),最终得到了目标形状。
同样的,使用最小池化也会遇到梯度问题,因此需要使用其他的方式进行计算来实现min的效果。文章中使用了加权求和的方式来近似实现min pooling。
当取权重
W
j
≈
1
W_j\approx1
Wj≈1时使用
S
+
(
x
)
S^+(x)
S+(x)只能近似
S
∗
(
x
)
S^*(x)
S∗(x),为了搞清楚二者为何不能等价,我简单列举了三种情况(其中凸集
C
C
C的数量n足够多):
- 当所有 C n + ( x ) C^+_n(x) Cn+(x)取值均等于0时,即该点在所有凸集内部
- 当所有 C n + ( x ) C^+_n(x) Cn+(x)取值均大于1时,即该点在所有凸集外部
- 当所有 C n + ( x ) C^+_n(x) Cn+(x)取值均为0.5时,即该点在所有凸集外部
对于情况1,即该点在所有凸集内部,因此该点一定在这些凸集组成的形状内部。
对于情况2与情况3,该点在所有凸集外部,因此该点一定在这些凸集组成的形状外部
该点在所有凸集的内部,自然有:该点一定在这些凸集的并集中。对比两者的计算结果:
情况 | 表达式结果 | 是否与事实相符 |
---|---|---|
1 | S ∗ ( x ) = 0 S^*(x)=0 S∗(x)=0 | 是 |
1 | S + ( x ) = 1 S^+(x)=1 S+(x)=1 | 是 |
2 | S ∗ ( x ) > 0 S^*(x)>0 S∗(x)>0 | 是 |
2 | S + ( x ) = 0 S^+(x)=0 S+(x)=0 | 是 |
3 | S ∗ ( x ) > 0 S^*(x)>0 S∗(x)>0 | 是 |
3 | S + ( x ) = 1 S^+(x)=1 S+(x)=1 | 否 |
可以看到,在大多数情况下, S + ( x ) S^+(x) S+(x)与 S ∗ ( x ) S^*(x) S∗(x)得到的结果都与事实相符,但是在情况3中,使用 S + ( x ) S^+(x) S+(x)得到的判断却出错了,因此无法完全替代 S ∗ ( x ) S^*(x) S∗(x)。
两阶段训练
上一部分我们得知使用
S
+
(
x
)
S^+(x)
S+(x)进行训练将无法得到准确的结果,而使用
S
∗
(
x
)
S^*(x)
S∗(x)进行训练又存在梯度问题。为了保证梯度传递的同时确保结果的准确性,文章采用了两阶段训练的方案。如下图:
在阶段1(又称连续阶段)中,所有权重连续变化,使用
S
+
(
x
)
S^+(x)
S+(x)来得到近似结果,见图4(b)。可以看到图中使用
S
∗
(
x
)
S^*(x)
S∗(x)进行训练,由于梯度消失的问题而无法优化权重参数,最终的重构效果很差,而使用
S
+
(
x
)
S^+(x)
S+(x)就没有这一问题。
但是由于此时得到的结果只是近似值,因此在阶段2(又称离散阶段)中,对权重进行量化,通过使用
S
∗
(
x
)
S^*(x)
S∗(x)微调来得到准确的结果,见图4(c,d)。
BSP-Net的局限
由于使用BSP对空间进行分割只能得到凸集,那么只有通过组合这些凸形状(零件)才能得到非凸的形状,对于简单的物体还比较好解决,如凳子,椅子,就可以用少量的零件拼装起来。但对于另外一些非凸的形状就不那么容易了。如一个杯子的杯壁部分就需要用多个形状拼接而成,就好像木桶侧边的一片片木板,但是如果这个杯子的内侧比较“圆润”,那么要想拼接出这样的曲线将需要大量的凸形状,效率太低。