Image Feature Extraction
Transformers
Safetensors
csd
feature-extraction
style-similarity
custom_code
Instructions to use bigshanedogg/CSD with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use bigshanedogg/CSD with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-feature-extraction", model="bigshanedogg/CSD", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("bigshanedogg/CSD", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
| # CSD (HuggingFace format) β unofficial port. Copyright (c) 2026 bigshanedogg. MIT License. | |
| # | |
| # Self-contained transformers port of the CSD style model from | |
| # "Measuring Style Similarity in Diffusion Models" (Somepalli et al., 2024) | |
| # https://github.com/learn2phoenix/CSD (code: MIT) | |
| # so it loads via AutoModel.from_pretrained(trust_remote_code=True) without the `clip` | |
| # package. The ViT-L/14 vision transformer below is vendored from OpenAI CLIP | |
| # https://github.com/openai/CLIP (MIT, (c) 2021 OpenAI) β MODIFIED: trimmed to the | |
| # vision tower, projection removed (folded into the CSD style/content heads). | |
| # The released CSD checkpoint (tomg-group-umd/CSD-ViT-L) is CC-BY-4.0. | |
| from collections import OrderedDict | |
| from typing import Optional | |
| import torch | |
| import torch.nn as nn | |
| from transformers import PretrainedConfig, PreTrainedModel | |
| from transformers.modeling_outputs import ModelOutput | |
| class CSDConfig(PretrainedConfig): | |
| model_type = "csd" | |
| def __init__( | |
| self, | |
| image_resolution: int = 224, | |
| patch_size: int = 14, | |
| width: int = 1024, | |
| layers: int = 24, | |
| heads: int = 16, | |
| embed_dim: int = 768, | |
| **kwargs, | |
| ): | |
| self.image_resolution = image_resolution | |
| self.patch_size = patch_size | |
| self.width = width | |
| self.layers = layers | |
| self.heads = heads | |
| self.embed_dim = embed_dim # style/content projection output dim | |
| super().__init__(**kwargs) | |
| # ββ vendored OpenAI CLIP vision tower (MIT, (c) 2021 OpenAI; MODIFIED) ββββββββββββββ | |
| class QuickGELU(nn.Module): | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| return x * torch.sigmoid(1.702 * x) | |
| class ResidualAttentionBlock(nn.Module): | |
| def __init__(self, d_model: int, n_head: int): | |
| super().__init__() | |
| self.attn = nn.MultiheadAttention(d_model, n_head) | |
| self.ln_1 = nn.LayerNorm(d_model) | |
| self.mlp = nn.Sequential( | |
| OrderedDict( | |
| [ | |
| ("c_fc", nn.Linear(d_model, d_model * 4)), | |
| ("gelu", QuickGELU()), | |
| ("c_proj", nn.Linear(d_model * 4, d_model)), | |
| ] | |
| ) | |
| ) | |
| self.ln_2 = nn.LayerNorm(d_model) | |
| def attention(self, x: torch.Tensor) -> torch.Tensor: | |
| return self.attn(x, x, x, need_weights=False, attn_mask=None)[0] | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| x = x + self.attention(self.ln_1(x)) | |
| x = x + self.mlp(self.ln_2(x)) | |
| return x | |
| class Transformer(nn.Module): | |
| def __init__(self, width: int, layers: int, heads: int): | |
| super().__init__() | |
| self.resblocks = nn.Sequential(*[ResidualAttentionBlock(width, heads) for _ in range(layers)]) | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| return self.resblocks(x) | |
| class VisionTransformer(nn.Module): | |
| def __init__(self, input_resolution: int, patch_size: int, width: int, layers: int, heads: int): | |
| super().__init__() | |
| self.conv1 = nn.Conv2d(3, width, kernel_size=patch_size, stride=patch_size, bias=False) | |
| _scale = width**-0.5 | |
| self.class_embedding = nn.Parameter(_scale * torch.randn(width)) | |
| _num_positions = (input_resolution // patch_size) ** 2 + 1 | |
| self.positional_embedding = nn.Parameter(_scale * torch.randn(_num_positions, width)) | |
| self.ln_pre = nn.LayerNorm(width) | |
| self.transformer = Transformer(width, layers, heads) | |
| self.ln_post = nn.LayerNorm(width) | |
| # NOTE: CSD sets backbone.proj = None and folds projection into last_layer_{style,content}. | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| x = self.conv1(x) # (B, width, grid, grid) | |
| x = x.reshape(x.shape[0], x.shape[1], -1).permute(0, 2, 1) # (B, grid**2, width) | |
| _cls = self.class_embedding.to(x.dtype) + torch.zeros(x.shape[0], 1, x.shape[-1], dtype=x.dtype, device=x.device) | |
| x = torch.cat([_cls, x], dim=1) # (B, grid**2 + 1, width) | |
| x = x + self.positional_embedding.to(x.dtype) | |
| x = self.ln_pre(x) | |
| x = x.permute(1, 0, 2) # NLD -> LND | |
| x = self.transformer(x) | |
| x = x.permute(1, 0, 2) # LND -> NLD | |
| x = self.ln_post(x[:, 0, :]) # take the [CLS] token | |
| return x | |
| class CSDOutput(ModelOutput): | |
| embeddings: Optional[torch.FloatTensor] = None # style embedding (L2-normalized) | |
| content_embeddings: Optional[torch.FloatTensor] = None | |
| last_hidden_states: Optional[torch.FloatTensor] = None # pre-projection ViT feature | |
| class CSDModel(PreTrainedModel): | |
| """CSD style/content encoder. ``embeddings`` is the L2-normalized style descriptor | |
| (``feature @ last_layer_style``); the perceptual/style scoring lives in the caller.""" | |
| config_class = CSDConfig | |
| def __init__(self, config: CSDConfig): | |
| super().__init__(config) | |
| self.backbone = VisionTransformer( | |
| input_resolution=config.image_resolution, | |
| patch_size=config.patch_size, | |
| width=config.width, | |
| layers=config.layers, | |
| heads=config.heads, | |
| ) | |
| self.last_layer_style = nn.Parameter(torch.empty(config.width, config.embed_dim)) | |
| self.last_layer_content = nn.Parameter(torch.empty(config.width, config.embed_dim)) | |
| # transformers>=5 sets weight-loading state (e.g. all_tied_weights_keys, read by | |
| # from_pretrained) in PreTrainedModel.post_init(); call it so the load doesn't | |
| # AttributeError. from_pretrained overwrites the freshly-inited weights afterward. | |
| self.post_init() | |
| def forward(self, pixel_values: torch.Tensor) -> CSDOutput: | |
| _feature = self.backbone(pixel_values) | |
| _style = nn.functional.normalize(_feature @ self.last_layer_style, dim=1, p=2) | |
| _content = nn.functional.normalize(_feature @ self.last_layer_content, dim=1, p=2) | |
| return CSDOutput(embeddings=_style, content_embeddings=_content, last_hidden_states=_feature) | |