Source code for plismbench.models.owkin

"""Models from Owkin, Inc. company."""

from __future__ import annotations

import numpy as np
import torch
from torchvision import transforms
from transformers import AutoImageProcessor, AutoModel

from plismbench.models.extractor import Extractor
from plismbench.models.utils import DEFAULT_DEVICE, prepare_module


[docs] class Phikon(Extractor): """Phikon model developped by Owkin available on Hugging-Face (1). .. note:: (1) https://huggingface.co/owkin/phikon Parameters ---------- device: int | list[int] | None = DEFAULT_DEVICE, Compute resources to use. If None, will use all available GPUs. If -1, extraction will run on CPU. mixed_precision: bool = True Whether to use mixed_precision. """ def __init__( self, device: int | list[int] | None = DEFAULT_DEVICE, mixed_precision: bool = False, ): super().__init__() self.output_dim = 768 self.mixed_precision = mixed_precision self.processor = AutoImageProcessor.from_pretrained("owkin/phikon") # feature_extractor = ViTModel.from_pretrained( # "owkin/phikon", add_pooling_layer=False # ) feature_extractor = AutoModel.from_pretrained("owkin/phikon") self.feature_extractor, self.device = prepare_module( feature_extractor, device, self.mixed_precision, ) if self.device is None: self.feature_extractor = self.feature_extractor.module
[docs] def process(self, image) -> torch.Tensor: """Process input images.""" phikon_input = self.processor(images=image, return_tensors="pt") return phikon_input["pixel_values"][0]
@property # type: ignore def transform(self) -> transforms.Lambda: """Transform method to apply element wise.""" return transforms.Lambda(self.process) def __call__(self, images: torch.Tensor) -> np.ndarray: """Compute and return features. Parameters ---------- images: torch.Tensor Input of size (n_tiles, n_channels, dim_x, dim_y). Returns ------- torch.Tensor: Tensor of size (n_tiles, features_dim). """ last_hidden_state = self.feature_extractor(images.to(self.device)) features = last_hidden_state[:, 0] return features.cpu().numpy()
[docs] class PhikonV2(Extractor): """Phikon V2 model developped by Owkin available on Hugging-Face (1). You will need to be granted access to be able to use this model. .. note:: (1) https://huggingface.co/owkin/phikon-v2 Parameters ---------- device: int | list[int] | None = DEFAULT_DEVICE, Compute resources to use. If None, will use all available GPUs. If -1, extraction will run on CPU. mixed_precision: bool = True Whether to use mixed_precision. """ def __init__( self, device: int | list[int] | None = DEFAULT_DEVICE, mixed_precision: bool = False, ): super().__init__() self.output_dim = 1024 self.mixed_precision = mixed_precision self.processor = AutoImageProcessor.from_pretrained("owkin/phikon-v2") feature_extractor = AutoModel.from_pretrained("owkin/phikon-v2") self.feature_extractor, self.device = prepare_module( feature_extractor, device, self.mixed_precision, ) if self.device is None: self.feature_extractor = self.feature_extractor.module
[docs] def process(self, image) -> torch.Tensor: """Process input images.""" phikon_input = self.processor(images=image, return_tensors="pt") return phikon_input["pixel_values"][0]
@property # type: ignore def transform(self) -> transforms.Lambda: """Transform method to apply element wise.""" return transforms.Lambda(self.process) def __call__(self, images: torch.Tensor) -> np.ndarray: """Compute and return features. Parameters ---------- images: torch.Tensor Input of size (n_tiles, n_channels, dim_x, dim_y). Returns ------- torch.Tensor: Tensor of size (n_tiles, features_dim). """ last_hidden_state = self.feature_extractor(images.to(self.device)) features = last_hidden_state[:, 0] return features.cpu().numpy()