Export of `quantized::linear_relu` operator not supported with `torch.onnx.export`
Labels: module: onnx, triaged

### 🐛 Describe the bug

Unable to export a custom quantized torch model with fused modules.

```
import torch

# define NN architecture
class PredictLiquidationsV1(torch.nn.Module):
    def __init__(self, input_features, output_features, hidden_units):
        super().__init__()
        self.quant = torch.ao.quantization.QuantStub()
        self.linear1 = torch.nn.Linear(in_features=input_features, out_features=hidden_units)
        self.relu1 = torch.nn.ReLU()
        self.dropout1 = torch.nn.Dropout(p = 0.2)
        self.linear2 = torch.nn.Linear(in_features=hidden_units, out_features=hidden_units)
        self.relu2 = torch.nn.ReLU()
        self.dropout2 = torch.nn.Dropout(p = 0.4)
        self.linear3 = torch.nn.Linear(in_features=hidden_units, out_features=output_features)
        self.dequant = torch.ao.quantization.DeQuantStub()        
        
    def forward(self, x):
        x = self.quant(x)
        x = self.linear1(x)
        x = self.relu1(x)
        x = self.dropout1(x)
        x = self.linear2(x)
        x = self.relu2(x)
        x = self.dropout2(x)
        x = self.linear3(x)
        x = self.dequant(x)
        return x
    
    def fuse_model(self):
        torch.ao.quantization.fuse_modules(self, [['linear1', 'relu1']], inplace=True)
        torch.ao.quantization.fuse_modules(self, [['linear2', 'relu2']], inplace=True)
    
# instantiate the model
model_1 = PredictLiquidationsV1(input_features=41, output_features=1, hidden_units=82)

model_1.fuse_model()

loss_fn = torch.nn.BCEWithLogitsLoss()
optimizer = torch.optim.Adam(params=model_1.parameters(), lr=0.001, weight_decay=0.01)

model_1.qconfig = torch.ao.quantization.get_default_qat_qconfig('x86')
torch.ao.quantization.prepare_qat(model_1, inplace=True)

# Train model
# ...

quantized_model_1 = torch.ao.quantization.convert(model_1.eval(), inplace=False)
quantized_model_1.eval()
# Export the quantized_model_1 (requires onnx to be installed in the env)
torch.onnx.export(quantized_model_1,
                  torch.randn((1,41), requires_grad = True),
                  'quantized_model_1.onnx',
                  opset_version=16,
                  input_names=['input'],
                  output_names=['output'],
                  dynamic_axes={'input' : {0 : 'batch_size'}, 'output' : {0 : 'batch_size'}})
```

