openpoints 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. openpoints/__init__.py +3 -0
  2. openpoints/cpp/__init__.py +6 -0
  3. openpoints/cpp/chamfer_dist/__init__.py +110 -0
  4. openpoints/cpp/chamfer_dist/setup.py +19 -0
  5. openpoints/cpp/chamfer_dist/test.py +34 -0
  6. openpoints/cpp/emd/__init__.py +3 -0
  7. openpoints/cpp/emd/emd.py +88 -0
  8. openpoints/cpp/emd/setup.py +27 -0
  9. openpoints/cpp/emd/test_emd_loss.py +45 -0
  10. openpoints/cpp/pointnet2_batch/__init__.py +24 -0
  11. openpoints/cpp/pointnet2_batch/setup.py +23 -0
  12. openpoints/cpp/pointops/__init__.py +0 -0
  13. openpoints/cpp/pointops/functions/__init__.py +0 -0
  14. openpoints/cpp/pointops/functions/pointops.py +314 -0
  15. openpoints/cpp/pointops/setup.py +37 -0
  16. openpoints/cpp/pointops/src/__init__.py +0 -0
  17. openpoints/dataset/__init__.py +10 -0
  18. openpoints/dataset/atom3d/__init__.py +1 -0
  19. openpoints/dataset/atom3d/psr.py +38 -0
  20. openpoints/dataset/build.py +98 -0
  21. openpoints/dataset/data_util.py +192 -0
  22. openpoints/dataset/datalist.py +67 -0
  23. openpoints/dataset/dataset_base.py +96 -0
  24. openpoints/dataset/graph_dataset/__init__.py +3 -0
  25. openpoints/dataset/graph_dataset/graph_dataset.py +93 -0
  26. openpoints/dataset/graph_dataset/stack_with_pad.py +91 -0
  27. openpoints/dataset/graph_dataset/structural_dataset.py +73 -0
  28. openpoints/dataset/graph_dataset/svd_encodings_dataset.py +110 -0
  29. openpoints/dataset/grid_sample.py +21 -0
  30. openpoints/dataset/matterport3d/__init__.py +1 -0
  31. openpoints/dataset/matterport3d/category_mapping.tsv +1660 -0
  32. openpoints/dataset/matterport3d/matterport3d.py +210 -0
  33. openpoints/dataset/matterport3d/matterport3d_dataprocessing.py +105 -0
  34. openpoints/dataset/modelnet/__init__.py +3 -0
  35. openpoints/dataset/modelnet/modelnet40_normal_resampled_loader.py +124 -0
  36. openpoints/dataset/modelnet/modelnet40_ply_2048_loader.py +160 -0
  37. openpoints/dataset/molhiv/__init__.py +1 -0
  38. openpoints/dataset/molhiv/data.py +59 -0
  39. openpoints/dataset/molpcba/__init__.py +1 -0
  40. openpoints/dataset/molpcba/data.py +59 -0
  41. openpoints/dataset/parsers/__init__.py +1 -0
  42. openpoints/dataset/parsers/class_map.py +19 -0
  43. openpoints/dataset/parsers/constants.py +1 -0
  44. openpoints/dataset/parsers/parser.py +17 -0
  45. openpoints/dataset/parsers/parser_factory.py +29 -0
  46. openpoints/dataset/parsers/parser_image_folder.py +69 -0
  47. openpoints/dataset/parsers/parser_image_in_tar.py +222 -0
  48. openpoints/dataset/parsers/parser_image_tar.py +72 -0
  49. openpoints/dataset/parsers/parser_tfds.py +297 -0
  50. openpoints/dataset/pcqm4m/__init__.py +1 -0
  51. openpoints/dataset/pcqm4m/data.py +62 -0
  52. openpoints/dataset/pcqm4mv2/__init__.py +1 -0
  53. openpoints/dataset/pcqm4mv2/data.py +87 -0
  54. openpoints/dataset/s3dis/__init__.py +2 -0
  55. openpoints/dataset/s3dis/s3dis.py +156 -0
  56. openpoints/dataset/s3dis/s3dis_block.py +96 -0
  57. openpoints/dataset/s3dis/s3dis_sphere.py +349 -0
  58. openpoints/dataset/scannetv2/__init__.py +1 -0
  59. openpoints/dataset/scannetv2/scannet.py +176 -0
  60. openpoints/dataset/scanobjectnn/__init__.py +3 -0
  61. openpoints/dataset/scanobjectnn/scanobjectnn.py +110 -0
  62. openpoints/dataset/semantic_kitti/__init__.py +1 -0
  63. openpoints/dataset/semantic_kitti/helper_tool.py +286 -0
  64. openpoints/dataset/semantic_kitti/label_mapping.yaml +211 -0
  65. openpoints/dataset/semantic_kitti/semantickitti.py +229 -0
  66. openpoints/dataset/semantic_kitti/utils/meta/anno_paths.txt +272 -0
  67. openpoints/dataset/semantic_kitti/utils/meta/class_names.txt +13 -0
  68. openpoints/dataset/semantic_kitti/utils/semantic-kitti.yaml +211 -0
  69. openpoints/dataset/shapenet/__init__.py +1 -0
  70. openpoints/dataset/shapenet/shapenet55.py +76 -0
  71. openpoints/dataset/shapenet/shapenetpart.py +121 -0
  72. openpoints/dataset/shapenetpart/__init__.py +1 -0
  73. openpoints/dataset/shapenetpart/shapenet55.py +75 -0
  74. openpoints/dataset/shapenetpart/shapenetpart.py +388 -0
  75. openpoints/dataset/vis2d.py +17 -0
  76. openpoints/dataset/vis3d.py +153 -0
  77. openpoints/loss/__init__.py +3 -0
  78. openpoints/loss/build.py +281 -0
  79. openpoints/loss/cross_entropy.py +38 -0
  80. openpoints/loss/distill_loss.py +76 -0
  81. openpoints/models/__init__.py +10 -0
  82. openpoints/models/backbone/Stratified_transformer.py +558 -0
  83. openpoints/models/backbone/__init__.py +11 -0
  84. openpoints/models/backbone/baafnet.py +527 -0
  85. openpoints/models/backbone/ball_dgcnn.py +123 -0
  86. openpoints/models/backbone/curvenet.py +793 -0
  87. openpoints/models/backbone/debug_invvit.py +114 -0
  88. openpoints/models/backbone/deepgcn.py +143 -0
  89. openpoints/models/backbone/dgcnn.py +119 -0
  90. openpoints/models/backbone/graphvit3d.py +134 -0
  91. openpoints/models/backbone/grouppointnet.py +100 -0
  92. openpoints/models/backbone/pct.py +163 -0
  93. openpoints/models/backbone/pointmlp.py +417 -0
  94. openpoints/models/backbone/pointnet.py +199 -0
  95. openpoints/models/backbone/pointnetv2.py +511 -0
  96. openpoints/models/backbone/pointnext.py +663 -0
  97. openpoints/models/backbone/pointnextPyG.py +555 -0
  98. openpoints/models/backbone/pointtransformer.py +293 -0
  99. openpoints/models/backbone/pointvector.py +853 -0
  100. openpoints/models/backbone/pointvit.py +392 -0
  101. openpoints/models/backbone/pointvit_inv.py +942 -0
  102. openpoints/models/backbone/pointvit_inv_old.py +784 -0
  103. openpoints/models/backbone/randlenet.py +318 -0
  104. openpoints/models/backbone/resnet.py +342 -0
  105. openpoints/models/backbone/simpleview.py +153 -0
  106. openpoints/models/backbone/simpleview_util.py +292 -0
  107. openpoints/models/build.py +13 -0
  108. openpoints/models/classification/__init__.py +5 -0
  109. openpoints/models/classification/cls_base.py +136 -0
  110. openpoints/models/classification/point_bert.py +154 -0
  111. openpoints/models/layers/__init__.py +14 -0
  112. openpoints/models/layers/activation.py +57 -0
  113. openpoints/models/layers/attention.py +103 -0
  114. openpoints/models/layers/conv.py +167 -0
  115. openpoints/models/layers/drop.py +164 -0
  116. openpoints/models/layers/graph_conv.py +122 -0
  117. openpoints/models/layers/group.py +415 -0
  118. openpoints/models/layers/group_embed.py +286 -0
  119. openpoints/models/layers/helpers.py +43 -0
  120. openpoints/models/layers/kmeans.py +119 -0
  121. openpoints/models/layers/knn.py +110 -0
  122. openpoints/models/layers/local_aggregation.py +286 -0
  123. openpoints/models/layers/mlp.py +129 -0
  124. openpoints/models/layers/norm.py +106 -0
  125. openpoints/models/layers/padding.py +56 -0
  126. openpoints/models/layers/patch_embed.py +37 -0
  127. openpoints/models/layers/registry.py +168 -0
  128. openpoints/models/layers/subsample.py +185 -0
  129. openpoints/models/layers/upsampling.py +106 -0
  130. openpoints/models/layers/weight_init.py +89 -0
  131. openpoints/models/reconstruction/__init__.py +8 -0
  132. openpoints/models/reconstruction/base_recontruct.py +216 -0
  133. openpoints/models/reconstruction/maskedpoint.py +116 -0
  134. openpoints/models/reconstruction/maskedpointgroup.py +168 -0
  135. openpoints/models/reconstruction/maskedpointvit.py +253 -0
  136. openpoints/models/reconstruction/nodeshuffle.py +11 -0
  137. openpoints/models/registry.py +149 -0
  138. openpoints/models/segmentation/__init__.py +6 -0
  139. openpoints/models/segmentation/base_seg.py +278 -0
  140. openpoints/models/segmentation/vit_seg.py +126 -0
  141. openpoints/optim/__init__.py +15 -0
  142. openpoints/optim/adabelief.py +201 -0
  143. openpoints/optim/adafactor.py +167 -0
  144. openpoints/optim/adahessian.py +156 -0
  145. openpoints/optim/adamp.py +105 -0
  146. openpoints/optim/adamw.py +122 -0
  147. openpoints/optim/lamb.py +192 -0
  148. openpoints/optim/lars.py +135 -0
  149. openpoints/optim/lookahead.py +61 -0
  150. openpoints/optim/madgrad.py +184 -0
  151. openpoints/optim/nadam.py +92 -0
  152. openpoints/optim/nvnovograd.py +120 -0
  153. openpoints/optim/optim_factory.py +306 -0
  154. openpoints/optim/radam.py +89 -0
  155. openpoints/optim/rmsprop_tf.py +139 -0
  156. openpoints/optim/sgdp.py +70 -0
  157. openpoints/scheduler/__init__.py +8 -0
  158. openpoints/scheduler/cosine_lr.py +124 -0
  159. openpoints/scheduler/multistep_lr.py +65 -0
  160. openpoints/scheduler/plateau_lr.py +113 -0
  161. openpoints/scheduler/poly_lr.py +116 -0
  162. openpoints/scheduler/scheduler.py +110 -0
  163. openpoints/scheduler/scheduler_factory.py +118 -0
  164. openpoints/scheduler/step_lr.py +65 -0
  165. openpoints/scheduler/tanh_lr.py +117 -0
  166. openpoints/transforms/__init__.py +7 -0
  167. openpoints/transforms/point_transform_cpu.py +332 -0
  168. openpoints/transforms/point_transformer_gpu.py +764 -0
  169. openpoints/transforms/transforms_factory.py +60 -0
  170. openpoints/utils/__init__.py +8 -0
  171. openpoints/utils/ckpt_util.py +438 -0
  172. openpoints/utils/config.py +113 -0
  173. openpoints/utils/dist_utils.py +54 -0
  174. openpoints/utils/logger.py +170 -0
  175. openpoints/utils/metrics.py +311 -0
  176. openpoints/utils/random.py +16 -0
  177. openpoints/utils/registry.py +294 -0
  178. openpoints/utils/str2bool.py +11 -0
  179. openpoints/utils/wandb.py +88 -0
  180. openpoints-0.1.0.dist-info/METADATA +150 -0
  181. openpoints-0.1.0.dist-info/RECORD +184 -0
  182. openpoints-0.1.0.dist-info/WHEEL +5 -0
  183. openpoints-0.1.0.dist-info/licenses/LICENSE +21 -0
  184. openpoints-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,784 @@
