Berlin Tech Meetup: The Future of Relational Foundation Models, Systems, and Real-World Applications

Register now:
PyG/Layer7 min read

PointNetConv: The Baseline for Point Cloud Learning

PointNetConv adapts PointNet's per-point MLP approach into a local message-passing layer. It is the simplest approach to learning on point clouds: apply an MLP within local neighborhoods, aggregate via max pooling. Fast, simple, and a strong baseline for 3D tasks.

PyTorch Geometric

TL;DR

  • 1PointNetConv applies a shared MLP to each point's features (concatenated with relative position) within local neighborhoods, then max-pools. The simplest point cloud message-passing layer.
  • 2Inspired by PointNet (Qi et al., 2016) and PointNet++ (Qi et al., 2017). PointNetConv in PyG operates on local neighborhoods (a PointNet++ concept), not globally like the original PointNet.
  • 3Input: node features (x), point positions (pos), and a k-NN edge_index. The layer handles both feature and spatial information.
  • 4Strong baseline for point cloud classification (ModelNet40) and segmentation (ShapeNet). EdgeConv is more expressive but slower.

Original Paper

PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space

Qi et al. (2017). NeurIPS 2017

Read paper →

What PointNetConv does

PointNetConv performs local point cloud convolution:

  1. For each point i, find its k nearest neighbors (pre-computed as edge_index)
  2. For each neighbor j, concatenate features with relative position: [h_j, pos_j - pos_i]
  3. Apply a shared MLP to each concatenated vector
  4. Max-pool over the neighborhood to get the updated point representation

PyG implementation

pointnet_model.py
import torch
import torch.nn.functional as F
from torch_geometric.nn import PointNetConv, global_max_pool, fps, radius
from torch_geometric.nn import knn_graph

class PointNet(torch.nn.Module):
    def __init__(self, out_channels):
        super().__init__()
        local_nn1 = torch.nn.Sequential(
            torch.nn.Linear(3 + 3, 64),  # 3 features + 3 relative position
            torch.nn.ReLU(),
            torch.nn.Linear(64, 64),
        )
        local_nn2 = torch.nn.Sequential(
            torch.nn.Linear(64 + 3, 128),
            torch.nn.ReLU(),
            torch.nn.Linear(128, 128),
        )
        self.conv1 = PointNetConv(local_nn=local_nn1)
        self.conv2 = PointNetConv(local_nn=local_nn2)
        self.classifier = torch.nn.Linear(128, out_channels)

    def forward(self, pos, batch):
        edge_index = knn_graph(pos, k=16, batch=batch)
        x = self.conv1(x=None, pos=pos, edge_index=edge_index)
        x = F.relu(x)
        edge_index = knn_graph(x, k=16, batch=batch)
        x = self.conv2(x=x, pos=pos, edge_index=edge_index)
        x = global_max_pool(x, batch)
        return self.classifier(x)

model = PointNet(out_channels=40)  # ModelNet40

x=None at layer 1 means only positions are used. After layer 1, both learned features and positions inform the neighborhood and messages.

When to use PointNetConv

  • Point cloud baseline. Fast, well-understood, and a standard comparison point for 3D deep learning.
  • Simple 3D classification. When global shape is more important than local detail (object recognition).
  • LiDAR data processing. Outdoor scene understanding where per-point MLPs with spatial context capture the necessary patterns.

When not to use PointNetConv

  • When local structure matters. EdgeConv captures richer local patterns via pairwise edge features. For segmentation tasks with fine boundaries, EdgeConv is usually better.
  • Non-geometric graphs. PointNetConv requires positional coordinates. For social/relational/citation graphs, use standard GNN layers.

Frequently asked questions

What is PointNetConv in PyTorch Geometric?

PointNetConv implements a local neighborhood variant of PointNet (inspired by PointNet++, Qi et al., 2017) as a message-passing layer in PyG. It processes point cloud neighborhoods by applying a shared MLP to each point's features (concatenated with relative position), then aggregates via max pooling. This captures local geometric patterns in 3D data.

How does PointNetConv differ from the original PointNet?

The original PointNet applies a shared MLP to each point independently, then max-pools globally over all points. PointNetConv in PyG follows the PointNet++ paradigm: it operates locally within each point's neighborhood, applies an MLP to relative coordinates plus features, then aggregates. This makes it a proper message-passing layer that captures local structure.

When should I use PointNetConv vs EdgeConv?

PointNetConv is simpler and faster: it applies an MLP to individual point features within neighborhoods. EdgeConv is more expressive: it computes pairwise edge features [h_i, h_j - h_i] and recomputes the graph dynamically. Use PointNetConv as a baseline, EdgeConv when local structure matters more.

What input does PointNetConv expect?

PointNetConv expects node features (x), point positions (pos), and edge_index defining the local neighborhoods (typically k-NN graph). The layer concatenates features with relative positions before applying the MLP, encoding both feature and spatial information.

Can PointNetConv handle features beyond XYZ coordinates?

Yes. You can pass additional features (normals, colors, intensity) as node features (x) alongside positions (pos). The MLP processes the concatenation of local features and relative positions, so any per-point features are incorporated.

Learn more about graph ML

PyTorch Geometric is the open-source foundation for graph neural networks. Explore more layers, concepts, and production patterns.