:param input: batch_size * in_c * in_h * in_w :param grad_output: batch_size * out_c * h * w :param layer: nn.module batch_size * out_c * (in_c*k_h*k_w + [1 if with bias]) :return:
(input, grad_output, layer)
| 67 | |
| 68 | @staticmethod |
| 69 | def conv2d(input, grad_output, layer): |
| 70 | """ |
| 71 | :param input: batch_size * in_c * in_h * in_w |
| 72 | :param grad_output: batch_size * out_c * h * w |
| 73 | :param layer: nn.module batch_size * out_c * (in_c*k_h*k_w + [1 if with bias]) |
| 74 | :return: |
| 75 | """ |
| 76 | with torch.no_grad(): |
| 77 | input = _extract_patches(input, layer.kernel_size, layer.stride, layer.padding) |
| 78 | input = input.view(-1, input.size(-1)) # b * hw * in_c*kh*kw |
| 79 | grad_output = grad_output.transpose(1, 2).transpose(2, 3) |
| 80 | grad_output = try_contiguous(grad_output).view(grad_output.size(0), -1, grad_output.size(-1)) |
| 81 | # b * hw * out_c |
| 82 | if layer.bias is not None: |
| 83 | input = torch.cat([input, input.new(input.size(0), 1).fill_(1)], 1) |
| 84 | input = input.view(grad_output.size(0), -1, input.size(-1)) # b * hw * in_c*kh*kw |
| 85 | grad = torch.einsum('abm,abn->amn', (grad_output, input)) |
| 86 | return grad |
| 87 | |
| 88 | |
| 89 | class ComputeCovA: |
nothing calls this directly
no test coverage detected