| 236 | |
| 237 | |
| 238 | class SpectrumHead(nn.Module): |
| 239 | def __init__( |
| 240 | self, |
| 241 | model_path: str, |
| 242 | embed_dim: int = 1024, |
| 243 | n_head: int = 4, |
| 244 | model_embed_dim: int = 768, |
| 245 | dropout: float = 0.1, |
| 246 | freeze_backbone: bool = True, |
| 247 | load_pretrained_weights=True, |
| 248 | ): |
| 249 | """ |
| 250 | Cross-attention spectrum module that takes a spectrum and passes it through a pretrained SpecFormer model and |
| 251 | then through a cross-attention mechanism and MLP to get the final embedding. |
| 252 | |
| 253 | Args: |
| 254 | save_path (str): Path to the checkpoint of the SpecFormer model. |
| 255 | embed_dim (int): Dimension of the AstroCLIP embedding. |
| 256 | n_head (int): Number of heads in the multihead attention. |
| 257 | model_embed_dim (int): Dimension of the SpecFormer embedding. |
| 258 | dropout (float): Dropout rate for MLP layers. |
| 259 | freeze_backbone (bool): Whether to freeze the backbone of the SpecFormer model. |
| 260 | """ |
| 261 | super().__init__() |
| 262 | # Load the model from the checkpoint |
| 263 | checkpoint = torch.load(model_path) |
| 264 | self.backbone = SpecFormer(**checkpoint["hyper_parameters"]) |
| 265 | if load_pretrained_weights: |
| 266 | self.backbone.load_state_dict(checkpoint["state_dict"]) |
| 267 | |
| 268 | # Freeze backbone if necessary |
| 269 | self.freeze_backbone = freeze_backbone |
| 270 | if self.freeze_backbone: |
| 271 | for param in self.backbone.parameters(): |
| 272 | param.requires_grad = False |
| 273 | |
| 274 | # Set up cross-attention |
| 275 | self.cross_attention = CrossAttentionHead( |
| 276 | embed_dim=embed_dim, |
| 277 | n_head=n_head, |
| 278 | model_embed_dim=model_embed_dim, |
| 279 | dropout=dropout, |
| 280 | ) |
| 281 | |
| 282 | # Set up MLP |
| 283 | self.mlp = MLP( |
| 284 | in_features=embed_dim, |
| 285 | hidden_features=4 * embed_dim, |
| 286 | dropout=dropout, |
| 287 | ) |
| 288 | |
| 289 | def forward( |
| 290 | self, x: torch.tensor, y: torch.tensor = None, return_weights: bool = False |
| 291 | ): |
| 292 | # Embed the spectrum using the pretrained model |
| 293 | with torch.set_grad_enabled(not self.freeze_backbone): |
| 294 | embedding = self.backbone(x)["embedding"] |
| 295 |
nothing calls this directly
no outgoing calls
no test coverage detected