MedSAM3

repository·main·Indexed 43 days ago

https://github.com/joey-s-liu/medsam3

A text-guided medical image segmentation model utilizing LoRA (Low-Rank Adaptation) fine-tuning on the SAM3 architecture. It enables segmentation of medical targets across Radiology, Optical, and Video modalities using natural language concepts instead of points or bounding boxes. The framework includes utilities for LoRA injection, COCO-format data loading via LoRASAM3Dataset, and inference via the infer_sam.py script.

Tokens
5.7K
Snippets
20
Records
24
Agent score
56%

What's inside MedSAM3

  1. Install MedSAM3

    main

    To set up the MedSAM3 environment, clone the repository, install the package in editable mode, and authenticate with Hugging Face to access the model weights.

    Prerequisites: This project is built upon SAM3 and SAM3_LoRA. Ensure you follow the base environment setup instructions for those projects if you encounter environment-related issues.

    # Clone repository
    git clone https://github.com/Joey-S-Liu/MedSAM3.git
    cd MedSAM3
    
    # Install dependencies
    pip install -e .
    
    # Login to Hugging Face
    hf auth login
    # Paste your token when prompted
  2. Configure LoRA weights in MedSAM3

    main

    To use specific LoRA weights during inference or training, you must specify the path to the weights in your configuration file.

    Open your configuration file (e.g., configs/full_lora_config.yaml) and update the output_dir field with the path to your downloaded LoRA weights.

  3. Train MedSAM3 using LoRA

    main

    To train the model using the provided LoRA fine-tuning implementation, run the train_sam3_lora_native.py script with a configuration file.

    Data Format: Training data must follow the COCO format, consistent with the standard SAM3 implementation.

    python3 train_sam3_lora_native.py --config configs/full_lora_config.yaml
  4. Run inference with infer_sam.py

    main

    Use the infer_sam.py script to perform text-guided (concept-guided) medical image segmentation. You provide a medical concept as a text prompt, and the model segments the corresponding target.

    Key Arguments:

    • --config: Path to the configuration YAML file (e.g., configs/full_lora_config.yaml).
    • --image: Path to the input medical image.
    • --prompt: The medical concept/text description of the target (e.g., "skin lesion").
    • --threshold: Confidence threshold for segmentation. Adjust this based on the modality (e.g., 0.8 for higher precision, 0.5 for higher sensitivity).
    • --nms-iou: Non-Maximum Suppression IoU threshold.
    • --output: Path where the resulting segmentation mask will be saved.
    python3 infer_sam.py \
      --config configs/full_lora_config.yaml \
      --image path/to/image.jpg \
      --prompt "skin lesion" \
      --threshold 0.5 \
      --nms-iou 0.5 \
      --output skin_lesion.png
  5. Configure LoRA injection with LoRAConfig

    main

    Use LoRAConfig to define how Low-Rank Adaptation (LoRA) is applied to a SAM3 model. You can specify the rank, scaling factor, dropout, and which specific module patterns should receive LoRA layers.

    Parameters:

    • rank (int): The rank of the LoRA matrices. Defaults to 4.
    • alpha (float): The LoRA scaling factor. Defaults to 1.0.
    • dropout (float): The dropout probability. Defaults to 0.0.
    • target_modules (List[str]): A list of module name patterns to target. If None, it defaults to a comprehensive list covering standard attention, vision backbone (ViT-style), language backbone (CLIP-style), and transformer FFN layers. If 'all' is included in the list, it enables all possible modules including in_proj for MultiheadAttention.

    Supported Target Module Patterns:

    • Standard attention: q_proj, k_proj, v_proj, out_proj
    • Vision backbone (ViT-style): qkv (fused), proj (output), fc1, fc2 (MLP)
    • Language backbone (CLIP-style): c_fc, c_proj (MLP)
    • Transformer FFN: linear1, linear2
    • Special: all (enables everything listed above plus in_proj)
    from src.lora.lora_utils import LoRAConfig
    
    config = LoRAConfig(
        rank=8,
        alpha=2.0,
        dropout=0.1,
        target_modules=["q_proj", "v_proj"]
    )
  6. Configure LoRATrainer parameters

    main

    When initializing LoRATrainer, you can configure the following parameters to control the training process:

    ParameterTypeDefaultDescription
    modelnn.ModuleRequiredThe SAM3 model to be fine-tuned.
    lora_configLoRAConfigRequiredConfiguration for LoRA injection.
    train_loaderDataLoaderRequiredTraining data loader.
    val_loaderDataLoaderRequiredValidation data loader.
    optimizertorch.optim.OptimizerRequiredOptimizer for training.
    schedulerOptional[Any]NoneLearning rate scheduler.
    devicestr"cuda"Target device (e.g., "cuda", "cpu").
    max_epochsint20Total number of training epochs.
    val_epoch_freqint5Frequency of validation (in epochs).
    log_dirstr"./logs"Directory for Tensorboard and training logs.
    checkpoint_dirstr"./checkpoints"Directory to save model checkpoints.
    save_freqint5Frequency of saving epoch checkpoints.
    gradient_accumulation_stepsint1Number of steps before updating weights.
    max_grad_normfloat1.0Maximum norm for gradient clipping.
    use_ampboolTrueWhether to use Automatic Mixed Precision.
    amp_dtypestr"bfloat16"AMP data type ("float16" or "bfloat16").
  7. Reference: infer_sam.py CLI arguments

    main

    The infer_sam.py script accepts the following command-line arguments for medical image segmentation:

    • --config: Path to the configuration file.
    • --image: Path to the input image.
    • --prompt: Text-based medical concept prompt.
    • --threshold: Segmentation threshold (float).
    • --nms-iou: NMS IoU threshold (float).
    • --output: Output file path for the segmentation result.
  8. Inject LoRA into a model using inject_lora_into_model

    main

    Use inject_lora_into_model to apply Low-Rank Adaptation (LoRA) to an existing model. This function facilitates the injection of LoRA layers into the model's architecture, allowing for efficient fine-tuning or adaptation.

    from src.lora import inject_lora_into_model
    
    # Assuming 'model' is your target model
    inject_lora_into_model(model, r=8, alpha=16)
  9. Manage LoRA parameters with get_lora_parameters

    main

    Use get_lora_parameters to retrieve only the parameters associated with the LoRA layers in a model. This is useful when you want to pass only the trainable LoRA weights to an optimizer during fine-tuning, rather than the entire model's parameters.

    from src.lora import get_lora_parameters
    
    lora_params = get_lora_parameters(model)
    # Pass lora_params to your optimizer
    optimizer = torch.optim.AdamW(lora_params, lr=1e-4)
  10. Use LoRASAM3Dataset for SAM3 LoRA fine-tuning

    main

    The LoRASAM3Dataset class is a PyTorch Dataset implementation designed for SAM3 LoRA fine-tuning using annotations in COCO format. It automatically handles loading images from a directory and mapping them to their corresponding annotations.

    Key behaviors:

    • Annotation Format: Expects a COCO-style JSON file.
    • Filtering: Automatically skips images that have no associated annotations.
    • Annotation Limiting: Uses max_ann_per_img to cap the number of annotations processed per image (default is 200) to prevent memory issues.
    • Output: When indexed, it returns a dictionary containing the image (as a PIL Image or transformed tensor), annotations (list of dicts), and image_info (metadata).
    from src.data.dataset import LoRASAM3Dataset
    
    dataset = LoRASAM3Dataset(
        img_folder="path/to/images",
        ann_file="path/to/annotations.json",
        transforms=my_transforms_function,
        max_ann_per_img=100
    )
    
    sample = dataset[0]
    # sample contains {'image': ..., 'annotations': ..., 'image_info': ...}
  11. Create training and validation dataloaders with create_dataloaders

    main

    The create_dataloaders utility function simplifies the setup of the training and validation pipelines. It instantiates two LoRASAM3Dataset objects and wraps them in PyTorch DataLoader instances using a custom collate_fn to handle batching.

    Arguments:

    • train_img_folder / train_ann_file: Paths for training data.
    • val_img_folder / val_ann_file: Paths for validation data.
    • batch_size: Number of samples per batch (default: 1).
    • num_workers: Number of subprocesses for data loading (default: 4).
    • pin_memory: Whether to use pinned memory (default: True).
    • train_transforms / val_transforms: Optional callable transforms for each set.
    • max_ann_per_img: Maximum annotations per image (default: 200).

    Returns:

    • A tuple of (train_dataloader, val_dataloader).
    from src.data.dataset import create_dataloaders
    
    train_loader, val_loader = create_dataloaders(
        train_img_folder="data/train/imgs",
        train_ann_file="data/train/ann.json",
        val_img_folder="data/val/imgs",
        val_ann_file="data/val/ann.json",
        batch_size=4,
        train_transforms=my_train_transforms,
        val_transforms=my_val_transforms
    )
  12. Manage LoRA weights: Extract, Load, and Merge

    main

    These utilities allow you to manage the lifecycle of LoRA parameters independently of the base model weights.

    • get_lora_state_dict(model): Returns a dictionary containing only the LoRA weights (lora_A and lora_B) for all LinearWithLoRA modules. This is useful for saving only the small adapter weights.
    • load_lora_state_dict(model, state_dict): Loads LoRA weights from a provided dictionary into the model's LinearWithLoRA layers.
    • merge_lora_weights(model): Permanently merges the LoRA weights into the base model's weights and converts LinearWithLoRA layers back into standard nn.Linear layers. This is typically used for inference deployment to avoid the overhead of LoRA computation.
    • get_lora_parameters(model): Returns a list of all trainable LoRA parameters, useful for passing directly to an optimizer.
    # To save only the adapters
    state_dict = get_lora_state_dict(model)
    torch.save(state_dict, "lora_weights.pt")
    
    # To load adapters
    state_dict = torch.load("lora_weights.pt")
    load_lora_state_dict(model, state_dict)
    
    # To merge for inference
    model = merge_lora_weights(model)