Forward function. Args: x: Input feature, tensor size (B, H*W, C). H, W: Spatial resolution of the input feature. mask_matrix: Attention mask for cyclic shift.
(self, x, mask_matrix)
| 228 | self.W = None |
| 229 | |
| 230 | def forward(self, x, mask_matrix): |
| 231 | """Forward function. |
| 232 | |
| 233 | Args: |
| 234 | x: Input feature, tensor size (B, H*W, C). |
| 235 | H, W: Spatial resolution of the input feature. |
| 236 | mask_matrix: Attention mask for cyclic shift. |
| 237 | """ |
| 238 | B, L, C = x.shape |
| 239 | H, W = self.H, self.W |
| 240 | assert L == H * W, 'input feature has wrong size' |
| 241 | |
| 242 | shortcut = x |
| 243 | x = self.norm1(x) |
| 244 | x = x.view(B, H, W, C) |
| 245 | |
| 246 | # pad feature maps to multiples of window size |
| 247 | pad_l = pad_t = 0 |
| 248 | pad_r = (self.window_size - W % self.window_size) % self.window_size |
| 249 | pad_b = (self.window_size - H % self.window_size) % self.window_size |
| 250 | x = F.pad(x, (0, 0, pad_l, pad_r, pad_t, pad_b)) |
| 251 | _, Hp, Wp, _ = x.shape |
| 252 | |
| 253 | # cyclic shift |
| 254 | if self.shift_size > 0: |
| 255 | shifted_x = torch.roll(x, |
| 256 | shifts=(-self.shift_size, -self.shift_size), |
| 257 | dims=(1, 2)) |
| 258 | attn_mask = mask_matrix |
| 259 | else: |
| 260 | shifted_x = x |
| 261 | attn_mask = None |
| 262 | |
| 263 | # partition windows |
| 264 | x_windows = window_partition( |
| 265 | shifted_x, self.window_size) # nW*B, window_size, window_size, C |
| 266 | x_windows = x_windows.view(-1, self.window_size * self.window_size, |
| 267 | C) # nW*B, window_size*window_size, C |
| 268 | |
| 269 | # W-MSA/SW-MSA |
| 270 | attn_windows = self.attn( |
| 271 | x_windows, mask=attn_mask) # nW*B, window_size*window_size, C |
| 272 | |
| 273 | # merge windows |
| 274 | attn_windows = attn_windows.view(-1, self.window_size, |
| 275 | self.window_size, C) |
| 276 | shifted_x = window_reverse(attn_windows, self.window_size, Hp, |
| 277 | Wp) # B H' W' C |
| 278 | |
| 279 | # reverse cyclic shift |
| 280 | if self.shift_size > 0: |
| 281 | x = torch.roll(shifted_x, |
| 282 | shifts=(self.shift_size, self.shift_size), |
| 283 | dims=(1, 2)) |
| 284 | else: |
| 285 | x = shifted_x |
| 286 | |
| 287 | if pad_r > 0 or pad_b > 0: |
nothing calls this directly
no test coverage detected