Skip to content

Commit

Permalink
Fix unfold2d and add test (#443)
Browse files Browse the repository at this point in the history
Summary:
Fixes #442.
TL;DR: F.pad has an unintuitive syntax (we need to indicated padding from last dimensions to first dimensions).
This PR fixes that in unfold2d and adds tests with non-symmetric pad/dilation/kernel_size/stride.

Pull Request resolved: #443

Reviewed By: karthikprasad

Differential Revision: D37451293

Pulled By: alexandresablayrolles

fbshipit-source-id: 0587325f4dcaa4d1dcd3068d9046825964b9d49f
  • Loading branch information
Alex Sablayrolles authored and facebook-github-bot committed Jul 8, 2022
1 parent 181c6b7 commit f125752
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
51 changes: 51 additions & 0 deletions opacus/tests/grad_samples/conv2d_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import torch
import torch.nn as nn
from hypothesis import given, settings
from opacus.utils.tensor_utils import unfold2d
from torch.testing import assert_allclose

from .common import GradSampleHooks_test, expander, shrinker

Expand Down Expand Up @@ -68,3 +70,52 @@ def test_conv2d(
groups=groups,
)
self.run_test(x, conv, batch_first=True, atol=10e-5, rtol=10e-4)

@given(
B=st.integers(1, 4),
C=st.sampled_from([1, 3, 32]),
H=st.integers(11, 17),
W=st.integers(11, 17),
k_w=st.integers(2, 3),
k_h=st.integers(2, 3),
stride_w=st.integers(1, 2),
stride_h=st.integers(1, 2),
pad_h=st.sampled_from([0, 2]),
pad_w=st.sampled_from([0, 2]),
dilation_w=st.integers(1, 3),
dilation_h=st.integers(1, 3),
)
@settings(deadline=10000)
def test_unfold2d(
self,
B: int,
C: int,
H: int,
W: int,
k_w: int,
k_h: int,
pad_w: int,
pad_h: int,
stride_w: int,
stride_h: int,
dilation_w: int,
dilation_h: int,
):
X = torch.randn(B, C, H, W)
X_unfold_torch = torch.nn.functional.unfold(
X,
kernel_size=(k_h, k_w),
padding=(pad_h, pad_w),
stride=(stride_w, stride_h),
dilation=(dilation_w, dilation_h),
)

X_unfold_opacus = unfold2d(
X,
kernel_size=(k_h, k_w),
padding=(pad_h, pad_w),
stride=(stride_w, stride_h),
dilation=(dilation_w, dilation_h),
)

assert_allclose(X_unfold_torch, X_unfold_opacus, atol=0, rtol=0)
3 changes: 2 additions & 1 deletion opacus/utils/tensor_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ def unfold2d(
W_effective = (
W + 2 * padding[1] - (kernel_size[1] + (kernel_size[1] - 1) * (dilation[1] - 1))
) // stride[1] + 1
input = F.pad(input, (padding[0], padding[0], padding[1], padding[1]))
# F.pad's first argument is the padding of the *last* dimension
input = F.pad(input, (padding[1], padding[1], padding[0], padding[0]))
*shape_pad, H_pad, W_pad = input.shape
strides = list(input.stride())
strides = strides[:-2] + [
Expand Down

0 comments on commit f125752

Please sign in to comment.