Stacktrace:
```
UnsupportedOperatorError                  Traceback (most recent call last)
/home/asad/Spectral/GitHubClone/modeler-credit-scoring-poc/zkml/model_experimantations/PT_NN_multiple_models_eval_v4_QAT.ipynb Cell 301 line 3
      1 quantized_model_1.eval()
      2 # Export the quantized_model_1 (requires onnx to be installed in the env)
----> 3 torch.onnx.export(quantized_model_1,
      4                   torch.randn((1,41), requires_grad = True).to(device),
      5                   '/home/asad/Spectral/GitHubClone/modeler-credit-scoring-poc/zkml/ezkl/onnx_quantized/quantized_model_1.onnx',
      6                   opset_version=16,
      7                   input_names=['input'],
      8                   output_names=['output'],
      9                   dynamic_axes={'input' : {0 : 'batch_size'}, 
     10                                   'output' : {0 : 'batch_size'}})

File ~/anaconda3/envs/zkml-ezkl/lib/python3.10/site-packages/torch/onnx/utils.py:511, in export(model, args, f, export_params, verbose, training, input_names, output_names, operator_export_type, opset_version, do_constant_folding, dynamic_axes, keep_initializers_as_inputs, custom_opsets, export_modules_as_functions, autograd_inlining)
    189 @_beartype.beartype
    190 def export(
    191     model: Union[torch.nn.Module, torch.jit.ScriptModule, torch.jit.ScriptFunction],
   (...)
    208     autograd_inlining: Optional[bool] = True,
    209 ) -> None:
    210     r"""Exports a model into ONNX format.
    211 
    212     If ``model`` is not a :class:`torch.jit.ScriptModule` nor a
   (...)
    508             All errors are subclasses of :class:`errors.OnnxExporterError`.
    509     """
--> 511     _export(
    512         model,
    513         args,
    514         f,
    515         export_params,
    516         verbose,
    517         training,
    518         input_names,
    519         output_names,
    520         operator_export_type=operator_export_type,
    521         opset_version=opset_version,
    522         do_constant_folding=do_constant_folding,
    523         dynamic_axes=dynamic_axes,
    524         keep_initializers_as_inputs=keep_initializers_as_inputs,
    525         custom_opsets=custom_opsets,
    526         export_modules_as_functions=export_modules_as_functions,
    527         autograd_inlining=autograd_inlining,
    528     )

File ~/anaconda3/envs/zkml-ezkl/lib/python3.10/site-packages/torch/onnx/utils.py:1577, in _export(model, args, f, export_params, verbose, training, input_names, output_names, operator_export_type, export_type, opset_version, do_constant_folding, dynamic_axes, keep_initializers_as_inputs, fixed_batch_size, custom_opsets, add_node_names, onnx_shape_inference, export_modules_as_functions, autograd_inlining)
   1574     dynamic_axes = {}
   1575 _validate_dynamic_axes(dynamic_axes, model, input_names, output_names)
-> 1577 graph, params_dict, torch_out = _model_to_graph(
   1578     model,
   1579     args,
   1580     verbose,
   1581     input_names,
   1582     output_names,
   1583     operator_export_type,
   1584     val_do_constant_folding,
   1585     fixed_batch_size=fixed_batch_size,
   1586     training=training,
   1587     dynamic_axes=dynamic_axes,
   1588 )
   1590 # TODO: Don't allocate a in-memory string for the protobuf
   1591 defer_weight_export = (
   1592     export_type is not _exporter_states.ExportTypes.PROTOBUF_FILE
   1593 )

File ~/anaconda3/envs/zkml-ezkl/lib/python3.10/site-packages/torch/onnx/utils.py:1134, in _model_to_graph(model, args, verbose, input_names, output_names, operator_export_type, do_constant_folding, _disable_torch_constant_prop, fixed_batch_size, training, dynamic_axes)
   1131 params_dict = _get_named_param_dict(graph, params)
   1133 try:
-> 1134     graph = _optimize_graph(
   1135         graph,
   1136         operator_export_type,
   1137         _disable_torch_constant_prop=_disable_torch_constant_prop,
   1138         fixed_batch_size=fixed_batch_size,
   1139         params_dict=params_dict,
   1140         dynamic_axes=dynamic_axes,
   1141         input_names=input_names,
   1142         module=module,
   1143     )
   1144 except Exception as e:
   1145     torch.onnx.log("Torch IR graph at exception: ", graph)

File ~/anaconda3/envs/zkml-ezkl/lib/python3.10/site-packages/torch/onnx/utils.py:672, in _optimize_graph(graph, operator_export_type, _disable_torch_constant_prop, fixed_batch_size, params_dict, dynamic_axes, input_names, module)
    669     _C._jit_pass_onnx_set_dynamic_input_shape(graph, dynamic_axes, input_names)
    670 _C._jit_pass_onnx_lint(graph)
--> 672 graph = _C._jit_pass_onnx(graph, operator_export_type)
    673 _C._jit_pass_onnx_lint(graph)
    674 _C._jit_pass_lint(graph)

File ~/anaconda3/envs/zkml-ezkl/lib/python3.10/site-packages/torch/onnx/utils.py:1929, in _run_symbolic_function(graph, block, node, inputs, env, operator_export_type)
   1925     if namespace == "onnx":
   1926         # Clone node to trigger ONNX shape inference
   1927         return graph_context.op(op_name, *inputs, **attrs, outputs=node.outputsSize())  # type: ignore[attr-defined]
-> 1929     raise errors.UnsupportedOperatorError(
   1930         symbolic_function_name,
   1931         opset_version,
   1932         symbolic_function_group.get_min_supported()
   1933         if symbolic_function_group
   1934         else None,
   1935     )
   1937 except RuntimeError:
   1938     if operator_export_type == _C_onnx.OperatorExportTypes.ONNX_FALLTHROUGH:

UnsupportedOperatorError: Exporting the operator 'quantized::linear_relu' to ONNX opset version 16 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.
```

