| """ | |
| Change Feature Engineering Module. | |
| This module implements the core change representation logic for temporal satellite imagery: | |
| delta_f (difference vector) and concatenated representations. These features are then mapped | |
| to a multimodal space via a lightweight projection head. | |
| """ | |
| import torch | |
| def compute_change_feature( | |
| embedding_T1: torch.Tensor, | |
| embedding_T2: torch.Tensor, | |
| mode: str = "difference" | |
| ) -> torch.Tensor: | |
| """ | |
| Compute the change feature representation from two temporal embeddings. | |
| Args: | |
| embedding_T1 (torch.Tensor): First time-step embedding. Shape: [batch_size, embed_dim]. | |
| embedding_T2 (torch.Tensor): Second time-step embedding. Shape: [batch_size, embed_dim]. | |
| mode (str): Feature computation mode. | |
| - "difference": delta_f = f_T2 - f_T1 (default) | |
| - "concatenate": [f_T1, f_T2] concatenated | |
| Returns: | |
| torch.Tensor: Change feature representation. Shape depends on mode: | |
| - difference: [batch_size, embed_dim] | |
| - concatenate: [batch_size, 2 * embed_dim] | |
| Example: | |
| >>> emb_t1 = torch.randn(4, 768) # batch of 4, CLIP ViT-L/14 dim | |
| >>> emb_t2 = torch.randn(4, 768) | |
| >>> delta = compute_change_feature(emb_t1, emb_t2, mode="difference") | |
| >>> print(delta.shape) # torch.Size([4, 768]) | |
| """ | |
| assert embedding_T1.size() == embedding_T2.size(), \ | |
| f"Embeddings must have same shape: {embedding_T1.size()} vs {embedding_T2.size()}" | |
| if mode.lower() == "difference": | |
| delta_f = embedding_T2 - embedding_T1 | |
| elif mode.lower() == "concatenate": | |
| delta_f = torch.cat([embedding_T1, embedding_T2], dim=-1) | |
| else: | |
| raise ValueError(f"Unknown mode: {mode}. Use 'difference' or 'concatenate'.") | |
| return delta_f | |