| 160 | module.weight.data[module.padding_idx].zero_() |
| 161 | |
| 162 | class SpatialVLAForConditionalGeneration(SpatialVLAPreTrainedModel, GenerationMixin): |
| 163 | def __init__(self, config: SpatialVLAConfig, vision_model=None, vision_zoe_model=None, projector_model=None, language_model=None): |
| 164 | super().__init__(config) |
| 165 | |
| 166 | self.vision_tower = vision_model or AutoModel.from_config(config=config.vision_config) |
| 167 | self.multi_modal_projector = projector_model or SpatialVLAMultiModalProjector(config) |
| 168 | self.vocab_size = config.text_config.vocab_size |
| 169 | if language_model is None: |
| 170 | language_model = Gemma2ForCausalLM(config=config.text_config) |
| 171 | if language_model._tied_weights_keys is not None: |
| 172 | self._tied_weights_keys = [f"language_model.{k}" for k in language_model._tied_weights_keys] |
| 173 | self.language_model = language_model |
| 174 | |
| 175 | if config.use_vision_zoe: |
| 176 | self.vision_zoe_model = vision_zoe_model or ZoeDepthForDepthEstimation(config.vision_zoe_config) |
| 177 | self.position_embedding_3d = Ego3DPositionEmbeddingMLP( |
| 178 | config.ego3d_patch_reso**2 * 3, num_pos_feats=config.vision_config.hidden_size, n_freqs=config.n_freqs |
| 179 | ) |
| 180 | # register buffer |
| 181 | patch_size, reso, image_size = config.vision_config.patch_size, config.ego3d_patch_reso, config.vision_config.image_size |
| 182 | y, x = torch.meshgrid(torch.arange(0, image_size, patch_size // reso), torch.arange(0, image_size, patch_size // reso), indexing="ij") # (h//sp w//sp) |
| 183 | y, x = y + patch_size / reso / 2, x + patch_size / reso / 2 |
| 184 | uv_h = torch.stack([x, y, torch.ones_like(x)], dim=0).reshape(3, -1) # (3 hw) |
| 185 | self.register_buffer("uv_h", uv_h, persistent=False) |
| 186 | |
| 187 | # shared spatial embeddings for <ACTION> <IMG> |
| 188 | if config.use_spatial_token: |
| 189 | self.spatial_embed_tokens = nn.Embedding(self.config.spatial_token_num, config.text_config.hidden_size) |
| 190 | else: |
| 191 | self.spatial_embed_tokens = None |
| 192 | self.pad_token_id = self.config.pad_token_id if self.config.pad_token_id is not None else -1 |
| 193 | |
| 194 | |
| 195 | def backproject_patch(self, K: torch.Tensor, depth: torch.Tensor, patch_size=14, reso=2) -> torch.Tensor: |
| 196 | """ |
| 197 | Backproject depth map to 3D points in camera coordinate. |
| 198 | Args: |
| 199 | K: camera intrinsic matrix (b 3 3) |
| 200 | depth: depth map (b 1 h w) |
| 201 | patch_size: patch size for siglip |
| 202 | reso: reso^2 -> sample points in each patch |
| 203 | patch sz = 14 ...... |
| 204 | ┌────────┬────────┐ |
| 205 | │ ─ ─ │ ─ ─ │ |
| 206 | │ points │ ├─ ─ ─ |
| 207 | │ ─ ─ │ ─ ─ │ |
| 208 | ├────────┼────────┤ |
| 209 | │ ─ ─ │ ─ ─ │ |
| 210 | │ │ │ |
| 211 | │ ─ ─ │ ─ ─ │ |
| 212 | └────────┴────────┘ |
| 213 | reso=2───►points=4 |
| 214 | │ |
| 215 | │ |
| 216 | """ |
| 217 | b, c, h, w = depth.shape |
| 218 | hp, wp = h // patch_size, w // patch_size |
| 219 | sub_hp = sub_wp = reso |