1
+ """ Vision Transformer (ViT) for Point Cloud Understanding in PyTorch
2
+ Hacked together by / Copyright 2020, Ross Wightman
3
+ Modified to 3D application by / Copyright 2022@Pix4Point team
4
+ """
5
+ import logging
6
+ from typing import List
7
+ import torch
8
+ import torch.nn as nn
9
+ from ..layers import create_norm, create_linearblock, create_convblock1d, three_interpolation, \
10
+ furthest_point_sample, random_sample
11
+ from ..layers.attention import Block
12
+ from .pointnext import FeaturePropogation
13
+ from ..build import MODELS, build_model_from_cfg
14
+ from torch.cuda.amp import custom_fwd, custom_bwd
15
+ import math
16
+ import sys
17
+
18
+ from ..layers import Mlp, DropPath, trunc_normal_, lecun_normal_
19
+
20
+ use_inv = True
21
+ use_customized_backprop = True
22
+
23
+
24
+ class RevBackProp(torch.autograd.Function):
25
+ @staticmethod
26
+ @custom_fwd
27
+ def forward(ctx, x, blocks, pos_embed=None, alpha=0., lambd=1.):
28
+ # print('during rev, alpha, lambda:', alpha, lambd) # TODO: DEBUG
29
+
30
+ for block in blocks:
31
+ x = block(x, pos_embed, alpha=alpha, lambd=lambd)
32
+
33
+ all_tensors = [x.detach(), pos_embed.detach() if pos_embed is not None else pos_embed]
34
+
35
+ ctx.save_for_backward(*all_tensors)
36
+ ctx.blocks = blocks
37
+ ctx.lambd = lambd
38
+ ctx.alpha = alpha
39
+
40
+ return x
41
+
42
+ @staticmethod
43
+ @custom_bwd
44
+ def backward(ctx, dy): # pragma: no cover
45
+
46
+ # retrieve params from ctx for backward
47
+ Y, pos_embed = ctx.saved_tensors
48
+ blocks = ctx.blocks
49
+ lambd = ctx.lambd
50
+ alpha = ctx.alpha
51
+
52
+ dY_1, dY_2 = torch.chunk(dy, 2, dim=-1)
53
+ Y_1, Y_2 = torch.chunk(Y, 2, dim=-1)
54
+
55
+ for _, blk in enumerate(blocks[::-1]):
56
+ Y_1, Y_2, dY_1, dY_2 = blk.backward_pass(
57
+ Y_1=Y_1,
58
+ Y_2=Y_2,
59
+ dY_1=dY_1,
60
+ dY_2=dY_2,
61
+ pos_embed=pos_embed,
62
+ alpha=alpha,
63
+ lambd=lambd,
64
+ )
65
+
66
+ dx = torch.cat([dY_1, dY_2], dim=-1)
67
+ del Y_1, Y_2, dY_1, dY_2
68
+ return dx, None, None, None, None
69
+
70
+ def seed_cuda():
71
+
72
+ # randomize seeds
73
+ # use cuda generator if available
74
+ if (
75
+ hasattr(torch.cuda, "default_generators")
76
+ and len(torch.cuda.default_generators) > 0
77
+ ):
78
+ # GPU
79
+ device_idx = torch.cuda.current_device()
80
+ seed = torch.cuda.default_generators[device_idx].seed()
81
+ else:
82
+ # CPU
83
+ seed = int(torch.seed() % sys.maxsize)
84
+
85
+ return seed
86
+
87
+ class InvFuncWrapper(nn.Module):
88
+ def __init__(self, Fm, Gm, split_dim=-1):
89
+
90
+ super(InvFuncWrapper, self).__init__()
91
+
92
+ self.Fm = Fm
93
+ self.Gm = Gm
94
+
95
+ self.split_dim = split_dim
96
+
97
+ def forward(self, x, pos_embed=None, alpha=0., lambd=1.):
98
+
99
+ # torch.manual_seed(2022)
100
+ x1, x2 = torch.chunk(x, 2, dim=self.split_dim)
101
+ # x1, x2 = x1.contiguous(), x2.contiguous()
102
+ fmd = self.Fm(x2, pos_embed, alpha)
103
+ y1 = lambd * x1 + fmd
104
+ del x1
105
+
106
+ # torch.manual_seed(2022)
107
+ gmd = self.Gm(y1, alpha)
108
+ y2 = lambd * x2 + gmd
109
+ del x2
110
+
111
+ out = torch.cat([y1, y2], dim=self.split_dim)
112
+ return out
113
+
114
+ def backward_pass(self, Y_1, Y_2, dY_1, dY_2, pos_embed=None, alpha=0., lambd=1.):
115
+
116
+ """
117
+ equations:
118
+ Y_1 = X_1 + F(X_2), F = Attention
119
+ Y_2 = X_2 + G(Y_1), G = MLP
120
+
121
+ equations for recompuation of activations:
122
+ X_2 = Y_2 - G(Y_1), G = MLP
123
+ X_1 = Y_1 - F(X_2), F = Attention
124
+ """
125
+ # device = Y_1.device
126
+ # print(f'Before Gm: {torch.cuda.memory_allocated(device)}')
127
+ with torch.enable_grad():
128
+ Y_1.requires_grad = True
129
+ g_Y_1 = self.Gm(Y_1, alpha)
130
+ # print(f'After Gm: {torch.cuda.memory_allocated(device)}')
131
+ g_Y_1.backward(dY_2, retain_graph=True)
132
+ # print(f'After backward: {torch.cuda.memory_allocated(device)}')
133
+ # print(f'After 1: {torch.cuda.memory_allocated(device)}')
134
+
135
+ with torch.no_grad():
136
+ X_2 = (Y_2 - g_Y_1) / lambd
137
+ del g_Y_1
138
+ dY_1 = dY_1 + Y_1.grad
139
+ Y_1.grad = None
140
+ # print(f'After 2: {torch.cuda.memory_allocated(device)}\n')
141
+ # print('*************************************************')
142
+
143
+ # print(f'Before Fm: {torch.cuda.memory_allocated(device)}')
144
+ with torch.enable_grad():
145
+ X_2.requires_grad = True
146
+ f_X_2 = self.Fm(X_2, pos_embed, alpha)
147
+ # print(f'After Fm: {torch.cuda.memory_allocated(device)}')
148
+ f_X_2.backward(dY_1, retain_graph=True)
149
+ # print(f'After backward: {torch.cuda.memory_allocated(device)}')
150
+
151
+ with torch.no_grad():
152
+ X_1 = (Y_1 - f_X_2) / lambd
153
+ del f_X_2, Y_1
154
+ dY_2 = lambd * dY_2 + X_2.grad
155
+ X_2.grad = None
156
+ X_2 = X_2.detach()
157
+
158
+ dY_1 = lambd * dY_1
159
+ # print(f'After 4: {torch.cuda.memory_allocated(device)}\n')
160
+ # print('*************************************************')
161
+
162
+ return X_1, X_2, dY_1, dY_2
163
+
164
+
165
+ '''
166
+ File Description: attention layer for transformer. borrowed from TIMM
167
+ '''
168
+ import torch
169
+ import torch.nn as nn
170
+ import torch.nn.functional as F
171
+
172
+
173
+
174
+ class Attention(nn.Module):
175
+ def __init__(self, dim, num_heads=8, qkv_bias=False, attn_drop=0., proj_drop=0.):
176
+ super().__init__()
177
+ self.num_heads = num_heads
178
+ # this is different from what I understand before.
179
+ # the num_heads here actually works as groups for shared attentions. it partition the channels to different groups.
180
+ head_dim = dim // num_heads
181
+ self.scale = head_dim ** -0.5
182
+
183
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
184
+ self.attn_drop = nn.Dropout(attn_drop)
185
+ self.proj = nn.Linear(dim, dim)
186
+ self.proj_drop = nn.Dropout(proj_drop)
187
+
188
+ def forward(self, x):
189
+ B, N, C = x.shape
190
+ qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
191
+ q, k, v = qkv.unbind(0) # make torchscript happy (cannot use tensor as tuple), shape [B, #Heads, N, C]
192
+
193
+ attn = (q @ k.transpose(-2, -1)) * self.scale
194
+ attn = attn.softmax(dim=-1)
195
+ attn = self.attn_drop(attn)
196
+
197
+ x = (attn @ v).transpose(1, 2).reshape(B, N, C)
198
+ x = self.proj(x)
199
+ x = self.proj_drop(x)
200
+ return x
201
+
202
+
203
+ class Block_inv_F(nn.Module):
204
+
205
+ def __init__(self, dim, num_heads, qkv_bias=False, drop=0., attn_drop=0., norm_args={'norm': 'ln'}, drop_path=None):
206
+ super().__init__()
207
+
208
+ self.drop_path = drop_path
209
+ self.norm1 = create_norm(norm_args, dim)
210
+ self.attn = Attention(dim, num_heads=num_heads, qkv_bias=qkv_bias, attn_drop=attn_drop, proj_drop=drop)
211
+ self.seeds = {}
212
+ self.seeds['droppath'] = seed_cuda()
213
+
214
+ def forward(self, x, pos_embed=None, alpha=0):
215
+ torch.manual_seed(self.seeds['droppath'])
216
+ # print('L216:', pos_embed)
217
+ if pos_embed is not None:
218
+ x = x + pos_embed
219
+ # print('L219:', pos_embed)
220
+ x = alpha*x + self.drop_path(self.attn(self.norm1(x)))
221
+ return x
222
+
223
+ class Block_inv_G(nn.Module):
224
+
225
+ def __init__(self, dim, mlp_ratio=4., drop=0., act_args={'act': 'gelu'}, norm_args={'norm': 'ln'}, drop_path=None):
226
+ super().__init__()
227
+
228
+ self.drop_path = drop_path
229
+ self.norm2 = create_norm(norm_args, dim)
230
+ mlp_hidden_dim = int(dim * mlp_ratio)
231
+ # invertable bottleneck layer
232
+ self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_args=act_args, drop=drop)
233
+ self.seeds = {}
234
+ self.seeds['droppath'] = seed_cuda()
235
+
236
+ def forward(self, x, alpha=0):
237
+ torch.manual_seed(self.seeds['droppath'])
238
+ x = alpha*x + self.drop_path(self.mlp(self.norm2(x)))
239
+ return x
240
+
241
+ class Block(nn.Module):
242
+
243
+ def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, drop=0., attn_drop=0.,
244
+ drop_path=0., act_args={'act': 'gelu'}, norm_args={'norm': 'ln'}):
245
+ super().__init__()
246
+
247
+ # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here
248
+ drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
249
+ Fm = Block_inv_F(dim=dim, num_heads=num_heads, qkv_bias=qkv_bias, drop=drop, attn_drop=attn_drop, norm_args=norm_args, drop_path=drop_path)
250
+ Gm = Block_inv_G(dim=dim, mlp_ratio=mlp_ratio, drop=drop, act_args=act_args, norm_args=norm_args, drop_path=drop_path)
251
+
252
+ if use_inv:
253
+ self.inv_block = InvFuncWrapper(Fm=Fm, Gm=Gm, split_dim=-1)
254
+ else:
255
+ self.Fm = Fm
256
+ self.Gm = Gm
257
+
258
+ def forward(self, x, pos_embed=None, alpha=0., lambd=1.):
259
+ if use_inv:
260
+ x = self.inv_block(x, pos_embed, alpha=alpha, lambd=lambd)
261
+ else:
262
+ x = self.Fm(x, pos_embed, alpha=1)
263
+ x = self.Gm(x)
264
+
265
+ return x
266
+
267
+ def backward_pass(self, Y_1, Y_2, dY_1, dY_2, pos_embed=None, alpha=0., lambd=1.):
268
+ return self.inv_block.backward_pass(
269
+ Y_1=Y_1,
270
+ Y_2=Y_2,
271
+ dY_1=dY_1,
272
+ dY_2=dY_2,
273
+ pos_embed=pos_embed,
274
+ alpha=alpha, lambd=lambd)
275
+
276
+ class TransformerEncoder(nn.Module):
277
+ """ Transformer Encoder without hierarchical structure
278
+ """
279
+
280
+ def __init__(self, embed_dim=768, depth=12, num_heads=12, mlp_ratio=4., qkv_bias=False,
281
+ drop_rate=0., attn_drop_rate=0., drop_path_rate=0.,
282
+ act_args={'act': 'gelu'}, norm_args={'norm': 'ln'}
283
+ ):
284
+ super().__init__()
285
+ self.blocks = nn.ModuleList([
286
+ Block(
287
+ dim=embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=qkv_bias,
288
+ drop=drop_rate, attn_drop=attn_drop_rate,
289
+ drop_path=drop_path_rate[i] if isinstance(drop_path_rate, list) else drop_path_rate,
290
+ norm_args=norm_args, act_args=act_args
291
+ )
292
+ for i in range(depth)])
293
+ self.depth = depth
294
+ # dilation = depth//3
295
+ # self.out_depth = list(range(depth))[dilation-1::dilation]
296
+
297
+ def forward(self, x, pos):
298
+ for _, block in enumerate(self.blocks):
299
+ # x = block(x)
300
+
301
+ # Injecting the positional information at each block.
302
+ # (Dehghani et al., 2018) and (Lan et al.,2019) observe better performance
303
+ # by further injecting the position information at each block
304
+ # Reference: Learning to Encode Position for Transformer with Continuous Dynamical Model.
305
+ # http://proceedings.mlr.press/v119/liu20n/liu20n.pdf
306
+ x = block(x + pos)
307
+ return x
308
+
309
+ def forward_features(self, x, pos, num_outs=None):
310
+ dilation = self.depth // num_outs
311
+ out_depth = list(range(self.depth))[(self.depth - (num_outs-1)*dilation -1) :: dilation]
312
+
313
+ out = []
314
+ for i, block in enumerate(self.blocks):
315
+ x = block(x + pos)
316
+ if i in out_depth:
317
+ out.append(x)
318
+ return out
319
+
320
+ @MODELS.register_module()
321
+ class InvPointViT(nn.Module):
322
+ """ Point Vision Transformer ++: with early convolutions
323
+ """
324
+ def __init__(self,
325
+ in_channels=3,
326
+ embed_dim=384, depth=12,
327
+ num_heads=6, mlp_ratio=4., qkv_bias=False,
328
+ drop_rate=0., attn_drop_rate=0., drop_path_rate=0.,
329
+ embed_args={'NAME': 'PointPatchEmbed',
330
+ 'num_groups': 256,
331
+ 'group_size': 32,
332
+ 'subsample': 'fps',
333
+ 'group': 'knn',
334
+ 'feature_type': 'fj',
335
+ 'norm_args': {'norm': 'in2d'},
336
+ },
337
+ norm_args={'norm': 'ln', 'eps': 1.0e-6},
338
+ act_args={'act': 'gelu'},
339
+ add_pos_each_block=True,
340
+ global_feat='cls,max',
341
+ distill=False,
342
+ init_epoch = 0,
343
+ start_epoch = 1,
344
+ end_epoch = 200,
345
+ freq=2,
346
+ init_lambd = 0.1,
347
+ lambd = 1.,
348
+ alpha = 0.,
349
+ option = -1,
350
+ **kwargs
351
+ ):
352
+ """
353
+ Args:
354
+ in_channels (int): number of input channels. Default: 6. (p + rgb)
355
+ embed_dim (int): embedding dimension
356
+ depth (int): depth of transformer
357
+ num_heads (int): number of attention heads
358
+ mlp_ratio (int): ratio of mlp hidden dim to embedding dim
359
+ qkv_bias (bool): enable bias for qkv if True
360
+ representation_size (Optional[int]): enable and set representation layer (pre-logits) to this value if set
361
+ drop_rate (float): dropout rate
362
+ attn_drop_rate (float): attention dropout rate
363
+ drop_path_rate (float): stochastic depth rate
364
+ embed_layer (nn.Module): patch embedding layer
365
+ norm_layer: (nn.Module): normalization layer
366
+ """
367
+ super().__init__()
368
+ if kwargs:
369
+ logging.warning(f"kwargs: {kwargs} are not used in {__class__.__name__}")
370
+ self.num_features = self.embed_dim = embed_dim # num_features for consistency with other models
371
+ embed_args.in_channels = in_channels
372
+ embed_args.embed_dim = embed_dim
373
+ self.patch_embed = build_model_from_cfg(embed_args)
374
+ self.cls_token = nn.Parameter(torch.randn(1, 1, self.embed_dim))
375
+ self.cls_pos = nn.Parameter(torch.randn(1, 1, self.embed_dim))
376
+ self.pos_embed = nn.Sequential(
377
+ create_linearblock(3, 128, norm_args=None, act_args=act_args),
378
+ nn.Linear(128, self.embed_dim)
379
+ )
380
+ if self.patch_embed.out_channels != self.embed_dim:
381
+ self.proj = nn.Linear(self.patch_embed.out_channels, self.embed_dim)
382
+ else:
383
+ self.proj = nn.Identity()
384
+ self.add_pos_each_block = add_pos_each_block
385
+ self.pos_drop = nn.Dropout(p=drop_rate)
386
+ dpr = [x.item() for x in torch.linspace(0, drop_path_rate, depth)] # stochastic depth decay rule
387
+ self.depth = depth
388
+ self.blocks = nn.ModuleList([
389
+ Block(
390
+ dim=self.embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=qkv_bias,
391
+ drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i],
392
+ norm_args=norm_args, act_args=act_args
393
+ )
394
+ for i in range(depth)])
395
+ self.norm = create_norm(norm_args, self.embed_dim) # Norm layer is extremely important here!
396
+ self.global_feat = global_feat.split(',')
397
+ self.out_channels = len(self.global_feat)*embed_dim
398
+ self.distill_channels = embed_dim
399
+ self.channel_list = self.patch_embed.channel_list
400
+ self.channel_list[-1] = embed_dim
401
+
402
+ # distill
403
+ if distill:
404
+ self.dist_token = nn.Parameter(torch.randn(1, 1, self.embed_dim))
405
+ self.dist_pos = nn.Parameter(torch.randn(1, 1, self.embed_dim))
406
+ self.n_tokens = 2
407
+ else:
408
+ self.dist_token = None
409
+ self.n_tokens = 1
410
+ self.initialize_weights()
411
+
412
+ self.init_epoch = init_epoch
413
+ self.start_epoch = start_epoch
414
+ self.end_epoch = end_epoch
415
+ self.freq = freq
416
+ self.alpha = alpha
417
+ self.init_lambd = init_lambd
418
+ self.lambd = lambd
419
+ self.option = option
420
+
421
+ def initialize_weights(self):
422
+ torch.nn.init.normal_(self.cls_token, std=.02)
423
+ torch.nn.init.normal_(self.cls_pos, std=.02)
424
+ if self.dist_token is not None:
425
+ torch.nn.init.normal_(self.dist_token, std=.02)
426
+ torch.nn.init.normal_(self.dist_pos, std=.02)
427
+ self.apply(self._init_weights)
428
+
429
+ @staticmethod
430
+ def _init_weights(m):
431
+ if isinstance(m, nn.Linear):
432
+ torch.nn.init.xavier_uniform_(m.weight)
433
+ if isinstance(m, nn.Linear) and m.bias is not None:
434
+ nn.init.constant_(m.bias, 0)
435
+ elif isinstance(m, (nn.LayerNorm, nn.GroupNorm, nn.BatchNorm2d, nn.BatchNorm1d)):
436
+ nn.init.constant_(m.bias, 0)
437
+ nn.init.constant_(m.weight, 1.0)
438
+
439
+ @torch.jit.ignore
440
+ def no_weight_decay(self):
441
+ return {'cls_token', 'dist_token', 'dist_token'}
442
+
443
+ def get_num_layers(self):
444
+ return self.depth
445
+
446
+ def get_alpha_lambd(self, epoch=-1):
447
+
448
+ if self.option != -1:
449
+ ###################### alpha ######################
450
+ if epoch < self.init_epoch: # Inference
451
+ alpha = 0.0
452
+ elif epoch < self.start_epoch:
453
+ alpha = 1.0
454
+ elif epoch >= self.start_epoch and epoch < self.end_epoch:
455
+ # Option 0: linear, interleave alpha and lambda
456
+ if self.option == 0.0:
457
+ alpha = round(min(max(-round(self.freq/(self.end_epoch-self.start_epoch), 2) * math.ceil((epoch-self.start_epoch-1-self.freq//2) / self.freq) + 1, 0), 1.), 2)
458
+ # self.option 1: linear alpha = (1/(A+1-N))*x + N/(N-A-1), lambd = 1 - alpha + 0.01
459
+ elif self.option == 1:
460
+ alpha = round(1/(self.start_epoch+1-self.end_epoch) * epoch + self.end_epoch/(self.end_epoch-self.start_epoch-1), 2)
461
+ # self.option 2: logarithmic
462
+ elif self.option == 2:
463
+ base = math.e
464
+ a = 1/(math.log((self.start_epoch+1) / self.end_epoch, base))
465
+ c = - a * math.log(self.end_epoch, base)
466
+ alpha = round(max(min(a * math.log(epoch, base) + c, 1.), 0), 2)
467
+ # self.option 3: exponential
468
+ elif self.option == 3:
469
+ base = math.e
470
+ a = 1/(pow(base, self.start_epoch+1) - pow(base, self.end_epoch))
471
+ c = - a * pow(base, self.end_epoch)
472
+ alpha = round(max(min(a * pow(base, epoch) + c, 1.), 0), 2)
473
+ # self.option 4: hand-crafted, increasing
474
+ elif self.option == 4:
475
+ alpha_list = [1., 1., 0.8, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.]
476
+ alpha = alpha_list[epoch - 1]
477
+
478
+ elif epoch >= self.end_epoch:
479
+ alpha = 0.0
480
+
481
+ ###################### lambda #####################
482
+ if epoch < self.init_epoch: # Inference
483
+ lambd = 1.0
484
+ elif epoch < self.start_epoch:
485
+ lambd = 0.0
486
+ elif epoch >= self.start_epoch and epoch < self.end_epoch:
487
+ if self.option == 0:
488
+ lambd = round(max(min(self.freq/(self.end_epoch-self.start_epoch) * math.ceil((epoch-self.start_epoch-1) / self.freq) + self.init_lambd, 1.), self.init_lambd), 2)
489
+ else:
490
+ lambd = round(min(1 - alpha + 0.1, 1.), 2)
491
+ elif epoch >= self.end_epoch:
492
+ lambd = 1.0
493
+ else:
494
+ alpha, lambd = self.alpha, self.lambd
495
+ # print('during rev, alpha, lambda:', alpha, lambd) # TODO: DEBUG
496
+ return alpha, lambd
497
+
498
+ def forward(self, p, x=None, epoch=-1):
499
+ if hasattr(p, 'keys'):
500
+ p, x, epoch = p['pos'], p['x'] if 'x' in p.keys() else None, p['epoch'] if 'epoch' in p.keys() else -1
501
+ if x is None:
502
+ x = p.clone().transpose(1, 2).contiguous()
503
+ p_list, x_list = self.patch_embed(p, x)
504
+ center_p, x = p_list[-1], self.proj(x_list[-1].transpose(1, 2))
505
+ pos_embed = self.pos_embed(center_p)
506
+
507
+ pos_embed = [self.cls_pos.expand(x.shape[0], -1, -1), pos_embed]
508
+ tokens = [self.cls_token.expand(x.shape[0], -1, -1), x]
509
+ if self.dist_token is not None:
510
+ pos_embed.insert(1, self.dist_pos.expand(x.shape[0], -1, -1))
511
+ tokens.insert(1, self.dist_token.expand(x.shape[0], -1, -1))
512
+ pos_embed = torch.cat(pos_embed, dim=1)
513
+ x = torch.cat(tokens, dim=1)
514
+
515
+ with torch.set_grad_enabled(epoch>=self.start_epoch):
516
+ alpha, lambd = self.get_alpha_lambd(epoch)
517
+ if self.add_pos_each_block:
518
+ if use_inv:
519
+ x = self._use_inv(x, pos_embed, alpha, lambd)
520
+ else:
521
+ for block in self.blocks:
522
+ x = block(x, pos_embed)
523
+ else:
524
+ x = self.pos_drop(x + pos_embed)
525
+ if use_inv:
526
+ x = self._use_inv(x, None, alpha, lambd)
527
+ else:
528
+ for block in self.blocks:
529
+ x = block(x)
530
+ x = self.norm(x)
531
+ return p_list, x_list, x
532
+
533
+ def _use_inv(self, x, pos_embed=None, alpha=0., lambd=1.):
534
+ x = torch.cat((x, x), dim=-1)
535
+ if use_customized_backprop:
536
+ x = RevBackProp.apply(x, self.blocks, pos_embed, alpha, lambd)
537
+ else:
538
+ for block in self.blocks:
539
+ x = block(x, pos_embed)
540
+ C = int(x.shape[-1] / 2)
541
+ x = (x[:,:,:C] + x[:,:,C:]) / 2
542
+ return x
543
+
544
+ def forward_cls_feat(self, p, x=None): # p: p, x: features
545
+ _, _, x = self.forward(p, x)
546
+ token_features = x[:, self.n_tokens:, :]
547
+ cls_feats = []
548
+ for token_type in self.global_feat:
549
+ if 'cls' in token_type:
550
+ cls_feats.append(x[:, 0, :])
551
+ elif 'max' in token_type:
552
+ cls_feats.append(torch.max(token_features, dim=1, keepdim=False)[0])
553
+ elif token_type in ['avg', 'mean']:
554
+ cls_feats.append(torch.mean(token_features, dim=1, keepdim=False))
555
+ global_features = torch.cat(cls_feats, dim=1)
556
+
557
+ if self.dist_token is not None and self.training:
558
+ return global_features, x[:, 1, :]
559
+ else:
560
+ return global_features
561
+
562
+ def forward_seg_feat(self, p, x=None, epoch=-1): # p: p, x: features
563
+ p_list, x_list, x = self.forward(p, x, epoch)
564
+ x_list[-1] = x.transpose(1, 2)
565
+ return p_list, x_list
566
+
567
+
568
+ @MODELS.register_module()
569
+ class InvPointViTDecoder(nn.Module):
570
+ """ Decoder of Point Vision Transformer for segmentation.
571
+ """
572
+ def __init__(self,
573
+ encoder_channel_list: List[int],
574
+ decoder_layers: int = 2,
575
+ n_decoder_stages: int = 2, # TODO: ablate this
576
+ scale: int = 4,
577
+ channel_scaling: int = 1,
578
+ sampler: str = 'fps',
579
+ global_feat=None,
580
+ progressive_input=False,
581
+ **kwargs
582
+ ):
583
+ super().__init__()
584
+ self.decoder_layers = decoder_layers
585
+ if global_feat is not None:
586
+ self.global_feat = global_feat.split(',')
587
+ num_global_feat = len(self.global_feat)
588
+ else:
589
+ self.global_feat = None
590
+ num_global_feat = 0
591
+
592
+ self.in_channels = encoder_channel_list[-1]
593
+ self.scale = scale
594
+ self.n_decoder_stages = n_decoder_stages
595
+
596
+ if progressive_input:
597
+ skip_dim = [self.in_channels//2**i for i in range(n_decoder_stages-1, 0, -1)]
598
+ else:
599
+ skip_dim = [0 for i in range(n_decoder_stages-1)]
600
+ skip_channels = [encoder_channel_list[0]] + skip_dim
601
+
602
+ fp_channels = [self.in_channels*channel_scaling]
603
+ for _ in range(n_decoder_stages-1):
604
+ fp_channels.insert(0, fp_channels[0] * channel_scaling)
605
+
606
+ decoder = [[] for _ in range(n_decoder_stages)]
607
+ for i in range(-1, -n_decoder_stages-1, -1):
608
+ decoder[i] = self._make_dec(
609
+ skip_channels[i], fp_channels[i])
610
+ self.decoder = nn.Sequential(*decoder)
611
+ self.out_channels = fp_channels[-n_decoder_stages] * (num_global_feat + 1)
612
+
613
+ if sampler.lower() == 'fps':
614
+ self.sample_fn = furthest_point_sample
615
+ elif sampler.lower() == 'random':
616
+ self.sample_fn = random_sample
617
+
618
+ def _make_dec(self, skip_channels, fp_channels):
619
+ layers = []
620
+ mlp = [skip_channels + self.in_channels] + \
621
+ [fp_channels] * self.decoder_layers
622
+ layers.append(FeaturePropogation(mlp))
623
+ self.in_channels = fp_channels
624
+ return nn.Sequential(*layers)
625
+
626
+ def forward(self, p, f):
627
+ """
628
+ Args:
629
+ p (List(Tensor)): List of tensor for p, length 2, input p and center p
630
+ f (List(Tensor)): List of tensor for feature maps, input features and out features
631
+ """
632
+ if len(p) != (self.n_decoder_stages + 1):
633
+ for i in range(self.n_decoder_stages - 1):
634
+ pos = p[i]
635
+ idx = self.sample_fn(pos, pos.shape[1] // self.scale).long()
636
+ new_p = torch.gather(pos, 1, idx.unsqueeze(-1).expand(-1, -1, 3))
637
+ p.insert(1, new_p)
638
+ f.insert(1, None)
639
+ cls_token = f[-1][:, :, 0:1]
640
+ f[-1] = f[-1][:, :, 1:].contiguous()
641
+
642
+ for i in range(-1, -len(self.decoder) - 1, -1):
643
+ f[i - 1] = self.decoder[i][1:](
644
+ [p[i], self.decoder[i][0]([p[i - 1], f[i - 1]], [p[i], f[i]])])[1]
645
+ f_out = f[-len(self.decoder) - 1]
646
+
647
+ if self.global_feat is not None:
648
+ global_feats = []
649
+ for token_type in self.global_feat:
650
+ if 'cls' in token_type:
651
+ global_feats.append(cls_token)
652
+ elif 'max' in token_type:
653
+ global_feats.append(torch.max(f_out, dim=2, keepdim=True)[0])
654
+ elif token_type in ['avg', 'mean']:
655
+ global_feats.append(torch.mean(f_out, dim=2, keepdim=True))
656
+ global_feats = torch.cat(global_feats, dim=1).expand(-1, -1, f_out.shape[-1])
657
+ f_out = torch.cat((global_feats, f_out), dim=1)
658
+ return f_out
659
+
660
+
661
+ @MODELS.register_module()
662
+ class InvPointViTPartDecoder(nn.Module):
663
+ """ Decoder of Point Vision Transformer for segmentation.
664
+ """
665
+ def __init__(self,
666
+ encoder_channel_list: List[int],
667
+ decoder_layers: int = 2,
668
+ n_decoder_stages: int = 2,
669
+ scale: int = 4,
670
+ channel_scaling: int = 1,
671
+ sampler: str = 'fps',
672
+ global_feat=None,
673
+ progressive_input=False,
674
+ cls_map='pointnet2',
675
+ num_classes: int = 16,
676
+ **kwargs
677
+ ):
678
+ super().__init__()
679
+ self.decoder_layers = decoder_layers
680
+ if global_feat is not None:
681
+ self.global_feat = global_feat.split(',')
682
+ num_global_feat = len(self.global_feat)
683
+ else:
684
+ self.global_feat = None
685
+ num_global_feat = 0
686
+
687
+ self.in_channels = encoder_channel_list[-1]
688
+ self.scale = scale
689
+ self.n_decoder_stages = n_decoder_stages
690
+
691
+ if progressive_input:
692
+ skip_dim = [self.in_channels//2**i for i in range(n_decoder_stages-1, 0, -1)]
693
+ else:
694
+ skip_dim = [0 for i in range(n_decoder_stages-1)]
695
+ skip_channels = [encoder_channel_list[0]] + skip_dim
696
+
697
+ fp_channels = [self.in_channels*channel_scaling]
698
+ for _ in range(n_decoder_stages-1):
699
+ fp_channels.insert(0, fp_channels[0] * channel_scaling)
700
+
701
+ self.cls_map = cls_map
702
+ self.num_classes = num_classes
703
+ act_args = kwargs.get('act_args', {'act': 'relu'})
704
+ if self.cls_map == 'curvenet':
705
+ # global features
706
+ self.global_conv2 = nn.Sequential(
707
+ create_convblock1d(fp_channels[-1] * 2, 128,
708
+ norm_args=None,
709
+ act_args=act_args))
710
+ self.global_conv1 = nn.Sequential(
711
+ create_convblock1d(fp_channels[-2] * 2, 64,
712
+ norm_args=None,
713
+ act_args=act_args))
714
+ skip_channels[0] += 64 + 128 + 16 # shape categories labels
715
+ elif self.cls_map == 'pointnet2':
716
+ self.convc = nn.Sequential(create_convblock1d(16, 64,
717
+ norm_args=None,
718
+ act_args=act_args))
719
+ skip_channels[0] += 64 # shape categories labels
720
+
721
+ decoder = [[] for _ in range(n_decoder_stages)]
722
+ for i in range(-1, -n_decoder_stages-1, -1):
723
+ decoder[i] = self._make_dec(
724
+ skip_channels[i], fp_channels[i])
725
+ self.decoder = nn.Sequential(*decoder)
726
+ self.out_channels = fp_channels[-n_decoder_stages] * (num_global_feat + 1)
727
+
728
+ if sampler.lower() == 'fps':
729
+ self.sample_fn = furthest_point_sample
730
+ elif sampler.lower() == 'random':
731
+ self.sample_fn = random_sample
732
+
733
+ def _make_dec(self, skip_channels, fp_channels):
734
+ layers = []
735
+ mlp = [skip_channels + self.in_channels] + \
736
+ [fp_channels] * self.decoder_layers
737
+ layers.append(FeaturePropogation(mlp))
738
+ self.in_channels = fp_channels
739
+ return nn.Sequential(*layers)
740
+
741
+ def forward(self, p, f, cls_label):
742
+ """
743
+ Args:
744
+ p (List(Tensor)): List of tensor for p, length 2, input p and center p
745
+ f (List(Tensor)): List of tensor for feature maps, input features and out features
746
+ """
747
+ if len(p) != (self.n_decoder_stages + 1):
748
+ for i in range(self.n_decoder_stages - 1):
749
+ pos = p[i]
750
+ idx = self.sample_fn(pos, pos.shape[1] // self.scale).long()
751
+ new_p = torch.gather(pos, 1, idx.unsqueeze(-1).expand(-1, -1, 3))
752
+ p.insert(1, new_p)
753
+ f.insert(1, None)
754
+ cls_token = f[-1][:, :, 0:1]
755
+ f[-1] = f[-1][:, :, 1:].contiguous()
756
+
757
+ B, N = p[0].shape[0:2]
758
+ if self.cls_map == 'pointnet2':
759
+ cls_one_hot = torch.zeros((B, self.num_classes), device=p[0].device)
760
+ cls_one_hot = cls_one_hot.scatter_(1, cls_label, 1).unsqueeze(-1).repeat(1, 1, N)
761
+ cls_one_hot = self.convc(cls_one_hot)
762
+
763
+ for i in range(-1, -len(self.decoder), -1):
764
+ f[i - 1] = self.decoder[i][1:](
765
+ [p[i], self.decoder[i][0]([p[i - 1], f[i - 1]], [p[i], f[i]])])[1]
766
+
767
+ i = -len(self.decoder)
768
+ f[i - 1] = self.decoder[i][1:](
769
+ [p[i], self.decoder[i][0]([p[i - 1], torch.cat([cls_one_hot, f[i - 1]], 1)], [p[i], f[i]])])[1]
770
+
771
+ f_out = f[-len(self.decoder) - 1]
772
+
773
+ if self.global_feat is not None:
774
+ global_feats = []
775
+ for token_type in self.global_feat:
776
+ if 'cls' in token_type:
777
+ global_feats.append(cls_token)
778
+ elif 'max' in token_type:
779
+ global_feats.append(torch.max(f_out, dim=2, keepdim=True)[0])
780
+ elif token_type in ['avg', 'mean']:
781
+ global_feats.append(torch.mean(f_out, dim=2, keepdim=True))
782
+ global_feats = torch.cat(global_feats, dim=1).expand(-1, -1, f_out.shape[-1])
783
+ f_out = torch.cat((global_feats, f_out), dim=1)
784
+ return f_out