Repository: pytorch
Issue: Unable to save model after removing weight normalization due to remaining hooks
Labels: module: serialization,triaged

### 🐛 Describe the bug

When converting models for inference, I encountered an issue where I couldn't save the converted model due to remaining hooks. Here's a minimal example reproducing the issue:

```python
import torch
from torch.nn import Conv1d
from torch.nn.utils.parametrizations import weight_norm
from torch.nn.utils.parametrize import remove_parametrizations
from io import BytesIO

conv = weight_norm(Conv1d(4, 4, 3))
print(conv._load_state_dict_pre_hooks)
conv = remove_parametrizations(module=conv, tensor_name="weight")
print(conv._load_state_dict_pre_hooks)
sink = BytesIO()
torch.save(conv, sink)  # exception
```

Output & exception:

```
OrderedDict([(0, <torch.nn.modules.module._WrappedHook object at 0x7f7c14f01b70>)])
OrderedDict([(0, <torch.nn.modules.module._WrappedHook object at 0x7f7c14f01b70>)])
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    torch.save(conv, sink)
  File ".venv/lib/python3.10/site-packages/torch/serialization.py", line 652, in save
    _save(obj, opened_zipfile, pickle_module, pickle_protocol, _disable_byteorder_record)
  File ".venv/lib/python3.10/site-packages/torch/serialization.py", line 864, in _save
    pickler.dump(obj)
AttributeError: Can't pickle local object 'weight_norm.<locals>._weight_norm_compat_hook'
```

### Analysis

The issue stems from the fact that the removable handle provided by _register_load_state_dict_pre_hook is discarded in the weight_norm function:

https://github.com/pytorch/pytorch/blob/0eba7e5451ac53c3e75be258236f3a11acaf2c1c/torch/nn/utils/parametrizations.py#L397

The hook registration function is defined here:

https://github.com/pytorch/pytorch/blob/0eba7e5451ac53c3e75be258236f3a11acaf2c1c/torch/nn/modules/module.py#L2248-L2252

### Possible solution

If we could figure out a way to store parameter_name-hook pair in parametrized module, we could then modify `remove_parametrizations` to look up hook that should be removed using the parameter name, and remove the hook.

### Versions

```
PyTorch version: 2.4.1+cu121
Is debug build: False
CUDA used to build PyTorch: 12.1
ROCM used to build PyTorch: N/A
                                                                                                                                                                                                
OS: Ubuntu 22.04.4 LTS (x86_64)
GCC version: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Clang version: 14.0.0-1ubuntu1.1
CMake version: version 3.27.2
Libc version: glibc-2.35
                                                                                                                                                                                                
Python version: 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (64-bit runtime)
Python platform: Linux-5.15.153.1-microsoft-standard-WSL2-x86_64-with-glibc2.35
Is CUDA available: True
CUDA runtime version: 11.5.119
CUDA_MODULE_LOADING set to: LAZY
GPU models and configuration: GPU 0: NVIDIA GeForce RTX 3070 Ti
Nvidia driver version: 546.12
cuDNN version: Probably one of the following:
/usr/lib/x86_64-linux-gnu/libcudnn.so.9.1.0
/usr/lib/x86_64-linux-gnu/libcudnn_adv.so.9.1.0
/usr/lib/x86_64-linux-gnu/libcudnn_cnn.so.9.1.0
/usr/lib/x86_64-linux-gnu/libcudnn_engines_precompiled.so.9.1.0
/usr/lib/x86_64-linux-gnu/libcudnn_engines_runtime_compiled.so.9.1.0
/usr/lib/x86_64-linux-gnu/libcudnn_graph.so.9.1.0
/usr/lib/x86_64-linux-gnu/libcudnn_heuristic.so.9.1.0
/usr/lib/x86_64-linux-gnu/libcudnn_ops.so.9.1.0
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:                      48 bits physical, 48 bits virtual
Byte Order:                         Little Endian
CPU(s):                             32
On-line CPU(s) list:                0-31
Vendor ID:                          AuthenticAMD
Model name:                         AMD Ryzen 9 5950X 16-Core Processor
CPU family:                         25
Model:                              33
Thread(s) per core:                 2
Core(s) per socket:                 16
Socket(s):                          1
Stepping:                           2
BogoMIPS:                           6800.06
Flags:                              fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl tsc_reliable nonstop_tsc cpuid extd_apicid pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy svm cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext perfctr_core ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves clzero xsaveerptr arat npt nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold v_vmsave_vmload umip vaes vpclmulqdq rdpid fsrm
Virtualization:                     AMD-V
Hypervisor vendor:                  Microsoft
Virtualization type:                full
L1d cache:                          512 KiB (16 instances)
L1i cache:                          512 KiB (16 instances)
L2 cache:                           8 MiB (16 instances)
L3 cache:                           32 MiB (1 instance)
Vulnerability Gather data sampling: Not affected
Vulnerability Itlb multihit:        Not affected
Vulnerability L1tf:                 Not affected
Vulnerability Mds:                  Not affected
Vulnerability Meltdown:             Not affected
Vulnerability Mmio stale data:      Not affected
Vulnerability Retbleed:             Not affected
Vulnerability Spec rstack overflow: Mitigation; safe RET, no microcode
Vulnerability Spec store bypass:    Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:           Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:           Mitigation; Retpolines, IBPB conditional, IBRS_FW, STIBP conditional, RSB filling, PBRSB-eIBRS Not affected
Vulnerability Srbds:                Not affected
Vulnerability Tsx async abort:      Not affected

Versions of relevant libraries:
[pip3] numpy==2.1.2
[pip3] torch==2.4.1
[pip3] triton==3.0.0
[conda] Could not collect
```

cc @mruberry @mikaylagawarecki