| 269 | |
| 270 | |
| 271 | class sparseKernelFT1d(nn.Module): |
| 272 | def __init__(self, |
| 273 | k, alpha, c=1, |
| 274 | nl=1, |
| 275 | initializer=None, |
| 276 | **kwargs): |
| 277 | super(sparseKernelFT1d, self).__init__() |
| 278 | |
| 279 | self.modes1 = alpha |
| 280 | self.scale = (1 / (c * k * c * k)) |
| 281 | self.weights1 = nn.Parameter(self.scale * torch.rand(c * k, c * k, self.modes1, dtype=torch.cfloat)) |
| 282 | self.weights1.requires_grad = True |
| 283 | self.k = k |
| 284 | |
| 285 | def compl_mul1d(self, x, weights): |
| 286 | # (batch, in_channel, x ), (in_channel, out_channel, x) -> (batch, out_channel, x) |
| 287 | return torch.einsum("bix,iox->box", x, weights) |
| 288 | |
| 289 | def forward(self, x): |
| 290 | B, N, c, k = x.shape # (B, N, c, k) |
| 291 | |
| 292 | x = x.view(B, N, -1) |
| 293 | x = x.permute(0, 2, 1) |
| 294 | x_fft = torch.fft.rfft(x) |
| 295 | # Multiply relevant Fourier modes |
| 296 | l = min(self.modes1, N // 2 + 1) |
| 297 | # l = N//2+1 |
| 298 | out_ft = torch.zeros(B, c * k, N // 2 + 1, device=x.device, dtype=torch.cfloat) |
| 299 | out_ft[:, :, :l] = self.compl_mul1d(x_fft[:, :, :l], self.weights1[:, :, :l]) |
| 300 | x = torch.fft.irfft(out_ft, n=N) |
| 301 | x = x.permute(0, 2, 1).view(B, N, c, k) |
| 302 | return x |
| 303 | |
| 304 | |
| 305 | # ## |