第七句
tf.summary.scalar('bn_decay', bn_decay)
查看pointnet學習(二)tf.summary.scalar含義
第八句
pred, end_points = MODEL.get_model(pointclouds_pl, is_training_pl, bn_decay=bn_decay)
字面意思是獲取模型。調用的是配置模型的get_model,這裏解讀配置的是pointnet_cls.py文件裏的model,主要神經網絡的搭建,初始化。具體實現爲
def get_model(point_cloud, is_training, bn_decay=None):
""" Classification PointNet, input is BxNx3, output Bx40 """
batch_size = point_cloud.get_shape()[0].value
num_point = point_cloud.get_shape()[1].value
end_points = {}
with tf.variable_scope('transform_net1') as sc:
transform = input_transform_net(point_cloud, is_training, bn_decay, K=3)
point_cloud_transformed = tf.matmul(point_cloud, transform)
input_image = tf.expand_dims(point_cloud_transformed, -1)
net = tf_util.conv2d(input_image, 64, [1,3],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='conv1', bn_decay=bn_decay)
net = tf_util.conv2d(net, 64, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='conv2', bn_decay=bn_decay)
with tf.variable_scope('transform_net2') as sc:
transform = feature_transform_net(net, is_training, bn_decay, K=64)
end_points['transform'] = transform
net_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)
net_transformed = tf.expand_dims(net_transformed, [2])
net = tf_util.conv2d(net_transformed, 64, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='conv3', bn_decay=bn_decay)
net = tf_util.conv2d(net, 128, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='conv4', bn_decay=bn_decay)
net = tf_util.conv2d(net, 1024, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='conv5', bn_decay=bn_decay)
# Symmetric function: max pooling
net = tf_util.max_pool2d(net, [num_point,1],
padding='VALID', scope='maxpool')
net = tf.reshape(net, [batch_size, -1])
net = tf_util.fully_connected(net, 512, bn=True, is_training=is_training,
scope='fc1', bn_decay=bn_decay)
net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,
scope='dp1')
net = tf_util.fully_connected(net, 256, bn=True, is_training=is_training,
scope='fc2', bn_decay=bn_decay)
net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,
scope='dp2')
net = tf_util.fully_connected(net, 40, activation_fn=None, scope='fc3')
return net, end_points
從返回值來看,model就是net以及end_points
然後看看輸入參數,第一個是pointcloud=pointclouds_pl,第二個是istrainning=is_training_pl,第三個是bn_decay=bn_decay。回想學習,pointnet學習(五)train函數,第五、六句
則可知,pointcloud是一個shape(32x1024x3)的三維的tensor,裏面存放點雲數據,istrainning是一個bool類型的tensor,shape沒有指定,
現在看getmodel函數體內code:
第一句,獲取bitchsize即爲32,第二句爲獲取點數量1024,第三句爲聲明一個endpoint爲dict字典
第四第五句,爲加載transformnet,因爲pointnet網絡在進行分類之前先進入transformnet將點雲旋轉爲正向方位,雖然有後續文章之處此net對後續分類並沒有什麼影響,但是還是照舊加上了。
tf.variable_scope('transform_net1') as sc
設置transformnet名字爲transform_net1。
transform = input_transform_net(point_cloud, is_training, bn_decay, K=3)
下面來看transform_net的構建,也是包括了跟model一樣的三個參數,除此之外添加了一個K參數。
定義另一維的kernel的值,此工程返回的transform_net的shape爲[32,3,3]輸出對應bitchsize個3x3旋轉矩陣,根據卷積,池化得到的大量特徵點的旋轉矩陣,有點類似圖像處理中提取特徵點,然後對比源和目標特徵點計算的旋轉矩陣的原理,參考pointnet學習(七)input_transform_net,
得到transformnet的輸出之後,與inputcloud進行叉乘,得到
第六句
point_cloud_transformed = tf.matmul(point_cloud, transform)
旋轉矩陣求得之後,那麼就應該讓我們的input的point_cloud經過相乘得到正向的點雲模型了,後面
第七句
input_image = tf.expand_dims(point_cloud_transformed, -1)
爲了卷積,繼續對旋轉後的32個batch的點雲模型進行卷積
第八、九句,
net = tf_util.conv2d(input_image, 64, [1,3],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='conv1', bn_decay=bn_decay)
net = tf_util.conv2d(net, 64, [1,1],
padding='VALID', stride=[1,1],
bn=True, is_training=is_training,
scope='conv2', bn_decay=bn_decay)
這兩句就很熟悉了,參考pointnet學習(八)tf_util.conv2d,也是對我旋轉後的點雲模型,xyz進行卷積,因爲輸出爲64,所以有64個1x3的核驗numpoint方向以及xyz方向,1,1步幅進行卷積,得到了32,1024,1,64的tensor,因爲沒有maxpolling所以依然是1024個點的每個點的xyz卷積和分爲64個channel存儲因爲同一個點讓64個1,3卷積kernel進行了卷積。
第九句,繼續進行卷積,依然出來32,1024,1,64的tensor這裏相當於對於這卷積後的xyz繼續乘以一個w+b的到的值
第十,十一句
with tf.variable_scope('transform_net2') as sc:
transform = feature_transform_net(net, is_training, bn_decay, K=64)
第二個transform的網絡層。是對特徵值進行旋轉偏移,參考pointnet input_transform_net
第十二句
net_transformed = tf.matmul(tf.squeeze(net, axis=[2]), transform)
先看tf.squeeze(net, axis=[2]),功能是,移除tensor中所有維度爲1的數據或者指定某一維的數據移除,這句是指移除32,1024,1,64中第三維數據,變爲32,1024,64的tensor。跟feature transform64*64進行矩陣相乘,旋轉,偏移。得到新的卷積得到特徵值之後的input、
第十三句
net_transformed = tf.expand_dims(net_transformed, [2])
重新將之前刪除的第三維拓展方便後續的卷積運算
十四~十八句。對32,1024,1,64的tensor進行卷積,分別輸出[32,1024,1,64]tensor,[32,1024,1,126]tensor,[32,1024,1,1024]tensor,最後maxpolling輸出得到[32,1,1,1024]tensor,重新reshape爲[32,1024]tensor.
十九句,初始化一個1024,512的weighttensor以及512,512的biastensor進行運算得到32,512的tensor
第二十句
net = tf_util.dropout(net, keep_prob=0.7, is_training=is_training,
scope='dp1')
第二十一二十二句與第十九二十句一樣,轉換爲32,256tensor,
第二十三句,最後一層fullyconnect,乘以weight+你、bias,最後得到32,40tensor,
至此,net與transformnet搭建完成