Skip to content

added the code for the 3D expert finetuning and evaluation#51

Open
Portgas37 wants to merge 1 commit intoEPFLiGHT:experts_newfrom
Portgas37:experts_new
Open

added the code for the 3D expert finetuning and evaluation#51
Portgas37 wants to merge 1 commit intoEPFLiGHT:experts_newfrom
Portgas37:experts_new

Conversation

@Portgas37
Copy link

No description provided.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “3D expert” training + evaluation bundle under src/multimeditron/experts/3D_expert/ to fine-tune a 3D CLIP-style model on .npy volumes and evaluate learned embeddings via a downstream MLP classifier.

Changes:

  • Introduces a HuggingFace Trainer-based fine-tuning script for GoodBaiBai88/M3D-CLIP with JSONL dataset loading + .npy pairing/expansion.
  • Adds 3D embedding extraction utilities and a fracture benchmark that trains/tests an MLP on extracted embeddings.
  • Adds a dedicated requirements file and a sample training YAML config for the 3D expert.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 23 comments.

Show a summary per file
File Description
src/multimeditron/experts/3D_expert/train_3D.py New 3D fine-tuning script (dataset mixing/expansion, preprocessing, Trainer wiring).
src/multimeditron/experts/3D_expert/requirements.txt Pinned dependency set intended for the 3D expert environment.
src/multimeditron/experts/3D_expert/mlp_eval.py New MLP-based downstream evaluation (k-fold CV + final test evaluation).
src/multimeditron/experts/3D_expert/load_from_clip.py Helper for loading a 3D CLIP model and encoding .npy volumes.
src/multimeditron/experts/3D_expert/configs/train.yaml Example YAML config for running train_3D.py.
src/multimeditron/experts/3D_expert/Benchmark.py New benchmark ABC base class for the 3D expert eval scripts.
src/multimeditron/experts/3D_expert/3D_fracture_eval.py Fracture benchmark that caches embeddings and runs MLP_eval.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +91 to +92
x = x.to("cuda")
label = label.to("cuda")
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several tensors are moved to the hardcoded device string "cuda" (e.g. in evaluate_fold()), ignoring self.device. This will crash on CPU-only environments and is inconsistent with the device selection in __init__. Use self.device (or the model’s parameter device) consistently when moving inputs/labels and creating loss tensors.

Suggested change
x = x.to("cuda")
label = label.to("cuda")
x = x.to(self.device)
label = label.to(self.device)

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,210 @@
from Benchmark import Benchmark
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These imports use bare module names (from Benchmark import Benchmark) which are ambiguous in this repo (there is also experts/evaluation_pipeline/disease_classification_pipeline/Benchmark.py). Depending on the working directory / PYTHONPATH, this can import the wrong module or fail. Prefer explicit relative imports within this folder (e.g. from .Benchmark import Benchmark) or a fully-qualified package import.

Suggested change
from Benchmark import Benchmark
from .Benchmark import Benchmark

Copilot uses AI. Check for mistakes.
Comment on lines +49 to +52
self.label.append(lab)
torch.save(self.data, file_name_data)
torch.save(self.label, file_name_lab)

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

torch.save(...) writes to <cwd>/embeddings/... but the code never creates the embeddings/ directory. If it doesn’t exist, saving will fail with FileNotFoundError. Create the directory (e.g. os.makedirs(..., exist_ok=True)) before these saves.

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +8
def load_model(model_name_or_path: str, device: torch.device = None, cache_dir: str = "/mloscratch/users/achahed/cache"):
"""
Load a 3D CLIP model from the given path.
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load_model() has a user-specific default cache_dir (an absolute /mloscratch/... path). This makes the helper non-portable outside that environment. Prefer defaulting cache_dir to None and letting HuggingFace use its standard cache location.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +45
- The image shape needs to be processed as 1*32*256*256
- The image needs to be normalized to 0-1 (Min-Max Normalization)
- The image format needs to be .npy
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring states the image must be normalized to 0–1 (Min-Max) and shaped to 1*32*256*256, but the function currently only loads the .npy and adjusts dimensions (no normalization/resampling). Either implement the preprocessing described here or update the docstring to match actual behavior.

Suggested change
- The image shape needs to be processed as 1*32*256*256
- The image needs to be normalized to 0-1 (Min-Max Normalization)
- The image format needs to be .npy
- The input image is expected to be stored as a NumPy array in a .npy file.
- The function will add missing batch/channel dimensions so that the final tensor
has shape (batch, channels, depth, height, width) before being passed to the model.
- The model is designed for images with spatial size [32, 256, 256] and in_channels=1;
this function does not perform any resizing or resampling, so the caller must ensure
the input volume has appropriate spatial dimensions.
- No Min-Max normalization is applied inside this function; if the model expects values
in a specific range (e.g., 01), the caller is responsible for performing that
preprocessing before saving/loading the .npy file.

Copilot uses AI. Check for mistakes.
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.clip_path = clip_path
self.clip_name = ""
def evaluate(self):
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method requires 1 positional argument, whereas overridden Benchmark.evaluate requires 2.
This method requires 1 positional argument, whereas overridden Benchmark.evaluate requires 2.

Suggested change
def evaluate(self):
def evaluate(self, *args, **kwargs):

Copilot uses AI. Check for mistakes.

return accuracy / self.k

def evaluate(self) -> float:
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method requires 1 positional argument, whereas overridden Benchmark.evaluate requires 2.
This method requires 1 positional argument, whereas overridden Benchmark.evaluate requires 2.

Suggested change
def evaluate(self) -> float:
def evaluate(self, data_loader=None) -> float:

Copilot uses AI. Check for mistakes.
import torch
import json
from load_from_clip import load_model, encode_img
import torch.nn as nn
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'nn' is not used.

Suggested change
import torch.nn as nn

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +3
from transformers import VisionTextDualEncoderConfig, VisionTextDualEncoderModel

Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'VisionTextDualEncoderConfig' is not used.
Import of 'VisionTextDualEncoderModel' is not used.

Suggested change
from transformers import VisionTextDualEncoderConfig, VisionTextDualEncoderModel

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +44
from transformers import (
AutoImageProcessor,
AutoModel,
AutoTokenizer,
HfArgumentParser,
VisionTextDualEncoderModel,
Trainer,
TrainingArguments,
set_seed,
)
Copy link

Copilot AI Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'VisionTextDualEncoderModel' is not used.
Import of 'AutoImageProcessor' is not used.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant