Fluent API for training arguments
Author: apohllo
Pull request: no

### Feature request

Provide a fluent API for defining the training arguments for the Trainer class.
Instead of writing:
```
arguments = TrainingArguments(output_dir="output", 
                              do_train=True, 
                              do_eval=True, 
                              evaluation_strategy='epoch',
                              per_device_train_batch_size=16,
                              per_device_eval_batch_size=16,
                              learning_rate=5e-05,
                              num_train_epochs=1,
                              logging_first_step=True,
                              logging_strategy='steps',
                              logging_steps=50,
                              save_strategy='epoch',
                              fp16=True,
                              )
```

one would be able to write:

```
arguments = TrainingArguments("output").
  evaluate(strategy='epoch', batch_size=16).
  logging(first_step=True, strategy='steps', steps=50)...
```

### Motivation

Currently, the arguments submitted to Trainers are defined in a separate class, which is fine.
Yet the constructor of that class has a tone of arguments. Some of these arguments naturally stick together.

Providing a fluent API, with related arguments provided in one call, would have the following benefits:
* One giant call to the constructor would be divided into smaller calls, making the documentation of the method much
   easier to read;
* It would be possible to chain argument construction - i.e. it would be easy to define a default set of options 
   (different than the defaults provided by the library) and then modify them according to some additional
   requirements, e.g. changing LR would be just a single call on the predefined arguments object. Currently, it is 
   obtained by changing the value of one of the many arguments, which is harder to spot, if that number is large.
* Related arguments would be grouped together via call, rather than prefix (e.g. logging),
* Related arguments could be checked together, e.g. currently `do_evaluate` is ignored if `evaluation_strategy` is 
   not `None`
   with fluent API an exception could be raised if someone set `evaluate=False` and sets `evaluation_strategy` to some
   meaningful value (this is actually possible to do currently, but would be much easier to implement if there's 
   separate call for that.

### Your contribution

Implementing the basic fluent API is easy (e.g. each argument has it's own corresponding method - no change to the API of the constructor), but does not fulfill all the objectives. Yet I could provide such a PR, as a starter for the more user friendly API.

Comments:
While I understand the idea of grouping related arguments together, the proposed approach is very functional, which is not something we use anywhere in the Transformers library. So this API would be at odds with the rest of Transformers.

Happy to explore other ways to group related arguments together however, if you have other ideas.

That would definitely help in terms of documentation and not having to scroll each time to find a description of the argument. And besides, it would help to shorten the names of the arguments.

However, I would add some type of `common` arguments, either in the main constructor or in the dedicated method, because some of the arguments can be shared between different stages, and redefining them in each method could be misleading and a little ambiguous for the library itself, especially if they have different values.

It could also help in integrating different argument passing packages, like `hydra`, in which we can group the arguments in the YAML file, which seems to be a more maintainable solution in comparison to the common `argparse` built-in package. As far as I know, it is widely used in corpos, such as NVIDIA.

This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md) are likely to be ignored.

I don't understand the argument against that approach, TBH. This is a builder pattern, which is very common in OOP. E.g. `StringBuilder` in Java uses almost the same idea (you modify the object and as far as I remember the builder is not returned). It's not functional, since you do not provide a function as an argument (i.e. this is what I understand as "functional"). 

Anyway, even though that approach is not present in Transformers, maybe it's a good moment to introduce it?
Currently, the API and the documentation of argument objects is harder and harder to use. The arguments are not sorted and there are 96!!! arguments in the TrainingArguments object. I am using the API and I am teaching NLP and OOP. When I introduce the object to my students, they have very hard time to go through and understand all the options. Many of them are completely unrelated to the training process (from the ML perspective). But the user cannot differentiation between the important and unimportant arguments.

So I think the argument classes should be extended with the suggested mechanism or a different mechanism which supports modularisation.

Hi @apohllo Sorry for the delay on this. Would something like in the PR linked above work for you?

This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md) are likely to be ignored.