(self, image)
| 229 | |
| 230 | |
| 231 | def forward(self, image): |
| 232 | # `image` has shape: [batch_size, num_channels, height, width]. |
| 233 | # Convolutional encoder with position embedding. |
| 234 | x = self.encoder_cnn(image) # CNN Backbone. |
| 235 | x = einops.rearrange(x, 'b c h w -> b h w c') |
| 236 | x = self.encoder_pos(x) # Position embedding. |
| 237 | x = spatial_flatten(x) # Flatten spatial dimensions (treat image as set). |
| 238 | x = self.mlp(self.layer_norm(x)) # Feedforward network on set. |
| 239 | # `x` has shape: [batch_size, width*height, input_size]. |
| 240 | |
| 241 | # Slot Attention module. |
| 242 | slots = self.slot_attention(x) |
| 243 | # `slots` has shape: [batch_size, num_slots, slot_size]. |
| 244 | |
| 245 | # Spatial broadcast decoder. |
| 246 | x = spatial_broadcast(slots, self.decoder_initial_size) |
| 247 | # `x` has shape: [batch_size*num_slots, height_init, width_init, slot_size]. |
| 248 | x = self.decoder_pos(x) |
| 249 | x = einops.rearrange(x, 'b_n h w c -> b_n c h w') |
| 250 | x = self.decoder_cnn(x) |
| 251 | # `x` has shape: [batch_size*num_slots, num_channels+1, height, width]. |
| 252 | |
| 253 | # Undo combination of slot and batch dimension; split alpha masks. |
| 254 | recons, masks = unstack_and_split(x, batch_size=image.shape[0], num_channels=self.in_out_channels) |
| 255 | # `recons` has shape: [batch_size, num_slots, num_channels, height, width]. |
| 256 | # `masks` has shape: [batch_size, num_slots, 1, height, width]. |
| 257 | |
| 258 | # Normalize alpha masks over slots. |
| 259 | masks = torch.softmax(masks, axis=1) |
| 260 | |
| 261 | recon_combined = torch.sum(recons * masks, axis=1) # Recombine image. |
| 262 | # `recon_combined` has shape: [batch_size, num_channels, height, width]. |
| 263 | return recon_combined, recons, masks, slots |
| 264 | |
| 265 | if __name__ =='__main__': |
| 266 | x = torch.rand(4,128,12,12).cuda() |
nothing calls this directly
no test coverage detected