3d Transformer项目记录

Updating.

Posted by tianchen on May 11, 2021

Exp Running

立个flag,要好好记录实验场景和数据

Running

确认一下目前的clean-base

  • PTBlock:
    • 1x1 Linear PosEnc
    • 没有强制kernel-size=1 (Projection 3x3 Conv)
  • TD/TULayer
    • 都不是PointTR-like
    • TD中StridedConv用kernel-size=2,TU中同理,Concat之后的Conv是kernel-size=3的
    • TDLayer就是只有一层Conv
  • Macro:
    • ks: [12, 12, 12, 12]
    • POINT_TR-like: 一开始的stem层以及最后一个大Block当中是3x3 Conv 而不是1x1 Linear

对比PoseEnc

  • 用的是k_8(56.5%) 和 ConvPos(53.x%)

对比FPS & StridedConv’s Sample

Debugging WholeScene

  1. new_base: 56.3 完全是base的情况

  2. StridedConv1x1 54.83%

    • 输入层和PTBlock中仍然用的是ks=3的

    • TULayer的Interpolation中的ConTransposed保持了2x2,但是outConv换成1x1了
    • TDLayer的Mapping换成了1x1 Stride2
  3. PTLike: (第一层和最后一层从Conv换成了Linear,没变化) 57.5%

  4. PT1x1: PTBlock中换成了1x1 conv 53.4

  5. PointLikeWithSample: 54.56%

    • 因为之前的1x1没有用Sample&group用了FPS-Only + PosEnc
  6. NewAll1x1: 53.75%

    • 之前崩溃的是用了FPS-Only的,是否也需要比对一下是不是FPS-only不行?
    • 这样整个主干就没有什么信息融合了,除了PosEnc
  7. Pure1x1

    • config.py中的ks换成了1,会影响第一个1x1 conv
    • 将TD中换成了LinearOnlyCatXYZ
    • EXPECT它不好,不然真没理由了…
    • 51.9%
    • 比之前49%的多了cat xyz
  8. 之前的OnlyConvPos: 47.5%: 用了Conv-based的PosEnc

    • 除了Pos里有Conv其他位置都没有Conv
    • 虽然用的是StridedConvTD但是,ks=1,本质上就是一个Linear
    • 把StridedConv的KS换成2?,其他都保持1
  9. TestConvPos上面的把StridedConv的ks换成2

    • expect它能比47.5%好一点…
    • 看情况能好,但是炸显存了
  • 改进了Val.sh
    • 花了半天时间搞import,但是并没有搞定
    • 目前将根目录下的models替换成了一个软连接,会改变位置,从models_中引过来,在val的时候先连接到output path,结束之后再连接回来
      • 之前的一些文件中models里可能没有存__init__.py,重新复制过来把
    • 然后在train函数的时候会强制link到当前的model下
    • 现在貌似load的是最后一个epoch的…
      • ln -s 到weights.pth的逻辑是在lib/utils的checkpoint函数里面的
      • 不是最后一个epoch最高,所以最后一个epoch final save的时候又把它re-link了
      • 所以记得手动改一下把…懒得在代码里改了,按说改link就行

  1. MinkResNet/6chs: 60.7%

    • 8 bs, LR:0.01,12000 iter(注意bs不一样对应的iter应该不一样)
  2. MinkTRVoxel/base

    • 8 bs, 之前跑的,51%
    • 全部是Strided TD/TU
    • PointTR with ball-query(radius的base_r是20,比knn的要大一圈,手动测了一下貌似换成base_r=5会比较合适一点), kernel-size=3
    • 不是很确定radius应该放多大,因为对比point-based点更密了,但是k是一样的,是不是理论上应该用更大的感受野
  3. MinkTRVoxel/All1x1: 49.5%左右
    • 8 bs, but k=12,
    • 第一个最后一个都是TD/TU
    • PTBlock用的KNN
    • TDLayer是PointTR-like,FPS_only, no concat xyz
    • TULayer是Interpolation & add
    • 看起来结果也算合理,因为相比于原本的PointTR少了一些层,如果目前的PT层本质上没有比Linear好的话,不如ResNet其实也正常,因为ResBlock中本身堆叠多个
  4. MinkTRVoxel/TR3x3: 51.8%
    • TD/TULayer用的仍然是PointTRlike
    • 第一层最后一层用的stridedConv
    • kernel-size统一是3x3
  5. 有卡的话感觉可以启动一个当前的LInear_Only的Ver. 49.368%
    • 与All1x1的差距,就在PTBlock中省去了QK操作,只有两个linear层
    • grouped_input_x加上了pose_tensor之后过alpha再取softmax,和point-ver差不多(point中是能和TR差不多)
    • 显存占用明显小了…就2G左右
  6. StridedConvLike: 57.8%%的版本

    • ks=3
    • TD、TULayer(以及第一个)用的都是StridedConv
  7. StridedConvWithBallQuery

  8. k_8: 62.46% - 这个是错的

  9. first_k_8

  10. CHECK一下是不是Dataloader写错了

    • 懒狗的话直接再用load-whole来跑一次ResNet就好
    • 或者check一下valid集合的代码
  11. 起一个和我们目前Block ArrangeMent一样的ResNet(maybe create resnet block with cur Transformer)

    • 启动的实验是Res18-like:59.26%
      • 按理说和Res16UNet18基本是等价的,只不过是TD与TU不一样,两个都可以跑一下。 Pure-Res18: 61.58%
  12. 将我们目前的最好的版本用LinearOnly测一下

    • 用全8的neighbor size
    • POINT_TR-like all False
    • USE_KNN=True
    • SKIP_ATTN = True
      • and use the 3x3 MInkConv but not 1x1 conv
      • KERNEL_SIZE=3
    • StridedLinearOnly: 59.6%
  13. 上面的最后valid结果有点问题,其实用的是train集合上的结果

    • 新启动了new_ks_8 用了正确的分batch方式以及正确的valid(按理说应该没有区别,的确仍然是56.6%)

    • 启动了一个DoubleTR的,让一个TR等效一个ResBlock 56.5% 并没有变好,看起来确实不能够直接加深

  14. 启动了一个WithDropout: 55.8% 更差了

  15. NoPosEnc: 56.3%

    • 与CVT的实现方式是吻合的,所以应该是生成QKV的时候如果用了Conv就会隐含了信息(hope so)
  16. OnlyConvPos: 47.5%

    • 除了delta(3x3 conv)生成pos_encoding其他都使用linear
  17. LinearOnlyNoPos: 53.5%

    • SKIP_ATTN,用一个3x3 conv的alpha映射
    • 没有Pos-encoding
  18. ConvPos: 54.x%

    • 一个和base唯一区别是用了conv-based的PosEnc的
  19. new_base

    • Kernel-size=2的合理版本: 仍然是55%
  20. PT1x1 & PT1x1NoPos

    • PT1x1 NoPos 55%(因为StridedConv里有neighbor aggregation,所以不需要了)

