Add W&B backend for hyperparameter sweep
Author: AyushExel
Pull request: yes

# Add support for W&B hyperparameter sweep
This PR:
* allows using wandb for running hyperparameter search.
* The runs are visualized on W&B sweeps dashboard
* This supports runnning sweeps on parallel devices, all reporting to the same central dashboard.

### Usage
**To run new a hyperparameter search:**
```
trainer.hyperparameter_search(
    backend="wandb", 
    project="transformers_sweep", # name of the project
    n_trials=5,
    metric="eval/loss", # metric to be optimized, default 'eval/loss'. A warning is raised if the passed metric is not found
)
```
This outputs a sweep id. Eg. `my_project/sweep_id`

**To run sweeps on parallel devices:**
Just pass sweep id which you want to run parallel
```
trainer.hyperparameter_search(
    backend="wandb", 
    sweep_id = "my_project/sweep_id"
)
```
## Example sweep [[Dashboard](https://wandb.ai/cayush/teansformers_sweep/sweeps/xrmhkad5?workspace=user-cayush)] - runs from 2 devices were reported in this dashboard.
![Screenshot from 2021-12-01 14-14-09](https://user-images.githubusercontent.com/15766192/144201225-81b57993-a718-4ac0-9078-02b6640d21b1.png)

## Before submitting
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [x] Did you read the [contributor guideline](https://github.com/huggingface/transformers/blob/master/CONTRIBUTING.md#start-contributing-pull-requests),
      Pull Request section?
- [ ] Was this discussed/approved via a Github issue or the [forum](https://discuss.huggingface.co/)? Please add a link
      to it if that's the case.
- [ ] Did you make sure to update the documentation with your changes? Here are the
      [documentation guidelines](https://github.com/huggingface/transformers/tree/master/docs), and
      [here are tips on formatting docstrings](https://github.com/huggingface/transformers/tree/master/docs#writing-source-documentation).
- [ ] Did you write any new necessary tests?

### Regarding tests
the testing suite didn't include any tests as it is tested on wandb's side. Same can be done for the sweeps integrations

## Who can review?
Tagging Boris as he did the W&B integration and Sylvain as this PR introduces changes in integrations and trainer
@borisdayma @sgugger


Comments:
Thanks for your PR! I will take a look at your PR and help out on tests after the holiday break - first week of January! Thanks for your patience.

@LysandreJik Hey! any updates on this?

Thank you for your PR, @AyushExel! All that remains is testing.

You can see an example of how it was done for `ray` and `sigopt` here: https://github.com/huggingface/transformers/blob/f21bc4215aa979a5f11a4988600bc84ad96bef5f/tests/test_trainer.py#L1582-L1692

Ideally, we would move all of that to an `integrations` folder in the [tests](https://github.com/huggingface/transformers/tree/master/tests) folder. Then we could add a `test_wandb_integration.py` which would contain a similar integration test to those above.

The idea is that when the test fail, we ping the author(s) of the PRs, this way we share the burden of the maintenance. 

Does that work for you?

@LysandreJik sounds good!
I've added the tests to the same file `test_trainer.py` for now. Do you want me to move it out to integrations before merging or is that a future project?

Thanks for adding the test! Can it run out of the box if wandb is installed? If I recall correctly there is some login to do no?

@sgugger I've kept anonymous mode on by default in the test so it should run. Please, Let me know if that's not the case and I'll think of a workaround

Having the test in is the important part, we can move to `integrations` in a future PR!

I'm getting the following error when running it:

```
test_trainer.py::TrainerHyperParameterWandbIntegrationTest::test_hyperparameter_search FAILED [100%]
tests/test_trainer.py:1724 (TrainerHyperParameterWandbIntegrationTest.test_hyperparameter_search)
self = <tests.test_trainer.TrainerHyperParameterWandbIntegrationTest testMethod=test_hyperparameter_search>

    def test_hyperparameter_search(self):
        class MyTrialShortNamer(TrialShortNamer):
            DEFAULTS = {"a": 0, "b": 0}
    
        def hp_space(trial):
    
            return {
                "method": "random",
                "metric": {},
                "parameters": {
                    "a": {"distribution": "uniform", "min": 1e-6, "max": 1e-4},
                    "b": {"distribution": "int_uniform", "min": 1, "max": 6},
                },
            }
    
        def model_init(config):
            if config is None:
                a = 0
                b = 0
            else:
                a = config["a"]
                b = config["b"]
            model_config = RegressionModelConfig(a=a, b=b, double_output=False)
    
            return RegressionPreTrainedModel(model_config)
    
        def hp_name(params):
            return MyTrialShortNamer.shortname(params)
    
        with tempfile.TemporaryDirectory() as tmp_dir:
            trainer = get_regression_trainer(
                output_dir=tmp_dir,
                learning_rate=0.1,
                logging_steps=1,
                evaluation_strategy=IntervalStrategy.EPOCH,
                save_strategy=IntervalStrategy.EPOCH,
                num_train_epochs=4,
                disable_tqdm=True,
                load_best_model_at_end=True,
                logging_dir="runs",
                run_name="test",
                model_init=model_init,
            )
            trainer.hyperparameter_search(
>               direction="minimize", hp_space=hp_space, hp_name=hp_name, backend="wandb", n_trials=4, anonymous="must"
            )

test_trainer.py:1769: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../src/transformers/trainer.py:1813: in hyperparameter_search
    best_run = backend_dict[backend](self, n_trials, direction, **kwargs)
../src/transformers/integrations.py:406: in run_hp_search_wandb
    sweep_id = wandb.sweep(sweep_config, project=project, entity=entity) if not sweep_id else sweep_id
../../../../transformers/.env/lib/python3.6/site-packages/wandb/sdk/wandb_sweep.py:101: in sweep
    wandb_login._login(_silent=True)
../../../../transformers/.env/lib/python3.6/site-packages/wandb/sdk/wandb_login.py:274: in _login
    wlogin.prompt_api_key()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <wandb.sdk.wandb_login._WandbLogin object at 0x7efde99d17b8>

    def prompt_api_key(self):
        key, status = self._prompt_api_key()
        if status == ApiKeyStatus.NOTTY:
            directive = (
                "wandb login [your_api_key]"
                if self._settings._cli_only_mode
                else "wandb.login(key=[your_api_key])"
            )
>           raise UsageError("api_key not configured (no-tty). call " + directive)
E           wandb.errors.UsageError: api_key not configured (no-tty). call wandb.login(key=[your_api_key])

../../../../transformers/.env/lib/python3.6/site-packages/wandb/sdk/wandb_login.py:209: UsageError
```

Should we setup an API key?

@LysandreJik I guess there are 2 options here.
* Add wandb api key as a github secret and run `wandb login $secret_key` in the CI test workflow setup
* Or Setup a dummy account meant only for test and login directly `wandb login key` without having to worry about exposing the api key

Hey @LysandreJik were you able to run the tests?

Hey @AyushExel, I think we can go with the first solution:
- Add wandb api key as a github secret and run wandb login $secret_key in the CI test workflow setup

Would you be able to share an API key we could register in secrets to get this working?

@LysandreJik each wandb account has an api key which is accessible at [wandb.ai/authorize](https://wandb.ai/authorize)

@LysandreJik it probably makes more sense for you to create a dummy wandb account with a hugging face email that you control and use this accounts API key :) 

Ok will give it a look!

I've added a key for a dummy account in the `WANDB_API_KEY` secret of this repo. Is it possible for you to leverage it in Github Actions and to pass it to this test in your PR?

@LysandreJik Yes..In github actions you can run `wandb login YOUR_SECRET_ WANDB_API_KEY` ,it will log you in on that system and the tests will execute fine

Right, I was asking if you could please add it to the GitHub action workflows in your PR. I've added the secret, you should be able to handle it from your PR now. 

The jobs that run with integrations are the following:
- https://github.com/huggingface/transformers/blob/master/.github/workflows/self-scheduled.yml#L21
- https://github.com/huggingface/transformers/blob/master/.github/workflows/self-scheduled.yml#L253

If this is not possible, then I will open a PR on your PR.

Thank you.

Okay got it.. I'm trying to set it up

@LysandreJik I've added the wandb login command in both the tests you mentioned. Can you please take a look?