| 713 | |
| 714 | |
| 715 | class SerializedUnpooling(PointModule): |
| 716 | def __init__( |
| 717 | self, |
| 718 | in_channels, |
| 719 | skip_channels, |
| 720 | out_channels, |
| 721 | norm_layer=None, |
| 722 | act_layer=None, |
| 723 | traceable=False, # record parent and cluster |
| 724 | ): |
| 725 | super().__init__() |
| 726 | self.proj = PointSequential(nn.Linear(in_channels, out_channels)) |
| 727 | self.proj_skip = PointSequential(nn.Linear(skip_channels, out_channels)) |
| 728 | |
| 729 | if norm_layer is not None: |
| 730 | self.proj.add(norm_layer(out_channels)) |
| 731 | self.proj_skip.add(norm_layer(out_channels)) |
| 732 | |
| 733 | if act_layer is not None: |
| 734 | self.proj.add(act_layer()) |
| 735 | self.proj_skip.add(act_layer()) |
| 736 | |
| 737 | self.traceable = traceable |
| 738 | |
| 739 | def forward(self, point): |
| 740 | assert "pooling_parent" in point.keys() |
| 741 | assert "pooling_inverse" in point.keys() |
| 742 | parent = point.pop("pooling_parent") |
| 743 | inverse = point.pop("pooling_inverse") |
| 744 | point = self.proj(point) |
| 745 | parent = self.proj_skip(parent) |
| 746 | parent.feat = parent.feat + point.feat[inverse] |
| 747 | |
| 748 | if self.traceable: |
| 749 | parent["unpooling_parent"] = point |
| 750 | return parent |
| 751 | |
| 752 | |
| 753 | class Embedding(PointModule): |