Interpretation of output from fine-tuned BERT for Masked Language Modeling.
Author: aurooj
Pull request: no

## ❓ Questions & Help
Hi, 

I need some help with interpretation of the output from a fine-tuned bert model. 
Here is what I have done so far:
I used `run_lm_finetuning.py` to fine-tune 'bert-base-uncased' model on my domain specific text data.

I fine-tuned the model for 3 epochs, and I get the following files after fine-tuning the process:

- config.json
- pytorch_model.bin
- training_args.bin

along with some other files such as :
- special_tokens_map.json
- tokenizer_config.json
- vocab.txt

I am loading this fine-tuned model using the following code:
````
config_class, model_class, tokenizer_class = BertConfig, BertForMaskedLM, BertTokenizer

config = config_class.from_pretrained('path/to/config/dir/config.json')       
self.text_feature_extractor = model_class.from_pretrained('path/to/fine-tuned-model/pytorch_model.bin',
                                            from_tf=bool('.ckpt' in 'path/to/fine-tuned-model/pytorch_model.bin'),
                                            config=config)
````

And get output from the model like this:
`raw_out_q = self.text_feature_extractor(q)
`
where q is a padded batch of shape B, SEQ_L tokenized by pre-trained BertTokenizer with the following line of code:
`sentence_indices = self.tokenizer.encode(sentence, add_special_tokens=True)`

The output from the fine-tuned model is a tuple of 2 objects: 
First one is of shape `(B, SEQ_L, 30522)`
The second object is however another tuple of 13 tensors: Each tensor is of shape` (B, SEQ_L, 768)
`

Now here are my questions: 
How should I interpret this output coming from the model?
For the first tensor, I know vocab_size for bert_base_uncased was 30522, but what does it represent here?
For the second tuple, do these 13 tensors represent output from each bert layer? 

For each sentence, I want a sentence-level feature and word-level features. I am aware that sentence-level feature is usually the first position in the sequence (against the "[CLS]" token), but any clarification will be super helpful and much appreciated.

Thanks!
<!-- A clear and concise description of the question. -->


Comments:
My bad! Should have read the documentation for BertForMaskedLM code:
```
Outputs: `Tuple` comprising various elements depending on the configuration (config) and inputs:
        **masked_lm_loss**: (`optional`, returned when ``masked_lm_labels`` is provided) ``torch.FloatTensor`` of shape ``(1,)``:
            Masked language modeling loss.
        **ltr_lm_loss**: (`optional`, returned when ``lm_labels`` is provided) ``torch.FloatTensor`` of shape ``(1,)``:
            Next token prediction loss.
        **prediction_scores**: ``torch.FloatTensor`` of shape ``(batch_size, sequence_length, config.vocab_size)``
            Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
        **hidden_states**: (`optional`, returned when ``config.output_hidden_states=True``)
            list of ``torch.FloatTensor`` (one for the output of each layer + the output of the embeddings)
            of shape ``(batch_size, sequence_length, hidden_size)``:
            Hidden-states of the model at the output of each layer plus the initial embedding outputs.
        **attentions**: (`optional`, returned when ``config.output_attentions=True``)
            list of ``torch.FloatTensor`` (one for each layer) of shape ``(batch_size, num_heads, sequence_length, sequence_length)``:
            Attentions weights after the attention softmax, used to compute the weighted average in the self-attention heads.
```

The second tuple of tensors is the hidden_states from each layer + initial embedding layer. (num_hidden_layers=12) in config file. 
Can someone please confirm the layer order? Should I extract output from top or bottom?

I have seen code examples using features from last 4 layers by indices like -1, -2, -3, -4, but just want to sure that it is what I should be doing as well.

Thanks!

Okay. I understand the output now and selecting only the last hidden representation, but my gpu get filled if I set config.output_hidden_states=True for the fine-tuned LM model (as it returns the output from all hidden layers). How can I make it to return output from the selected layers only?

Hi, thank you for sharing. Just want to ensure that the **last hidden state** could be derived by querying from indices = -1? I am super confused that there are 13 hidden states, I do not know whether the first one or last one is the last hidden states. Hope for your reply. Thanks!

Yeah, I have the same confusion too. But considering the convention people used in other examples and/or issues, I am considering index = -1 belongs to the last hidden layer. 
Anyone is welcome to correct me if I am wrong. 

@aurooj, @mingbocui you're both right: the last hidden state corresponds to the index -1. The index 0 corresponds to the output of the embedding layer, the index 1 corresponds to the output of the first layer, etc.

@LysandreJik Thanks for your reply. Can you please help me with this?

> Okay. I understand the output now and selecting only the last hidden representation, but my gpu get filled if I set config.output_hidden_states=True for the fine-tuned LM model (as it returns the output from all hidden layers). How can I make it to return output from the selected layers only?



We currently have no way of returning the output of the selected layers only. You would have to manually re-implement the forward method of BERT and output only the layers you're interested in.

If you're looking to fine-tune BERT with the `bert-base-uncased` checkpoint and are concerned about the memory usage, maybe you could use DistilBERT with the `distilbert-base-uncased` checkpoint, which is based on BERT but has a much lower memory usage.

Oh okay. Good to have some pointers to get what I want. 
Thanks!

@LysandreJik using the same approach as @aurooj mentioned, I'm getting tuple of 1 length, specifically this one
> First one is of shape (B, SEQ_L, 30522)

Also, there are so many checkpoint-### folders created (starting from 500 to 8500).
Is it the expected behavior?


I'm not sure I understand your first question.

You can manage when the checkpoints are saved using the `--save_steps` argument. You can check the full list of arguments in the script (now renamed `run_language_modeling`) available [here](https://github.com/huggingface/transformers/blob/master/examples/run_language_modeling.py#L478-L613).

Looking at the code was extremely helpful, I was able to continue fine-tuning from the saved checkpoints and understanding the arguments, though complete documentation of it would be ideal. 
About my first question, I did the same things @aurooj mentioned, but instead of 2 length tuple, I got 1 length tuple from `BertForMaskedLM` of shape `(B, SEQ_L, 30522)`

You can show the arguments of that script alongside their documentation by running `python run_language_modeling.py --help`.
Concerning what was returned by `BertForMaksedLM`, that seems normal as this is what is mentioned in the [documentation](https://huggingface.co/transformers/model_doc/bert.html#bertformaskedlm). The output tuple can contain up to 5 items, 4 of which are optional.

My bad, even after reading the documentation. somehow it got in my mind that 3 were optional not 4.
Thank you.  
Note to self, 

> Reading documentation is paramount too.

Hey @aurooj @nauman-chaudhary - I am very interested to see how you have done the fine-tuning for the masked LM task. Would really appreciate if you could share some insights. Thank you very much in advance!