Feature Extraction
Transformers
Safetensors
English
remote-sensing
earth-observation
self-supervised-learning
sentinel-2
multispectral
sar
vision
softcon
vit
resnet
dinov2
Instructions to use BiliSakura/SOFTCON-transformers with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use BiliSakura/SOFTCON-transformers with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="BiliSakura/SOFTCON-transformers")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("BiliSakura/SOFTCON-transformers", dtype="auto") - Notebooks
- Google Colab
- Kaggle
| # Copyright 2024 The SoftCon Authors and The HuggingFace Inc. team. | |
| """Self-contained SoftCon model and config for trust_remote_code loading.""" | |
| from typing import Optional | |
| import torch | |
| import torch.nn as nn | |
| from torchvision import models | |
| from transformers.configuration_utils import PretrainedConfig as PreTrainedConfig | |
| from transformers.modeling_outputs import BaseModelOutputWithPooling, ImageClassifierOutput | |
| from transformers.modeling_utils import PreTrainedModel | |
| from transformers.models.dinov2.configuration_dinov2 import Dinov2Config | |
| from transformers.models.dinov2.modeling_dinov2 import Dinov2Model | |
| from transformers.processing_utils import Unpack | |
| from transformers.utils import TransformersKwargs, logging | |
| logger = logging.get_logger(__name__) | |
| class SoftConConfig(PreTrainedConfig): | |
| model_type = "softcon" | |
| def __init__( | |
| self, | |
| backbone="resnet50", | |
| num_channels=13, | |
| modality="s2c", | |
| hidden_size=2048, | |
| image_size=224, | |
| patch_size=14, | |
| init_values=1e-5, | |
| num_hidden_layers=None, | |
| num_attention_heads=None, | |
| num_register_tokens=0, | |
| block_chunks=0, | |
| num_labels=0, | |
| **kwargs, | |
| ): | |
| super().__init__(**kwargs) | |
| self.backbone = backbone | |
| self.num_channels = num_channels | |
| self.modality = modality | |
| self.hidden_size = hidden_size | |
| self.image_size = image_size | |
| self.patch_size = patch_size | |
| self.init_values = init_values | |
| self.num_hidden_layers = num_hidden_layers | |
| self.num_attention_heads = num_attention_heads | |
| self.num_register_tokens = num_register_tokens | |
| self.block_chunks = block_chunks | |
| self.num_labels = num_labels | |
| def get_dinov2_config(self) -> Dinov2Config: | |
| if self.backbone not in {"vit_small", "vit_base"}: | |
| raise ValueError(f"Backbone '{self.backbone}' is not a ViT encoder.") | |
| if self.num_hidden_layers is None or self.num_attention_heads is None: | |
| raise ValueError( | |
| "ViT models require `num_hidden_layers` and `num_attention_heads` in the model config." | |
| ) | |
| return Dinov2Config( | |
| hidden_size=self.hidden_size, | |
| num_hidden_layers=self.num_hidden_layers, | |
| num_attention_heads=self.num_attention_heads, | |
| image_size=self.image_size, | |
| patch_size=self.patch_size, | |
| num_channels=self.num_channels, | |
| layerscale_value=self.init_values, | |
| use_mask_token=False, | |
| ) | |
| class SoftConPreTrainedModel(PreTrainedModel): | |
| config: SoftConConfig | |
| base_model_prefix = "softcon" | |
| main_input_name = "pixel_values" | |
| input_modalities = ("image",) | |
| supports_gradient_checkpointing = False | |
| def _build_resnet_encoder(config: SoftConConfig) -> nn.Module: | |
| backbone = models.resnet50(weights=None) | |
| if config.num_channels != 3: | |
| backbone.conv1 = nn.Conv2d(config.num_channels, 64, kernel_size=7, stride=2, padding=3, bias=False) | |
| backbone.fc = nn.Identity() | |
| return backbone | |
| def _build_vit_encoder(config: SoftConConfig) -> Dinov2Model: | |
| return Dinov2Model(config.get_dinov2_config()) | |
| def _build_encoder(config: SoftConConfig) -> nn.Module: | |
| if config.backbone == "resnet50": | |
| return _build_resnet_encoder(config) | |
| if config.backbone in {"vit_small", "vit_base"}: | |
| return _build_vit_encoder(config) | |
| raise ValueError(f"Unsupported backbone '{config.backbone}'") | |
| class SoftConModel(SoftConPreTrainedModel): | |
| def __init__(self, config: SoftConConfig): | |
| super().__init__(config) | |
| self.encoder = _build_encoder(config) | |
| self.post_init() | |
| def _forward_resnet(self, pixel_values: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]: | |
| x = self.encoder.conv1(pixel_values) | |
| x = self.encoder.bn1(x) | |
| x = self.encoder.relu(x) | |
| x = self.encoder.maxpool(x) | |
| x = self.encoder.layer1(x) | |
| x = self.encoder.layer2(x) | |
| x = self.encoder.layer3(x) | |
| x = self.encoder.layer4(x) | |
| last_hidden_state = x.flatten(2).transpose(1, 2) | |
| pooler_output = self.encoder.avgpool(x).flatten(1) | |
| return last_hidden_state, pooler_output | |
| def _forward_vit(self, pixel_values: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]: | |
| outputs = self.encoder(pixel_values=pixel_values, return_dict=True) | |
| return outputs.last_hidden_state, outputs.pooler_output | |
| def forward( | |
| self, | |
| pixel_values: Optional[torch.Tensor] = None, | |
| return_dict: Optional[bool] = None, | |
| **kwargs: Unpack[TransformersKwargs], | |
| ) -> BaseModelOutputWithPooling: | |
| if pixel_values is None: | |
| raise ValueError("You must specify `pixel_values`") | |
| pixel_values = pixel_values.to(dtype=self.dtype) | |
| if return_dict is None: | |
| return_dict = self.config.use_return_dict | |
| if self.config.backbone == "resnet50": | |
| last_hidden_state, pooler_output = self._forward_resnet(pixel_values) | |
| else: | |
| last_hidden_state, pooler_output = self._forward_vit(pixel_values) | |
| if not return_dict: | |
| return (last_hidden_state, pooler_output) | |
| return BaseModelOutputWithPooling(last_hidden_state=last_hidden_state, pooler_output=pooler_output) | |
| class SoftConForImageClassification(SoftConPreTrainedModel): | |
| def __init__(self, config: SoftConConfig): | |
| super().__init__(config) | |
| self.softcon = SoftConModel(config) | |
| self.classifier = ( | |
| nn.Linear(config.hidden_size, config.num_labels) if config.num_labels > 0 else nn.Identity() | |
| ) | |
| self.post_init() | |
| def forward( | |
| self, | |
| pixel_values: Optional[torch.Tensor] = None, | |
| labels: Optional[torch.Tensor] = None, | |
| return_dict: Optional[bool] = None, | |
| **kwargs: Unpack[TransformersKwargs], | |
| ) -> ImageClassifierOutput: | |
| outputs = self.softcon(pixel_values=pixel_values, return_dict=True, **kwargs) | |
| logits = self.classifier(outputs.pooler_output) | |
| loss = None | |
| if labels is not None: | |
| loss = self.loss_function(labels, logits, self.config, **kwargs) | |
| if not return_dict: | |
| output = (logits,) + outputs[1:] | |
| return ((loss,) + output) if loss is not None else output | |
| return ImageClassifierOutput( | |
| loss=loss, | |
| logits=logits, | |
| hidden_states=outputs.hidden_states, | |
| attentions=outputs.attentions, | |
| ) | |
| __all__ = [ | |
| "SoftConConfig", | |
| "SoftConForImageClassification", | |
| "SoftConModel", | |
| "SoftConPreTrainedModel", | |
| ] | |