加入Instance Label

  • 老版本的实现:l
  • Dataset中直接也loding一个pth文件。这个是可以直接用GT的
  • 然后如何使用pred信息:
    • 先就直接把需要用的给连接到我需要的目录下,直接在log_dir下找pred文件
    • 加arg传arg有点困难(本来是可以直接传arg的,但是有点麻烦)
  • test函数中将pred存下来:
    • 先加save-pred把,写好了,现在返回的是312的
    • 需要确定一下点数是否是一致的
  • 添加了一个is_export的模式 in main.py

    • export出来了点数和train时候的不一样*可能是没有搞定
    • 过了elastic-distorition之后点数没有变,但是值不一样了,因为coord变了,所以dataloading之后也变了,干!
      • 没有固定住seed,固定住之后可以了,之前valid的时候没有控制seed
      • 看起来在train集合上的准确性有所下降,按理说还是应该infer出最clean的,不带aug的
    • 每一次的shuffle怎么不一样了?
    • SpatioTemporalSegmentation/test.py at master · chrischoy/SpatioTemporalSegmentation (github.com)
    • 最粗糙的解决方案按理说是生成pred的时候就用和train一样的dataloadin
  • Dataloader中也需要改
  • 挺烦的一件事是如果对之前跑出来的ckpt,会报错config里没有新加入的arg,需要修正一下子。
  • 新的问题是Voxel-based出来是一个batch揉在一起的,需要手动分开一下

  • 发现了穿不进去,点数对不上等一系列问题……
  • 现在导出之后在scannet_pickels的目录下创立了一个gt_aux_train.pth来提供gt,另外如果用export模式,也可以在log-dir下产生pred-train和preds_val.pth
  • 在新的训练开始之前要先把pth文件给link到log-dir下,分别是preds_train/val.pth

