utils.train_loop#
Training and evaluation loops for BRIDGE-style binary classification.
This module contains thin PyTorch training/validation utilities used by the BRIDGE pipeline. It implements:
train(): One-epoch training loop with gradient clipping and running metric aggregation.validate(): Evaluation loop that returns dataset-level metrics plus concatenated labels/probabilities.validate2(): Inference-only loop that returns probabilities (sigmoid applied), no labels required.validate_without_sigmoid(): Inference-only loop that returns raw outputs (no sigmoid), useful for logits or already-probabilistic models.
Who this module is for#
Users training BRIDGE (or BRIDGE-compatible) binary classifiers.
Developers who want a simple, reproducible training loop consistent with the paper/repo.
Model I/O contract#
The functions here assume the model signature is:
logits = model(x, attn, s, motif, plfold)
where each input is batch-first (B is batch size). The model output is assumed to be
a logit (or logit-like score) per sample.
Expected output shape:
(B,)or(B, 1)Probabilities are computed as
torch.sigmoid(logits)when metrics are computed.
If your model already outputs probabilities, prefer validate_without_sigmoid()
(or adjust this module to avoid applying sigmoid twice).
DataLoader batch conventions#
Two batch formats are supported depending on the function:
- Training / labeled evaluation (
train(),validate()) Each batch from the loader must be a 6-tuple:
(x0, x00, x000, x0000, x00000, y0)
with the following semantics:
x0 -> x : Transformer / RBPformer features x00 -> attn : attention / adjacency-like tensor (for graph branch) x000 -> s : structure tensor x0000 -> motif : motif tensor x00000 -> plfold : biochemical features tensor y0 -> y : binary labels (0/1)
- Inference only (
validate2(),validate_without_sigmoid()) Each batch must be a 5-tuple (no labels):
(x0, x00, x000, x0000, x00000)
Tensor dtypes and device placement#
All inputs are converted to float and moved to device. Labels are moved to
device and cast to float for loss computation. For metrics, labels are converted to
CPU integer arrays and predictions to CPU float arrays.
Metrics#
Metrics are computed via utils.metrics.MLMetrics with objective="binary".
Internally, this uses:
prob = sigmoid(logits)
and computes accuracy / ROC-AUC / PR-AUC / F1 / MCC plus confusion counts.
The training loop calls:
met.update(y_np, p_np, [loss.item()])
so the mean loss for the epoch is tracked as an extra field appended to the metric vector.
Important behavior and caveats#
- Skipping degenerate batches (train only)
train()skips batches where labels are single-class:all-negative:
y0.sum() == 0all-positive:
y0.sum() == batch_size
This means: - those batches do not contribute to optimization updates, - and do not contribute to metric aggregation.
Warning
This behavior is only correct if your training sampling strategy can produce single-class batches and you explicitly want to skip them. If you need every sample to contribute to training, remove this condition or ensure balanced batching.
- Gradient clipping
train()appliestorch.nn.utils.clip_grad_norm_(model.parameters(), 5)each step. Adjust the max-norm if you change optimizer/loss scaling.- Shape alignment
criterion(output, y)must be valid; in practice, ensureyis shaped likeoutput(e.g., both(B, 1)). If your model outputs(B,)but labels are(B, 1), you may want toy = y.view_as(output)(or squeeze) upstream.
Example
from torch.nn import BCEWithLogitsLoss
from torch.optim import Adam
model = BRIDGE(...).to(device)
criterion = BCEWithLogitsLoss()
optimizer = Adam(model.parameters(), lr=1e-4)
# one epoch
met_train = train(model, device, train_loader, criterion, optimizer, batch_size=64)
# evaluation
met_val, y_val, p_val = validate(model, device, val_loader, criterion)
# inference only
p_test = validate2(model, device, test_loader_no_labels, criterion)
Functions
|
Train one epoch and accumulate binary classification metrics. |
|
Evaluate a binary classifier and return metrics, labels, and probabilities. |
|
Run inference and return predicted probabilities only (no labels). |
|
Run inference and return raw model outputs (no sigmoid applied). |
- utils.train_loop.train(model, device, train_loader, criterion, optimizer, batch_size)[source]#
Train one epoch and accumulate binary classification metrics.
This function runs a standard PyTorch training loop over
train_loader: forward -> loss -> backward -> gradient clipping -> optimizer step. Metrics are tracked viautils.metrics.MLMetrics(objective="binary").- Parameters:
model (torch.nn.Module) – Model callable with signature
model(x, attn, s, motif, plfold)returning logits.device (torch.device) – Target device used to move tensors and model.
train_loader (torch.utils.data.DataLoader) – Iterable over training batches, each yielding the 6-tuple described above.
criterion (callable) – Loss function. Common choice is
torch.nn.BCEWithLogitsLosswhen outputs are logits.optimizer (torch.optim.Optimizer) – Optimizer for updating model parameters.
batch_size (int) – Expected batch size used for detecting all-positive/all-negative batches.
- Returns:
utils.metrics.MLMetrics Metric accumulator updated over all non-skipped batches. Contains aggregated binary-classification metrics and mean loss (as passed via
met.update).
Notes
Expected batch format
Each batch from
train_loadermust be a 6-tuple:(x0, x00, x000, x0000, x00000, y0)
Semantics (names used inside this function):
x0->x: RBPformer feature tensorx00->attn: attention / adjacency-like tensorx000->s: structural tensorx0000->motif: motif tensorx00000->plfold: biochemical tensory0->y: binary labels (0/1)
Tensor conventions
Batch dimension is the first axis for all inputs:
(B, ...).Model returns logits of shape
(B,)or(B, 1).criterion(output, y)must be valid (e.g.,BCEWithLogitsLosswith matching shapes).Probabilities for metrics are computed as
torch.sigmoid(output).
Special handling
Degenerate batches are skipped:
all-negative:
y0.sum() == 0all-positive:
y0.sum() == batch_size
This avoids metric updates and optimization steps on single-class batches.
- utils.train_loop.validate(model, device, test_loader, criterion)[source]#
Evaluate a binary classifier and return metrics, labels, and probabilities.
Runs the model in evaluation mode over
test_loader, collecting: - concatenated labelsy_all- concatenated probabilitiesp_all(computed assigmoid(logits)) - mean loss across batches- Parameters:
model (torch.nn.Module) – Model callable with signature
model(x, attn, s, motif, plfold)returning logits.device (torch.device) – Target device.
test_loader (torch.utils.data.DataLoader) – Iterable over evaluation batches.
criterion (callable) – Loss function compatible with logits and labels.
- Returns:
- -met (
MLMetrics) Metric accumulator updated once with concatenated arrays and mean loss.
- -y_all (
ndarray) Concatenated labels for all samples. Shape typically
(N,)or(N, 1).- -p_all (
ndarray) Concatenated probabilities for all samples. Shape matches
y_all.
- -met (
Notes
Expected batch format
Each batch from
test_loadermust be a 6-tuple:(x0, x00, x000, x0000, x00000, y0)
Semantics:
x0->x: RBPformer feature tensorx00->attn: attention / adjacency-like tensorx000->s: structural tensorx0000->motif: motif tensorx00000->plfold: biochemical tensory0->y: binary labels (0/1)
Tensor conventions
Model returns logits; probabilities are computed as
torch.sigmoid(output).Arrays are concatenated along the first axis to produce dataset-level outputs.
- utils.train_loop.validate2(model, device, test_loader, criterion)[source]#
Run inference and return predicted probabilities only (no labels).
This function assumes
test_loaderyields inputs only (noy0) and returns concatenated probabilities computed astorch.sigmoid(logits).- Parameters:
model (torch.nn.Module) – Model callable with signature
model(x, attn, s, motif, plfold)returning logits.device (torch.device) – Target device.
test_loader (torch.utils.data.DataLoader) – Iterable over inference batches (no labels).
criterion (callable) – Unused. Kept for API compatibility with other validation functions.
- Returns:
np.ndarray Concatenated probabilities for all samples. Shape typically
(N,)or(N, 1).
Notes
Expected batch format
Each batch from
test_loadermust be a 5-tuple:(x0, x00, x000, x0000, x00000)
Semantics:
x0->x: RBPformer feature tensorx00->attn: attention / adjacency-like tensorx000->s: structural tensorx0000->motif: motif tensorx00000->plfold: biochemical tensor
- utils.train_loop.validate_without_sigmoid(model, device, test_loader, criterion)[source]#
Run inference and return raw model outputs (no sigmoid applied).
This function is identical to
validate2()except it returns the raw model outputs directly (i.e., notorch.sigmoid). This is useful when downstream code wants logits, applies custom transformations, or when the model already outputs probabilities.- Parameters:
model (torch.nn.Module) – Model callable with signature
model(x, attn, s, motif, plfold)returning raw outputs.device (torch.device) – Target device.
test_loader (torch.utils.data.DataLoader) – Iterable over inference batches.
criterion (callable) – Unused. Kept for API compatibility.
- Returns:
np.ndarray Concatenated raw outputs for all samples. Shape typically
(N,)or(N, 1).
Notes
Expected batch format
Each batch from
test_loadermust be a 5-tuple:(x0, x00, x000, x0000, x00000)
Semantics:
x0->x: RBPformer feature tensorx00->attn: attention / adjacency-like tensorx000->s: structural tensorx0000->motif: motif tensorx00000->plfold: biochemical tensor