PointNet复现

一、代码运行

1.分类任务

1.1训练

python train.py --batch_size=8

显卡显存太小,只能跑batch size为8的,训练250个epoch。

1.2测试

python  evaluate.py --visu

结果:

eval mean loss: 0.488872
eval accuracy: 0.878444
eval avg class acc: 0.851238
  airplane:     0.980
   bathtub:     0.860
       bed:     0.950
     bench:     0.700
 bookshelf:     0.900
    bottle:     0.950
      bowl:     0.950
       car:     1.000
     chair:     0.970
      cone:     0.900
       cup:     0.650
   curtain:     0.800
      desk:     0.791
      door:     0.850
   dresser:     0.651
flower_pot:     0.200
 glass_box:     0.950
    guitar:     1.000
  keyboard:     1.000
      lamp:     0.950
    laptop:     1.000
    mantel:     0.950
   monitor:     0.940
night_stand:    0.698
    person:     0.950
     piano:     0.860
     plant:     0.780
     radio:     0.800
range_hood:     0.910
      sink:     0.750
      sofa:     0.960
    stairs:     0.850
     stool:     0.800
     table:     0.810
      tent:     0.950
    toilet:     0.960
  tv_stand:     0.820
      vase:     0.810
  wardrobe:     0.650
      xbox:     0.800

论文中的结果是:86.2/89.2,相比论文中差了一些,可能是batch size的问题。

2. part segmentation

代码在part_seg下,进去sh download_data.sh下载数据集,然后运行trian.py训练,test.py测试。分割任务的显存占用更高,我只能跑batchsize=4的…。最终模型的结果比论文里也低了接近两个点(0.8197/0.837)。

Accuracy: 0.923867
IoU: 0.819725
         02691156 Total Number: 341
         02691156 Accuracy: 0.9096132876935942
         02691156 IoU: 0.8228572722404234
         02773838 Total Number: 14
         02773838 Accuracy: 0.9517263003758022
         02773838 IoU: 0.7696178300040108
         02954340 Total Number: 11
         02954340 Accuracy: 0.8923338109796698
         02954340 IoU: 0.7994510477239435
         02958343 Total Number: 158
         02958343 Accuracy: 0.9047723118262955
         02958343 IoU: 0.734290400637856
         03001627 Total Number: 704
         03001627 Accuracy: 0.9394946531815962
         03001627 IoU: 0.8910455703735352
         03261776 Total Number: 14
         03261776 Accuracy: 0.9178562164306641
         03261776 IoU: 0.7298440933227539
         03467517 Total Number: 159
         03467517 Accuracy: 0.9630299694133255
         03467517 IoU: 0.9014740949906643
         03624134 Total Number: 80
         03624134 Accuracy: 0.8905808448791503
         03624134 IoU: 0.8044050216674805
         03636649 Total Number: 286
         03636649 Accuracy: 0.8275325214946186
         03636649 IoU: 0.7223616379957932
         03642806 Total Number: 83
         03642806 Accuracy: 0.9772439060440983
         03642806 IoU: 0.9505088530391096
         03790512 Total Number: 51
         03790512 Accuracy: 0.8500167996275658
         03790512 IoU: 0.633358824486826
         03797390 Total Number: 38
         03797390 Accuracy: 0.9923725128173828
         03797390 IoU: 0.921830227500514
         03948459 Total Number: 44
         03948459 Accuracy: 0.9490793401544745
         03948459 IoU: 0.7901863618330522
         04099429 Total Number: 12
         04099429 Accuracy: 0.7942575613657633
         04099429 IoU: 0.5516049861907959
         04225987 Total Number: 31
         04225987 Accuracy: 0.9462758341143208
         04225987 IoU: 0.7356803032659716
         04379243 Total Number: 848
         04379243 Accuracy: 0.9443713494066922
         04379243 IoU: 0.7989320575066332

二、代码解读

1.train.py

定义了训练的过程。

1.1 parser & FLAGS

定义所需的各种参数和默认值,打包放在FLAGS里,可以在命令行进行交互。

1.2 get_learning_rate()/get_bn_decay()

