Skip to content

NC (Node classification)

hypertorch.nc

NcModule

Bases: LightningModule

A LightningModule base class for multiclass node-classification models.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module. Defaults to None.

classifier Module

Module that maps node features to class logits.

loss_fn Module

Multiclass loss function.

metrics_log_kwargs dict[str, Any]

Keyword arguments passed to metric log calls.

train_metrics MetricCollection | None

Optional training metrics.

val_metrics MetricCollection | None

Optional validation metrics.

test_metrics MetricCollection | None

Optional test metrics.

Source code in hypertorch/nc/common.py
class NcModule(L.LightningModule):
    """
    A LightningModule base class for multiclass node-classification models.

    Attributes:
        encoder: Optional encoder module. Defaults to ``None``.
        classifier: Module that maps node features to class logits.
        loss_fn: Multiclass loss function.
        metrics_log_kwargs: Keyword arguments passed to metric log calls.
        train_metrics: Optional training metrics.
        val_metrics: Optional validation metrics.
        test_metrics: Optional test metrics.
    """

    def __init__(
        self,
        classifier: nn.Module,
        loss_fn: nn.Module,
        encoder: nn.Module | None = None,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the NC module.

        Args:
            classifier: Module producing one class-logit row per node.
            loss_fn: Loss function used on supervised target nodes.
            encoder: Optional encoder module. Defaults to ``None``.
            metrics: Optional metric collection cloned independently per stage.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
        """
        super().__init__()
        self.encoder: nn.Module | None = encoder
        self.classifier: nn.Module = classifier
        self.loss_fn: nn.Module = loss_fn
        self.metrics_log_kwargs: dict[str, Any] = metrics_log_kwargs or {}

        if metrics is not None:
            self.train_metrics: MetricCollection | None = metrics.clone(
                prefix=stage_metric_prefix(Stage.TRAIN)
            )
            self.val_metrics: MetricCollection | None = metrics.clone(
                prefix=stage_metric_prefix(Stage.VAL)
            )
            self.test_metrics: MetricCollection | None = metrics.clone(
                prefix=stage_metric_prefix(Stage.TEST)
            )
        else:
            self.train_metrics = None
            self.val_metrics = None
            self.test_metrics = None

    def _compute_loss(
        self,
        logits: Tensor,
        labels: Tensor,
        batch_size: int,
        stage: Stage,
    ) -> Tensor:
        """
        Compute and log loss based on logits and labels.

        Args:
            logits: The predicted logits from the model.
            labels: The true labels corresponding to the logits.
            batch_size: The size of the current batch, used for logging.
            stage: The current stage (train/val/test) for logging purposes.

        Returns:
            loss: The computed loss tensor.
        """
        loss = self.loss_fn(logits, labels)
        self.log(
            name=stage_metric_name(stage, "loss"),
            value=loss,
            prog_bar=True,
            batch_size=batch_size,
            **self.metrics_log_kwargs,
        )
        return loss

    def _compute_metrics(
        self,
        logits: Tensor,
        labels: Tensor,
        batch_size: int,
        stage: Stage,
    ) -> None:
        """
        Compute and log metrics based on logits and labels.

        Uses class-based torchmetrics with proper multi-batch accumulation:
        1. ``update()`` accumulates predictions/targets across batches.
        2. Passing the MetricCollection to ``self.log_dict()`` tells Lightning to call
            ``compute()`` at epoch end and ``reset()`` automatically.

        Args:
            logits: The predicted logits from the model.
            labels: The true labels corresponding to the logits.
            batch_size: The size of the current batch, used for logging.
            stage: The current stage (train/val/test) for logging purposes.
        """
        stage_metrics = self._get_stage_metrics(stage)
        if stage_metrics is None:
            return  # No metrics to compute for this stage
        self._configure_metric_distributed_available(stage_metrics)

        # Accumulate predictions/targets for this batch
        stage_metrics.update(logits, labels)
        self.log_dict(
            stage_metrics,
            prog_bar=True,
            on_step=False,
            on_epoch=True,  # Compute and log metrics at epoch end for proper accumulation
            batch_size=batch_size,
            **self.metrics_log_kwargs,
        )

    def _get_stage_metrics(self, stage: Stage) -> MetricCollection | None:
        """
        Return the metric collection for the given stage.
        """
        match stage:
            case Stage.TRAIN:
                return self.train_metrics
            case Stage.VAL:
                return self.val_metrics
            case Stage.TEST:
                return self.test_metrics
            case _:
                raise ValueError(f"Unrecognized stage: {stage}")

    def _configure_metric_distributed_available(self, metrics: MetricCollection) -> None:
        """
        Make torchmetrics sync decisions follow the active Lightning trainer.
        """
        for metric in metrics.values(copy_state=False):
            metric.distributed_available_fn = self._distributed_available_fn

    def _distributed_available_fn(self) -> bool:
        """
        Return whether metrics should synchronize for the current trainer.
        """
        if self._trainer is None:
            return False
        return (
            self._trainer.world_size > 1
            and torch.distributed.is_available()
            and torch.distributed.is_initialized()
        )

    def _target_logits_and_labels(self, logits: Tensor, batch: HData) -> tuple[Tensor, Tensor]:
        """
        Select supervised node logits and labels from a batch.

        Args:
            logits: Node logits of shape ``[num_nodes, num_classes]``.
            batch: Batch containing node labels and an optional target mask.

        Returns:
            target_logits: Logits for supervised nodes.
            target_labels: Labels for supervised nodes.
        """
        target_node_mask = batch.target_node_mask
        target_logits = logits[target_node_mask]
        target_labels = batch.y[target_node_mask]
        return target_logits, target_labels

__init__(classifier, loss_fn, encoder=None, metrics=None, metrics_log_kwargs=None)

Initialize the NC module.

Parameters:

Name Type Description Default
classifier Module

Module producing one class-logit row per node.

required
loss_fn Module

Loss function used on supervised target nodes.

required
encoder Module | None

Optional encoder module. Defaults to None.

None
metrics MetricCollection | None

Optional metric collection cloned independently per stage.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls.

None
Source code in hypertorch/nc/common.py
def __init__(
    self,
    classifier: nn.Module,
    loss_fn: nn.Module,
    encoder: nn.Module | None = None,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the NC module.

    Args:
        classifier: Module producing one class-logit row per node.
        loss_fn: Loss function used on supervised target nodes.
        encoder: Optional encoder module. Defaults to ``None``.
        metrics: Optional metric collection cloned independently per stage.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
    """
    super().__init__()
    self.encoder: nn.Module | None = encoder
    self.classifier: nn.Module = classifier
    self.loss_fn: nn.Module = loss_fn
    self.metrics_log_kwargs: dict[str, Any] = metrics_log_kwargs or {}

    if metrics is not None:
        self.train_metrics: MetricCollection | None = metrics.clone(
            prefix=stage_metric_prefix(Stage.TRAIN)
        )
        self.val_metrics: MetricCollection | None = metrics.clone(
            prefix=stage_metric_prefix(Stage.VAL)
        )
        self.test_metrics: MetricCollection | None = metrics.clone(
            prefix=stage_metric_prefix(Stage.TEST)
        )
    else:
        self.train_metrics = None
        self.val_metrics = None
        self.test_metrics = None

CommonNeighborsNcModule

Bases: NcModule

A LightningModule for the CommonNeighbors node-classification heuristic.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module inherited from NcModule. Defaults to None.

classifier Module

Identity placeholder inherited from NcModule.

loss_fn Module

Loss function inherited from NcModule.

metrics_log_kwargs dict[str, Any]

Metric logging keyword arguments inherited from NcModule.

train_metrics MetricCollection | None

Optional training metrics inherited from NcModule.

val_metrics MetricCollection | None

Optional validation metrics inherited from NcModule.

test_metrics MetricCollection | None

Optional test metrics inherited from NcModule.

node_to_neighbors dict[int, Neighborhood]

Precomputed training-world node neighborhoods.

automatic_optimization bool

Disabled because this module has no trainable optimization.

Source code in hypertorch/nc/common_neighbors_nc.py
class CommonNeighborsNcModule(NcModule):
    """
    A LightningModule for the CommonNeighbors node-classification heuristic.

    Attributes:
        encoder: Optional encoder module inherited from ``NcModule``. Defaults to ``None``.
        classifier: Identity placeholder inherited from ``NcModule``.
        loss_fn: Loss function inherited from ``NcModule``.
        metrics_log_kwargs: Metric logging keyword arguments inherited from ``NcModule``.
        train_metrics: Optional training metrics inherited from ``NcModule``.
        val_metrics: Optional validation metrics inherited from ``NcModule``.
        test_metrics: Optional test metrics inherited from ``NcModule``.
        node_to_neighbors: Precomputed training-world node neighborhoods.
        automatic_optimization: Disabled because this module has no trainable optimization.
    """

    def __init__(
        self,
        train_hdata: HData,
        num_classes: int,
        aggregation: Literal["mean", "min", "sum"] = "sum",
        exclude_self_reference: bool = True,
        classifier: nn.Module | None = None,
        loss_fn: nn.Module | None = None,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the CommonNeighbors NC module.

        Args:
            train_hdata: Training data used to precompute neighborhoods and labeled
                reference nodes.
            num_classes: Number of node classes.
            aggregation: Method used to aggregate reference-node scores per class.
                Defaults to ``"sum"``.
            exclude_self_reference: Whether a node should ignore itself when it also
                appears among labeled reference nodes. Defaults to ``True``.
            classifier: Optional classifier module.
            loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
            metrics: Optional metric collection for evaluation. Defaults to ``None``.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
                Defaults to ``None``.
        """
        super().__init__(
            classifier=classifier
            if classifier is not None
            else self.__default_classifier(
                train_hdata=train_hdata,
                num_classes=num_classes,
                aggregation=aggregation,
                exclude_self_reference=exclude_self_reference,
            ),
            loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
            metrics=metrics,
            metrics_log_kwargs=metrics_log_kwargs,
        )

        # Pre-compute neighbors of training nodes based on training edges only
        # to create a "known world" for the model to make predictions from
        self.node_to_neighbors: dict[int, Neighborhood] = Hypergraph.from_hyperedge_index(
            hyperedge_index=HyperedgeIndex(
                hyperedge_index=train_hdata.hyperedge_index,
            )
            .to_global(global_node_ids=train_hdata.global_node_ids)
            .item
        ).neighbors_of_all()

        self.automatic_optimization: bool = False

    def forward(self, global_node_ids: Tensor) -> Tensor:
        """
        Compute common-neighbor class scores for the given nodes.

        Args:
            global_node_ids: Stable node IDs matching the training-world node IDs.

        Returns:
            logits: Node-class scores of shape ``(num_nodes, num_classes)``.
        """
        return self.classifier(
            candidate_nodes=global_node_ids,
            node_to_neighbors=self.node_to_neighbors,
        )

    def on_fit_start(self) -> None:
        """
        Warn users if they are running unnecessary training epochs.
        """
        if self.trainer.max_epochs is None or self.trainer.max_epochs > 0:
            warnings.warn(
                f"{self.__class__.__name__} is a non-trainable heuristic model. "
                "No optimization occurs. Set max_epochs=0 in your trainer for instant evaluation.",
                UserWarning,
                stacklevel=2,
            )

    def training_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Return a zero loss for the non-trainable heuristic.

        Args:
            batch: Input batch, unused.
            batch_idx: Batch index, unused.

        Returns:
            loss: Zero scalar tensor on the module device.
        """
        return torch.tensor(0.0, dtype=torch.float, device=self.device)

    def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Return a zero validation loss for the non-trainable heuristic.

        Args:
            batch: Input batch, unused.
            batch_idx: Batch index, unused.

        Returns:
            loss: Zero scalar tensor on the module device.
        """
        return torch.tensor(0.0, dtype=torch.float, device=self.device)

    def test_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Evaluate a test batch.

        Args:
            batch: Test batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Test loss.
        """
        return self.__step(batch, stage=Stage.TEST)

    def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Predict common-neighbor class scores for a batch.

        Args:
            batch: Prediction batch.
            batch_idx: Batch index, unused.

        Returns:
            logits: Predicted node-class scores.
        """
        return self.forward(batch.global_node_ids)

    def configure_optimizers(self) -> None:
        """
        Return no optimizer for the non-trainable heuristic.

        Returns:
            optimizer: No optimizer is configured, so always returns ``None``.
        """
        # No training, so no optimizers needed

    def __step(self, batch: HData, stage: Stage) -> Tensor:
        """
        Shared evaluation logic for all stages.

        Args:
            batch: `HData` object containing the hypergraph.
            stage: Current evaluation stage.

        Returns:
            loss: Computed loss.
        """
        scores = self.forward(batch.global_node_ids)
        target_logits, target_labels = self._target_logits_and_labels(scores, batch)
        batch_size = int(target_labels.size(0))

        loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
        self._compute_metrics(target_logits, target_labels, batch_size, stage)

        return loss

    def __class_to_node_ids(self, train_hdata: HData, num_classes: int) -> dict[int, list[int]]:
        """
        Group labeled training nodes by class.

        Args:
            train_hdata: Training data containing node labels and train node mask.
            num_classes: Number of node classes.

        Returns:
            class_to_node_ids: Dictionary mapping class IDs to lists of node IDs.
        """
        class_to_node_ids: dict[int, list[int]] = {class_id: [] for class_id in range(num_classes)}
        train_node_ids = train_hdata.global_node_ids[train_hdata.target_node_mask].tolist()
        train_class_labels = train_hdata.y[train_hdata.target_node_mask].tolist()

        for node_id, class_label in zip(train_node_ids, train_class_labels, strict=True):
            class_to_node_ids[int(class_label)].append(int(node_id))

        return class_to_node_ids

    def __default_classifier(
        self,
        train_hdata: HData,
        num_classes: int,
        aggregation: Literal["mean", "min", "sum"],
        exclude_self_reference: bool = True,
    ) -> CommonNeighbors:
        """
        Create a default CommonNeighbors classifier with a CommonNeighborsNodeScorer.

        Args:
            train_hdata: Training data containing node labels and train node mask.
            num_classes: Number of node classes.
            aggregation: Method used to aggregate reference-node scores per class.
            exclude_self_reference: Whether a node should ignore itself when it also
                appears among labeled reference nodes.

        Returns:
            classifier: A CommonNeighbors classifier with a CommonNeighborsNodeScorer.
        """
        class_to_node_ids = self.__class_to_node_ids(
            train_hdata=train_hdata,
            num_classes=num_classes,
        )

        scorer = CommonNeighborsNodeScorer(
            num_classes=num_classes,
            class_to_node_ids=class_to_node_ids,
            aggregation=aggregation,
            exclude_self_reference=exclude_self_reference,
        )

        return CommonNeighbors(aggregation=aggregation, scorer=scorer)

__init__(train_hdata, num_classes, aggregation='sum', exclude_self_reference=True, classifier=None, loss_fn=None, metrics=None, metrics_log_kwargs=None)

Initialize the CommonNeighbors NC module.

Parameters:

Name Type Description Default
train_hdata HData

Training data used to precompute neighborhoods and labeled reference nodes.

required
num_classes int

Number of node classes.

required
aggregation Literal['mean', 'min', 'sum']

Method used to aggregate reference-node scores per class. Defaults to "sum".

'sum'
exclude_self_reference bool

Whether a node should ignore itself when it also appears among labeled reference nodes. Defaults to True.

True
classifier Module | None

Optional classifier module.

None
loss_fn Module | None

Optional loss function. Defaults to CrossEntropyLoss.

None
metrics MetricCollection | None

Optional metric collection for evaluation. Defaults to None.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls. Defaults to None.

None
Source code in hypertorch/nc/common_neighbors_nc.py
def __init__(
    self,
    train_hdata: HData,
    num_classes: int,
    aggregation: Literal["mean", "min", "sum"] = "sum",
    exclude_self_reference: bool = True,
    classifier: nn.Module | None = None,
    loss_fn: nn.Module | None = None,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the CommonNeighbors NC module.

    Args:
        train_hdata: Training data used to precompute neighborhoods and labeled
            reference nodes.
        num_classes: Number of node classes.
        aggregation: Method used to aggregate reference-node scores per class.
            Defaults to ``"sum"``.
        exclude_self_reference: Whether a node should ignore itself when it also
            appears among labeled reference nodes. Defaults to ``True``.
        classifier: Optional classifier module.
        loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
        metrics: Optional metric collection for evaluation. Defaults to ``None``.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
            Defaults to ``None``.
    """
    super().__init__(
        classifier=classifier
        if classifier is not None
        else self.__default_classifier(
            train_hdata=train_hdata,
            num_classes=num_classes,
            aggregation=aggregation,
            exclude_self_reference=exclude_self_reference,
        ),
        loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
        metrics=metrics,
        metrics_log_kwargs=metrics_log_kwargs,
    )

    # Pre-compute neighbors of training nodes based on training edges only
    # to create a "known world" for the model to make predictions from
    self.node_to_neighbors: dict[int, Neighborhood] = Hypergraph.from_hyperedge_index(
        hyperedge_index=HyperedgeIndex(
            hyperedge_index=train_hdata.hyperedge_index,
        )
        .to_global(global_node_ids=train_hdata.global_node_ids)
        .item
    ).neighbors_of_all()

    self.automatic_optimization: bool = False

forward(global_node_ids)

Compute common-neighbor class scores for the given nodes.

Parameters:

Name Type Description Default
global_node_ids Tensor

Stable node IDs matching the training-world node IDs.

required

Returns:

Name Type Description
logits Tensor

Node-class scores of shape (num_nodes, num_classes).

Source code in hypertorch/nc/common_neighbors_nc.py
def forward(self, global_node_ids: Tensor) -> Tensor:
    """
    Compute common-neighbor class scores for the given nodes.

    Args:
        global_node_ids: Stable node IDs matching the training-world node IDs.

    Returns:
        logits: Node-class scores of shape ``(num_nodes, num_classes)``.
    """
    return self.classifier(
        candidate_nodes=global_node_ids,
        node_to_neighbors=self.node_to_neighbors,
    )

on_fit_start()

Warn users if they are running unnecessary training epochs.

Source code in hypertorch/nc/common_neighbors_nc.py
def on_fit_start(self) -> None:
    """
    Warn users if they are running unnecessary training epochs.
    """
    if self.trainer.max_epochs is None or self.trainer.max_epochs > 0:
        warnings.warn(
            f"{self.__class__.__name__} is a non-trainable heuristic model. "
            "No optimization occurs. Set max_epochs=0 in your trainer for instant evaluation.",
            UserWarning,
            stacklevel=2,
        )

training_step(batch, batch_idx)

Return a zero loss for the non-trainable heuristic.

Parameters:

Name Type Description Default
batch HData

Input batch, unused.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Zero scalar tensor on the module device.

Source code in hypertorch/nc/common_neighbors_nc.py
def training_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Return a zero loss for the non-trainable heuristic.

    Args:
        batch: Input batch, unused.
        batch_idx: Batch index, unused.

    Returns:
        loss: Zero scalar tensor on the module device.
    """
    return torch.tensor(0.0, dtype=torch.float, device=self.device)

validation_step(batch, batch_idx)

Return a zero validation loss for the non-trainable heuristic.

Parameters:

Name Type Description Default
batch HData

Input batch, unused.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Zero scalar tensor on the module device.

Source code in hypertorch/nc/common_neighbors_nc.py
def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Return a zero validation loss for the non-trainable heuristic.

    Args:
        batch: Input batch, unused.
        batch_idx: Batch index, unused.

    Returns:
        loss: Zero scalar tensor on the module device.
    """
    return torch.tensor(0.0, dtype=torch.float, device=self.device)

test_step(batch, batch_idx)

Evaluate a test batch.

Parameters:

Name Type Description Default
batch HData

Test batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Test loss.

Source code in hypertorch/nc/common_neighbors_nc.py
def test_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Evaluate a test batch.

    Args:
        batch: Test batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Test loss.
    """
    return self.__step(batch, stage=Stage.TEST)

predict_step(batch, batch_idx)

Predict common-neighbor class scores for a batch.

Parameters:

Name Type Description Default
batch HData

Prediction batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
logits Tensor

Predicted node-class scores.

Source code in hypertorch/nc/common_neighbors_nc.py
def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Predict common-neighbor class scores for a batch.

    Args:
        batch: Prediction batch.
        batch_idx: Batch index, unused.

    Returns:
        logits: Predicted node-class scores.
    """
    return self.forward(batch.global_node_ids)

configure_optimizers()

Return no optimizer for the non-trainable heuristic.

Returns:

Name Type Description
optimizer None

No optimizer is configured, so always returns None.

Source code in hypertorch/nc/common_neighbors_nc.py
def configure_optimizers(self) -> None:
    """
    Return no optimizer for the non-trainable heuristic.

    Returns:
        optimizer: No optimizer is configured, so always returns ``None``.
    """

__step(batch, stage)

Shared evaluation logic for all stages.

Parameters:

Name Type Description Default
batch HData

HData object containing the hypergraph.

required
stage Stage

Current evaluation stage.

required

Returns:

Name Type Description
loss Tensor

Computed loss.

Source code in hypertorch/nc/common_neighbors_nc.py
def __step(self, batch: HData, stage: Stage) -> Tensor:
    """
    Shared evaluation logic for all stages.

    Args:
        batch: `HData` object containing the hypergraph.
        stage: Current evaluation stage.

    Returns:
        loss: Computed loss.
    """
    scores = self.forward(batch.global_node_ids)
    target_logits, target_labels = self._target_logits_and_labels(scores, batch)
    batch_size = int(target_labels.size(0))

    loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
    self._compute_metrics(target_logits, target_labels, batch_size, stage)

    return loss

__class_to_node_ids(train_hdata, num_classes)

Group labeled training nodes by class.

Parameters:

Name Type Description Default
train_hdata HData

Training data containing node labels and train node mask.

required
num_classes int

Number of node classes.

required

Returns:

Name Type Description
class_to_node_ids dict[int, list[int]]

Dictionary mapping class IDs to lists of node IDs.

Source code in hypertorch/nc/common_neighbors_nc.py
def __class_to_node_ids(self, train_hdata: HData, num_classes: int) -> dict[int, list[int]]:
    """
    Group labeled training nodes by class.

    Args:
        train_hdata: Training data containing node labels and train node mask.
        num_classes: Number of node classes.

    Returns:
        class_to_node_ids: Dictionary mapping class IDs to lists of node IDs.
    """
    class_to_node_ids: dict[int, list[int]] = {class_id: [] for class_id in range(num_classes)}
    train_node_ids = train_hdata.global_node_ids[train_hdata.target_node_mask].tolist()
    train_class_labels = train_hdata.y[train_hdata.target_node_mask].tolist()

    for node_id, class_label in zip(train_node_ids, train_class_labels, strict=True):
        class_to_node_ids[int(class_label)].append(int(node_id))

    return class_to_node_ids

__default_classifier(train_hdata, num_classes, aggregation, exclude_self_reference=True)

Create a default CommonNeighbors classifier with a CommonNeighborsNodeScorer.

Parameters:

Name Type Description Default
train_hdata HData

Training data containing node labels and train node mask.

required
num_classes int

Number of node classes.

required
aggregation Literal['mean', 'min', 'sum']

Method used to aggregate reference-node scores per class.

required
exclude_self_reference bool

Whether a node should ignore itself when it also appears among labeled reference nodes.

True

Returns:

Name Type Description
classifier CommonNeighbors

A CommonNeighbors classifier with a CommonNeighborsNodeScorer.

Source code in hypertorch/nc/common_neighbors_nc.py
def __default_classifier(
    self,
    train_hdata: HData,
    num_classes: int,
    aggregation: Literal["mean", "min", "sum"],
    exclude_self_reference: bool = True,
) -> CommonNeighbors:
    """
    Create a default CommonNeighbors classifier with a CommonNeighborsNodeScorer.

    Args:
        train_hdata: Training data containing node labels and train node mask.
        num_classes: Number of node classes.
        aggregation: Method used to aggregate reference-node scores per class.
        exclude_self_reference: Whether a node should ignore itself when it also
            appears among labeled reference nodes.

    Returns:
        classifier: A CommonNeighbors classifier with a CommonNeighborsNodeScorer.
    """
    class_to_node_ids = self.__class_to_node_ids(
        train_hdata=train_hdata,
        num_classes=num_classes,
    )

    scorer = CommonNeighborsNodeScorer(
        num_classes=num_classes,
        class_to_node_ids=class_to_node_ids,
        aggregation=aggregation,
        exclude_self_reference=exclude_self_reference,
    )

    return CommonNeighbors(aggregation=aggregation, scorer=scorer)

GCNNcConfig

Bases: TypedDict

Configuration for the GCN classifier in GCNNcModule.

Attributes:

Name Type Description
in_channels int

Number of input features per node.

out_channels int

Number of node classes.

hidden_channels NotRequired[int]

Number of hidden units in intermediate GCN layers.

num_layers NotRequired[int]

Number of GCN layers. Defaults to 2.

drop_rate NotRequired[float]

Dropout rate applied after each hidden GCN layer. Defaults to 0.0.

bias NotRequired[bool]

Whether to include bias terms. Defaults to True.

improved NotRequired[bool]

Whether to use the improved GCN normalization. Defaults to False.

add_self_loops NotRequired[bool]

Whether to add self-loops before convolution. Defaults to True.

normalize NotRequired[bool]

Whether to normalize the adjacency matrix in GCNConv. Defaults to True.

cached NotRequired[bool]

Whether to cache the normalized graph in GCNConv. Defaults to False.

graph_reduction_strategy NotRequired[GraphReductionStrategy]

Strategy for reducing the hypergraph to a graph. Defaults to "clique_expansion".

num_nodes NotRequired[int]

Optional total number of nodes to use during graph reduction.

activation_fn NotRequired[ActivationFn]

Activation function to use after each hidden layer. Defaults to nn.ReLU.

activation_fn_kwargs NotRequired[dict]

Keyword arguments for the activation function. Defaults to empty dict.

Source code in hypertorch/nc/gcn_nc.py
class GCNNcConfig(TypedDict):
    """
    Configuration for the GCN classifier in ``GCNNcModule``.

    Attributes:
        in_channels: Number of input features per node.
        out_channels: Number of node classes.
        hidden_channels: Number of hidden units in intermediate GCN layers.
        num_layers: Number of GCN layers. Defaults to ``2``.
        drop_rate: Dropout rate applied after each hidden GCN layer. Defaults to ``0.0``.
        bias: Whether to include bias terms. Defaults to ``True``.
        improved: Whether to use the improved GCN normalization. Defaults to ``False``.
        add_self_loops: Whether to add self-loops before convolution. Defaults to ``True``.
        normalize: Whether to normalize the adjacency matrix in ``GCNConv``. Defaults to ``True``.
        cached: Whether to cache the normalized graph in ``GCNConv``. Defaults to ``False``.
        graph_reduction_strategy: Strategy for reducing the hypergraph to a graph.
            Defaults to ``"clique_expansion"``.
        num_nodes: Optional total number of nodes to use during graph reduction.
        activation_fn: Activation function to use after each hidden layer.
            Defaults to ``nn.ReLU``.
        activation_fn_kwargs: Keyword arguments for the activation function.
            Defaults to empty dict.
    """

    in_channels: int
    out_channels: int
    hidden_channels: NotRequired[int]
    num_layers: NotRequired[int]
    drop_rate: NotRequired[float]
    bias: NotRequired[bool]
    improved: NotRequired[bool]
    add_self_loops: NotRequired[bool]
    normalize: NotRequired[bool]
    cached: NotRequired[bool]
    graph_reduction_strategy: NotRequired[GraphReductionStrategy]
    num_nodes: NotRequired[int]
    activation_fn: NotRequired[ActivationFn]
    activation_fn_kwargs: NotRequired[dict]

GCNNcModule

Bases: NcModule

A LightningModule for GCN-based multiclass node classification.

Reduces the hypergraph to a graph, then applies GCN layers to produce per-node class logits.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module inherited from NcModule. Defaults to None.

classifier Module

GCN classifier module inherited from NcModule.

loss_fn Module

Loss function inherited from NcModule.

metrics_log_kwargs dict[str, Any]

Metric logging keyword arguments inherited from NcModule.

train_metrics MetricCollection | None

Optional training metrics inherited from NcModule.

val_metrics MetricCollection | None

Optional validation metrics inherited from NcModule.

test_metrics MetricCollection | None

Optional test metrics inherited from NcModule.

lr float

Learning rate for the optimizer. Defaults to 0.01.

weight_decay float

L2 regularization. Defaults to 5e-4.

Source code in hypertorch/nc/gcn_nc.py
class GCNNcModule(NcModule):
    """
    A LightningModule for GCN-based multiclass node classification.

    Reduces the hypergraph to a graph, then applies GCN
    layers to produce per-node class logits.

    Attributes:
        encoder: Optional encoder module inherited from ``NcModule``. Defaults to ``None``.
        classifier: GCN classifier module inherited from ``NcModule``.
        loss_fn: Loss function inherited from ``NcModule``.
        metrics_log_kwargs: Metric logging keyword arguments inherited from ``NcModule``.
        train_metrics: Optional training metrics inherited from ``NcModule``.
        val_metrics: Optional validation metrics inherited from ``NcModule``.
        test_metrics: Optional test metrics inherited from ``NcModule``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
    """

    def __init__(
        self,
        classifier_config: GCNNcConfig,
        loss_fn: nn.Module | None = None,
        lr: float = 0.01,
        weight_decay: float = 5e-4,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the GCN NC module.

        Args:
            classifier_config: Configuration for the GCN classifier.
            loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
            lr: Learning rate for the optimizer. Defaults to ``0.01``.
            weight_decay: L2 regularization. Defaults to ``5e-4``.
            metrics: Optional metric collection for evaluation. Defaults to ``None``.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
                Useful for configuring distributed synchronization behavior
                of ``torchmetrics``. Defaults to ``None``.
        """
        classifier = GCN(
            in_channels=classifier_config["in_channels"],
            out_channels=classifier_config["out_channels"],
            hidden_channels=classifier_config.get("hidden_channels"),
            num_layers=classifier_config.get("num_layers", 2),
            drop_rate=classifier_config.get("drop_rate", 0.0),
            bias=classifier_config.get("bias", True),
            activation_fn=classifier_config.get("activation_fn"),
            activation_fn_kwargs=classifier_config.get("activation_fn_kwargs"),
            improved=classifier_config.get("improved", False),
            add_self_loops=classifier_config.get("add_self_loops", True),
            normalize=classifier_config.get("normalize", True),
            cached=classifier_config.get("cached", False),
        )

        super().__init__(
            classifier=classifier,
            loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
            metrics=metrics,
            metrics_log_kwargs=metrics_log_kwargs,
        )

        self.classifier_config: GCNNcConfig = classifier_config
        self.lr: float = lr
        self.weight_decay: float = weight_decay

    def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
        """
        Predict node-class logits from node features and hypergraph structure.

        Examples:
            Given 4 nodes with 3 features each and 2 output classes:
                >>> x.shape
                ... torch.Size([4, 3])
                >>> hyperedge_index.shape
                ... torch.Size([2, 6])

            The forward pass maps each node to one row of class logits:
                >>> logits = model.forward(x, hyperedge_index)
                >>> logits.shape
                ... torch.Size([4, 2])

        Args:
            x: Node feature matrix of shape ``(num_nodes, in_channels)``.
            hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

        Returns:
            logits: Node-class logits of shape ``(num_nodes, num_classes)``.
        """
        # Reduce hypergraph to graph and remove self-loops
        reduced_edge_index = HyperedgeIndex(hyperedge_index).reduce(
            strategy=self.classifier_config.get(
                "graph_reduction_strategy",
                GraphReductionStrategyEnum.CLIQUE_EXPANSION,
            ),
            num_nodes=self.classifier_config.get("num_nodes"),
        )
        edge_index = EdgeIndex(reduced_edge_index).remove_selfloops().item

        return self.classifier(x, edge_index)

    def training_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a training step.

        Args:
            batch: Training batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Training loss.
        """
        return self.__eval_step(batch, Stage.TRAIN)

    def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a validation step.

        Args:
            batch: Validation batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Validation loss.
        """
        return self.__eval_step(batch, Stage.VAL)

    def test_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a test step.

        Args:
            batch: Test batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Test loss.
        """
        return self.__eval_step(batch, Stage.TEST)

    def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Predict node-class logits for a batch.

        Args:
            batch: Prediction batch.
            batch_idx: Batch index, unused.

        Returns:
            logits: Predicted node-class logits.
        """
        return self.forward(batch.x, batch.hyperedge_index)

    def configure_optimizers(self) -> optim.Adam:
        """
        Configure the optimizer.

        Returns:
            optimizer: Adam optimizer.
        """
        return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

    def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
        """
        Run shared evaluation logic for a stage.

        Args:
            batch: Input batch.
            stage: Current evaluation stage.

        Returns:
            loss: Computed loss.
        """
        logits = self.forward(batch.x, batch.hyperedge_index)
        target_logits, target_labels = self._target_logits_and_labels(logits, batch)
        batch_size = int(target_labels.size(0))

        loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
        self._compute_metrics(target_logits, target_labels, batch_size, stage)
        return loss

__init__(classifier_config, loss_fn=None, lr=0.01, weight_decay=0.0005, metrics=None, metrics_log_kwargs=None)

Initialize the GCN NC module.

Parameters:

Name Type Description Default
classifier_config GCNNcConfig

Configuration for the GCN classifier.

required
loss_fn Module | None

Optional loss function. Defaults to CrossEntropyLoss.

None
lr float

Learning rate for the optimizer. Defaults to 0.01.

0.01
weight_decay float

L2 regularization. Defaults to 5e-4.

0.0005
metrics MetricCollection | None

Optional metric collection for evaluation. Defaults to None.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls. Useful for configuring distributed synchronization behavior of torchmetrics. Defaults to None.

None
Source code in hypertorch/nc/gcn_nc.py
def __init__(
    self,
    classifier_config: GCNNcConfig,
    loss_fn: nn.Module | None = None,
    lr: float = 0.01,
    weight_decay: float = 5e-4,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the GCN NC module.

    Args:
        classifier_config: Configuration for the GCN classifier.
        loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
        metrics: Optional metric collection for evaluation. Defaults to ``None``.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
            Useful for configuring distributed synchronization behavior
            of ``torchmetrics``. Defaults to ``None``.
    """
    classifier = GCN(
        in_channels=classifier_config["in_channels"],
        out_channels=classifier_config["out_channels"],
        hidden_channels=classifier_config.get("hidden_channels"),
        num_layers=classifier_config.get("num_layers", 2),
        drop_rate=classifier_config.get("drop_rate", 0.0),
        bias=classifier_config.get("bias", True),
        activation_fn=classifier_config.get("activation_fn"),
        activation_fn_kwargs=classifier_config.get("activation_fn_kwargs"),
        improved=classifier_config.get("improved", False),
        add_self_loops=classifier_config.get("add_self_loops", True),
        normalize=classifier_config.get("normalize", True),
        cached=classifier_config.get("cached", False),
    )

    super().__init__(
        classifier=classifier,
        loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
        metrics=metrics,
        metrics_log_kwargs=metrics_log_kwargs,
    )

    self.classifier_config: GCNNcConfig = classifier_config
    self.lr: float = lr
    self.weight_decay: float = weight_decay

forward(x, hyperedge_index)

Predict node-class logits from node features and hypergraph structure.

Examples:

Given 4 nodes with 3 features each and 2 output classes: >>> x.shape ... torch.Size([4, 3]) >>> hyperedge_index.shape ... torch.Size([2, 6])

The forward pass maps each node to one row of class logits: >>> logits = model.forward(x, hyperedge_index) >>> logits.shape ... torch.Size([4, 2])

Parameters:

Name Type Description Default
x Tensor

Node feature matrix of shape (num_nodes, in_channels).

required
hyperedge_index Tensor

Hyperedge connectivity of shape (2, num_incidences).

required

Returns:

Name Type Description
logits Tensor

Node-class logits of shape (num_nodes, num_classes).

Source code in hypertorch/nc/gcn_nc.py
def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
    """
    Predict node-class logits from node features and hypergraph structure.

    Examples:
        Given 4 nodes with 3 features each and 2 output classes:
            >>> x.shape
            ... torch.Size([4, 3])
            >>> hyperedge_index.shape
            ... torch.Size([2, 6])

        The forward pass maps each node to one row of class logits:
            >>> logits = model.forward(x, hyperedge_index)
            >>> logits.shape
            ... torch.Size([4, 2])

    Args:
        x: Node feature matrix of shape ``(num_nodes, in_channels)``.
        hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

    Returns:
        logits: Node-class logits of shape ``(num_nodes, num_classes)``.
    """
    # Reduce hypergraph to graph and remove self-loops
    reduced_edge_index = HyperedgeIndex(hyperedge_index).reduce(
        strategy=self.classifier_config.get(
            "graph_reduction_strategy",
            GraphReductionStrategyEnum.CLIQUE_EXPANSION,
        ),
        num_nodes=self.classifier_config.get("num_nodes"),
    )
    edge_index = EdgeIndex(reduced_edge_index).remove_selfloops().item

    return self.classifier(x, edge_index)

training_step(batch, batch_idx)

Run a training step.

Parameters:

Name Type Description Default
batch HData

Training batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Training loss.

Source code in hypertorch/nc/gcn_nc.py
def training_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a training step.

    Args:
        batch: Training batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Training loss.
    """
    return self.__eval_step(batch, Stage.TRAIN)

validation_step(batch, batch_idx)

Run a validation step.

Parameters:

Name Type Description Default
batch HData

Validation batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Validation loss.

Source code in hypertorch/nc/gcn_nc.py
def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a validation step.

    Args:
        batch: Validation batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Validation loss.
    """
    return self.__eval_step(batch, Stage.VAL)

test_step(batch, batch_idx)

Run a test step.

Parameters:

Name Type Description Default
batch HData

Test batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Test loss.

Source code in hypertorch/nc/gcn_nc.py
def test_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a test step.

    Args:
        batch: Test batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Test loss.
    """
    return self.__eval_step(batch, Stage.TEST)

predict_step(batch, batch_idx)

Predict node-class logits for a batch.

Parameters:

Name Type Description Default
batch HData

Prediction batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
logits Tensor

Predicted node-class logits.

Source code in hypertorch/nc/gcn_nc.py
def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Predict node-class logits for a batch.

    Args:
        batch: Prediction batch.
        batch_idx: Batch index, unused.

    Returns:
        logits: Predicted node-class logits.
    """
    return self.forward(batch.x, batch.hyperedge_index)

configure_optimizers()

Configure the optimizer.

Returns:

Name Type Description
optimizer Adam

Adam optimizer.

Source code in hypertorch/nc/gcn_nc.py
def configure_optimizers(self) -> optim.Adam:
    """
    Configure the optimizer.

    Returns:
        optimizer: Adam optimizer.
    """
    return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

__eval_step(batch, stage)

Run shared evaluation logic for a stage.

Parameters:

Name Type Description Default
batch HData

Input batch.

required
stage Stage

Current evaluation stage.

required

Returns:

Name Type Description
loss Tensor

Computed loss.

Source code in hypertorch/nc/gcn_nc.py
def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
    """
    Run shared evaluation logic for a stage.

    Args:
        batch: Input batch.
        stage: Current evaluation stage.

    Returns:
        loss: Computed loss.
    """
    logits = self.forward(batch.x, batch.hyperedge_index)
    target_logits, target_labels = self._target_logits_and_labels(logits, batch)
    batch_size = int(target_labels.size(0))

    loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
    self._compute_metrics(target_logits, target_labels, batch_size, stage)
    return loss

HGNNNcConfig

Bases: TypedDict

Configuration for the HGNN classifier in HGNNNcModule.

Attributes:

Name Type Description
in_channels int

Number of input features per node.

hidden_channels int

Number of hidden units in the intermediate HGNN layer.

out_channels int

Number of node classes.

bias NotRequired[bool]

Whether to include bias terms. Defaults to True.

use_batch_normalization NotRequired[bool]

Whether to use batch normalization. Defaults to False.

drop_rate NotRequired[float]

Dropout rate. Defaults to 0.5.

Source code in hypertorch/nc/hgnn_nc.py
class HGNNNcConfig(TypedDict):
    """
    Configuration for the HGNN classifier in ``HGNNNcModule``.

    Attributes:
        in_channels: Number of input features per node.
        hidden_channels: Number of hidden units in the intermediate HGNN layer.
        out_channels: Number of node classes.
        bias: Whether to include bias terms. Defaults to ``True``.
        use_batch_normalization: Whether to use batch normalization. Defaults to ``False``.
        drop_rate: Dropout rate. Defaults to ``0.5``.
    """

    in_channels: int
    hidden_channels: int
    out_channels: int
    bias: NotRequired[bool]
    use_batch_normalization: NotRequired[bool]
    drop_rate: NotRequired[float]

HGNNNcModule

Bases: NcModule

A LightningModule for HGNN-based multiclass node classification.

Uses HGNN to transform node features and hypergraph incidence structure directly into per-node class logits. During training, validation, and testing, loss and metrics are computed on supervised target nodes selected by HData.target_node_mask.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module inherited from NcModule. Defaults to None.

classifier Module

HGNN classifier module inherited from NcModule.

loss_fn Module

Loss function inherited from NcModule.

metrics_log_kwargs dict[str, Any]

Metric logging keyword arguments inherited from NcModule.

train_metrics MetricCollection | None

Optional training metrics inherited from NcModule.

val_metrics MetricCollection | None

Optional validation metrics inherited from NcModule.

test_metrics MetricCollection | None

Optional test metrics inherited from NcModule.

lr float

Learning rate for the optimizer. Defaults to 0.01.

weight_decay float

L2 regularization. Defaults to 5e-4.

Source code in hypertorch/nc/hgnn_nc.py
class HGNNNcModule(NcModule):
    """
    A LightningModule for HGNN-based multiclass node classification.

    Uses HGNN to transform node features and hypergraph incidence structure directly into
    per-node class logits. During training, validation, and testing, loss and metrics
    are computed on supervised target nodes selected by ``HData.target_node_mask``.

    Attributes:
        encoder: Optional encoder module inherited from ``NcModule``. Defaults to ``None``.
        classifier: HGNN classifier module inherited from ``NcModule``.
        loss_fn: Loss function inherited from ``NcModule``.
        metrics_log_kwargs: Metric logging keyword arguments inherited from ``NcModule``.
        train_metrics: Optional training metrics inherited from ``NcModule``.
        val_metrics: Optional validation metrics inherited from ``NcModule``.
        test_metrics: Optional test metrics inherited from ``NcModule``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
    """

    def __init__(
        self,
        classifier_config: HGNNNcConfig,
        loss_fn: nn.Module | None = None,
        lr: float = 0.01,
        weight_decay: float = 5e-4,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the HGNN NC module.

        Args:
            classifier_config: Configuration for the HGNN classifier.
            loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
            lr: Learning rate for the optimizer. Defaults to ``0.01``.
            weight_decay: L2 regularization. Defaults to ``5e-4``.
            metrics: Optional metric collection for evaluation. Defaults to ``None``.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
                Useful for configuring distributed synchronization behavior
                of ``torchmetrics``. Defaults to ``None``.
        """
        classifier = HGNN(
            in_channels=classifier_config["in_channels"],
            hidden_channels=classifier_config["hidden_channels"],
            num_classes=classifier_config["out_channels"],
            bias=classifier_config.get("bias", True),
            use_batch_normalization=classifier_config.get("use_batch_normalization", False),
            drop_rate=classifier_config.get("drop_rate", 0.5),
        )

        super().__init__(
            classifier=classifier,
            loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
            metrics=metrics,
            metrics_log_kwargs=metrics_log_kwargs,
        )

        self.lr: float = lr
        self.weight_decay: float = weight_decay

    def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
        """
        Predict node-class logits from node features and hypergraph structure.

        Examples:
            Given 4 nodes with 3 features each and 2 output classes:
                >>> x.shape
                ... torch.Size([4, 3])
                >>> hyperedge_index.shape
                ... torch.Size([2, 6])

            The forward pass maps each node to one row of class logits:
                >>> logits = model.forward(x, hyperedge_index)
                >>> logits.shape
                ... torch.Size([4, 2])

        Args:
            x: Node feature matrix of shape ``(num_nodes, in_channels)``.
            hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

        Returns:
            logits: Node-class logits of shape ``(num_nodes, num_classes)``.
        """
        return self.classifier(x, hyperedge_index)

    def training_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a training step.

        Args:
            batch: Training batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Training loss.
        """
        return self.__eval_step(batch, Stage.TRAIN)

    def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a validation step.

        Args:
            batch: Validation batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Validation loss.
        """
        return self.__eval_step(batch, Stage.VAL)

    def test_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a test step.

        Args:
            batch: Test batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Test loss.
        """
        return self.__eval_step(batch, Stage.TEST)

    def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Predict node-class logits for a batch.

        Args:
            batch: Prediction batch.
            batch_idx: Batch index, unused.

        Returns:
            logits: Predicted node-class logits.
        """
        return self.forward(batch.x, batch.hyperedge_index)

    def configure_optimizers(self) -> optim.Adam:
        """
        Configure the optimizer.

        Returns:
            optimizer: Adam optimizer.
        """
        return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

    def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
        """
        Run shared evaluation logic for a stage.

        Args:
            batch: Input batch.
            stage: Current evaluation stage.

        Returns:
            loss: Computed loss.
        """
        logits = self.forward(batch.x, batch.hyperedge_index)
        target_logits, target_labels = self._target_logits_and_labels(logits, batch)
        batch_size = int(target_labels.size(0))

        loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
        self._compute_metrics(target_logits, target_labels, batch_size, stage)
        return loss

__init__(classifier_config, loss_fn=None, lr=0.01, weight_decay=0.0005, metrics=None, metrics_log_kwargs=None)

Initialize the HGNN NC module.

Parameters:

Name Type Description Default
classifier_config HGNNNcConfig

Configuration for the HGNN classifier.

required
loss_fn Module | None

Optional loss function. Defaults to CrossEntropyLoss.

None
lr float

Learning rate for the optimizer. Defaults to 0.01.

0.01
weight_decay float

L2 regularization. Defaults to 5e-4.

0.0005
metrics MetricCollection | None

Optional metric collection for evaluation. Defaults to None.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls. Useful for configuring distributed synchronization behavior of torchmetrics. Defaults to None.

None
Source code in hypertorch/nc/hgnn_nc.py
def __init__(
    self,
    classifier_config: HGNNNcConfig,
    loss_fn: nn.Module | None = None,
    lr: float = 0.01,
    weight_decay: float = 5e-4,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the HGNN NC module.

    Args:
        classifier_config: Configuration for the HGNN classifier.
        loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
        metrics: Optional metric collection for evaluation. Defaults to ``None``.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
            Useful for configuring distributed synchronization behavior
            of ``torchmetrics``. Defaults to ``None``.
    """
    classifier = HGNN(
        in_channels=classifier_config["in_channels"],
        hidden_channels=classifier_config["hidden_channels"],
        num_classes=classifier_config["out_channels"],
        bias=classifier_config.get("bias", True),
        use_batch_normalization=classifier_config.get("use_batch_normalization", False),
        drop_rate=classifier_config.get("drop_rate", 0.5),
    )

    super().__init__(
        classifier=classifier,
        loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
        metrics=metrics,
        metrics_log_kwargs=metrics_log_kwargs,
    )

    self.lr: float = lr
    self.weight_decay: float = weight_decay

forward(x, hyperedge_index)

Predict node-class logits from node features and hypergraph structure.

Examples:

Given 4 nodes with 3 features each and 2 output classes: >>> x.shape ... torch.Size([4, 3]) >>> hyperedge_index.shape ... torch.Size([2, 6])

The forward pass maps each node to one row of class logits: >>> logits = model.forward(x, hyperedge_index) >>> logits.shape ... torch.Size([4, 2])

Parameters:

Name Type Description Default
x Tensor

Node feature matrix of shape (num_nodes, in_channels).

required
hyperedge_index Tensor

Hyperedge connectivity of shape (2, num_incidences).

required

Returns:

Name Type Description
logits Tensor

Node-class logits of shape (num_nodes, num_classes).

Source code in hypertorch/nc/hgnn_nc.py
def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
    """
    Predict node-class logits from node features and hypergraph structure.

    Examples:
        Given 4 nodes with 3 features each and 2 output classes:
            >>> x.shape
            ... torch.Size([4, 3])
            >>> hyperedge_index.shape
            ... torch.Size([2, 6])

        The forward pass maps each node to one row of class logits:
            >>> logits = model.forward(x, hyperedge_index)
            >>> logits.shape
            ... torch.Size([4, 2])

    Args:
        x: Node feature matrix of shape ``(num_nodes, in_channels)``.
        hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

    Returns:
        logits: Node-class logits of shape ``(num_nodes, num_classes)``.
    """
    return self.classifier(x, hyperedge_index)

training_step(batch, batch_idx)

Run a training step.

Parameters:

Name Type Description Default
batch HData

Training batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Training loss.

Source code in hypertorch/nc/hgnn_nc.py
def training_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a training step.

    Args:
        batch: Training batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Training loss.
    """
    return self.__eval_step(batch, Stage.TRAIN)

validation_step(batch, batch_idx)

Run a validation step.

Parameters:

Name Type Description Default
batch HData

Validation batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Validation loss.

Source code in hypertorch/nc/hgnn_nc.py
def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a validation step.

    Args:
        batch: Validation batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Validation loss.
    """
    return self.__eval_step(batch, Stage.VAL)

test_step(batch, batch_idx)

Run a test step.

Parameters:

Name Type Description Default
batch HData

Test batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Test loss.

Source code in hypertorch/nc/hgnn_nc.py
def test_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a test step.

    Args:
        batch: Test batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Test loss.
    """
    return self.__eval_step(batch, Stage.TEST)

predict_step(batch, batch_idx)

Predict node-class logits for a batch.

Parameters:

Name Type Description Default
batch HData

Prediction batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
logits Tensor

Predicted node-class logits.

Source code in hypertorch/nc/hgnn_nc.py
def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Predict node-class logits for a batch.

    Args:
        batch: Prediction batch.
        batch_idx: Batch index, unused.

    Returns:
        logits: Predicted node-class logits.
    """
    return self.forward(batch.x, batch.hyperedge_index)

configure_optimizers()

Configure the optimizer.

Returns:

Name Type Description
optimizer Adam

Adam optimizer.

Source code in hypertorch/nc/hgnn_nc.py
def configure_optimizers(self) -> optim.Adam:
    """
    Configure the optimizer.

    Returns:
        optimizer: Adam optimizer.
    """
    return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

__eval_step(batch, stage)

Run shared evaluation logic for a stage.

Parameters:

Name Type Description Default
batch HData

Input batch.

required
stage Stage

Current evaluation stage.

required

Returns:

Name Type Description
loss Tensor

Computed loss.

Source code in hypertorch/nc/hgnn_nc.py
def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
    """
    Run shared evaluation logic for a stage.

    Args:
        batch: Input batch.
        stage: Current evaluation stage.

    Returns:
        loss: Computed loss.
    """
    logits = self.forward(batch.x, batch.hyperedge_index)
    target_logits, target_labels = self._target_logits_and_labels(logits, batch)
    batch_size = int(target_labels.size(0))

    loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
    self._compute_metrics(target_logits, target_labels, batch_size, stage)
    return loss

HNHNNcConfig

Bases: TypedDict

Configuration for the HNHN classifier in HNHNNcModule.

Attributes:

Name Type Description
in_channels int

Number of input features per node.

hidden_channels int

Number of hidden units in the intermediate HNHN layer.

out_channels int

Number of node classes.

bias NotRequired[bool]

Whether to include bias terms. Defaults to True.

use_batch_normalization NotRequired[bool]

Whether to use batch normalization. Defaults to False.

drop_rate NotRequired[float]

Dropout rate. Defaults to 0.5.

Source code in hypertorch/nc/hnhn_nc.py
class HNHNNcConfig(TypedDict):
    """
    Configuration for the HNHN classifier in ``HNHNNcModule``.

    Attributes:
        in_channels: Number of input features per node.
        hidden_channels: Number of hidden units in the intermediate HNHN layer.
        out_channels: Number of node classes.
        bias: Whether to include bias terms. Defaults to ``True``.
        use_batch_normalization: Whether to use batch normalization. Defaults to ``False``.
        drop_rate: Dropout rate. Defaults to ``0.5``.
    """

    in_channels: int
    hidden_channels: int
    out_channels: int
    bias: NotRequired[bool]
    use_batch_normalization: NotRequired[bool]
    drop_rate: NotRequired[float]

HNHNNcModule

Bases: NcModule

A LightningModule for HNHN-based multiclass node classification.

Uses HNHN to transform node features and hypergraph incidence structure into per-node class logits through explicit hyperedge neurons. During training, validation, and testing, loss and metrics are computed on supervised target nodes selected by HData.target_node_mask.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module inherited from NcModule. Defaults to None.

classifier Module

HNHN classifier module inherited from NcModule.

loss_fn Module

Loss function inherited from NcModule.

metrics_log_kwargs dict[str, Any]

Metric logging keyword arguments inherited from NcModule.

train_metrics MetricCollection | None

Optional training metrics inherited from NcModule.

val_metrics MetricCollection | None

Optional validation metrics inherited from NcModule.

test_metrics MetricCollection | None

Optional test metrics inherited from NcModule.

lr float

Learning rate for the optimizer. Defaults to 0.01.

weight_decay float

L2 regularization. Defaults to 5e-4.

Source code in hypertorch/nc/hnhn_nc.py
class HNHNNcModule(NcModule):
    """
    A LightningModule for HNHN-based multiclass node classification.

    Uses HNHN to transform node features and hypergraph incidence structure into
    per-node class logits through explicit hyperedge neurons. During training,
    validation, and testing, loss and metrics are computed on supervised target
    nodes selected by ``HData.target_node_mask``.

    Attributes:
        encoder: Optional encoder module inherited from ``NcModule``. Defaults to ``None``.
        classifier: HNHN classifier module inherited from ``NcModule``.
        loss_fn: Loss function inherited from ``NcModule``.
        metrics_log_kwargs: Metric logging keyword arguments inherited from ``NcModule``.
        train_metrics: Optional training metrics inherited from ``NcModule``.
        val_metrics: Optional validation metrics inherited from ``NcModule``.
        test_metrics: Optional test metrics inherited from ``NcModule``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
    """

    def __init__(
        self,
        classifier_config: HNHNNcConfig,
        loss_fn: nn.Module | None = None,
        lr: float = 0.01,
        weight_decay: float = 5e-4,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the HNHN NC module.

        Args:
            classifier_config: Configuration for the HNHN classifier.
            loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
            lr: Learning rate for the optimizer. Defaults to ``0.01``.
            weight_decay: L2 regularization. Defaults to ``5e-4``.
            metrics: Optional metric collection for evaluation. Defaults to ``None``.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
                Useful for configuring distributed synchronization behavior
                of ``torchmetrics``. Defaults to ``None``.
        """
        classifier = HNHN(
            in_channels=classifier_config["in_channels"],
            hidden_channels=classifier_config["hidden_channels"],
            num_classes=classifier_config["out_channels"],
            bias=classifier_config.get("bias", True),
            use_batch_normalization=classifier_config.get("use_batch_normalization", False),
            drop_rate=classifier_config.get("drop_rate", 0.5),
        )

        super().__init__(
            classifier=classifier,
            loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
            metrics=metrics,
            metrics_log_kwargs=metrics_log_kwargs,
        )

        self.lr: float = lr
        self.weight_decay: float = weight_decay

    def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
        """
        Predict node-class logits from node features and hypergraph structure.

        Examples:
            Given 4 nodes with 3 features each and 2 output classes:
                >>> x.shape
                ... torch.Size([4, 3])
                >>> hyperedge_index.shape
                ... torch.Size([2, 6])

            The forward pass maps each node to one row of class logits:
                >>> logits = model.forward(x, hyperedge_index)
                >>> logits.shape
                ... torch.Size([4, 2])

        Args:
            x: Node feature matrix of shape ``(num_nodes, in_channels)``.
            hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

        Returns:
            logits: Node-class logits of shape ``(num_nodes, num_classes)``.
        """
        return self.classifier(x, hyperedge_index)

    def training_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a training step.

        Args:
            batch: Training batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Training loss.
        """
        return self.__eval_step(batch, Stage.TRAIN)

    def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a validation step.

        Args:
            batch: Validation batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Validation loss.
        """
        return self.__eval_step(batch, Stage.VAL)

    def test_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a test step.

        Args:
            batch: Test batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Test loss.
        """
        return self.__eval_step(batch, Stage.TEST)

    def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Predict node-class logits for a batch.

        Args:
            batch: Prediction batch.
            batch_idx: Batch index, unused.

        Returns:
            logits: Predicted node-class logits.
        """
        return self.forward(batch.x, batch.hyperedge_index)

    def configure_optimizers(self) -> optim.Adam:
        """
        Configure the optimizer.

        Returns:
            optimizer: Adam optimizer.
        """
        return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

    def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
        """
        Run shared evaluation logic for a stage.

        Args:
            batch: Input batch.
            stage: Current evaluation stage.

        Returns:
            loss: Computed loss.
        """
        logits = self.forward(batch.x, batch.hyperedge_index)
        target_logits, target_labels = self._target_logits_and_labels(logits, batch)
        batch_size = int(target_labels.size(0))

        loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
        self._compute_metrics(target_logits, target_labels, batch_size, stage)
        return loss

__init__(classifier_config, loss_fn=None, lr=0.01, weight_decay=0.0005, metrics=None, metrics_log_kwargs=None)

Initialize the HNHN NC module.

Parameters:

Name Type Description Default
classifier_config HNHNNcConfig

Configuration for the HNHN classifier.

required
loss_fn Module | None

Optional loss function. Defaults to CrossEntropyLoss.

None
lr float

Learning rate for the optimizer. Defaults to 0.01.

0.01
weight_decay float

L2 regularization. Defaults to 5e-4.

0.0005
metrics MetricCollection | None

Optional metric collection for evaluation. Defaults to None.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls. Useful for configuring distributed synchronization behavior of torchmetrics. Defaults to None.

None
Source code in hypertorch/nc/hnhn_nc.py
def __init__(
    self,
    classifier_config: HNHNNcConfig,
    loss_fn: nn.Module | None = None,
    lr: float = 0.01,
    weight_decay: float = 5e-4,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the HNHN NC module.

    Args:
        classifier_config: Configuration for the HNHN classifier.
        loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
        metrics: Optional metric collection for evaluation. Defaults to ``None``.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
            Useful for configuring distributed synchronization behavior
            of ``torchmetrics``. Defaults to ``None``.
    """
    classifier = HNHN(
        in_channels=classifier_config["in_channels"],
        hidden_channels=classifier_config["hidden_channels"],
        num_classes=classifier_config["out_channels"],
        bias=classifier_config.get("bias", True),
        use_batch_normalization=classifier_config.get("use_batch_normalization", False),
        drop_rate=classifier_config.get("drop_rate", 0.5),
    )

    super().__init__(
        classifier=classifier,
        loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
        metrics=metrics,
        metrics_log_kwargs=metrics_log_kwargs,
    )

    self.lr: float = lr
    self.weight_decay: float = weight_decay

forward(x, hyperedge_index)

Predict node-class logits from node features and hypergraph structure.

Examples:

Given 4 nodes with 3 features each and 2 output classes: >>> x.shape ... torch.Size([4, 3]) >>> hyperedge_index.shape ... torch.Size([2, 6])

The forward pass maps each node to one row of class logits: >>> logits = model.forward(x, hyperedge_index) >>> logits.shape ... torch.Size([4, 2])

Parameters:

Name Type Description Default
x Tensor

Node feature matrix of shape (num_nodes, in_channels).

required
hyperedge_index Tensor

Hyperedge connectivity of shape (2, num_incidences).

required

Returns:

Name Type Description
logits Tensor

Node-class logits of shape (num_nodes, num_classes).

Source code in hypertorch/nc/hnhn_nc.py
def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
    """
    Predict node-class logits from node features and hypergraph structure.

    Examples:
        Given 4 nodes with 3 features each and 2 output classes:
            >>> x.shape
            ... torch.Size([4, 3])
            >>> hyperedge_index.shape
            ... torch.Size([2, 6])

        The forward pass maps each node to one row of class logits:
            >>> logits = model.forward(x, hyperedge_index)
            >>> logits.shape
            ... torch.Size([4, 2])

    Args:
        x: Node feature matrix of shape ``(num_nodes, in_channels)``.
        hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

    Returns:
        logits: Node-class logits of shape ``(num_nodes, num_classes)``.
    """
    return self.classifier(x, hyperedge_index)

training_step(batch, batch_idx)

Run a training step.

Parameters:

Name Type Description Default
batch HData

Training batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Training loss.

Source code in hypertorch/nc/hnhn_nc.py
def training_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a training step.

    Args:
        batch: Training batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Training loss.
    """
    return self.__eval_step(batch, Stage.TRAIN)

validation_step(batch, batch_idx)

Run a validation step.

Parameters:

Name Type Description Default
batch HData

Validation batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Validation loss.

Source code in hypertorch/nc/hnhn_nc.py
def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a validation step.

    Args:
        batch: Validation batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Validation loss.
    """
    return self.__eval_step(batch, Stage.VAL)

test_step(batch, batch_idx)

Run a test step.

Parameters:

Name Type Description Default
batch HData

Test batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Test loss.

Source code in hypertorch/nc/hnhn_nc.py
def test_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a test step.

    Args:
        batch: Test batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Test loss.
    """
    return self.__eval_step(batch, Stage.TEST)

predict_step(batch, batch_idx)

Predict node-class logits for a batch.

Parameters:

Name Type Description Default
batch HData

Prediction batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
logits Tensor

Predicted node-class logits.

Source code in hypertorch/nc/hnhn_nc.py
def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Predict node-class logits for a batch.

    Args:
        batch: Prediction batch.
        batch_idx: Batch index, unused.

    Returns:
        logits: Predicted node-class logits.
    """
    return self.forward(batch.x, batch.hyperedge_index)

configure_optimizers()

Configure the optimizer.

Returns:

Name Type Description
optimizer Adam

Adam optimizer.

Source code in hypertorch/nc/hnhn_nc.py
def configure_optimizers(self) -> optim.Adam:
    """
    Configure the optimizer.

    Returns:
        optimizer: Adam optimizer.
    """
    return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

__eval_step(batch, stage)

Run shared evaluation logic for a stage.

Parameters:

Name Type Description Default
batch HData

Input batch.

required
stage Stage

Current evaluation stage.

required

Returns:

Name Type Description
loss Tensor

Computed loss.

Source code in hypertorch/nc/hnhn_nc.py
def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
    """
    Run shared evaluation logic for a stage.

    Args:
        batch: Input batch.
        stage: Current evaluation stage.

    Returns:
        loss: Computed loss.
    """
    logits = self.forward(batch.x, batch.hyperedge_index)
    target_logits, target_labels = self._target_logits_and_labels(logits, batch)
    batch_size = int(target_labels.size(0))

    loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
    self._compute_metrics(target_logits, target_labels, batch_size, stage)
    return loss

HGNNPNcConfig

Bases: TypedDict

Configuration for the HGNN+ classifier in HGNNPNcModule.

Attributes:

Name Type Description
in_channels int

Number of input features per node.

hidden_channels int

Number of hidden units in the intermediate HGNN+ layer.

out_channels int

Number of node classes.

bias NotRequired[bool]

Whether to include bias terms. Defaults to True.

use_batch_normalization NotRequired[bool]

Whether to use batch normalization. Defaults to False.

drop_rate NotRequired[float]

Dropout rate. Defaults to 0.5.

Source code in hypertorch/nc/hgnnp_nc.py
class HGNNPNcConfig(TypedDict):
    """
    Configuration for the HGNN+ classifier in ``HGNNPNcModule``.

    Attributes:
        in_channels: Number of input features per node.
        hidden_channels: Number of hidden units in the intermediate HGNN+ layer.
        out_channels: Number of node classes.
        bias: Whether to include bias terms. Defaults to ``True``.
        use_batch_normalization: Whether to use batch normalization. Defaults to ``False``.
        drop_rate: Dropout rate. Defaults to ``0.5``.
    """

    in_channels: int
    hidden_channels: int
    out_channels: int
    bias: NotRequired[bool]
    use_batch_normalization: NotRequired[bool]
    drop_rate: NotRequired[float]

HGNNPNcModule

Bases: NcModule

A LightningModule for HGNN+-based multiclass node classification.

Uses HGNN+ to transform node features and hypergraph incidence structure directly into per-node class logits. During training, validation, and testing, loss and metrics are computed on supervised target nodes selected by HData.target_node_mask.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module inherited from NcModule. Defaults to None.

classifier Module

HGNN+ classifier module inherited from NcModule.

loss_fn Module

Loss function inherited from NcModule.

metrics_log_kwargs dict[str, Any]

Metric logging keyword arguments inherited from NcModule.

train_metrics MetricCollection | None

Optional training metrics inherited from NcModule.

val_metrics MetricCollection | None

Optional validation metrics inherited from NcModule.

test_metrics MetricCollection | None

Optional test metrics inherited from NcModule.

lr float

Learning rate for the optimizer. Defaults to 0.01.

weight_decay float

L2 regularization. Defaults to 5e-4.

Source code in hypertorch/nc/hgnnp_nc.py
class HGNNPNcModule(NcModule):
    """
    A LightningModule for HGNN+-based multiclass node classification.

    Uses HGNN+ to transform node features and hypergraph incidence structure directly into
    per-node class logits. During training, validation, and testing, loss and metrics
    are computed on supervised target nodes selected by ``HData.target_node_mask``.

    Attributes:
        encoder: Optional encoder module inherited from ``NcModule``. Defaults to ``None``.
        classifier: HGNN+ classifier module inherited from ``NcModule``.
        loss_fn: Loss function inherited from ``NcModule``.
        metrics_log_kwargs: Metric logging keyword arguments inherited from ``NcModule``.
        train_metrics: Optional training metrics inherited from ``NcModule``.
        val_metrics: Optional validation metrics inherited from ``NcModule``.
        test_metrics: Optional test metrics inherited from ``NcModule``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
    """

    def __init__(
        self,
        classifier_config: HGNNPNcConfig,
        loss_fn: nn.Module | None = None,
        lr: float = 0.01,
        weight_decay: float = 5e-4,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the HGNN+ NC module.

        Args:
            classifier_config: Configuration for the HGNN+ classifier.
            loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
            lr: Learning rate for the optimizer. Defaults to ``0.01``.
            weight_decay: L2 regularization. Defaults to ``5e-4``.
            metrics: Optional metric collection for evaluation. Defaults to ``None``.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
                Useful for configuring distributed synchronization behavior
                of ``torchmetrics``. Defaults to ``None``.
        """
        classifier = HGNNP(
            in_channels=classifier_config["in_channels"],
            hidden_channels=classifier_config["hidden_channels"],
            num_classes=classifier_config["out_channels"],
            bias=classifier_config.get("bias", True),
            use_batch_normalization=classifier_config.get("use_batch_normalization", False),
            drop_rate=classifier_config.get("drop_rate", 0.5),
        )

        super().__init__(
            classifier=classifier,
            loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
            metrics=metrics,
            metrics_log_kwargs=metrics_log_kwargs,
        )

        self.lr: float = lr
        self.weight_decay: float = weight_decay

    def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
        """
        Predict node-class logits from node features and hypergraph structure.

        Examples:
            Given 4 nodes with 3 features each and 2 output classes:
                >>> x.shape
                ... torch.Size([4, 3])
                >>> hyperedge_index.shape
                ... torch.Size([2, 6])

            The forward pass maps each node to one row of class logits:
                >>> logits = model.forward(x, hyperedge_index)
                >>> logits.shape
                ... torch.Size([4, 2])

        Args:
            x: Node feature matrix of shape ``(num_nodes, in_channels)``.
            hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

        Returns:
            logits: Node-class logits of shape ``(num_nodes, num_classes)``.
        """
        return self.classifier(x, hyperedge_index)

    def training_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a training step.

        Args:
            batch: Training batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Training loss.
        """
        return self.__eval_step(batch, Stage.TRAIN)

    def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a validation step.

        Args:
            batch: Validation batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Validation loss.
        """
        return self.__eval_step(batch, Stage.VAL)

    def test_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a test step.

        Args:
            batch: Test batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Test loss.
        """
        return self.__eval_step(batch, Stage.TEST)

    def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Predict node-class logits for a batch.

        Args:
            batch: Prediction batch.
            batch_idx: Batch index, unused.

        Returns:
            logits: Predicted node-class logits.
        """
        return self.forward(batch.x, batch.hyperedge_index)

    def configure_optimizers(self) -> optim.Adam:
        """
        Configure the optimizer.

        Returns:
            optimizer: Adam optimizer.
        """
        return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

    def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
        """
        Run shared evaluation logic for a stage.

        Args:
            batch: Input batch.
            stage: Current evaluation stage.

        Returns:
            loss: Computed loss.
        """
        logits = self.forward(batch.x, batch.hyperedge_index)
        target_logits, target_labels = self._target_logits_and_labels(logits, batch)
        batch_size = int(target_labels.size(0))

        loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
        self._compute_metrics(target_logits, target_labels, batch_size, stage)
        return loss

__init__(classifier_config, loss_fn=None, lr=0.01, weight_decay=0.0005, metrics=None, metrics_log_kwargs=None)

Initialize the HGNN+ NC module.

Parameters:

Name Type Description Default
classifier_config HGNNPNcConfig

Configuration for the HGNN+ classifier.

required
loss_fn Module | None

Optional loss function. Defaults to CrossEntropyLoss.

None
lr float

Learning rate for the optimizer. Defaults to 0.01.

0.01
weight_decay float

L2 regularization. Defaults to 5e-4.

0.0005
metrics MetricCollection | None

Optional metric collection for evaluation. Defaults to None.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls. Useful for configuring distributed synchronization behavior of torchmetrics. Defaults to None.

None
Source code in hypertorch/nc/hgnnp_nc.py
def __init__(
    self,
    classifier_config: HGNNPNcConfig,
    loss_fn: nn.Module | None = None,
    lr: float = 0.01,
    weight_decay: float = 5e-4,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the HGNN+ NC module.

    Args:
        classifier_config: Configuration for the HGNN+ classifier.
        loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
        metrics: Optional metric collection for evaluation. Defaults to ``None``.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
            Useful for configuring distributed synchronization behavior
            of ``torchmetrics``. Defaults to ``None``.
    """
    classifier = HGNNP(
        in_channels=classifier_config["in_channels"],
        hidden_channels=classifier_config["hidden_channels"],
        num_classes=classifier_config["out_channels"],
        bias=classifier_config.get("bias", True),
        use_batch_normalization=classifier_config.get("use_batch_normalization", False),
        drop_rate=classifier_config.get("drop_rate", 0.5),
    )

    super().__init__(
        classifier=classifier,
        loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
        metrics=metrics,
        metrics_log_kwargs=metrics_log_kwargs,
    )

    self.lr: float = lr
    self.weight_decay: float = weight_decay

forward(x, hyperedge_index)

Predict node-class logits from node features and hypergraph structure.

Examples:

Given 4 nodes with 3 features each and 2 output classes: >>> x.shape ... torch.Size([4, 3]) >>> hyperedge_index.shape ... torch.Size([2, 6])

The forward pass maps each node to one row of class logits: >>> logits = model.forward(x, hyperedge_index) >>> logits.shape ... torch.Size([4, 2])

Parameters:

Name Type Description Default
x Tensor

Node feature matrix of shape (num_nodes, in_channels).

required
hyperedge_index Tensor

Hyperedge connectivity of shape (2, num_incidences).

required

Returns:

Name Type Description
logits Tensor

Node-class logits of shape (num_nodes, num_classes).

Source code in hypertorch/nc/hgnnp_nc.py
def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
    """
    Predict node-class logits from node features and hypergraph structure.

    Examples:
        Given 4 nodes with 3 features each and 2 output classes:
            >>> x.shape
            ... torch.Size([4, 3])
            >>> hyperedge_index.shape
            ... torch.Size([2, 6])

        The forward pass maps each node to one row of class logits:
            >>> logits = model.forward(x, hyperedge_index)
            >>> logits.shape
            ... torch.Size([4, 2])

    Args:
        x: Node feature matrix of shape ``(num_nodes, in_channels)``.
        hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

    Returns:
        logits: Node-class logits of shape ``(num_nodes, num_classes)``.
    """
    return self.classifier(x, hyperedge_index)

training_step(batch, batch_idx)

Run a training step.

Parameters:

Name Type Description Default
batch HData

Training batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Training loss.

Source code in hypertorch/nc/hgnnp_nc.py
def training_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a training step.

    Args:
        batch: Training batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Training loss.
    """
    return self.__eval_step(batch, Stage.TRAIN)

validation_step(batch, batch_idx)

Run a validation step.

Parameters:

Name Type Description Default
batch HData

Validation batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Validation loss.

Source code in hypertorch/nc/hgnnp_nc.py
def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a validation step.

    Args:
        batch: Validation batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Validation loss.
    """
    return self.__eval_step(batch, Stage.VAL)

test_step(batch, batch_idx)

Run a test step.

Parameters:

Name Type Description Default
batch HData

Test batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Test loss.

Source code in hypertorch/nc/hgnnp_nc.py
def test_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a test step.

    Args:
        batch: Test batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Test loss.
    """
    return self.__eval_step(batch, Stage.TEST)

predict_step(batch, batch_idx)

Predict node-class logits for a batch.

Parameters:

Name Type Description Default
batch HData

Prediction batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
logits Tensor

Predicted node-class logits.

Source code in hypertorch/nc/hgnnp_nc.py
def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Predict node-class logits for a batch.

    Args:
        batch: Prediction batch.
        batch_idx: Batch index, unused.

    Returns:
        logits: Predicted node-class logits.
    """
    return self.forward(batch.x, batch.hyperedge_index)

configure_optimizers()

Configure the optimizer.

Returns:

Name Type Description
optimizer Adam

Adam optimizer.

Source code in hypertorch/nc/hgnnp_nc.py
def configure_optimizers(self) -> optim.Adam:
    """
    Configure the optimizer.

    Returns:
        optimizer: Adam optimizer.
    """
    return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

__eval_step(batch, stage)

Run shared evaluation logic for a stage.

Parameters:

Name Type Description Default
batch HData

Input batch.

required
stage Stage

Current evaluation stage.

required

Returns:

Name Type Description
loss Tensor

Computed loss.

Source code in hypertorch/nc/hgnnp_nc.py
def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
    """
    Run shared evaluation logic for a stage.

    Args:
        batch: Input batch.
        stage: Current evaluation stage.

    Returns:
        loss: Computed loss.
    """
    logits = self.forward(batch.x, batch.hyperedge_index)
    target_logits, target_labels = self._target_logits_and_labels(logits, batch)
    batch_size = int(target_labels.size(0))

    loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
    self._compute_metrics(target_logits, target_labels, batch_size, stage)
    return loss

HyperGCNNcConfig

Bases: TypedDict

Configuration for the HyperGCN classifier in HyperGCNNcModule.

Attributes:

Name Type Description
in_channels int

Number of input features per node.

hidden_channels int

Number of hidden units in the intermediate HyperGCN layer.

out_channels int

Number of node classes.

bias NotRequired[bool]

Whether to include bias terms. Defaults to True.

use_batch_normalization NotRequired[bool]

Whether to use batch normalization. Defaults to False.

drop_rate NotRequired[float]

Dropout rate. Defaults to 0.5.

use_mediator NotRequired[bool]

Whether to use mediator nodes for hyperedge-to-edge conversion. Defaults to False.

fast NotRequired[bool]

Whether to cache the graph structure after first computation. Defaults to True.

seed NotRequired[int]

Optional random seed for the random reduction of hyperedges to edges. Defaults to None.

Source code in hypertorch/nc/hypergcn_nc.py
class HyperGCNNcConfig(TypedDict):
    """
    Configuration for the HyperGCN classifier in ``HyperGCNNcModule``.

    Attributes:
        in_channels: Number of input features per node.
        hidden_channels: Number of hidden units in the intermediate HyperGCN layer.
        out_channels: Number of node classes.
        bias: Whether to include bias terms. Defaults to ``True``.
        use_batch_normalization: Whether to use batch normalization. Defaults to ``False``.
        drop_rate: Dropout rate. Defaults to ``0.5``.
        use_mediator: Whether to use mediator nodes for hyperedge-to-edge conversion.
            Defaults to ``False``.
        fast: Whether to cache the graph structure after first computation.
            Defaults to ``True``.
        seed: Optional random seed for the random reduction of hyperedges to edges.
            Defaults to ``None``.
    """

    in_channels: int
    hidden_channels: int
    out_channels: int
    bias: NotRequired[bool]
    use_batch_normalization: NotRequired[bool]
    drop_rate: NotRequired[float]
    use_mediator: NotRequired[bool]
    fast: NotRequired[bool]
    seed: NotRequired[int]

HyperGCNNcModule

Bases: NcModule

A LightningModule for HyperGCN-based multiclass node classification.

Uses HyperGCN to transform node features and hypergraph structure directly into per-node class logits. During training, validation, and testing, loss and metrics are computed on supervised target nodes selected by HData.target_node_mask.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module inherited from NcModule. Defaults to None.

classifier Module

HyperGCN classifier module inherited from NcModule.

loss_fn Module

Loss function inherited from NcModule.

metrics_log_kwargs dict[str, Any]

Metric logging keyword arguments inherited from NcModule.

train_metrics MetricCollection | None

Optional training metrics inherited from NcModule.

val_metrics MetricCollection | None

Optional validation metrics inherited from NcModule.

test_metrics MetricCollection | None

Optional test metrics inherited from NcModule.

lr float

Learning rate for the optimizer. Defaults to 0.01.

weight_decay float

L2 regularization. Defaults to 5e-4.

Source code in hypertorch/nc/hypergcn_nc.py
class HyperGCNNcModule(NcModule):
    """
    A LightningModule for HyperGCN-based multiclass node classification.

    Uses HyperGCN to transform node features and hypergraph structure directly into
    per-node class logits. During training, validation, and testing, loss and metrics
    are computed on supervised target nodes selected by ``HData.target_node_mask``.

    Attributes:
        encoder: Optional encoder module inherited from ``NcModule``. Defaults to ``None``.
        classifier: HyperGCN classifier module inherited from ``NcModule``.
        loss_fn: Loss function inherited from ``NcModule``.
        metrics_log_kwargs: Metric logging keyword arguments inherited from ``NcModule``.
        train_metrics: Optional training metrics inherited from ``NcModule``.
        val_metrics: Optional validation metrics inherited from ``NcModule``.
        test_metrics: Optional test metrics inherited from ``NcModule``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
    """

    def __init__(
        self,
        classifier_config: HyperGCNNcConfig,
        loss_fn: nn.Module | None = None,
        lr: float = 0.01,
        weight_decay: float = 5e-4,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the HyperGCN NC module.

        Args:
            classifier_config: Configuration for the HyperGCN classifier.
            loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
            lr: Learning rate for the optimizer. Defaults to ``0.01``.
            weight_decay: L2 regularization. Defaults to ``5e-4``.
            metrics: Optional metric collection for evaluation. Defaults to ``None``.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
                Useful for configuring distributed synchronization behavior
                of ``torchmetrics``. Defaults to ``None``.
        """
        classifier = HyperGCN(
            in_channels=classifier_config["in_channels"],
            hidden_channels=classifier_config["hidden_channels"],
            num_classes=classifier_config["out_channels"],
            bias=classifier_config.get("bias", True),
            use_batch_normalization=classifier_config.get("use_batch_normalization", False),
            drop_rate=classifier_config.get("drop_rate", 0.5),
            use_mediator=classifier_config.get("use_mediator", False),
            fast=classifier_config.get("fast", True),
            seed=classifier_config.get("seed"),
        )

        super().__init__(
            classifier=classifier,
            loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
            metrics=metrics,
            metrics_log_kwargs=metrics_log_kwargs,
        )

        self.lr: float = lr
        self.weight_decay: float = weight_decay

    def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
        """
        Predict node-class logits from node features and hypergraph structure.

        Examples:
            Given 4 nodes with 3 features each and 2 output classes:
                >>> x.shape
                ... torch.Size([4, 3])
                >>> hyperedge_index.shape
                ... torch.Size([2, 6])

            The forward pass maps each node to one row of class logits:
                >>> logits = model.forward(x, hyperedge_index)
                >>> logits.shape
                ... torch.Size([4, 2])

        Args:
            x: Node feature matrix of shape ``(num_nodes, in_channels)``.
            hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

        Returns:
            logits: Node-class logits of shape ``(num_nodes, num_classes)``.
        """
        return self.classifier(x, hyperedge_index)

    def training_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a training step.

        Args:
            batch: Training batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Training loss.
        """
        return self.__eval_step(batch, Stage.TRAIN)

    def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a validation step.

        Args:
            batch: Validation batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Validation loss.
        """
        return self.__eval_step(batch, Stage.VAL)

    def test_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a test step.

        Args:
            batch: Test batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Test loss.
        """
        return self.__eval_step(batch, Stage.TEST)

    def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Predict node-class logits for a batch.

        Args:
            batch: Prediction batch.
            batch_idx: Batch index, unused.

        Returns:
            logits: Predicted node-class logits.
        """
        return self.forward(batch.x, batch.hyperedge_index)

    def configure_optimizers(self) -> optim.Adam:
        """
        Configure the optimizer.

        Returns:
            optimizer: Adam optimizer.
        """
        return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

    def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
        """
        Run shared evaluation logic for a stage.

        Args:
            batch: Input batch.
            stage: Current evaluation stage.

        Returns:
            loss: Computed loss.
        """
        logits = self.forward(batch.x, batch.hyperedge_index)
        target_logits, target_labels = self._target_logits_and_labels(logits, batch)
        batch_size = int(target_labels.size(0))

        loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
        self._compute_metrics(target_logits, target_labels, batch_size, stage)
        return loss

__init__(classifier_config, loss_fn=None, lr=0.01, weight_decay=0.0005, metrics=None, metrics_log_kwargs=None)

Initialize the HyperGCN NC module.

Parameters:

Name Type Description Default
classifier_config HyperGCNNcConfig

Configuration for the HyperGCN classifier.

required
loss_fn Module | None

Optional loss function. Defaults to CrossEntropyLoss.

None
lr float

Learning rate for the optimizer. Defaults to 0.01.

0.01
weight_decay float

L2 regularization. Defaults to 5e-4.

0.0005
metrics MetricCollection | None

Optional metric collection for evaluation. Defaults to None.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls. Useful for configuring distributed synchronization behavior of torchmetrics. Defaults to None.

None
Source code in hypertorch/nc/hypergcn_nc.py
def __init__(
    self,
    classifier_config: HyperGCNNcConfig,
    loss_fn: nn.Module | None = None,
    lr: float = 0.01,
    weight_decay: float = 5e-4,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the HyperGCN NC module.

    Args:
        classifier_config: Configuration for the HyperGCN classifier.
        loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
        lr: Learning rate for the optimizer. Defaults to ``0.01``.
        weight_decay: L2 regularization. Defaults to ``5e-4``.
        metrics: Optional metric collection for evaluation. Defaults to ``None``.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
            Useful for configuring distributed synchronization behavior
            of ``torchmetrics``. Defaults to ``None``.
    """
    classifier = HyperGCN(
        in_channels=classifier_config["in_channels"],
        hidden_channels=classifier_config["hidden_channels"],
        num_classes=classifier_config["out_channels"],
        bias=classifier_config.get("bias", True),
        use_batch_normalization=classifier_config.get("use_batch_normalization", False),
        drop_rate=classifier_config.get("drop_rate", 0.5),
        use_mediator=classifier_config.get("use_mediator", False),
        fast=classifier_config.get("fast", True),
        seed=classifier_config.get("seed"),
    )

    super().__init__(
        classifier=classifier,
        loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
        metrics=metrics,
        metrics_log_kwargs=metrics_log_kwargs,
    )

    self.lr: float = lr
    self.weight_decay: float = weight_decay

forward(x, hyperedge_index)

Predict node-class logits from node features and hypergraph structure.

Examples:

Given 4 nodes with 3 features each and 2 output classes: >>> x.shape ... torch.Size([4, 3]) >>> hyperedge_index.shape ... torch.Size([2, 6])

The forward pass maps each node to one row of class logits: >>> logits = model.forward(x, hyperedge_index) >>> logits.shape ... torch.Size([4, 2])

Parameters:

Name Type Description Default
x Tensor

Node feature matrix of shape (num_nodes, in_channels).

required
hyperedge_index Tensor

Hyperedge connectivity of shape (2, num_incidences).

required

Returns:

Name Type Description
logits Tensor

Node-class logits of shape (num_nodes, num_classes).

Source code in hypertorch/nc/hypergcn_nc.py
def forward(self, x: Tensor, hyperedge_index: Tensor) -> Tensor:
    """
    Predict node-class logits from node features and hypergraph structure.

    Examples:
        Given 4 nodes with 3 features each and 2 output classes:
            >>> x.shape
            ... torch.Size([4, 3])
            >>> hyperedge_index.shape
            ... torch.Size([2, 6])

        The forward pass maps each node to one row of class logits:
            >>> logits = model.forward(x, hyperedge_index)
            >>> logits.shape
            ... torch.Size([4, 2])

    Args:
        x: Node feature matrix of shape ``(num_nodes, in_channels)``.
        hyperedge_index: Hyperedge connectivity of shape ``(2, num_incidences)``.

    Returns:
        logits: Node-class logits of shape ``(num_nodes, num_classes)``.
    """
    return self.classifier(x, hyperedge_index)

training_step(batch, batch_idx)

Run a training step.

Parameters:

Name Type Description Default
batch HData

Training batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Training loss.

Source code in hypertorch/nc/hypergcn_nc.py
def training_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a training step.

    Args:
        batch: Training batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Training loss.
    """
    return self.__eval_step(batch, Stage.TRAIN)

validation_step(batch, batch_idx)

Run a validation step.

Parameters:

Name Type Description Default
batch HData

Validation batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Validation loss.

Source code in hypertorch/nc/hypergcn_nc.py
def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a validation step.

    Args:
        batch: Validation batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Validation loss.
    """
    return self.__eval_step(batch, Stage.VAL)

test_step(batch, batch_idx)

Run a test step.

Parameters:

Name Type Description Default
batch HData

Test batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Test loss.

Source code in hypertorch/nc/hypergcn_nc.py
def test_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a test step.

    Args:
        batch: Test batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Test loss.
    """
    return self.__eval_step(batch, Stage.TEST)

predict_step(batch, batch_idx)

Predict node-class logits for a batch.

Parameters:

Name Type Description Default
batch HData

Prediction batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
logits Tensor

Predicted node-class logits.

Source code in hypertorch/nc/hypergcn_nc.py
def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Predict node-class logits for a batch.

    Args:
        batch: Prediction batch.
        batch_idx: Batch index, unused.

    Returns:
        logits: Predicted node-class logits.
    """
    return self.forward(batch.x, batch.hyperedge_index)

configure_optimizers()

Configure the optimizer.

Returns:

Name Type Description
optimizer Adam

Adam optimizer.

Source code in hypertorch/nc/hypergcn_nc.py
def configure_optimizers(self) -> optim.Adam:
    """
    Configure the optimizer.

    Returns:
        optimizer: Adam optimizer.
    """
    return optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.weight_decay)

__eval_step(batch, stage)

Run shared evaluation logic for a stage.

Parameters:

Name Type Description Default
batch HData

Input batch.

required
stage Stage

Current evaluation stage.

required

Returns:

Name Type Description
loss Tensor

Computed loss.

Source code in hypertorch/nc/hypergcn_nc.py
def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
    """
    Run shared evaluation logic for a stage.

    Args:
        batch: Input batch.
        stage: Current evaluation stage.

    Returns:
        loss: Computed loss.
    """
    logits = self.forward(batch.x, batch.hyperedge_index)
    target_logits, target_labels = self._target_logits_and_labels(logits, batch)
    batch_size = int(target_labels.size(0))

    loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
    self._compute_metrics(target_logits, target_labels, batch_size, stage)
    return loss

MLPNcModule

Bases: NcModule

A LightningModule for MLP-based multiclass node classification.

Uses an MLP classifier to map node features directly to per-node class logits. During training, validation, and testing, loss and metrics are computed on the supervised target nodes selected by HData.target_node_mask when present.

Attributes:

Name Type Description
encoder Module | None

Optional encoder module inherited from NcModule. Defaults to None.

classifier Module

MLP classifier module inherited from NcModule.

loss_fn Module

Loss function inherited from NcModule.

metrics_log_kwargs dict[str, Any]

Metric logging keyword arguments inherited from NcModule.

train_metrics MetricCollection | None

Optional training metrics inherited from NcModule.

val_metrics MetricCollection | None

Optional validation metrics inherited from NcModule.

test_metrics MetricCollection | None

Optional test metrics inherited from NcModule.

lr float

Learning rate for the optimizer. Defaults to 0.001.

Source code in hypertorch/nc/mlp_nc.py
class MLPNcModule(NcModule):
    """
    A LightningModule for MLP-based multiclass node classification.

    Uses an MLP classifier to map node features directly to per-node class logits.
    During training, validation, and testing, loss and metrics are computed on the
    supervised target nodes selected by ``HData.target_node_mask`` when present.

    Attributes:
        encoder: Optional encoder module inherited from ``NcModule``. Defaults to ``None``.
        classifier: MLP classifier module inherited from ``NcModule``.
        loss_fn: Loss function inherited from ``NcModule``.
        metrics_log_kwargs: Metric logging keyword arguments inherited from ``NcModule``.
        train_metrics: Optional training metrics inherited from ``NcModule``.
        val_metrics: Optional validation metrics inherited from ``NcModule``.
        test_metrics: Optional test metrics inherited from ``NcModule``.
        lr: Learning rate for the optimizer. Defaults to ``0.001``.
    """

    def __init__(
        self,
        classifier_config: MLPNcConfig,
        loss_fn: nn.Module | None = None,
        lr: float = 0.001,
        metrics: MetricCollection | None = None,
        metrics_log_kwargs: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize the MLP NC module.

        Args:
            classifier_config: Configuration for the MLP classifier.
            loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
            lr: Learning rate for the optimizer. Defaults to ``0.001``.
            metrics: Optional metric collection for evaluation. Defaults to ``None``.
            metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
                Useful for configuring distributed synchronization behavior
                of ``torchmetrics``. Defaults to ``None``.
        """
        classifier = MLP(
            in_channels=classifier_config["in_channels"],
            hidden_channels=classifier_config.get("hidden_channels"),
            out_channels=classifier_config["out_channels"],
            num_layers=classifier_config.get("num_layers", 1),
            activation_fn=classifier_config.get("activation_fn"),
            activation_fn_kwargs=classifier_config.get("activation_fn_kwargs"),
            normalization_fn=classifier_config.get("normalization_fn"),
            normalization_fn_kwargs=classifier_config.get("normalization_fn_kwargs"),
            bias=classifier_config.get("bias", True),
            drop_rate=classifier_config.get("drop_rate", 0.0),
        )

        super().__init__(
            classifier=classifier,
            loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
            metrics=metrics,
            metrics_log_kwargs=metrics_log_kwargs,
        )

        self.lr: float = lr

    def forward(self, x: Tensor) -> Tensor:
        """
        Predict node-class logits from node features.

        Examples:
            Given 4 nodes with 3 features each and 2 output classes:
                >>> x = [[0.1, 0.2, 0.3],   # node 0
                ...      [0.4, 0.5, 0.6],   # node 1
                ...      [0.7, 0.8, 0.9],   # node 2
                ...      [1.0, 1.1, 1.2]]   # node 3

            The forward pass maps each node to one row of class logits:
                >>> logits = model.forward(x)
                >>> logits.shape
                torch.Size([4, 2])

        Args:
            x: Node feature matrix of shape ``(num_nodes, in_channels)``.

        Returns:
            logits: Node-class logits of shape ``(num_nodes, num_classes)``.
        """
        return self.classifier(x)

    def training_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a training step.

        Args:
            batch: Training batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Training loss.
        """
        return self.__eval_step(batch, Stage.TRAIN)

    def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a validation step.

        Args:
            batch: Validation batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Validation loss.
        """
        return self.__eval_step(batch, Stage.VAL)

    def test_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Run a test step.

        Args:
            batch: Test batch.
            batch_idx: Batch index, unused.

        Returns:
            loss: Test loss.
        """
        return self.__eval_step(batch, Stage.TEST)

    def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
        """
        Predict node-class logits for a batch.

        Args:
            batch: Prediction batch.
            batch_idx: Batch index, unused.

        Returns:
            logits: Predicted node-class logits.
        """
        return self.forward(batch.x)

    def configure_optimizers(self) -> optim.Adam:
        """
        Configure the optimizer.

        Returns:
            optimizer: Adam optimizer.
        """
        return optim.Adam(self.parameters(), lr=self.lr)

    def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
        """
        Run shared evaluation logic for a stage.

        Args:
            batch: Input batch.
            stage: Current evaluation stage.

        Returns:
            loss: Computed loss.
        """
        logits = self.forward(batch.x)
        target_logits, target_labels = self._target_logits_and_labels(logits, batch)
        batch_size = int(target_labels.size(0))

        loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
        self._compute_metrics(target_logits, target_labels, batch_size, stage)
        return loss

__init__(classifier_config, loss_fn=None, lr=0.001, metrics=None, metrics_log_kwargs=None)

Initialize the MLP NC module.

Parameters:

Name Type Description Default
classifier_config MLPNcConfig

Configuration for the MLP classifier.

required
loss_fn Module | None

Optional loss function. Defaults to CrossEntropyLoss.

None
lr float

Learning rate for the optimizer. Defaults to 0.001.

0.001
metrics MetricCollection | None

Optional metric collection for evaluation. Defaults to None.

None
metrics_log_kwargs dict[str, Any] | None

Additional keyword arguments passed to metric log calls. Useful for configuring distributed synchronization behavior of torchmetrics. Defaults to None.

None
Source code in hypertorch/nc/mlp_nc.py
def __init__(
    self,
    classifier_config: MLPNcConfig,
    loss_fn: nn.Module | None = None,
    lr: float = 0.001,
    metrics: MetricCollection | None = None,
    metrics_log_kwargs: dict[str, Any] | None = None,
) -> None:
    """
    Initialize the MLP NC module.

    Args:
        classifier_config: Configuration for the MLP classifier.
        loss_fn: Optional loss function. Defaults to ``CrossEntropyLoss``.
        lr: Learning rate for the optimizer. Defaults to ``0.001``.
        metrics: Optional metric collection for evaluation. Defaults to ``None``.
        metrics_log_kwargs: Additional keyword arguments passed to metric log calls.
            Useful for configuring distributed synchronization behavior
            of ``torchmetrics``. Defaults to ``None``.
    """
    classifier = MLP(
        in_channels=classifier_config["in_channels"],
        hidden_channels=classifier_config.get("hidden_channels"),
        out_channels=classifier_config["out_channels"],
        num_layers=classifier_config.get("num_layers", 1),
        activation_fn=classifier_config.get("activation_fn"),
        activation_fn_kwargs=classifier_config.get("activation_fn_kwargs"),
        normalization_fn=classifier_config.get("normalization_fn"),
        normalization_fn_kwargs=classifier_config.get("normalization_fn_kwargs"),
        bias=classifier_config.get("bias", True),
        drop_rate=classifier_config.get("drop_rate", 0.0),
    )

    super().__init__(
        classifier=classifier,
        loss_fn=loss_fn if loss_fn is not None else nn.CrossEntropyLoss(),
        metrics=metrics,
        metrics_log_kwargs=metrics_log_kwargs,
    )

    self.lr: float = lr

forward(x)

Predict node-class logits from node features.

Examples:

Given 4 nodes with 3 features each and 2 output classes: >>> x = [[0.1, 0.2, 0.3], # node 0 ... [0.4, 0.5, 0.6], # node 1 ... [0.7, 0.8, 0.9], # node 2 ... [1.0, 1.1, 1.2]] # node 3

The forward pass maps each node to one row of class logits: >>> logits = model.forward(x) >>> logits.shape torch.Size([4, 2])

Parameters:

Name Type Description Default
x Tensor

Node feature matrix of shape (num_nodes, in_channels).

required

Returns:

Name Type Description
logits Tensor

Node-class logits of shape (num_nodes, num_classes).

Source code in hypertorch/nc/mlp_nc.py
def forward(self, x: Tensor) -> Tensor:
    """
    Predict node-class logits from node features.

    Examples:
        Given 4 nodes with 3 features each and 2 output classes:
            >>> x = [[0.1, 0.2, 0.3],   # node 0
            ...      [0.4, 0.5, 0.6],   # node 1
            ...      [0.7, 0.8, 0.9],   # node 2
            ...      [1.0, 1.1, 1.2]]   # node 3

        The forward pass maps each node to one row of class logits:
            >>> logits = model.forward(x)
            >>> logits.shape
            torch.Size([4, 2])

    Args:
        x: Node feature matrix of shape ``(num_nodes, in_channels)``.

    Returns:
        logits: Node-class logits of shape ``(num_nodes, num_classes)``.
    """
    return self.classifier(x)

training_step(batch, batch_idx)

Run a training step.

Parameters:

Name Type Description Default
batch HData

Training batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Training loss.

Source code in hypertorch/nc/mlp_nc.py
def training_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a training step.

    Args:
        batch: Training batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Training loss.
    """
    return self.__eval_step(batch, Stage.TRAIN)

validation_step(batch, batch_idx)

Run a validation step.

Parameters:

Name Type Description Default
batch HData

Validation batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Validation loss.

Source code in hypertorch/nc/mlp_nc.py
def validation_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a validation step.

    Args:
        batch: Validation batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Validation loss.
    """
    return self.__eval_step(batch, Stage.VAL)

test_step(batch, batch_idx)

Run a test step.

Parameters:

Name Type Description Default
batch HData

Test batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
loss Tensor

Test loss.

Source code in hypertorch/nc/mlp_nc.py
def test_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Run a test step.

    Args:
        batch: Test batch.
        batch_idx: Batch index, unused.

    Returns:
        loss: Test loss.
    """
    return self.__eval_step(batch, Stage.TEST)

predict_step(batch, batch_idx)

Predict node-class logits for a batch.

Parameters:

Name Type Description Default
batch HData

Prediction batch.

required
batch_idx int

Batch index, unused.

required

Returns:

Name Type Description
logits Tensor

Predicted node-class logits.

Source code in hypertorch/nc/mlp_nc.py
def predict_step(self, batch: HData, batch_idx: int) -> Tensor:
    """
    Predict node-class logits for a batch.

    Args:
        batch: Prediction batch.
        batch_idx: Batch index, unused.

    Returns:
        logits: Predicted node-class logits.
    """
    return self.forward(batch.x)

configure_optimizers()

Configure the optimizer.

Returns:

Name Type Description
optimizer Adam

Adam optimizer.

Source code in hypertorch/nc/mlp_nc.py
def configure_optimizers(self) -> optim.Adam:
    """
    Configure the optimizer.

    Returns:
        optimizer: Adam optimizer.
    """
    return optim.Adam(self.parameters(), lr=self.lr)

__eval_step(batch, stage)

Run shared evaluation logic for a stage.

Parameters:

Name Type Description Default
batch HData

Input batch.

required
stage Stage

Current evaluation stage.

required

Returns:

Name Type Description
loss Tensor

Computed loss.

Source code in hypertorch/nc/mlp_nc.py
def __eval_step(self, batch: HData, stage: Stage) -> Tensor:
    """
    Run shared evaluation logic for a stage.

    Args:
        batch: Input batch.
        stage: Current evaluation stage.

    Returns:
        loss: Computed loss.
    """
    logits = self.forward(batch.x)
    target_logits, target_labels = self._target_logits_and_labels(logits, batch)
    batch_size = int(target_labels.size(0))

    loss = self._compute_loss(target_logits, target_labels, batch_size, stage)
    self._compute_metrics(target_logits, target_labels, batch_size, stage)
    return loss

MLPNcConfig

Bases: TypedDict

Configuration for the MLP classifier in MLPNcModule.

Attributes:

Name Type Description
in_channels int

Number of input features per node.

out_channels int

Number of node classes.

num_layers NotRequired[int]

Number of layers in the MLP classifier.

hidden_channels NotRequired[int | None]

Optional number of hidden units per layer. If None, no hidden layers are used and the classifier is a simple linear layer.

activation_fn NotRequired[ActivationFn | None]

Optional activation function class to use in the MLP classifier. If None, no activation function is applied.

activation_fn_kwargs NotRequired[dict | None]

Optional dictionary of keyword arguments to pass to the activation function constructor.

normalization_fn NotRequired[NormalizationFn | None]

Optional normalization function class to use in the MLP classifier. If None, no normalization is applied.

normalization_fn_kwargs NotRequired[dict | None]

Optional dictionary of keyword arguments to pass to the normalization function constructor.

bias NotRequired[bool]

Whether to include bias terms in the MLP layers. Defaults to True.

drop_rate NotRequired[float]

Dropout rate to apply after each MLP layer except the last one. Defaults to 0.0.

Source code in hypertorch/nc/mlp_nc.py
class MLPNcConfig(TypedDict):
    """
    Configuration for the MLP classifier in ``MLPNcModule``.

    Attributes:
        in_channels: Number of input features per node.
        out_channels: Number of node classes.
        num_layers: Number of layers in the MLP classifier.
        hidden_channels: Optional number of hidden units per layer. If ``None``, no hidden layers
            are used and the classifier is a simple linear layer.
        activation_fn: Optional activation function class to use in the MLP classifier.
            If ``None``, no activation function is applied.
        activation_fn_kwargs: Optional dictionary of keyword arguments to pass to the activation
            function constructor.
        normalization_fn: Optional normalization function class to use in the MLP classifier.
            If ``None``, no normalization is applied.
        normalization_fn_kwargs: Optional dictionary of keyword arguments to pass to the
            normalization function constructor.
        bias: Whether to include bias terms in the MLP layers. Defaults to ``True``.
        drop_rate: Dropout rate to apply after each MLP layer except the last one.
            Defaults to ``0.0``.
    """

    in_channels: int
    out_channels: int
    num_layers: NotRequired[int]
    hidden_channels: NotRequired[int | None]
    activation_fn: NotRequired[ActivationFn | None]
    activation_fn_kwargs: NotRequired[dict | None]
    normalization_fn: NotRequired[NormalizationFn | None]
    normalization_fn_kwargs: NotRequired[dict | None]
    bias: NotRequired[bool]
    drop_rate: NotRequired[float]