Add e2e test for conv+bn (#27348)

Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/27348

att

Test Plan:
python test/test_quantization.py

Imported from OSS

Differential Revision: D18182920

fbshipit-source-id: 40edc4d85903f979cd4755d6785d2842faa4d566
diff --git a/test/common_quantization.py b/test/common_quantization.py
index 9793628..442e24d 100644
--- a/test/common_quantization.py
+++ b/test/common_quantization.py
@@ -161,6 +161,7 @@
             self.assertEqual(scripted_output, ref_output)
 
 # Below are a series of neural net models to use in testing quantization
+# Single layer models
 class SingleLayerLinearModel(torch.nn.Module):
     def __init__(self):
         super(SingleLayerLinearModel, self).__init__()
@@ -200,7 +201,6 @@
         x = self.lstm(x)
         return x
 
-
 class ConvModel(torch.nn.Module):
     def __init__(self):
         super(ConvModel, self).__init__()
@@ -224,6 +224,33 @@
         x = self.dequant(x)
         return x
 
+class ConvBnModel(torch.nn.Module):
+    def __init__(self):
+        super(ConvBnModel, self).__init__()
+        self.conv = torch.nn.Conv2d(3, 5, 3, bias=False).to(dtype=torch.float)
+        self.bn = torch.nn.BatchNorm2d(5).to(dtype=torch.float)
+
+    def forward(self, x):
+        x = self.conv(x)
+        x = self.bn(x)
+        return x
+
+class AnnotatedConvBnModel(torch.nn.Module):
+    def __init__(self):
+        super(AnnotatedConvBnModel, self).__init__()
+        self.qconfig = default_qconfig
+        self.conv = torch.nn.Conv2d(3, 5, 3, bias=False).to(dtype=torch.float)
+        self.bn = torch.nn.BatchNorm2d(5).to(dtype=torch.float)
+        self.quant = QuantStub()
+        self.dequant = DeQuantStub()
+
+    def forward(self, x):
+        x = self.quant(x)
+        x = self.conv(x)
+        x = self.bn(x)
+        x = self.dequant(x)
+        return x
+
 class TwoLayerLinearModel(torch.nn.Module):
     def __init__(self):
         super(TwoLayerLinearModel, self).__init__()
diff --git a/test/test_quantization.py b/test/test_quantization.py
index ce8225d..0490060 100644
--- a/test/test_quantization.py
+++ b/test/test_quantization.py
@@ -7,7 +7,7 @@
 import torch.nn.intrinsic.quantized as nniq
 import torch.nn.intrinsic.qat as nniqat
 from torch.quantization import \
-    QConfig, QConfigDynamic, default_observer, default_weight_observer, get_observer_dict,\
+    QConfigDynamic, get_observer_dict, default_weight_observer, \
     quantize, prepare, convert, prepare_qat, quantize_qat, fuse_modules, \
     quantize_dynamic, default_qconfig, default_debug_qconfig, default_qat_qconfig, \
     default_dynamic_qconfig, HistogramObserver, MinMaxObserver, PerChannelMinMaxObserver,\
@@ -20,6 +20,7 @@
 from common_quantization import QuantizationTestCase, \
     AnnotatedSingleLayerLinearModel, SingleLayerLinearModel, \
     AnnotatedConvModel, ConvModel, \
+    AnnotatedConvBnModel, ConvBnModel, \
     SkipQuantModel, QuantStubModel, \
     ModelForFusion, ModelWithSequentialFusion, ManualLinearQATModel, ManualConvLinearQATModel, \
     ModelWithFunctionals, \
@@ -671,7 +672,7 @@
 )
 class GraphModePostTrainingQuantTest(QuantizationTestCase):
     @_tmp_donotuse_dont_inline_everything
-    def test_single_layer(self):
+    def test_single_liner(self):
         r"""Compare the result of quantizing single linear layer in
         eager mode and graph mode
         """
@@ -686,9 +687,7 @@
                                self.calib_data)
 
         qconfig_dict = {
-            '': QConfig(
-                activation=default_observer,
-                weight=default_weight_observer)
+            '': default_qconfig
         }
         model_script = quantize_script(
             torch.jit.script(linear_model),
@@ -726,6 +725,33 @@
         result_script = model_script(self.img_data[0][0])
         self.assertEqual(result_eager, result_script)
 
+    @unittest.skip("This doesn't work right now, re-enable after fold_convbn is fixed")
+    def test_conv_bn(self):
+        r"""Compare the result of quantizing conv + bn layer in
+        eager mode and graph mode
+        """
+        # eager mode
+        conv_model = AnnotatedConvBnModel().eval()
+        conv_model_to_script = ConvBnModel().eval()
+        # copy the weight from eager mode so that we can
+        # compare the result of the two quantized models later
+        conv_model_to_script.conv.weight = torch.nn.Parameter(conv_model.conv.weight.detach())
+        fuse_modules(conv_model, ['conv', 'bn'], inplace=True)
+        model_eager = quantize(conv_model, default_eval_fn,
+                               self.img_data)
+        qconfig_dict = {
+            '': default_qconfig
+        }
+        model_script = quantize_script(
+            torch.jit.script(conv_model_to_script),
+            qconfig_dict,
+            default_eval_fn,
+            [self.img_data],
+            inplace=False)
+        result_eager = model_eager(self.img_data[0][0])
+        result_script = model_script(self.img_data[0][0])
+        self.assertEqual(result_eager, result_script)
+
     @unittest.skip("quantization for inlined linear is not working right now")
     def test_nested(self):
         # Eager mode