def loop(data_loader, model, optimizer, scheduler, device):
    batch_size = data_loader.batch_size
    data_loader = (tqdm(data_loader) if (optimizer is not None) else data_loader)
    (loss_sum, y_true, y_pred) = (0.0, list(), list())
    for batch in data_loader:
        (smiles, mols, batch_node_features, batch_edge_features, batch_distance_matrix, labels) = batch
        batch_masks = (torch.sum(torch.abs(batch_node_features), dim=(- 1)) != 0)
        batch_node_features = batch_node_features.to(device)
        batch_edge_features = batch_edge_features.to(device)
        batch_distance_matrix = batch_distance_matrix.to(device)
        batch_masks = batch_masks.to(device)
        labels = labels.to(device)
        outputs = model(batch_node_features, batch_edge_features, batch_distance_matrix, batch_masks, device)
        loss = cal_loss(y_true=labels, y_pred=outputs, device=device)
        loss_sum += loss.item()
        if (optimizer is not None):
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        if (scheduler is not None):
            scheduler.step()
        labels = labels.detach().cpu().numpy()
        outputs = outputs.detach().cpu().numpy()
        y_true.append([])
        y_pred.append([])
        for (label, output) in zip(labels, outputs):
            (label, output) = (label.flatten(), output.flatten())
            for (l, o) in zip(label, output):
                if (l != 0.0):
                    y_true[(- 1)].append(l)
                    y_pred[(- 1)].append(o)
        torch.cuda.empty_cache()
    results = cal_metric(y_true=y_true, y_pred=y_pred)
    results['loss'] = (loss_sum / (len(data_loader) * batch_size))
    return results
def loop(data_loader, model, optimizer, scheduler, device):
    batch_size = data_loader.batch_size
    data_loader = (tqdm(data_loader) if (optimizer is not None) else data_loader)
    (loss_sum, y_true, y_pred) = (0.0, list(), list())
    for batch in data_loader:
        (smiles, mols, batch_node_features, batch_edge_features, batch_distance_matrix, labels) = batch
        batch_masks = (torch.sum(torch.abs(batch_node_features), dim=(- 1)) != 0)
        batch_node_features = batch_node_features.to(device)
        batch_edge_features = batch_edge_features.to(device)
        batch_distance_matrix = batch_distance_matrix.to(device)
        batch_masks = batch_masks.to(device)
        labels = labels.to(device)
        outputs = model(batch_node_features, batch_edge_features, batch_distance_matrix, batch_masks, device)
        loss = cal_loss(y_true=labels, y_pred=outputs, device=device)
        loss_sum += loss.item()
        if (optimizer is not None):
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        if (scheduler is not None):
            scheduler.step()
        labels = labels.detach().cpu().numpy()
        outputs = outputs.detach().cpu().numpy()
        y_true.append([])
        y_pred.append([])
        for (label, output) in zip(labels, outputs):
            (label, output) = (label.flatten(), output.flatten())
            for (l, o) in zip(label, output):
                if (l != 0.0):
                    y_true[(- 1)].append(l)
                    y_pred[(- 1)].append(o)
        torch.cuda.empty_cache()
    results = cal_metric(y_true=y_true, y_pred=y_pred)
    results['loss'] = (loss_sum / (len(data_loader) * batch_size))
    return results