Download model.py from herman7h/Rayan-Q1: direct link, hf CLI and curl.
- Browser
- Download file 3.44 kB
-
https://huggingface.co/herman7h/Rayan-Q1/resolve/main/model.py
- Command line
-
hf download hf://herman7h/Rayan-Q1/model.py
-
curl -L -o model.py https://huggingface.co/herman7h/Rayan-Q1/resolve/main/model.py
3.44 kB
| #model.py | |
| import torch | |
| import torch.nn as nn | |
| import open_clip | |
| class CONFIG: | |
| # Model parameters | |
| clip_model_name = "ViT-B-32" | |
| pretrained_dataset = "laion400m_e31" | |
| embedding_dim = 512 | |
| fusion_type = 'sum' # 'sum', 'concat', or 'attention' | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| image_size = (224, 224) | |
| batch_size = 16 | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| class FusionModel(nn.Module): | |
| def __init__(self, clip_model, fusion_type='sum'): | |
| super(FusionModel, self).__init__() | |
| self.clip_model = clip_model | |
| self.fusion_type = fusion_type | |
| # Depending on the fusion type, define the combined embedding size | |
| if fusion_type == 'sum': | |
| self.combined_dim = CONFIG.embedding_dim | |
| elif fusion_type == 'concat': | |
| self.combined_dim = CONFIG.embedding_dim * 2 | |
| elif fusion_type == 'attention': | |
| self.combined_dim = CONFIG.embedding_dim | |
| # Define the attention layer | |
| self.attention = nn.MultiheadAttention(embed_dim=CONFIG.embedding_dim, num_heads=8) | |
| else: | |
| raise ValueError("Invalid fusion type") | |
| # MLP to project the combined embedding to the final embedding space | |
| self.mlp = nn.Sequential( | |
| nn.Linear(self.combined_dim, CONFIG.embedding_dim), | |
| nn.ReLU(), | |
| nn.Dropout(p=0.1), | |
| nn.Linear(CONFIG.embedding_dim, CONFIG.embedding_dim) | |
| ) | |
| def forward(self, image, text): | |
| # Encode image and text using CLIP encoders | |
| image_features = self.clip_model.encode_image(image) # Shape: [batch_size, embedding_dim] | |
| text_tokens = open_clip.tokenize(text).to(CONFIG.device) # Tokenize text | |
| text_features = self.clip_model.encode_text(text_tokens) # Shape: [batch_size, embedding_dim] | |
| # Normalize the features | |
| image_features = image_features / image_features.norm(dim=-1, keepdim=True) | |
| text_features = text_features / text_features.norm(dim=-1, keepdim=True) | |
| # Fusion strategies | |
| if self.fusion_type == 'sum': | |
| combined_features = image_features + text_features | |
| elif self.fusion_type == 'concat': | |
| combined_features = torch.cat([image_features, text_features], dim=-1) | |
| elif self.fusion_type == 'attention': | |
| combined_features = self.attention_fusion(image_features, text_features) | |
| else: | |
| raise ValueError("Invalid fusion type") | |
| # Pass through MLP | |
| output = self.mlp(combined_features) | |
| return output | |
| def attention_fusion(self, image_features, text_features): | |
| # Reshape features to (sequence_length, batch_size, embedding_dim) | |
| # Since we have two features per sample, sequence_length = 2 | |
| features = torch.stack([image_features, text_features], dim=0) # Shape: [2, batch_size, embedding_dim] | |
| # Multi-head attention expects inputs in shape (sequence_length, batch_size, embedding_dim) | |
| # Query, Key, Value are all the features in this case | |
| attn_output, _ = self.attention(features, features, features) # Shape: [2, batch_size, embedding_dim] | |
| # Aggregate the attention outputs (e.g., take the mean over the sequence length) | |
| combined_features = attn_output.mean(dim=0) # Shape: [batch_size, embedding_dim] | |
| return combined_features | |