Separate batch的用法

image-20210527114542131

  • 本来以为是[0:4]之间是5个值的,但是我重新测试了一下是4个值?而对于一个长度为100的tensor,我索引[0:100]是可以的,而x[100]是不对的
    • 核心的区别是单个索引还是区间索引!!所以说原先写错了
    • image-20210527115058888

Voxel-based的模型输出之后在Val iou掉了很多?

  1. 从62 -> 56
  2. 注意现在config.json需要修改ignore-index了,之前跑的需要在里面把255改成-1
  3. train的时候调用的就是这个函数,打印出来的结果是对的
    • 只能猜测是存ckpt的时候出了问题
  4. resnet好像没啥问题,出来还是60.39%(如果不用load_whole)

问题所在是测试的时候用错了Dataset…并不是…

对Point-based和Voxel-based的IOU的区别

  1. Voxel-based中现在用的是Voxeliaztion之后的labels(经过了降采样)
  2. 这么做的话不同的Voxel size是否能够保持,看代码中直接是对Voxelize之后的target算的precision以及iou
  3. 不受val_bs的影响
    • 我load ckpt之后在train的时候resume就是高的,但是valid就不行???
  4. 对比了两者model,发现model确实也有区别(因为过了一次inference重新累积了,差距确实比较小)
    • 现在两者的model完全一致,但是还是不对,只能考虑val-loader的问题
  5. 不可思议,换了Resnet的model,它们就是一样的?
  6. image-20210527173353493
    • 真正的原因是load_whole的时候…之前是用config.is_train来界定的,导致了错误…我的问题…真的浪费时间。