使用tf.train.exponential_decay()函数对lr和bn_momentum进行衰减。

tf.train.exponential_decay(
                      BASE_LEARNING_RATE,  # Base learning rate.the value will be decayed.
                      batch * BATCH_SIZE,  # Current index into the dataset.
                      DECAY_STEP,          # Decay step.
                      DECAY_RATE,          # Decay rate.
                      staircase=True)      # True:decay every decay step.
					                       # False:decay every real setp.

1.3 train()

设置loss、model等节点,和超参数、place holder一起放在ops里。并不真正run,控制每个epoch的训练。

1.4 train_one_epoch()

把训练数据分成len(TRAIN_FILES)份。每份数据中,按照batch_size取一个batch进行训练。一个batch的数据进行数据增强,包括rotate和jitter,是由provider.py实现的。
根据ops里ph相关的参数构造feed_dict,并从中取出构造的训练、预测、loss等节点,作为sess.run()的参数进行训练。

1.5 eval_one_epoch()

与train的部分相同,也是把测试文件份成几分,每一份把每个batch喂进去,计算总的准确率,作为训练中每个epoch的测试。

2. models

models文件夹下,存放了训练所用的三种网络结构,cls、seg、T-NET。所用到的卷积等网络结构,在utils/tf_uitl.py中实现。
网络输入为B*N*3。B是batch_size,N是一个样本中点的个数,3是点云维度(三维坐标)。这里把一个样本看做了N*3的矩阵,类似二维图片,之后在其上进行卷积等操作。
值得说明的是,网络提取的特征不是3这个维度,这个维度在网络开始就被卷成了1,特征维度是输入expand出的新维度。
论文中所提及的MLP,在这里也是用卷积实现的。

2.1 pointnet_cls.py

这个文件实现了网络的分类结构。
输出为B*40,是每个样本对于每个类别的概率。
网络结构在get_model()中定义,loss则在get_loss中定义。

网络结构

按照网络流程,将整个网络分为以下几个阶段。
网络输入:[B,N,3,1]

  1. 特征提取
    这部分使用的都是2d-conv。
    首先用[1,3]的卷积核将电云的宽卷成1,使用64个卷积核,得到输出维度[B,N,1,64]。再接一个[1,1]的卷积核,再次提取特征。
  2. STN
    这个部分看做子网络,单独使用model/transform_net.py实现。
    实现过程中,先用几次[1,1]的卷积将特征升维,得到[B,N,1,1024]。然后在N维度上使用max pooling,reshape得到[B,1024]。在经过FC进行特征降维,得到[B,256]。再生成一个[256,64*64]的T-NET,相乘后得到[B,4096],reshape成[B,64,64]
    T-NET和原输入tensor做张量乘法,expand第二维,得到STN的输出[B,N,1,64]
  3. 特征整合
    又是一系列的[1,1]卷积,将特征升维到[B,N,1,1024]
  4. 对称操作
    在N维度上使用max pooling,再reshape掉为1的维度,得到[B,1024]
  5. 预测结果
    接续几个FC和drop out,降维到40,得到结果[B,40]
loss设计

loss分为三部分:

  • classify_loss:分类的交叉熵损失。
  • mat_diff_loss:这个用于强迫T-NET把自己学的很正交。
  • reg_weight:正则项。

3.utils

这个文件夹提供了一些工具函数。

3.1 data_prep_util.py

实现数据的读取,单个文件路径存在.txt文件中,从中读取文件名,join父路径,读到数据,做成数据集。

3.2 pc_util.py

提供了一些三维数据处理的函数,包括点云和volume的转换,点云可视化,点云的读写。

3.3 tf.util.py

自己封装的一些层,实现了各种卷积,pooling,fc。也实现了权重初始化的函数。
但是网络好像只用到了2D卷积,max pooing?

4. provider.py

实现了数据读取,数据处理,数据增强的函数。
包括:

  • shuffle。
  • rotate:构造一个旋转矩阵,乘到点云上。
  • jitter:构造一个抖动,用clip限制一下,加到原数据上。

你可能感兴趣的:(三维物体识别,深度学习,tensorflow)