code: def train(model, dataset, device):
      dataloader = create_dataloader(dataset, device)
      optimizer = torch.optim.Adam(model.parameters(), lr=1e-2)
  
      for epoch in range(10):
          model.train()
          total_loss = 0
          ########################################################################
          # (HIGHLIGHT) Iterate over the dataloader and train the model with all
          # mini-batches.
          ########################################################################
          for step, data in enumerate(dataloader):
              # Get node pairs with labels for loss calculation.
              compacted_pairs, labels = data.node_pairs_with_labels
  
              # The features of sampled nodes.
              x = data.node_features["feat"]
  
              # Forward.
              y = model(data.blocks, x)
              logits = model.predictor(
                  y[compacted_pairs[0].long()]
                  * y[compacted_pairs[1].long()]
              ).squeeze()
  
              # Compute loss.
              loss = F.binary_cross_entropy_with_logits(
                  logits, labels.float()
              )
  
              # Backward.
              optimizer.zero_grad()
              loss.backward()
              optimizer.step()
  
              total_loss += loss.item()
  
          print(
              f"Epoch {epoch:03d} | Loss {total_loss / (step + 1):.3f}"
          )
  
file_path: dgl/examples/sampling/graphbolt/quickstart/link_prediction.py
imports: import dgl.graphbolt
  import torch
  import torch.nn
  import torch.nn.functional
  from dgl.nn import SAGEConv
  from torcheval.metrics import BinaryAUROC
label_desc: Use image node_id 3 for calling a global function with example usage: train(model, dataset, device) without return types