Split LMBert model in two
Author: sgugger
Pull request: yes

As discussed in #4711, the `BertForMaskedLM` model should be split in two to avoid having two different labels argument, one model for causal LM, one for masked LM. This PR follows up on that and does the split.

It introduces a new `BertLMHeadModel` (also added to the `__init__` and the docs) with a test. As discussed, there is no deprecation warning if someone tries to use the `lm_labels` in `BertForMaskedLM` (since it was experimental), but an error message telling the user to use `BertLMHeadModel`.

I did not add `BertLMHeadModel` in the automodel logic since we probably want users to use causal models for this? Let me know if I should add it even if it's not the best model for that task.

I also removed `lm_labels` in the `EncoderDecoderModel` since it was only there to support that argument in `BertForMaskedLM` (which then removes the corresponding test).

Comments:
# [Codecov](https://codecov.io/gh/huggingface/transformers/pull/4874?src=pr&el=h1) Report
> Merging [#4874](https://codecov.io/gh/huggingface/transformers/pull/4874?src=pr&el=desc) into [master](https://codecov.io/gh/huggingface/transformers/commit/3ae2e86baffc1fea8b8b93695fb5a10941fd63dc&el=desc) will **decrease** coverage by `0.68%`.
> The diff coverage is `88.88%`.

[![Impacted file tree graph](https://codecov.io/gh/huggingface/transformers/pull/4874/graphs/tree.svg?width=650&height=150&src=pr&token=9qOlN6Hb1c)](https://codecov.io/gh/huggingface/transformers/pull/4874?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #4874      +/-   ##
==========================================
- Coverage   77.11%   76.43%   -0.69%     
==========================================
  Files         128      128              
  Lines       21651    21671      +20     
==========================================
- Hits        16697    16564     -133     
- Misses       4954     5107     +153     
```


| [Impacted Files](https://codecov.io/gh/huggingface/transformers/pull/4874?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/transformers/modeling\_encoder\_decoder.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9tb2RlbGluZ19lbmNvZGVyX2RlY29kZXIucHk=) | `92.20% <ø> (ø)` | |
| [src/transformers/modeling\_bert.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9tb2RlbGluZ19iZXJ0LnB5) | `88.17% <88.88%> (-0.12%)` | :arrow_down: |
| [src/transformers/modeling\_tf\_pytorch\_utils.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9tb2RlbGluZ190Zl9weXRvcmNoX3V0aWxzLnB5) | `8.72% <0.00%> (-81.21%)` | :arrow_down: |
| [src/transformers/modeling\_ctrl.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9tb2RlbGluZ19jdHJsLnB5) | `96.56% <0.00%> (-2.58%)` | :arrow_down: |
| [src/transformers/modeling\_xlnet.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9tb2RlbGluZ194bG5ldC5weQ==) | `76.31% <0.00%> (-2.31%)` | :arrow_down: |
| [src/transformers/modeling\_openai.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9tb2RlbGluZ19vcGVuYWkucHk=) | `79.51% <0.00%> (-1.39%)` | :arrow_down: |
| [src/transformers/trainer.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy90cmFpbmVyLnB5) | `38.26% <0.00%> (-1.18%)` | :arrow_down: |
| [src/transformers/benchmark/benchmark\_utils.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9iZW5jaG1hcmsvYmVuY2htYXJrX3V0aWxzLnB5) | `72.80% <0.00%> (-0.30%)` | :arrow_down: |
| [src/transformers/file\_utils.py](https://codecov.io/gh/huggingface/transformers/pull/4874/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9maWxlX3V0aWxzLnB5) | `73.79% <0.00%> (+0.40%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/huggingface/transformers/pull/4874?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/huggingface/transformers/pull/4874?src=pr&el=footer). Last update [3ae2e86...56a698f](https://codecov.io/gh/huggingface/transformers/pull/4874?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


It's possible to do it in a non-breaking way with a deprecation warning if a not-None `labels_lm` is passed to `BertForMaskedLM`. I was following the discussion of #4711 that implied it was okay to have a breaking change for this.

I'm fine with this PR. IMO, `BertForMaskedLM` was never really used before for causal language modeling except when using Bert in an encoder-decoder setting and the encoder-decoder code is not really released yet. Also since we keep the same names for the submodules `self.bert` and `self.cls`, there won't be any errors or inconsistencies when loading pre-trained weights into the Bert2Bert encoder-decoder. 

In my opinion, this change is necessary to have a clean separation between masked lm and causal lm (Reformer and Longformer will eventually run into the same issue).

The heavily used `BertForMaskedLM` for the normal masked encoder bert model does not change at all except for `lm_labels`, so that's good in terms of backward compatibility. 

One thing which is problematic though is that the `MODEL_WITH_LM_HEAD_MAPPING` contains a mixture of causal models and masked encoder models at the moment: https://github.com/huggingface/transformers/blob/02e5f79662d72cccdca81a47e3001a5f6d36e5b1/src/transformers/modeling_auto.py#L187

Now since Bert has both a causal model and a masked encoder model we need two mappings. 

I would suggest here to create 2 new mappings `MODEL_FOR_MASKED_LM_MAPPING` and `MODEL_FOR_CAUSAL_LM_MAPPING` and two new AutoModels: `AutoModelForMaksedLM` , `AutoModelForCausalLM`  and for now keep `AutoModelWithLMHead` as it is and add a depreciated warning to it. 

We can add `BertLMHeadModel` to `MODEL_FOR_CAUSAL_LM_MAPPING` and change to `AutoModelForCausalLM` in the encoder-decoder model. Also @thomwolf and @julien-c here

I agree with @patrickvonplaten on the need to split `AutoModelWithLMHead` in two. Note that if the name `AutoModelForCausalLM` is picked, we should then rename (with a deprecation first of course) all `ModeltypeLMHeadModel` to `ModeltypeForCausalLM` for consistency (and clarity since just saying it has an LM head doesn't tell us if it's intended to be masked or causal).

I agree that having two additional `AutoXXX` classes for the distinction between masked/causal would be nice. We should, however, keep the `AutoModelWithLMHead` class available for backwards compatibility.

I don't agree with renaming all causal model with language modeling heads `XXXForCausalLM`. It would be more consistent, but is an aesthetic change with a very big breaking change. Even adding aliases to keep backwards compatibility would create a large overhead for the user, in my opinion, as all those classes would exist twice when importing from the library.

In that case I would advocate to keep `AutoModelWithLMHead` for causal language models and only add an `AutoModelForMaskedLM`. Consistency is cosmetic, I agree, but it also helps not confusing beginners.

1) For now, I think the best solution would be to keep `AutoModelForMaskedLM` as it is and add two new `AutoXXX` classes. The EncoderDecoderModel would be the first model to use  `AutoModelForCausalLM` in its code. 

`AutoModelWithLMHead` is heavily used for all kinds of masked bert encoder models, so if we create an `AutoModelForMaskedLM` and move `BertForMaskedLM` there, we would have a lot of breaking change. I think we could add a depreciation warning to `AutoModelWithLMHead` though.  

2) I'm a bit indifferent to renaming all other model classes. While I'm also a big fan of consistency I agree with @LysandreJik in that I think it's a big user-facing API change that is not really urgent atm.

In the short term, I would advocate only exposing the classical "masked-lm" flavour of BERT through AutoModelWithLMHead (as is done in this PR), and not even documenting/adding BertLMHeadModel to the `__init__`, as it's only used as a building block to other models.

In the longer term, I'd be ok with creating `AutoModelFor{Masked,Causal}LM` (name TBD for the second one) and not even creating a deprecation for `AutoModelWithLMHead`, forcing users to explicitly choose one or the other. This would need to be a major release though.

@julien-c as long as we do a major release for the AutoModel renaming, I'm all for this!

> In the short term, I would advocate only exposing the classical "masked-lm" flavour of BERT through AutoModelWithLMHead (as is done in this PR), and not even documenting/adding BertLMHeadModel to the `__init__`, as it's only used as a building block to other models.
> 
> In the longer term, I'd be ok with creating `AutoModelFor{Masked,Causal}LM` (name TBD for the second one) and not even creating a deprecation for `AutoModelWithLMHead`, forcing users to explicitly choose one or the other. This would need to be a major release though.

For the encoder decoder models, I think we need `BertLMHeadModel` in the `init` and we would also need a `AutoModelForCausalLM`. Here: https://github.com/huggingface/transformers/blob/29c36e9f3678702e5ffd3fe2f1c9f6c1d6672578/src/transformers/modeling_encoder_decoder.py#L160 we need to instantiate a `BertWithCausalLM`

I'm fine either way, I think you guys got all the important issues (backward compatibility versus cleanly building the future). I like what @patrickvonplaten and @julien-c are proposing.

Fixed conflicts and followed @julien-c advice. @LysandreJik or @patrickvonplaten, could you do one final review just to make sure everything is fine to merge?

This currently breaks the encoder-decoder framework `from_encoder_decoder_pretrained()` method. Will do a PR tomorrow to fix it.