对齐新的Dataset以支持load-whole

  • 两者之间的target的区别(加了一个train iou):
    • crossEnt的ignore_idx是255
    • WholeScene的target是有一个255
    • 而pred是0-19一共20类别
  • Dataset: 1. ScannetSparseVoxel的getitem中有一个load_ply函数了,这个函数输入是一个PATH,取出raw的pc,然后做Voxelization * 改成init网络的时候直接load整个集,然后load_ply直接给索引回去 2. 给dataset添加了一个load_whole的参数
  • todo:
    • 读到的scene-id是/data/eva_share_users/zhaotianchen/scannet/raw/metadata
      • 需要对比clean的ply文件和当前这种MinkResNet处理过的ply文件区别
      • 或者我直接读我做好的clean的pth
        • 还是这么做吧因为我们需要用到我们自己会生成的instance label
        • 原理上已经验证过pth中的与segs.sens(原本文件)是一致的
    • 搞清楚机理了,现在需要实际进去测试一下
      • 改ignore_mask = -1看看
      • 需要把所有的东西都给映射到[-1, 0~19]
        • train_point当中的label是[0-20],应该写了一个加减的dirty fix,先放着把,我们把train函数改了先
    • 我们的pth中是已经经过map之后的label(0-20)
      • 但是scannet_processed当中还是没有处理过之前的
      • 所以点数上和unique label上都有区别,需要对齐一下
      • ignore_mask = 255,可以换成-1
      • config中的ignore_label也换成1了-1
    • 我记得点数上有点问题来着,保持和目前ply文件一致?
      • 需要可视化一下:pth文件里可能将一些class离谱的点给删除了
      • 不记得data-idx是否一致了
      • 已经ck过如果都将label正确映射为-1的话(对应原先的255)剩下的点是一致的
    • ignore-index需要修改,会连带着train.py中的一大堆逻辑
    • 又一个feat_size不一样的问题,raise了assertion
      • 因为我们目前的输入feat突然是float64
    • 注意在train函数里要将那个 precision_at_one 丢一个ignore_index=-1进去(默认是255我现在也要改成-1了!以及算iou的时候也一样要变-1,valid讲道理也要一样改)
    • 注意我们改了mask的值,说不定用不load-whole会出问题*
    • phase的定义(ScannetSparseVoxel):
      • initialize_dataloader中可以feed进一个phase的参数
        • phase用来选择data_paths,是一个读文件名字的
        • 然后再Datset对应的类里面,传入了data_paths,直接是一个list了,并没有传到最里面(我感觉需要dirty fix了…)
      • phase是一个类似enumerate的变量,TRAIN / VAL
      • 目前在main.py中会feed in,config.val_phase,默认值是VAL
      • p

  1. 现在正在跑的一个test_clean: 其实和标准的也有区别…就是所有的PTBlock的(非DS的时候)少了linear_top,以及TD的TR块少了linear_down
    • 看起来和完全clean的基本一致
    • 看起来不需要linear-top
    • 56.5%
  2. 重新起一个test_clean2都带linear-top/linear_down,但是N对上的(显存占用更多了,改了bs为15) 55.8%

    • 还是低了一点?看起来linear层会有问题?
    • TD层需要linear-down?和我们正常的是没有的
  3. 所有的block都取消linear_down(因为怀疑是maxpool之后又过了一个linear层有点不合理)

    • 比起2来说明显更低了,不应该这么做 no_linea_top_down: 56.0%
    • 表现出的是normalTR中的linear-down关键(它用的是sum不是pool?,而TR中的lineardown无所谓)
  4. 所有的dsblock都不带linear_down与top,而一般的block保持一样 no_linear_td: 55.1%

    • 上面2个都对TDLayer的输入加了一个linear-top,然后不work了

    • expect它和第一个test_clean结果差不多(区别就是这里normal TR块也有linear_top,而第一个没了)
    • 这个讲道理和TDLayer才是一样的

结论,有无linear层不重要,本身就会有近0.5%的acc波动(maybe bs?造成了iter-size少了一丢丢)

  1. 起一个12bs的作为base(用no_linear_td作为base)
    • 没有完成test,train iou弱了一些
    • 56.0%
  2. 12bs_2作为与第一个一样的配置(都不用linear-top)
    • 比较正常,可以match
    • 56.6% 基本正常能够match上
  3. 尝试了一个skip_all, 直接fps之后过
    • 完了发现不能match了…,all-skip基本没掉?
    • 还需要去看是为啥
    • 更高了…final_iou: 58.9%
  4. 对MixedTR用当前的all-skip策略起了一个训练,看看会不会掉点 - 没有问题 57.7
  5. 正在尝试看VoxelTR中是哪里出了问题:!!!

    • 说明了确实voxel-based不cat xyz确实变化更大(是不是query&Group与KNN的区别,或者是coord的信息损失?) 56% -> 51%

    • 正在跑的test是没有catXYZ:
      • expect他们都在50%左右
    • test2就是FPS-only
      • 看起来比cat上xyz的TD要好一些(maybe加入xyz信息的方式有问题,因为没有relative,所以就用了绝对坐标的mean)
    • test3就是original的
  6. 以及存下来的map貌似不全,以及可以channel维度减少一点

    • 临时将save-freq改为了100,已经修正好了,改回来了
  7. 训练了一个NoCatXYZ but skip_attn的PointTR,来作为对比

    • expect: 它受到xyz的影响没有这么大(会不会是query & KNN的区别)
    • 果然几乎都没有低… 55.9%
  8. 给Voxel-based也写了一个用KNN的

    • knn_base:raw MLP
    • knn_with_xyz: concat-xyz’s TDLayer
    • knn_fps: fps
  9. debugging the fuckin FPS with query

    • QuerySkipTD
    • 55.8% back to normal
  10. 改好了新的group方式之后启动了3个旧实验:

    1. test_clean: pointnet++ like
    2. all_skip linear
    3. TR-like WeightedSumTD
    4. 补充两个新实验WeightedMax & LinearWithPos
      • WeightedMax 59%
      • PointWithPos: 57.9%
  11. PointBiggerR: 更大radius下的pointnet++
    • pointnetBiggerR 56.9%没崩
  12. 在Voxel-based的scope下用正确的radius来用

    • 用StridedConv看如何
    • 用StrideConv1x1 + Interpolation: 低了不少
    • 正在debug中尝试FPS之后接一个ME的conv,看看是否有问题
      • 我觉得sample几乎是一样的…
      • 但是到了深层它们的点数会不一样,stridedConv会降采样不下去
    • debug用knn+minkConv,低了一些
    • debug2和原来一致 Query+normalConv
    • debug3 Query+MinkConv still OK
    • debug4 KNN+StridedConv 更低
    • debug5 Query+StridedeConv 但是没有那么的低
  13. deugging the nan

    • torch.isnan在input_mlp的时候weight炸了
    • 发现是需要linear-down,怪起来了, dont know why,加上
  • 可能会存在的几个bug:
    • 目前的StridedMinkTR可能会炸显存
    • 可能在test的时候报错
      • image-20210522180455705

