BertForMaskedLM training fails when using iterable eval_dataset and DataCollatorForLanguageModeling collator.
Author: joerenner
Pull request: no

## Environment info
<!-- You can run the command `transformers-cli env` and copy-and-paste its output below.
     Don't forget to fill out the missing fields in that output! -->

- `transformers` version: 4.6.1
- Platform: Linux-5.8.0-48-generic-x86_64-with-debian-bullseye-sid
- Python version: 3.7.9
- PyTorch version (GPU?): 1.7.1 (False)
- Tensorflow version (GPU?): not installed (NA)
- Using GPU in script?: False
- Using distributed or parallel set-up in script?: False


### Who can help
<!-- Your issue 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.

Library:

- tokenizers: @LysandreJik
- trainer: @sgugger

 -->

## Information

Model I am using (Bert, XLNet ...): Bert

The problem arises when using:
* [ x] my own modified scripts: (give details below)

The tasks I am working on is:
* [x ] my own task or dataset: (give details below)

## To reproduce

Steps to reproduce the behavior:

1. Instantiate a Trainer with a BertForMaskedLM model, and an iterable dataset passed in for the "eval_dataset", and DataCollatorForLanguageModeling as the collator.
2. Call train()


../../.pyenv/versions/3.7.9/lib/python3.7/site-packages/transformers/trainer.py:1334: in train
    self._maybe_log_save_evaluate(tr_loss, model, trial, epoch)
../../.pyenv/versions/3.7.9/lib/python3.7/site-packages/transformers/trainer.py:1405: in _maybe_log_save_evaluate
    metrics = self.evaluate()
../../.pyenv/versions/3.7.9/lib/python3.7/site-packages/transformers/trainer.py:2011: in evaluate
    output.metrics.update(speed_metrics(metric_key_prefix, start_time, output.num_samples))
```python
    def speed_metrics(split, start_time, num_samples=None):
        runtime = time.time() - start_time
        result = {f"{split}_runtime": round(runtime, 4)}
        if num_samples is not None:
           samples_per_second = 1 / (runtime / num_samples) # ZeroDivisionError: float division by zero here
```       

When evaluation_loop() gets called with an iterable eval dataset, it uses the "observed_num_examples" value to return the number of samples:
https://github.com/huggingface/transformers/blob/a9c797f93de97984771b7b902ce1e6b0aed98f96/src/transformers/trainer.py#L2155

```python
        observed_num_examples = 0
        # Main evaluation loop
        for step, inputs in enumerate(dataloader):
            # Update the observed num examples
            observed_batch_size = find_batch_size(inputs)
            if observed_batch_size is not None:
                observed_num_examples += observed_batch_size
```

The problem is, transformers.trainer_pt_utils.find_batch_size fails to find the correct batch size if the input is a BatchEncoding object (which is what DataCollatorForLanguageModeling returns if it is passed a dict or BatchEncoding):

https://github.com/huggingface/transformers/blob/0b0a598452b02278075a75f84b5ca7bb457224ad/src/transformers/trainer_pt_utils.py#L106

```python
        def find_batch_size(tensors):
            """
            Find the first dimension of a tensor in a nested list/tuple/dict of tensors.
            """
            if isinstance(tensors, (list, tuple)):
                for t in tensors:
                    result = find_batch_size(t)
                    if result is not None:
                        return result
            elif isinstance(tensors, dict):  # <---  returns false if "tensors" is BatchEncoding, should maybe return True?
                for key, value in tensors.items():
                    result = find_batch_size(value)
                    if result is not None:
                        return result
            elif isinstance(tensors, torch.Tensor):
                return tensors.shape[0] if len(tensors.shape) &gt;= 1 else None
            elif isinstance(tensors, np.ndarray):
                return tensors.shape[0] if len(tensors.shape) &gt;= 1 else None
```

This leads the observed_num_examples variable to not get updated, and since the input dataset is iterable, the output of evaluation_loop() has the "num_samples" variable set to 0:

https://github.com/huggingface/transformers/blob/a9c797f93de97984771b7b902ce1e6b0aed98f96/src/transformers/trainer.py#L2212

```python
                if not isinstance(eval_dataset, IterableDataset):
                    num_samples = len(eval_dataset)
                elif isinstance(eval_dataset, IterableDatasetShard):
                    num_samples = eval_dataset.num_examples
                else:
                    num_samples = observed_num_examples    # observed_num_examples is falsely set to 0 
```

which leads to the above ZeroDivisionError error.

This should be a quick fix in the find_batch_size function unless I am mistaken.

## Expected behavior
The training finishes with no error.


Comments:
Might be of interest to @sgugger 

Fixed by #11890