Repository: pytorch
Issue: Select parameters and buffers by pattern (using fnmatch or re) 
Labels: module: nn,module: optimizer,triaged

### 🚀 The feature, motivation and pitch

I'm working on serializing training configuration, and one sticking point is the definition of the parameter groups in the optimizer. Everything except the parameters are easily serializable. 

A simple feature to fix this would be to add a `pattern` option to `_named_members`,` parameters`, `named_parameters`, `buffers`, `named_buffers` in nn.Module.
The standard python libraries [fnmatch](https://docs.python.org/3/library/fnmatch.html) or [re](https://docs.python.org/3/library/re.html) provide simple and familiar ways  to create those patterns.

It can be done in a single or couple lines in `_named_members` (see additional context).
All the other functions (` parameters`, `named_parameters`, `buffers`, `named_buffers`) directly depend on `_named_members` .

I'm making this Feature Request before a Pull Request because I'm not familiar with how proposal are managed for pytorch. I can make a Pull Request if this is a good idea.

Example of use:
Using the examples on doc https://pytorch.org/docs/stable/optim.html

The following code is not easily serializable:
```python
optim.SGD([
   {'params': model.base.parameters(), 'lr': 1e-2},
   {'params': model.classifier.parameters()}
], lr=1e-3, momentum=0.9)
```
But with a pattern (using fnmatch) it is:
```python
optim.SGD([
   {'params': model.parameters(pattern="base.*"),  'lr': 1e-2},
   {'params': model.parameters(pattern="classifier.*")}
], lr=1e-3, momentum=0.9)
```

And an example of configuration file could be:
```yaml
optimizers:
  - class: SGD
    params:
        - pattern: "base.*"
          lr: 1e-2
        - pattern: "classifier.*"
    lr: 1e-3
    momentum: 0.9
```

More complex pattern might not be possible with fnmatch:
```python
bias_params = [p for name, p in self.named_parameters() if 'bias' in name]
others = [p for name, p in self.named_parameters() if 'bias' not in name]

optim.SGD([
   {'params': others},
   {'params': bias_params, 'weight_decay': 0}
], weight_decay=1e-2, lr=1e-2)
```

But with but is possible with re
```python
optim.SGD([
   {'params': model.parameters(pattern=".*(?<!\.bias)")},
   {'params': model.parameters(pattern=".*\.bias"), 'weight_decay': 0} 
], weight_decay=1e-2, lr=1e-2)
```

With a configuration:
```yaml
optimizers:
  - class: SGD
    params:
        - pattern: '.*(?<!\.bias)'
        - pattern: '.*\.bias'
          weight_decay: 0
    weight_decay: 1e-2
    lr: 1e-2
```


Some open questions for me are:
1. Should it be included in pytorch or done externally ?
2. fnmatch or re ?
3. if re, fullmatch or match ?
4. either way, what flags would make sense?

### Alternatives

Possible alternatives
- Overwriting the nn.Module class externally (I'm already doing this)
- Adding filter after the call to named_parameters
- Can be added in new methods of nn.Module rather than named_parameters & co

However it might be quite useful (including in other context than setting an optimizer) it would be a shame not to have this by default.

### Additional context

See [_named_members in nn.Module](https://github.com/pytorch/pytorch/blob/v2.5.0-rc6/torch/nn/modules/module.py#L2591)

Proposal with fnmatch
```python
def _named_members(self, get_members_fn, prefix='', recurse=True, remove_duplicate: bool = True, pattern: Optional[str] = None):
        r"""Help yield various names + members of modules."""
        memo = set()
        modules = self.named_modules(prefix=prefix, remove_duplicate=remove_duplicate) if recurse else [(prefix, self)]
        for module_prefix, module in modules:
            members = get_members_fn(module)
            for k, v in members:
                if v is None or v in memo:
                    continue
                if remove_duplicate:
                    memo.add(v)
                name = module_prefix + ('.' if module_prefix else '') + k

               if pattern is None or fnmatch.fnmatch(name, pattern):  # Added line
                   yield name, v
```

Proposal with re. I used .fullmatch because it seemed more natural but could be discussed.
```python
def _named_members(self, get_members_fn, prefix='', recurse=True, remove_duplicate: bool = True, pattern: Optional[str] = None):
        r"""Help yield various names + members of modules."""
        if pattern is not None:  # Added line
            pattern = re.compile(pattern)  # Added line
        memo = set()
        modules = self.named_modules(prefix=prefix, remove_duplicate=remove_duplicate) if recurse else [(prefix, self)]
        for module_prefix, module in modules:
            members = get_members_fn(module)
            for k, v in members:
                if v is None or v in memo:
                    continue
                if remove_duplicate:
                    memo.add(v)
                name = module_prefix + ('.' if module_prefix else '') + k

               if pattern is None or pattern.fullmatch(name):  # Added line
                   yield name, v
```

The other functions (`parameters`, `named_parameters`, `buffers` and `named_buffers`) just have to be modified to pass the value of `pattern` forward.

cc @albanD @mruberry @jbschlosser @walterddr @mikaylagawarecki @vincentqb @janeyx99 @crcrpar