### Install IMDL-BenCo Source: https://github.com/scu-zjz/imdlbenco/blob/main/README.md Use pip to install the library from PyPI. ```bash pip install imdlbenco ``` -------------------------------- ### Verify Installation Source: https://github.com/scu-zjz/imdlbenco/blob/main/README.md Check the installed version of the library using CLI commands. ```bash benco -v ``` ```bash benco --version ``` -------------------------------- ### Define a Custom Model with IMDLBenCo Registry Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Example of creating a custom PyTorch model registered with the IMDLBenCo MODELS registry. It includes a standard forward pass and loss computation, adhering to the framework's output interface. Requires `torch` and `torch.nn`. ```python from IMDLBenCo.registry import MODELS import torch import torch.nn as nn @MODELS.register_module() class MyCustomModel(nn.Module): def __init__(self, my_param: int, # Custom parameters auto-parsed by argparser pretrain_path: str = None): super().__init__() self.encoder = nn.Sequential( nn.Conv2d(3, 64, 3, padding=1), nn.ReLU(), nn.Conv2d(64, 64, 3, padding=1), nn.ReLU() ) self.decoder = nn.Conv2d(64, 1, 1) self.classifier = nn.AdaptiveAvgPool2d(1) self.loss_fn = nn.BCEWithLogitsLoss() def forward(self, image, mask, label, edge_mask=None, *args, **kwargs): # Forward pass features = self.encoder(image) pred_mask = self.decoder(features) pred_label = self.classifier(torch.sigmoid(pred_mask)).squeeze() # Compute losses mask_loss = self.loss_fn(pred_mask, mask) label_loss = nn.BCELoss()(pred_label, label.float()) total_loss = mask_loss + 0.1 * label_loss # Required output format return { # Required: loss for backward pass "backward_loss": total_loss, # Required: predicted mask (will auto-compute pixel metrics) "pred_mask": torch.sigmoid(pred_mask), # Required: predicted label (None if model doesn't predict labels) "pred_label": pred_label, # Optional: losses for visualization in TensorBoard "visual_loss": { "mask_loss": mask_loss, "label_loss": label_loss, "total_loss": total_loss }, # Optional: images/masks for visualization "visual_image": { "pred_mask": torch.sigmoid(pred_mask), "features": features[:, 0:1, :, :] # First channel as heatmap } } # Test the model if __name__ == "__main__": model = MODELS.build("MyCustomModel", my_param=32) x = torch.randn(2, 3, 256, 256) mask = torch.randint(0, 2, (2, 1, 256, 256)).float() label = torch.tensor([1.0, 0.0]) out = model(x, mask, label) print(f"Loss: {out['backward_loss'].item():.4f}") ``` -------------------------------- ### Get Pre-configured Albumentations Transforms Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Retrieves pre-defined augmentation pipelines for training, testing, padding, or resizing. These include various image manipulation and augmentation techniques. ```python from IMDLBenCo.transforms import get_albu_transforms, RandomCopyMove, RandomInpainting, EdgeMaskGenerator import albumentations as albu # Get pre-configured transforms train_transforms = get_albu_transforms(type_='train', output_size=(1024, 1024)) # Includes: RandomScale, RandomCopyMove, RandomInpainting, Flip, # BrightnessContrast, ImageCompression, Rotate, GaussianBlur test_transforms = get_albu_transforms(type_='test', output_size=(1024, 1024)) # Minimal transforms for testing pad_transforms = get_albu_transforms(type_='pad', output_size=(1024, 1024)) # Padding, Normalization, ToTensor resize_transforms = get_albu_transforms(type_='resize', output_size=(512, 512)) # Resize, Normalization, ToTensor ``` -------------------------------- ### Initialize Project via CLI Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Set up a new project environment with templates and scripts. ```bash # Initialize base environment with training scripts and custom model template benco init base # Initialize with model zoo (includes pre-configured run scripts for all models) benco init model_zoo # Initialize with backbone support benco init backbone ``` -------------------------------- ### Execute Training Script Source: https://github.com/scu-zjz/imdlbenco/blob/main/IMDLBenCo/statics/base/README-IMDLBenCo.md Run the training process for the default model. Ensure the dataset is configured according to the project README before execution. ```shell sh train_mymodel.sh ``` -------------------------------- ### Manage Components with Registry Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Use the registry system to register custom models and retrieve existing ones. ```python from IMDLBenCo.registry import Registry, MODELS, DATASETS, POSTFUNCS # View all registered models print(MODELS) # Output: Table showing all registered model names and their classes # Register a custom model using decorator @MODELS.register_module() class MyCustomModel(nn.Module): def __init__(self, param1: int): super().__init__() self.layer = nn.Conv2d(3, 1, 3, padding=1) def forward(self, image, mask, label, *args, **kwargs): pred_mask = self.layer(image) loss = nn.BCEWithLogitsLoss()(pred_mask, mask) return { "backward_loss": loss, "pred_mask": torch.sigmoid(pred_mask), "pred_label": torch.mean(pred_mask, dim=(1,2,3)), "visual_loss": {"loss": loss}, "visual_image": {"pred_mask": pred_mask} } # Retrieve and instantiate a model by name model_class = MODELS.get("IML_ViT") model = model_class(input_size=1024, patch_size=16) # Build model with arguments model = MODELS.build("IML_ViT", input_size=1024, embed_dim=768) # Check if a model is registered if MODELS.has("MVSSNet"): print("MVSSNet is available") ``` -------------------------------- ### Initialize and use CAT-Net Model Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes the CAT-Net model using a configuration file. This model leverages JPEG compression artifacts (DCT coefficients) and RGB features. Requires DCT coefficients and quantization tables as input. ```python from IMDLBenCo import MODELS import torch # Initialize CAT-Net (requires config file) model = MODELS.build( "Cat_Net", cfg_file='/path/to/configs/CAT_full.yaml' ) # CAT-Net requires DCT coefficients and quantization tables image = torch.randn(2, 3, 512, 512) mask = torch.randint(0, 2, (2, 1, 512, 512)).float() DCT_coef = torch.randn(2, 512, 512) # DCT coefficients from JPEG qtables = torch.randn(2, 8, 8) # Quantization tables output = model( image=image, mask=mask, DCT_coef=DCT_coef, qtables=qtables ) # CAT-Net post-processing function for data loading from IMDLBenCo.model_zoo import cat_net_post_func # Use as post_func in dataset to extract JPEG features # Assuming JsonDataset is defined elsewhere # dataset = JsonDataset( # path='/path/to/dataset.json', # is_resizing=True, # output_size=(512, 512), # post_funcs=[cat_net_post_func] # Adds DCT_coef and qtables to data_dict # ) ``` -------------------------------- ### Distributed Training Script for IML-ViT Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Shell script to initiate distributed training for the IML-ViT model using `torchrun`. It configures visible CUDA devices, node/process counts, and various training parameters including data paths, learning rates, and output directories. Logs are redirected to specified files. ```bash #!/bin/bash # demo_train_iml_vit.sh base_dir="./output_dir" mkdir -p ${base_dir} CUDA_VISIBLE_DEVICES=0,1 \ torchrun \ --standalone \ --nnodes=1 \ --nproc_per_node=2 \ ./train.py \ --model IML_ViT \ --edge_lambda 20 \ --vit_pretrain_path /path/to/mae_pretrain_vit_base.pth \ --world_size 2 \ --batch_size 2 \ --data_path /path/to/CASIA2.0 \ --epochs 200 \ --lr 1e-4 \ --image_size 1024 \ --if_padding \ --min_lr 5e-7 \ --weight_decay 0.05 \ --edge_mask_width 7 \ --test_data_path "/path/to/CASIA1.0" \ --warmup_epochs 2 \ --output_dir ${base_dir}/ \ --log_dir ${base_dir}/ \ --accum_iter 8 \ --seed 42 \ --test_period 4 \ 2> ${base_dir}/error.log 1>${base_dir}/logs.log ``` -------------------------------- ### Initialize TruFor Model for Phase 2 and Phase 3 Training Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes the TruFor model for different training phases. Phase 2 trains the anomaly decoder using Noiseprint++ and MiT-B2 weights. Phase 3 trains the detection head using a checkpoint from Phase 2. ```python from IMDLBenCo import MODELS import torch # Phase 2 training: Anomaly decoder training model = MODELS.build( "Trufor", phase=2, # Phase 2: Train anomaly decoder np_pretrain_weights='/path/to/noiseprint_weights.pth', mit_b2_pretrain_weights='/path/to/mit_b2_weights.pth', config_path='/path/to/configs/trufor.yaml' ) # Phase 3 training: Detection head training model_phase3 = MODELS.build( "Trufor", phase=3, # Phase 3: Train detection head det_resume_ckpt='/path/to/phase2_checkpoint.pth', config_path='/path/to/configs/trufor.yaml' ) # Forward pass (example for Phase 2 model) image = torch.randn(2, 3, 512, 512) mask = torch.randint(0, 2, (2, 1, 512, 512)).float() label = torch.tensor([1, 0]).float() output = model(image=image, mask=mask, label=label) # TruFor provides confidence maps and detection outputs pred_mask = output['pred_mask'] pred_label = output['pred_label'] ``` -------------------------------- ### Execute Testing Scripts Source: https://github.com/scu-zjz/imdlbenco/blob/main/IMDLBenCo/statics/base/README-IMDLBenCo.md Run performance and robustness tests on the saved model. ```shell sh test_mymodel.sh ``` ```shell sh test_robust_mymodel.sh ``` -------------------------------- ### Initialize and use SparseViT Model Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes the SparseViT model, which constructs non-semantic feature extractors via self-supervised sparse attention. The backbone can also be used separately. ```python from IMDLBenCo import MODELS import torch # Initialize SparseViT model = MODELS.build("SparseViT") # Or use the backbone separately backbone = MODELS.build("SparseViTBackbone") # Forward pass image = torch.randn(2, 3, 512, 512) mask = torch.randint(0, 2, (2, 1, 512, 512)).float() output = model(image=image, mask=mask) ``` -------------------------------- ### Initialize and use MVSSNet Model Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes the MVSSNet model with specified parameters for dual-branch architecture, Sobel edge detection, and image-level classification. Use for combined mask and label prediction. ```python from IMDLBenCo import MODELS import torch # Initialize MVSS-Net model = MODELS.build( "MVSSNet", nclass=1, aux=False, sobel=True, # Use Sobel edge detection if_label=True, # Include image-level classification loss constrain=True, # Use Bayar constraint for noise extraction n_input=3, pretrained_base=True ) # Prepare inputs image = torch.randn(2, 3, 512, 512) mask = torch.randint(0, 2, (2, 1, 512, 512)).float() edge_mask = torch.randint(0, 2, (2, 1, 512, 512)).float() label = torch.tensor([1, 0]).float() # Image-level labels # Forward pass output = model( image=image, mask=mask, edge_mask=edge_mask, label=label ) # MVSS-Net provides both mask and label predictions pred_mask = output['pred_mask'] # [B, 1, H, W] pred_label = output['pred_label'] # [B] - Image-level prediction loss = output['backward_loss'] # Individual losses for monitoring print(output['visual_loss']['predict_loss']) # Segmentation loss print(output['visual_loss']['edge_loss']) # Edge detection loss print(output['visual_loss']['label_loss']) # Classification loss ``` -------------------------------- ### Testing Script for IML-ViT with Checkpoint Loading Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Shell script to run testing for the IML-ViT model, including loading a specified checkpoint. It configures CUDA devices, distributed settings, and paths to test data and checkpoints. Output logs are redirected. ```bash #!/bin/bash # demo_test_iml_vit.sh base_dir="./eval_dir" mkdir -p ${base_dir} CUDA_VISIBLE_DEVICES=0 \ torchrun \ --standalone \ --nnodes=1 \ --nproc_per_node=1 \ ./test.py \ --model IML_ViT \ --edge_mask_width 7 \ --world_size 1 \ --test_data_json "./test_datasets.json" \ --checkpoint_path "/path/to/checkpoint.pth" \ --test_batch_size 1 \ --image_size 1024 \ --if_padding \ --output_dir ${base_dir}/ \ --log_dir ${base_dir}/ \ 2> ${base_dir}/error.log 1>${base_dir}/logs.log ``` -------------------------------- ### Create Custom Augmentation Pipeline Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Builds a custom augmentation pipeline using Albumentations, incorporating specific transforms like RandomCopyMove and RandomInpainting. Set probabilities and parameters for each transform. ```python from IMDLBenCo.transforms import get_albu_transforms, RandomCopyMove, RandomInpainting, EdgeMaskGenerator import albumentations as albu # Custom augmentation pipeline with copy-move custom_transforms = albu.Compose([ RandomCopyMove( max_h=0.8, # Max copy region height (ratio) max_w=0.8, # Max copy region width (ratio) min_h=0.05, # Min copy region height (ratio) min_w=0.05, # Min copy region width (ratio) mask_value=255, # Value for manipulated region in mask p=0.3 # Probability ), RandomInpainting( max_h=0.5, max_w=0.5, p=0.2 ), albu.HorizontalFlip(p=0.5), albu.RandomBrightnessContrast(p=0.5), ]) ``` -------------------------------- ### Initialize IML-ViT Model Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Builds the IML-ViT model, a Vision Transformer for image manipulation localization. Configure input size, patch size, embedding dimensions, pre-trained weights, FPN settings, and loss weights. ```python import torch from IMDLBenCo import MODELS # Initialize IML-ViT model model = MODELS.build( "IML_ViT", input_size=1024, patch_size=16, embed_dim=768, vit_pretrain_path='/path/to/mae_pretrain_vit_base.pth', fpn_channels=256, fpn_scale_factors=(4.0, 2.0, 1.0, 0.5), mlp_embeding_dim=256, predict_head_norm="BN", # Options: "BN", "IN", "LN" edge_lambda=20 # Weight for edge loss ) ``` -------------------------------- ### Load Dataset with JsonDataset Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes JsonDataset from a JSON configuration file. Supports image-mask path pairs and negative samples. Use with DataLoader for batch processing. ```python from IMDLBenCo.datasets import JsonDataset # JSON file format example (balanced_dataset.json): # [ # ["/path/to/Tp/image1.jpg", "/path/to/Gt/mask1.png"], # ["/path/to/Tp/image2.jpg", "/path/to/Gt/mask2.png"], # ["/path/to/authentic.jpg", "Negative"] # Authentic image, no manipulation # ] # Initialize from JSON configuration dataset = JsonDataset( path='/path/to/dataset_config.json', is_resizing=True, is_padding=False, output_size=(512, 512), edge_width=7 ) # Iterate through dataset from torch.utils.data import DataLoader dataloader = DataLoader(dataset, batch_size=4, shuffle=True, num_workers=4) for batch in dataloader: images = batch['image'] # [B, 3, H, W] masks = batch['mask'] # [B, 1, H, W] labels = batch['label'] # [B] - 0 or 1 edge_masks = batch.get('edge_mask') # [B, 1, H, W] if edge_width specified break ``` -------------------------------- ### Initialize ImageF1 Evaluator Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes the ImageF1 evaluator, which computes image-level F1 scores and supports distributed training. Set the threshold for classification. ```python from IMDLBenCo.evaluation import ImageF1 import torch # Initialize evaluator evaluator = ImageF1(threshold=0.5) ``` -------------------------------- ### Initialize and use Mesorch Model Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes the Mesorch model, which uses a parallel CNN+Transformer architecture. Use for handling image semantics and non-semantic forensic features simultaneously. ```python from IMDLBenCo import MODELS import torch # Initialize Mesorch model = MODELS.build("Mesorch") # Standard forward pass image = torch.randn(2, 3, 512, 512) mask = torch.randint(0, 2, (2, 1, 512, 512)).float() edge_mask = torch.randint(0, 2, (2, 1, 512, 512)).float() output = model(image=image, mask=mask, edge_mask=edge_mask) pred_mask = output['pred_mask'] loss = output['backward_loss'] ``` -------------------------------- ### Create Balanced Dataset Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Combines multiple datasets with balanced sampling. Can use default paths or a custom JSON configuration. Specify sample number per dataset and epoch. ```python from IMDLBenCo.datasets import BalancedDataset # Using default dataset paths (requires specific directory structure) dataset = BalancedDataset( path=None, # Use default paths sample_number=1840 # Samples per dataset per epoch ) # Using custom JSON configuration # balanced_dataset.json format: # [ # ["ManiDataset", "/path/to/CASIA2.0"], # ["JsonDataset", "/path/to/tampCOCO/sp_COCO_list.json"], # ["JsonDataset", "/path/to/tampCOCO/cm_COCO_list.json"] # ] dataset = BalancedDataset( path='/path/to/balanced_dataset.json', sample_number=2000, is_padding=True, output_size=(1024, 1024), edge_width=7 ) # Print dataset info print(dataset) ``` -------------------------------- ### Load Datasets with ManiDataset Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Load image manipulation datasets from a directory structure containing tampered images and ground truth masks. ```python from IMDLBenCo.datasets import ManiDataset from IMDLBenCo.transforms import get_albu_transforms # Create common transforms for training augmentation train_transforms = get_albu_transforms(type_='train', output_size=(1024, 1024)) # Initialize dataset with padding (preserves aspect ratio) dataset = ManiDataset( path='/path/to/dataset', # Must contain Tp/ and Gt/ subdirectories is_padding=True, # Pad images to output_size is_resizing=False, # Don't resize (mutually exclusive with padding) output_size=(1024, 1024), # Target output size common_transforms=train_transforms, # Augmentation transforms edge_width=7, # Generate edge masks with this width img_loader=pil_loader # Image loading function ) # Access dataset samples sample = dataset[0] print(f"Image shape: {sample['image'].shape}") # torch.Tensor [3, H, W] print(f"Mask shape: {sample['mask'].shape}") # torch.Tensor [1, H, W] print(f"Label: {sample['label']}") # 0 (authentic) or 1 (manipulated) print(f"Original shape: {sample['origin_shape']}") # Original image dimensions print(f"Name: {sample['name']}") # Image filename # With padding, shape_mask indicates valid pixel regions if 'shape_mask' in sample: print(f"Shape mask: {sample['shape_mask'].shape}") # [1, H, W] # Dataset info print(dataset) # [ManiDataset] at /path/to/dataset, with length of 1,234 ``` -------------------------------- ### Initialize and Use PixelF1 Evaluator Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Computes pixel-level F1 scores for manipulation masks with support for origin, reverse, and double modes. ```python from IMDLBenCo.evaluation import PixelF1 import torch # Initialize with different modes evaluator_origin = PixelF1(threshold=0.5, mode="origin") # Standard F1 evaluator_reverse = PixelF1(threshold=0.5, mode="reverse") # Reversed prediction evaluator_double = PixelF1(threshold=0.5, mode="double") # Max of both # Batch update returns per-image F1 scores pred_mask = torch.sigmoid(model_output['pred_mask']) # [B, 1, H, W] gt_mask = batch['mask'] # [B, 1, H, W] shape_mask = batch.get('shape_mask') # [B, 1, H, W] for padded images # Get F1 for each image in batch f1_scores = evaluator_origin.batch_update( predict=pred_mask, mask=gt_mask, shape_mask=shape_mask # Optional: masks out padded regions ) print(f"Per-image F1 scores: {f1_scores}") # Tensor of shape [B] # Compute mean F1 over batch mean_f1 = f1_scores.mean() ``` -------------------------------- ### Initialize and Use PixelIOU Evaluator Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Computes Intersection over Union for manipulation mask predictions. ```python from IMDLBenCo.evaluation import PixelIOU import torch # Initialize with mode evaluator = PixelIOU(threshold=0.5, mode="origin") # "origin", "reverse", "double" # Compute per-image IOU pred_mask = torch.sigmoid(model_output['pred_mask']) gt_mask = batch['mask'] iou_scores = evaluator.batch_update( predict=pred_mask, mask=gt_mask, shape_mask=batch.get('shape_mask') ) mean_iou = iou_scores.mean() print(f"Mean Pixel IOU: {mean_iou:.4f}") ``` -------------------------------- ### Initialize and Use PixelAUC Evaluator Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Computes pixel-level AUC for manipulation masks, returning 0.0 for authentic images with all-zero masks. ```python from IMDLBenCo.evaluation import PixelAUC import torch # Initialize with mode options evaluator = PixelAUC(threshold=0.5, mode="origin") # "origin", "reverse", or "double" # Compute per-image AUC pred_mask = model_output['pred_mask'] # [B, 1, H, W] gt_mask = batch['mask'] # [B, 1, H, W] shape_mask = batch.get('shape_mask') # Optional # Returns AUC for each image auc_scores = evaluator.batch_update( predict=pred_mask, mask=gt_mask, shape_mask=shape_mask ) print(f"Per-image AUC: {auc_scores}") # Tensor [B] # Note: Returns 0.0 for images with all-zero masks (authentic images) # Filter these when computing mean if needed valid_auc = auc_scores[gt_mask.sum(dim=(1,2,3)) > 0] mean_auc = valid_auc.mean() ``` -------------------------------- ### IML-ViT Model Forward Pass Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Performs a forward pass with the IML-ViT model. Requires input image, ground truth mask, and optionally an edge mask. Outputs model predictions. ```python import torch from IMDLBenCo import MODELS # Forward pass image = torch.randn(2, 3, 1024, 1024) # [B, C, H, W] mask = torch.randint(0, 2, (2, 1, 1024, 1024)).float() # Ground truth edge_mask = torch.randint(0, 2, (2, 1, 1024, 1024)).float() # Edge mask output = model(image=image, mask=mask, edge_mask=edge_mask) ``` -------------------------------- ### Generate Edge Masks Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Initializes and uses EdgeMaskGenerator to create dilated edge masks from ground truth masks. This is useful for boundary-aware training. ```python from IMDLBenCo.transforms import get_albu_transforms, RandomCopyMove, RandomInpainting, EdgeMaskGenerator import albumentations as albu # Edge mask generator for boundary-aware training edge_generator = EdgeMaskGenerator(edge_width=7) edge_mask = edge_generator(ground_truth_mask) # Returns dilated edge mask ``` -------------------------------- ### Perform Image-level F1 Evaluation Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Updates the evaluator with batch predictions and computes the final F1 score at the end of an epoch. ```python # During training/testing loop for batch in dataloader: pred_labels = model(batch['image'])['pred_label'] # Predicted probabilities true_labels = batch['label'] # Ground truth (0 or 1) # Update with batch predictions evaluator.batch_update(pred_labels, true_labels) # Handle remaining samples (for uneven batch sizes in distributed setting) evaluator.remain_update(remaining_pred_labels, remaining_true_labels) # Compute final F1 score at epoch end (handles distributed aggregation) f1_score = evaluator.epoch_update() print(f"Image-level F1: {f1_score:.4f}") # Reset for next epoch evaluator.recovery() ``` -------------------------------- ### Perform Image-level AUC Evaluation Source: https://context7.com/scu-zjz/imdlbenco/llms.txt Computes image-level AUC with distributed training support by accumulating predictions across batches. ```python from IMDLBenCo.evaluation import ImageAUC import torch # Initialize evaluator evaluator = ImageAUC(threshold=0.5) # Accumulate predictions across batches for batch in dataloader: output = model(batch['image'], batch['mask'], batch['label']) pred_labels = output['pred_label'] true_labels = batch['label'] evaluator.batch_update(pred_labels, true_labels) # Handle remaining samples evaluator.remain_update(remaining_pred, remaining_label) # Compute AUC (uses sklearn internally after gathering from all GPUs) auc = evaluator.epoch_update() print(f"Image-level AUC: {auc:.4f}") # Reset for next epoch evaluator.recovery() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.