Fixes Loss for TransfoXL when using Trainer API
Author: gugarosa
Pull request: yes

# What does this PR do?

<!--
Congratulations! You've made it this far! You're not quite done yet though.

Once merged, your PR is going to appear in the release notes with the title you set, so make sure it's a great title that fully reflects the extent of your awesome contribution.

Then, please replace this with a description of the change and which issue is fixed (if applicable). Please also include relevant motivation and context. List any dependencies (if any) that are required for this change.

Once you're done, someone will review your PR shortly (see the section "Who can review?" below to tag some potential reviewers). They may suggest changes to make the code even better. If no one reviewed your PR after a week has passed, don't hesitate to post a new comment @-mentioning the same persons---sometimes notifications get lost.
-->

<!-- Remove if not applicable -->

This PR address the problem of using TransfoXL with the Trainer API by introducing straightforward changes, as follows:

- Changes the `losses` parameter from TransfoXL output to `loss`, allowing its usage with the Trainer API;
- Reduces the loss by mean calculation and by ignoring pad tokens;
- Adds a checker that will validate whether input labels are not only composed by pad tokens, which eventually breaks the loss calculation (tested on a full wikitext-103 version). 

I have been working and training TransfoXL from scratch for the past months, and so far this is the most stable code that I could get with huggingface/transformers.

Let me know if there is anything else that should be changed!

PS: fast testing script: `python examples/pytorch/language-modeling/run_clm.py --model_name_or_path transfo-xl-wt103 --dataset_name wikitext --dataset_config_name wikitext-103-raw-v1 --output_dir out`

## 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.
- [X] 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).
- [X] Did you write any new necessary tests?


## Who can review?

Anyone in the community is free to review the PR once the tests have passed. Feel free to tag
members/contributors who may be interested in your PR.

@patrickvonplaten 

<!-- Your PR will be replied to more quickly if you can figure out the right person to tag with @

 If you know how to use git blame, that is the easiest way, otherwise, here is a rough guide of **who to tag**.
 Please tag fewer than 3 people.

Models:

- albert, bert, xlm: @LysandreJik
- blenderbot, bart, marian, pegasus, encoderdecoder,  t5: @patrickvonplaten, @patil-suraj
- longformer, reformer, transfoxl, xlnet: @patrickvonplaten
- fsmt: @stas00
- funnel: @sgugger
- gpt2: @patrickvonplaten, @LysandreJik
- rag: @patrickvonplaten, @lhoestq
- tensorflow: @LysandreJik

Library:

- benchmarks: @patrickvonplaten
- deepspeed: @stas00
- ray/raytune: @richardliaw, @amogkam
- text generation: @patrickvonplaten
- tokenizers: @n1t0, @LysandreJik
- trainer: @sgugger
- pipelines: @LysandreJik

Documentation: @sgugger

HF projects:

- datasets: [different repo](https://github.com/huggingface/datasets)
- rust tokenizers: [different repo](https://github.com/huggingface/tokenizers)

Examples:

- maintained examples (not research project or legacy): @sgugger, @patil-suraj
- research_projects/bert-loses-patience: @JetRunner
- research_projects/distillation: @VictorSanh

 -->

🚨🚨 **Breaking change TransfoXL** 🚨🚨

This PR introduces a breaking change.
Previously the output attribute ``losses`` can be found at index 0. Now it is at index 2 in case `labels` are passed. 

This means if you code previously used:

```python
losses = model(input_ids, labels=labels)[0]
```

it should now change to:

```python
losses = model(input_ids, labels=labels)[2]
```

Comments:
Thanks a lot for the very in-detail explanations @gugarosa ! I like your proposals and IMO we could do the following:

1) Output both `loss` and `losses` whereas `losses` is still in "vector"-form and we introduce a new `loss` output that has your proposed form. So the following use cases should work:

```python
from transformers import TransfoXLLMHead

model = TransfoXLLMHead.from_pretrained(...)

# 1) keep backward compatibility -> this should be an output in vector form
losses = model(input_ids).losses 

# 2) allow model to be used in trainer -> this should be in scalar form
loss = model(input_ids).loss 
```

2) Then regarding the tuple order we will probably have to do a breaking change with the new tuple order looking as follows:
(loss, ...., lossses)   <- this means that 

```python
losses = model(input_ids)[0] 
# is now changed to
loss = model(input_ids)[0] 
```

which is ok IMO given that most people use `outputs.losses` ...

What do you think @sgugger @LysandreJik ?


Awesome! @gugarosa - feel free to go ahead with the discussed approach if you want :-)

Sorry for taking too long, I had a family issue and went off for the week.

Nevertheless, I have updated the PR with the requested changes (thanks so much!), so please feel free to criticize them or request for newer changes. I have also tested with the proposed snippet and everything seems to be working!

```
import torch
from transformers import TransfoXLLMHeadModel

# Constants
BATCH_SIZE = 1
SEQ_LEN = 32

# Loads model from Hub and defines random inputs
model = TransfoXLLMHeadModel.from_pretrained('transfo-xl-wt103')
input_ids = torch.randint(0, 10000, (BATCH_SIZE, SEQ_LEN))

# 1) keep backward compatibility -> this should be an output in vector form
losses = model(input_ids, labels=input_ids).losses 

# 2) allow model to be used in trainer -> this should be in scalar form
loss = model(input_ids, labels=input_ids).loss 

# Asserts the outputs' shapes
assert losses.shape == (BATCH_SIZE, SEQ_LEN - 1)
assert loss.shape == ()
```

Best regards,
Gustavo.

Thanks for the feedback! I have squashed the commit with the styling changes and all tests seems to be passing now.

Cool looks good to me! Left a 🚨🚨 breaking 🚨🚨 message at the top of the PR to make users aware 

@LysandreJik - feel free to merge if you're ok with the small breaking change

I am perfectly fine with adding a `loss` output so that it's compatible with the `Trainer`, less-so to push `losses` to be moved to another place in the returned output.

I checked the usage for TransfoXL and we had 17k uses in the past month with the latest `master`, so this is bound to affect some users.

Is the path here the only one we can take? Can't we make the switch from `losses` to `loss` as a first return value opt-in, so that it works only if users explicitly mention that they're okay with the new behavior? This way we could switch for the v5, while preventing the breaking change.

Something like a `trainer_compatible` flag for the transfo-XL configuration, which would put `loss` as the first return instead of `losses`. WDYT?
 

@LysandreJik - that sounds good to me. Think it does make sense to aim for 100% backward compatibility here. @sgugger what do you think?

That works for me. Also wants to highlight that this would only be necessary if the user specifies `return_dict=False`, as when the outputs is one of our `ModelOutput`, the `Trainer` indexes with the key "loss" and not the first index.

@gugarosa, would you like to take a stab at this? Otherwise let me know and I'm happy to help out :)

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.

I'll try and make time for this this week if nobody beats me to it.

Couldn't push directly to your fork so I opened a PR here: https://github.com/gugarosa/transformers/pull/1

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.

@gugarosa please let me know if you'd like me to take over the PR. I believe all that remains is to merge the PR I opened here: https://github.com/gugarosa/transformers/pull/1 and we can merge this current PR then.

Thanks!

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.