在3D点云SECOND模型中涉及到了ConvTranspose2d反卷积运算,具体ConvTranspose2d反卷积的运算原理可自行搜索了解相关内容,本文主要结合实例分析具体运算的数学过程。
ConvTranspose2d反卷积 输入特征数据:
feat.shape = (1, 256, 100, 88)
#注后续为了便于在可视化feat数据,均将特征图由4维转换为3维,即通过:
feat= feat.reshape(feat.shape[1],feat.shape[2],feat.shape[3])
#习惯性将特征通道放到第三维,故需换序
feat = feat.transpose([1,2,0])
由此得到调整后的特征输入数据为:
feat.shape = (100, 88, 256)
具体值为:
ConvTranspose2d反卷积 滤波核:
filter.shape = (256, 256, 2, 2)
#换序
filter = filter.transpose([2,3,0,1])
由此得到调整后的滤波核数据为:
filter.shape = (2, 2, 256, 256)
ConvTranspose2d反卷积 输出特征数据:
feat_out.shape = (1, 256, 200, 176)
同输入特征一样将其调整为:
feat_out.shape = (200, 176, 256)
具体值为:
定义一个2d卷积函数
import tensorflow as tf
def float_conv2d(feat_in,filter_in):
# 二维卷积运算过程
if feat_in.ndim==3:
feat = feat_in.reshape(1,feat_in.shape[0],feat_in.shape[1],feat_in.shape[2])
else:
feat = feat_in #顺序示例:1x112x112x32
if filter_in.ndim==2:
filter_in = filter_in.reshape(1,1,filter_in.shape[0],filter_in.shape[1])
else:
filter_in = filter_in
filter = filter_in #顺序示例:3x3x32x64
conv_o = tf.nn.conv2d(feat, filter, strides=[1,1,1,1], padding='SAME')
#将卷积结果输出 TF格式下将Tensor转为numpy
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
conv_oo = sess.run(conv_o)
conv_oo = conv_oo.reshape(conv_oo.shape[1],conv_oo.shape[2],conv_oo.shape[3])
return conv_oo
运算方式1:
将feat每行每列中间插值0,具体实现过程如下:
feat1 = np.zeros((feat.shape[0]*2,feat.shape[1]*2,feat.shape[2]), np.float32)
for i in range(feat.shape[0]):
for j in range(feat.shape[1]):
feat1[2*i,2*j,:] = feat[i,j,:]
得到feat1.shape = (200, 176, 256),具体数值为:
将其和filter进行卷积得到:
feat_out1=float_conv2d(feat1,filter)
具体数值如下所示:
比对数据:
err1=feat_out1-feat_out
通过比对可发现feat_out1与feat_out不匹配,故该方式验证失败,在SECOND模型中并非这种方式实现的ConvTranspose2d反卷积运算。
运算方式2:
2x2的滤波核每一个点得到一个输出结果,依次构成输出特征中相邻2x2的特征数据:
实现过程:
out0=float_conv2d(feat,filter[0,0,:,:])
out1=float_conv2d(feat,filter[0,1,:,:])
out2=float_conv2d(feat,filter[1,0,:,:])
out3=float_conv2d(feat,filter[1,1,:,:])
feat_out2 = np.zeros((feat_out.shape[0],feat_out.shape[1],feat_out.shape[2]), np.float32)
for i in range(out0.shape[0]):
for j in range(out0.shape[1]):
feat_out2[2*i,2*j,:] = out0[i,j,:]
feat_out2[2*i,2*j+1,:] = out1[i,j,:]
feat_out2[2*i+1,2*j,:] = out2[i,j,:]
feat_out2[2*i+1,2*j+1,:] = out3[i,j,:]
feat_out2的结果:
比对数据:
err2=feat_out2-feat_out
通过比对可发现feat_out2与feat_out匹配,故该方式验证成功,在SECOND模型中使用的就是这种方式实现的ConvTranspose2d反卷积运算。
结论
在SECOND模型中ConvTranspose2d反卷积运算具体实现过程为:2x2的滤波核每一个点得到一个输出结果,依次构成输出特征中相邻2x2的特征数据:
out0=float_conv2d(feat,filter[0,0,:,:])
out1=float_conv2d(feat,filter[0,1,:,:])
out2=float_conv2d(feat,filter[1,0,:,:])
out3=float_conv2d(feat,filter[1,1,:,:])
feat_out2 = np.zeros((feat_out.shape[0],feat_out.shape[1],feat_out.shape[2]), np.float32)
for i in range(out0.shape[0]):
for j in range(out0.shape[1]):
feat_out2[2*i,2*j,:] = out0[i,j,:]
feat_out2[2*i,2*j+1,:] = out1[i,j,:]
feat_out2[2*i+1,2*j,:] = out2[i,j,:]
feat_out2[2*i+1,2*j+1,:] = out3[i,j,:]