Pointnet++

MSG: 各个radius的feature concat起来了,grouper变多等效width变大

(SAModule) sample&group每次都做了downsample

  • SAModule等效为一个TD+PointTR

(FPModule) Upsampling,interpolation+Concat&Projection

看PointTR与PointNet++相比到底好在了哪里

  • 新启一个纯PointTR的实验,在clean_TR
  • No positional encoding(现在的pct_util当中是没有pos_encoding的, on card4 no_pos_encoding

  • 刚改好了skip QK只有v做maxpooling的实验一会测试一下再跑

  • 试一下当前的KNN到底会不会炸显存,如果点数很多的话*
    • 会的…在KNN这里
  • niansong新跑的VoxeTR改优之前大概在50%,MinkResNet在58% - ck一下为啥之前只有40多
    • /home/zhaotianchen/project/zns-dir/SpatioTemporalSegmentation-ScanNet/outputs/ScannetSparseVoxelizationDataset/MinkowskiVoxelTransformer/exprt_multi
    • 需要跑一个新的整scene的VoxelTR
      • 对比两者的区别: (TULayer中的out_conv的ks不一样,感觉不是很本质…)
        • 看到现在已经发现有区别了,一开始的score低一些
      • 因为Transformer块中的kernel_size设置成了1
      • 启动了新的MinkTR在整个scene上的精度
      • base: - 50.7% on card 6
      • Compared with ResNet - 60%
      • 与pointTR结构上还是有一些区别的,比如说中间和最后没有少了两个block(因为显存issue)
  • train函数中,给整个Scene的加了一个arg来控制是否用6 chs
    • 不过输入的mlp的dim可能需要对应修改一下,3 -> 6,直接手改8
    • base_xyz:  49%  on card 7 没有什么变化,和分块scene上现象不一

TODO:

说明了Transformer没有学习到Pointnet-like的TransitionDown操作,需要探索why?

  1. TODO: 改TD只用一个FPS,不用group&projection
  • 仍然还是需要一个Projection不然dim对不上,以及不能利用xyz信息
  • 之前的cat_xyz是将neighbor的xyz都减去中心点的坐标*,目前新的xyz做不到加入这个
  • 只能先把xyz坐标给norm一下(除以mean把就),然后一个linear-BN给映射到64-dim把
  • fps_only on cardn 5 46%
  1. TODO: 是否是neighborhood的Group点范围
  • 实际打印出来ck了一下,大概16个点的距离,浅层在1~2,后面能够到6~7
    • 在sample&group的时候
    • dat = x.C[new_indices[0,0].long()]; dat - dat[0]
  • biggerStridedTD on card 6 41.4%
  1. Maybe 可以从整scene上FPS一定的voxel对比VoxelTR与MinkResNet (8192 points)
  • 写一个新的dataloader
  • 一定程度上可能会因为各个scene之间的sample间隔而有问题下
  • 但是test怎么做?先sample再iterpolate?

  • 如果这几个不work的话,就是Transformer没有学到TD
    • 完全不加constraint的话,就很难学好 -> fixed part of the arch(类似我认为的引入一些anchor transformer)
    • 中间不一定要加pointnet的block,或许可以以其他形式引导transformer的优化
  • 测试一下整scene上的VoxelTR与MinkResNet
    • TDLayer可能会出现问题:

2021-05-21

  • TD层有一个巨大的影响
    • Transformer的引入貌似弥补了position信息的丢失
    • 原本(-10%)
    • 启动了一个MixedTrans的不带xyz的,在test,6卡上; 貌似最后区别不大,55% (-1%)
    • 启动了MInkTrans,最后的在51%左右(-3.5%)
  • 是否kernel_size=1和TD就是不兼容(之前试过,确认一下)
    • 启动了MinkTrans下的STrideConvTD on card 5
    • 掉到了42%
  • Voxel中的Conv中加回来
    • stem改成3x3
    • 生成qkv的改
    • linear-top/down改
    • middle-linear保持了1x1
    • OOM了…,重新启动之后 mIoU: 54.2%并没有变高,基本一致
  • 加了一个vanilla的版本确定我的merge没有错
    • MinkTrans/test on card 7,看起来ok
  • 加了一个只有TU换成voxel-based的形式:
    • JustVoxelTU
    • 跑起来报错了,做不到,因为前面并不是stridedConv,导致内部的tensor_stride不是2,作罢
  • 貌似目前的VoxelTR的Query&Group与KNN有一些区别
    • TODO: 也改成KNN?
    • :question:: 整scene上的架构preference会与当前的有区别。
    • 目前的KNN实现方式在整scene上不feasible…(是不是还是迁移到整scene上?)

完成之后的实验按照日期放在下面

2021-05-11

  • 启动了一个MixedTransformer,固定npoint个点做downsample的实验(与固定点的PointTR Setting类似)

  • 因为昨天的实验启动的时候用的是N=2,所以严格来说和最开始N=4 downsampling rate的PointTR有区别

  • 发现了一个细节是TD层中有没有把xyz作为feature加入进去影响比较大

    • pointnet的一个legacy
    • 对于absolute的coord来说,加入dense的位置信息有help,
  • 目前PointTR(discrete-input)与MinkTR相当: mIOU ~54%,同等情况下的MixedTR却更高(58%),其与PointTR的唯一区别就是有没有对输入点做归化(一样Coord的Feature给downsample掉)

    • 区别在with/without KNN:用的是query&group,并没有严格的KNN

      • 应该就是2/3的唯一区别了,可能是因为r以及感受野的原因
    • PointTR和VoxelInputTR的区别在,下采样的点数是固定为N/2个(对point-based的情况是固定的,因为输入都是4096点,而VoxelInput的则不定个 )

      • 将VoxelInput的输入换成了固定的点数(与Point保持一致)变成了54.9%(一下子就掉下来了)
    1. PointTR(pointr_base): 53.4%
    2. VoxelTR(minktr_base): 54.6%
    3. PointTR using voxel input(mixedtr_base): 56.1%

Code-base & Details

Alpha in skip_only PTBlock

align了一些另外几个细节

  1. linear_top down去掉
  2. alpha的embedding改了一下shape(第二个linear层产生expansion),以及加上relu
  3. 主要的区别在于downsample_rate是4还是2(4的时候有时候会nan,不知道2的时候是不是)

Expansion in PTBlock

为了让PTBlock也支持Downsample进行了设计

  • 在最先开始(Linear-top之前)加入了一个FPS,并且降采样了xyz和points

  • residue是fps之后的结果
  • 对于channel数目加入了一个self.expansion的参数,linear-top会映射到2x ch(hidden-dim),后面(out_dim)也一直保持

为了保持接口一致,把TD层的输出变成了两个

对PTBlock的输出,如果downsample的话,就不加residue了

Resume:

  • Resume的用法:
    • 在train.sh里面输入export RESUME=True,就会load ckpt
    • 但是state里面存好了iter-size,如果iter-size到了就会自动进valid,所以需要改一下设置
    • 在train函数里面会检索 if config.train而我给他搞了一个默认的值是False,会触发这个,我先很dirty的用了判断是不是 == ‘True’,不是就置None(有那么一点蠢比)

val_batch_size:

如果在test的时候输入了config作为参数,一开始是会被load进来(via main.py --batch_size被main函数一开始的gen_config中得到),但是由于后面又loading了test_config(train时候用的config),所以就决定不了了,为了方便我们要么还是直接改config吧。(虽然不是很严谨)

  • 改了个接口通过val_batch_size来喂进去了
  • 修改了config.py中的默认为8

save方式

在目前的train_points.py中其实并没有在train函数内进行valid(因为dataloader需要额外的),所以只有在save_freq的时候会调用一个save_inter(目前把valid的改为每2k个iter了)

而在一般的train函数中是在valid和save的时候都执行了save_iter,

貌似因为某些原因save_iter会卡住vim,可能涉及了Intense的磁盘读写

VoixelTR types

  • 把输入用3还是6 channel写成了一个config.xyz_input,这样就不用同时改model/train/valid了

KS_config

  • 在config中加了一个ks,表示TR里的ks是1还是3
  • PTBlock也需要输入一个kernel_size的arg
  • 目前我只改动了mink_transformer_voxel.py

KNN in PTBlock

  1. pct_utils.py:
    • 先做KNN(输入点数N/4,或者是输入npoint/2)
    • 然后依据KNN对每个点group K个(对phai和alpha)
  2. pct_voxel_utils.py
    • 直接用的是QueryAndGroup函数,输入一个r一个k
      • /home/zhaotianchen/project/point-transformer/pt-cls/pointnet2_ops_lib/pointnet2_ops/_ext-src/src/ball_query_gpu.cu这个路径下
      • 通过ball_query得到一系列idx再做grouping
      • 顺序的从random-shuffled的点中(循环点数k)找到nsample个fit in radius的点

PTBlock

  1. Linear-Top层: in_dim -> hidden_dim

    • 对MinkResNet-like的,可能in-dim和hidden-dim不一样,后续的qkv都是从hidden-dim来的
  2. QKV的Mapping: hidden_dim -> out_dim(AttentionMap的尺度)

    • 就是一个1x1 Conv(Linear)
    • \phai是直接由input-feature过一个Linear,然后broadcast到psi(xK)
    • \psi是先过一个Linear,从neighbor feature中取k个
    • \alpha与\psi类似
  3. Pose_encoding:(\delta) [3, out_dim] -> 因为要和\alpha(value)加在一起,所以也需要成out_dim:
  4. Attn_paer

    • (q-k+pose_encode)加在一起过一个MLP(gamma): out_dim -> vector_dim

    • 这样之后的结果做一个Softmax就是attn_map了
    • 然后再乘上\alpha+pos_enc
  5. LinearDown: [out_dim -> in_dim]

    • 最后revert回到in_dim来加shortcut

MinkVoxelTR与MinkTR

  • minkVoxelTR更类似于MInkResNet,而minkTR类似PointTR,两者区别:
    • 输入stem是否做降采样,第一个PTBlock其实就是tensor-stride=2,到了最后一层再做一个interpolation插回来
    • 少了中间一个最大的512-dim的TR-block(minkresnet最大的块也是只有256)
  • MInkVoxelTR与ResNet的区别
    • 一个block里可能有很多的resnet层,(最深的地方有6个,而TR层只有一个)
    • 最后concat了与输入尺度一致的层之后没有过PTBlock直接接了final_fc(可能可以加上)

Algorithms