diff --git a/src/accelerate/utils.py b/src/accelerate/utils.py
index b8428733b..991997282 100644
--- a/src/accelerate/utils.py
+++ b/src/accelerate/utils.py
@@ -15,7 +15,7 @@
 import importlib
 import os
 import random
-from collections import UserDict
+from collections.abc import Mapping
 from dataclasses import dataclass, field
 from enum import Enum
 from typing import List, Optional, Union
@@ -163,7 +163,7 @@ def recursively_apply(func, data, *args, test_type=is_torch_tensor, error_on_oth
                 for o in data
             ),
         )
-    elif isinstance(data, UserDict):
+    elif isinstance(data, Mapping):
         return type(data)(
             {
                 k: recursively_apply(
@@ -172,15 +172,6 @@ def recursively_apply(func, data, *args, test_type=is_torch_tensor, error_on_oth
                 for k, v in data.items()
             }
         )
-    elif isinstance(data, dict):
-        return type(data)(
-            **{
-                k: recursively_apply(
-                    func, v, *args, test_type=test_type, error_on_other_type=error_on_other_type, **kwargs
-                )
-                for k, v in data.items()
-            }
-        )
     elif test_type(data):
         return func(data, *args, **kwargs)
     elif error_on_other_type:
@@ -310,7 +301,7 @@ def extract_model_from_parallel(model):
 def _tpu_gather(tensor, name="gather tensor"):
     if isinstance(tensor, (list, tuple)):
         return honor_type(tensor, (_tpu_gather(t, name=f"{name}_{i}") for i, t in enumerate(tensor)))
-    elif isinstance(tensor, (dict, UserDict)):
+    elif isinstance(tensor, Mapping):
         return type(tensor)({k: _tpu_gather(v, name=f"{name}_{k}") for k, v in tensor.items()})
     elif not isinstance(tensor, torch.Tensor):
         raise TypeError(f"Can't gather the values of type {type(tensor)}, only of nested list/tuple/dicts of tensors.")
@@ -365,7 +356,7 @@ def _gpu_broadcast_one(tensor, src=0):
 def _tpu_broadcast(tensor, src=0, name="broadcast tensor"):
     if isinstance(tensor, (list, tuple)):
         return honor_type(tensor, (_tpu_broadcast(t, name=f"{name}_{i}") for i, t in enumerate(tensor)))
-    elif isinstance(tensor, (dict, UserDict)):
+    elif isinstance(tensor, Mapping):
         return type(tensor)({k: _tpu_broadcast(v, name=f"{name}_{k}") for k, v in tensor.items()})
     return xm.mesh_reduce(name, tensor, lambda x: x[src])
 
@@ -448,7 +439,7 @@ def find_batch_size(data):
     """
     if isinstance(data, (tuple, list)):
         return find_batch_size(data[0])
-    elif isinstance(data, (dict, UserDict)):
+    elif isinstance(data, Mapping):
         for k in data.keys():
             return find_batch_size(data[k])
     elif not isinstance(data, torch.Tensor):
@@ -471,10 +462,8 @@ def concatenate(data, dim=0):
     """
     if isinstance(data[0], (tuple, list)):
         return honor_type(data[0], (concatenate([d[i] for d in data], dim=dim) for i in range(len(data[0]))))
-    elif isinstance(data[0], UserDict):
+    elif isinstance(data[0], Mapping):
         return type(data[0])({k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
-    elif isinstance(data[0], dict):
-        return type(data[0])(**{k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
     elif not isinstance(data[0], torch.Tensor):
         raise TypeError(f"Can only concatenate tensors but got {type(data[0])}")
     return torch.cat(data, dim=dim)


Review comments: body: You would need to remove the `**` for this to work with UserDict I believe.
```suggestion
            {
```
diff_hunk: @@ -163,16 +163,7 @@ def recursively_apply(func, data, *args, test_type=is_torch_tensor, error_on_oth
                 for o in data
             ),
         )
-    elif isinstance(data, UserDict):
-        return type(data)(
-            {
-                k: recursively_apply(
-                    func, v, *args, test_type=test_type, error_on_other_type=error_on_other_type, **kwargs
-                )
-                for k, v in data.items()
-            }
-        )
-    elif isinstance(data, dict):
+    elif isinstance(data, Mapping):
         return type(data)(
             **{
body: ```suggestion
        return type(data[0])({k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
```
Same here
diff_hunk: @@ -471,9 +462,7 @@ def concatenate(data, dim=0):
     """
     if isinstance(data[0], (tuple, list)):
         return honor_type(data[0], (concatenate([d[i] for d in data], dim=dim) for i in range(len(data[0]))))
-    elif isinstance(data[0], UserDict):
-        return type(data[0])({k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
-    elif isinstance(data[0], dict):
+    elif isinstance(data[0], Mapping):
         return type(data[0])(**{k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
body: `UserDict` also works with the `**` syntax. You can test this with the following code or by looking at the source [here](https://github.com/python/cpython/blob/2c56c97f015a7ea81719615ddcf3c745fba5b4f3/Lib/collections/__init__.py#L964-L984) (warning you that the code is a bit messy in Python 3.6-3.8 compared to Python 3.9 😄):
```python
from collections import UserDict
assert UserDict(**{"a": 1, "b": 2}) == UserDict({"a": 1, "b": 2})
```
diff_hunk: @@ -163,16 +163,7 @@ def recursively_apply(func, data, *args, test_type=is_torch_tensor, error_on_oth
                 for o in data
             ),
         )
-    elif isinstance(data, UserDict):
-        return type(data)(
-            {
-                k: recursively_apply(
-                    func, v, *args, test_type=test_type, error_on_other_type=error_on_other_type, **kwargs
-                )
-                for k, v in data.items()
-            }
-        )
-    elif isinstance(data, dict):
+    elif isinstance(data, Mapping):
         return type(data)(
             **{
body: But not the `BatchEncoding` subclass we are doing all of this for :-)

You can try and see that:
```
from transformers import BatchEncoding
assert BatchEncoding(**{"a": 1, "b": 2}) == BatchEncoding({"a": 1, "b": 2})
```
fails
diff_hunk: @@ -163,16 +163,7 @@ def recursively_apply(func, data, *args, test_type=is_torch_tensor, error_on_oth
                 for o in data
             ),
         )
-    elif isinstance(data, UserDict):
-        return type(data)(
-            {
-                k: recursively_apply(
-                    func, v, *args, test_type=test_type, error_on_other_type=error_on_other_type, **kwargs
-                )
-                for k, v in data.items()
-            }
-        )
-    elif isinstance(data, dict):
+    elif isinstance(data, Mapping):
         return type(data)(
             **{
body: Oh, I see. Thanks.
diff_hunk: @@ -163,16 +163,7 @@ def recursively_apply(func, data, *args, test_type=is_torch_tensor, error_on_oth
                 for o in data
             ),
         )
-    elif isinstance(data, UserDict):
-        return type(data)(
-            {
-                k: recursively_apply(
-                    func, v, *args, test_type=test_type, error_on_other_type=error_on_other_type, **kwargs
-                )
-                for k, v in data.items()
-            }
-        )
-    elif isinstance(data, dict):
+    elif isinstance(data, Mapping):
         return type(data)(
             **{
body: This one still needs to be changed.
diff_hunk: @@ -471,9 +462,7 @@ def concatenate(data, dim=0):
     """
     if isinstance(data[0], (tuple, list)):
         return honor_type(data[0], (concatenate([d[i] for d in data], dim=dim) for i in range(len(data[0]))))
-    elif isinstance(data[0], UserDict):
-        return type(data[0])({k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
-    elif isinstance(data[0], dict):
+    elif isinstance(data[0], Mapping):
         return type(data[0])(**{k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
body: But besides replacing `(dict, UserDict)` with `Mapping` in the `isinstance` checks, the code right now is identical to the code you pushed in the initial PR. However, I see an additional simplification we can use if we abandon the `**` syntax (maybe that is what you are aiming for).
diff_hunk: @@ -471,9 +462,7 @@ def concatenate(data, dim=0):
     """
     if isinstance(data[0], (tuple, list)):
         return honor_type(data[0], (concatenate([d[i] for d in data], dim=dim) for i in range(len(data[0]))))
-    elif isinstance(data[0], UserDict):
-        return type(data[0])({k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})
-    elif isinstance(data[0], dict):
+    elif isinstance(data[0], Mapping):
         return type(data[0])(**{k: concatenate([d[k] for d in data], dim=dim) for k in data[0].keys()})

Discussion: body: cc @sgugger 
body: @sgugger I've reverted the changes in these two functions, so now the code should work with `BatchEncoding`. However, even though this would add some complexity, maybe a cleaner approach would be to use a specific check for `BatchEncoding`. But for now, I think the current solution is good enough.
body: Thanks again for your contribution!