### Versions

PyTorch version: 2.1.0.dev20230727+cu121
Is debug build: False
CUDA used to build PyTorch: 12.1
ROCM used to build PyTorch: N/A

OS: Ubuntu 22.04.3 LTS (x86_64)
GCC version: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Clang version: Could not collect
CMake version: Could not collect
Libc version: glibc-2.35

Python version: 3.10.12 (main, Jul  5 2023, 18:54:27) [GCC 11.2.0] (64-bit runtime)
Python platform: Linux-6.2.0-1011-gcp-x86_64-with-glibc2.35
Is CUDA available: False
CUDA runtime version: 11.5.119
CUDA_MODULE_LOADING set to: N/A
GPU models and configuration: Could not collect
Nvidia driver version: Could not collect
cuDNN version: Could not collect
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True

CPU:
Architecture:                    x86_64
CPU op-mode(s):                  32-bit, 64-bit
Address sizes:                   46 bits physical, 48 bits virtual
Byte Order:                      Little Endian
CPU(s):                          32
On-line CPU(s) list:             0-31
Vendor ID:                       GenuineIntel
Model name:                      Intel(R) Xeon(R) CPU @ 2.30GHz
CPU family:                      6
Model:                           63
Thread(s) per core:              2
Core(s) per socket:              16
Socket(s):                       1
Stepping:                        0
BogoMIPS:                        4599.99
Flags:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm invpcid_single pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat md_clear arch_capabilities
Hypervisor vendor:               KVM
Virtualization type:             full
L1d cache:                       512 KiB (16 instances)
L1i cache:                       512 KiB (16 instances)
L2 cache:                        4 MiB (16 instances)
L3 cache:                        45 MiB (1 instance)
NUMA node(s):                    1
NUMA node0 CPU(s):               0-31
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Mitigation; PTE Inversion
Vulnerability Mds:               Mitigation; Clear CPU buffers; SMT Host state unknown
Vulnerability Meltdown:          Mitigation; PTI
Vulnerability Mmio stale data:   Vulnerable: Clear CPU buffers attempted, no microcode; SMT Host state unknown
Vulnerability Retbleed:          Mitigation; IBRS
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; IBRS, IBPB conditional, STIBP conditional, RSB filling, PBRSB-eIBRS Not affected
Vulnerability Srbds:             Not affected
Vulnerability Tsx async abort:   Not affected

Versions of relevant libraries:
[pip3] numpy==1.25.0
[pip3] pytorch-triton==2.1.0+9e3e10c5ed
[pip3] torch==2.1.0.dev20230727+cu121
[pip3] torchaudio==2.1.0.dev20230727+cu121
[pip3] torchmetrics==1.0.1
[pip3] torchvision==0.16.0.dev20230727+cu121
[conda] blas                      1.0                         mkl  
[conda] mkl                       2023.1.0         h6d00ec8_46342  
[conda] mkl-service               2.4.0           py310h5eee18b_1  
[conda] mkl_fft                   1.3.6           py310h1128e8f_1  
[conda] mkl_random                1.2.2           py310h1128e8f_1  
[conda] numpy                     1.25.0          py310h5f9d8c6_0  
[conda] numpy-base                1.25.0          py310hb5e798b_0  
[conda] pytorch-triton            2.1.0+9e3e10c5ed          pypi_0    pypi
[conda] torch                     2.1.0.dev20230727+cu121          pypi_0    pypi
[conda] torchaudio                2.1.0.dev20230727+cu121          pypi_0    pypi
[conda] torchmetrics              1.0.1                    pypi_0    pypi
[conda] torchvision               0.16.0.dev20230727+cu121          pypi_0    pypi