replacing model head failure
Author: quantitative-technologies
Pull request: no

## Environment info

- `transformers` version: 4.11.0.dev0
- Platform: Linux-5.4.104+-x86_64-with-Ubuntu-18.04-bionic
- Python version: 3.7.11
- PyTorch version (GPU?): 1.9.0+cu102 (True)
- Tensorflow version (GPU?): 2.6.0 (True)
- Flax version (CPU?/GPU?/TPU?): not installed (NA)
- Jax version: not installed
- JaxLib version: not installed
- Using GPU in script?: yes, but not necessary
- Using distributed or parallel set-up in script?: no

### Who can help

@LysandreJik

## Information

Model I am using (Bert, XLNet ...): bert-base-uncased

But I have also seen the same behaviour with albert-large-v2

The problem arises when using:

My own code


The tasks I am working on is:
* [ ] an official GLUE/SQUaD task: (give the name)
* [ x] my own task or dataset: (give details below)

## To reproduce

Steps to reproduce the behavior:

1. Initialize a CLM model
2. Replace the head of this model with a Masked LM head (following the [directions](https://github.com/huggingface/transformers/issues/8901#issuecomment-737300387) of @LysandreJik). 

There is a [notebook](https://colab.research.google.com/drive/194l9a5itoOcf1DTXPv1C6TftNTb-KB6y?usp=sharing) with complete code.

Here is the code for replacing the head.

```
from transformers import AutoModelForSequenceClassification, BertForMaskedLM

clm_model = AutoModelForSequenceClassification.from_pretrained(CHECKPOINT)
clm_model_path = f'clm_model.{CHECKPOINT}'
clm_model.save_pretrained(clm_model_path)

set_seed(INITIALIZATION_SEED)
mlm_model_from_clm = BertForMaskedLM.from_pretrained(clm_model_path)
mlm_model_from_clm_path = f'mlm_model_from_clm.{CHECKPOINT}.{INITIALIZATION_SEED}'
mlm_model_from_clm.save_pretrained(mlm_model_from_clm_path)

%env MLM_MODEL_FROM_CLM_PATH=$mlm_model_from_clm_path
```

<!-- If you have code snippets, error messages, stack traces please provide them here as well.
     Important! Use code tags to correctly format your code. See https://help.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks#syntax-highlighting
     Do not use screenshots, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.-->

## Expected behavior

Expect the above model to be identical to the model obtained directly from the hub:

```
from transformers import AutoModelForMaskedLM, AutoTokenizer, set_seed

set_seed(INITIALIZATION_SEED)
mlm_model = AutoModelForMaskedLM.from_pretrained(CHECKPOINT)
mlm_model_path = f'mlm_model.{CHECKPOINT}.{INITIALIZATION_SEED}'
mlm_model.save_pretrained(mlm_model_path)

%env MLM_MODEL_PATH=$mlm_model_path
```

However, they are not the same:

```
compare_two_models(mlm_model, mlm_model_from_clm)
```

shows that the models have the same weights, but not for the masked LM head. 

```
Models differ on layer 197: cls.predictions.bias
Models differ on layer 198: cls.predictions.transform.dense.weight
Models differ on layer 199: cls.predictions.transform.dense.bias
Models differ on layer 200: cls.predictions.transform.LayerNorm.weight
Models differ on layer 201: cls.predictions.transform.LayerNorm.bias
```

I at least expected `mlm_model_from_clm` to be ready to use for the masked LM task. However, it is not at all:

Using the huggingface script `transformers/examples/pytorch/language-modeling/run_mlm.py` to determine MLM perplexity, the `mlm_model` has perplexity 9.012 as expected; however, the `mlm_model_from_clm` obtained by replacing the head has perplexity > 50,000. 

All of the steps are done in the notebook referenced above.


Comments:
I am not sure how `compare_two_models` works but it seems that the pooling layer (used for the CLS token) is part of the base BERT model but not the other CLM model architecture.

See here for details of the pooling layer (the authors mistakenly forgot to mention this in the original BERT paper AFAIK): https://github.com/huggingface/transformers/issues/7540#issuecomment-704155218

In fact these two snippets from how the encoder part gets initialized in the two classes explain why that is the case:

BertForSequenceClassification:
https://github.com/huggingface/transformers/blob/c164c651dc382635f1135cf843e8fbd523d5e293/src/transformers/models/bert/modeling_bert.py#L1487-L1494

BertMaskedLM:
https://github.com/huggingface/transformers/blob/c164c651dc382635f1135cf843e8fbd523d5e293/src/transformers/models/bert/modeling_bert.py#L1286-L1289



> I am not sure how `compare_two_models` works but it seems that the pooling layer (used for the CLS token) is part of the base BERT model but not the other CLM model architecture.
> 
> See here for details of the pooling layer (the authors mistakenly forgot to mention this in the original BERT paper AFAIK): [#7540 (comment)](https://github.com/huggingface/transformers/issues/7540#issuecomment-704155218)

OK, thanks. I was wondering what the pooling layer was for. 

You could see the code in the notebook I referenced above, but I will put it here for convenience:

```
import numpy as np

def compare_two_models(m1, m2):
  params1 = list(m1.named_parameters())
  params2 = list(m2.named_parameters())
  layers1 = [(name, params.shape) for name, params in params1]
  layers2 = [(name, params.shape) for name, params in params2]

  if layers1 != layers2:
    print('Models have different architectures')
    return False

  def _compare_layers(p1, p2):
    for i, ((name1, params1), (name2, params2)) in enumerate(zip(p1, p2)):
      assert name1 == name2
      yield i, name1, np.all(params1.detach().numpy() == params2.detach().numpy())

  for i, n, same in _compare_layers(params1, params2):
    if not same:
      print(f'Models differ on layer {i}: {n}')
```

However, I believe you missed the point of my issue. *Both* `mlm_model` and `mlm_model_from_clm` are masked LM models, and *neither* has a pooling layer. Their architecture is the same. The issue is that the MLM head of `mlm_model_from_clm` is not getting initialized correctly. 

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/master/CONTRIBUTING.md) are likely to be ignored.