# Caractéristiques du jeu de données

[Features](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Features) définit la structure interne d'un jeu de données. Il est utilisé pour spécifier le format de sérialisation sous-jacent. Ce qui est plus intéressant pour vous, c'est que [Features](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Features) contient des informations de haut niveau sur tout, des noms et types de colonnes au [ClassLabel](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.ClassLabel). Vous pouvez considérer [Features](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Features) comme la colonne vertébrale d'un jeu de données.

Le format [Features](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Features) est simple : `dict[column_name, column_type]`. Il s’agit d’un dictionnaire de paires nom de colonne et type de colonne. Le type de colonne offre un large éventail d’options pour décrire le type de données dont vous disposez.

Examinons les caractéristiques du jeu de données MRPC issu du benchmark GLUE :

```py
>>> from datasets import load_dataset
>>> dataset = load_dataset('nyu-mll/glue', 'mrpc', split='train')
>>> dataset.features
{'idx': Value('int32'),
 'label': ClassLabel(names=['not_equivalent', 'equivalent']),
 'sentence1': Value('string'),
 'sentence2': Value('string'),
}
```

La fonctionnalité [Value](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Value) indique à 🤗 Datasets :

- Le type de données `idx` est `int32`.
- Les types de données `sentence1` et `sentence2` sont `string`.

🤗 Datasets prend en charge de nombreux autres types de données, tels que `bool`, `float32` et `binary`, pour n’en citer que quelques-uns.

> [!TIP]
> Reportez-vous à [Value](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Value) pour la liste complète des types de données pris en charge.

La fonctionnalité [ClassLabel](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.ClassLabel) indique à 🤗 Datasets que la colonne `label` contient deux classes. Les classes sont étiquetées `not_equivalent` et `equivalent`. Les étiquettes sont stockées sous forme d’entiers dans le jeu de données. Lors de la récupération des étiquettes, [ClassLabel.int2str()](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.ClassLabel.int2str) et [ClassLabel.str2int()](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.ClassLabel.str2int) effectuent la conversion de la valeur entière vers le nom de l’étiquette, et inversement.

Si votre type de données contient une liste d'objets, vous devez utiliser la fonctionnalité [List](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.List). Vous vous souvenez du jeu de données SQuAD ?

```py
>>> from datasets import load_dataset
>>> dataset = load_dataset('rajpurkar/squad', split='train')
>>> dataset.features
{'id': Value('string'),
 'title': Value('string'),
 'context': Value('string'),
 'question': Value('string'),
 'answers': {'text': List(Value('string')),
  'answer_start': List(Value('int32'))}}
```

Le champ `answers` est construit à l'aide du dictionnaire de caractéristiques car il contient deux sous-champs, `text` et `answer_start`, qui sont respectivement des listes de `string` et de `int32`.

> [!TIP]
> Consultez la section [flatten](./process#flatten) pour découvrir comment extraire les sous-champs imbriqués en tant que colonnes indépendantes.

Le type de fonctionnalité tableau est utile pour créer des tableaux de différentes tailles. Vous pouvez créer des tableaux à deux dimensions à l'aide de [Array2D](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Array2D), et même des tableaux à cinq dimensions à l'aide de [Array5D](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Array5D).

```py
>>> features = Features({'a': Array2D(shape=(1, 3), dtype='int32')})
```

Le type de tableau permet également de rendre la première dimension du tableau dynamique. Cela est utile pour traiter des séquences de longueurs variables, telles que des phrases, sans avoir à compléter ou tronquer l'entrée pour obtenir une forme uniforme.

```py
>>> features = Features({'a': Array3D(shape=(None, 5, 2), dtype='int32')})
```

## Caractéristique audio

Les jeux de données audio possèdent une colonne de type [Audio](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Audio), qui contient trois champs importants :

- `array` : les données audio décodées, représentées sous forme de tableau unidimensionnel.
- `path` : le chemin vers le fichier audio téléchargé.
- `sampling_rate` : le taux d'échantillonnage des données audio.

Lorsque vous chargez un jeu de données audio et que vous appelez la colonne audio, la fonctionnalité [Audio](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Audio) décode et rééchantillonne automatiquement le fichier audio :

```py
>>> from datasets import load_dataset, Audio

>>> dataset = load_dataset("PolyAI/minds14", "en-US", split="train")
>>> dataset[0]["audio"]
<datasets.features._torchcodec.AudioDecoder object at 0x11642b6a0>
```

> [!WARNING]
> Accédez à un jeu de données audio en utilisant d'abord l'index de la ligne, puis la colonne `audio` - `dataset[0]["audio"]` - afin d'éviter de décoder et de rééchantillonner tous les fichiers audio du jeu de données. Sinon, cela peut être un processus lent et chronophage si vous disposez d'un jeu de données volumineux.

Avec `decode=False`, le type [Audio](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Audio) vous fournit simplement le chemin ou les octets du fichier audio, sans le décoder en un objet torchcodec `AudioDecoder`,

```py
>>> dataset = load_dataset("PolyAI/minds14", "en-US", split="train").cast_column("audio", Audio(decode=False))
>>> dataset[0]
{'audio': {'bytes': None,
  'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav'},
 'english_transcription': 'I would like to set up a joint account with my partner',
 'intent_class': 11,
 'lang_id': 4,
 'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav',
 'transcription': 'I would like to set up a joint account with my partner'}
```

## Fonctionnalité d'image

Les jeux de données d'images possèdent une colonne de type [Image](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Image), qui charge des objets `PIL.Image` à partir d'images stockées sous forme d'octets :

Lorsque vous chargez un jeu de données d'images et appelez la colonne d'images, la fonctionnalité [Image](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Image) décode automatiquement le fichier image :

```py
>>> from datasets import load_dataset, Image

>>> dataset = load_dataset("AI-Lab-Makerere/beans", split="train")
>>> dataset[0]["image"]
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=500x500 at 0x125506CF8>
```

> [!WARNING]
> Accédez à un jeu de données d’images en utilisant d’abord l’index de la ligne, puis la colonne `image` - `dataset[0]["image"]` - afin d’éviter de décoder tous les fichiers d’images du jeu de données. Sinon, cela peut être un processus lent et chronophage si vous disposez d’un jeu de données volumineux.

Avec `decode=False`, le type [Image](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Image) vous fournit simplement le chemin ou les octets du fichier image, sans le décoder en `PIL.Image`,

```py
>>> dataset = load_dataset("AI-Lab-Makerere/beans", split="train").cast_column("image", Image(decode=False))
>>> dataset[0]["image"]
{'bytes': None,
 'path': '/Users/username/.cache/huggingface/datasets/downloads/extracted/772e7c1fba622cff102b85dd74bcce46e8168634df4eaade7bedd3b8d91d3cd7/train/healthy/healthy_train.265.jpg'}
```

Selon le jeu de données, vous obtiendrez soit le chemin de l'image téléchargée localement, soit le contenu de l'image sous forme d'octets si le jeu de données n'est pas constitué de fichiers individuels.

Vous pouvez également définir un jeu de données d'images à partir de tableaux numpy :

```python
>>> ds = Dataset.from_dict({"i": [np.zeros(shape=(16, 16, 3), dtype=np.uint8)]}, features=Features({"i": Image()}))
```

Et dans ce cas, les tableaux numpy sont encodés en PNG (ou en TIFF si la précision des valeurs des pixels est importante).

Pour les tableaux multi-canaux comme RGB ou RGBA, seul uint8 est pris en charge. Si vous utilisez une précision plus élevée, un avertissement est affiché et le tableau est converti en uint8. Pour les images en niveaux de gris, vous pouvez utiliser la précision entière ou flottante de votre choix, à condition qu’elle soit compatible avec `Pillow`. Un avertissement est affiché si la précision entière ou flottante de votre image est trop élevée, et dans ce cas le tableau est converti vers une précision inférieure : un tableau int64 est converti en int32, et un tableau float64 est converti en float32.

## Fonctionnalité Mesh

Les jeux de données maillés possèdent une colonne de type [Mesh](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Mesh), qui charge les fichiers de maillage 3D en tant qu'objets `trimesh`.

Lorsque vous chargez un jeu de données de maillage et appelez la colonne de maillage, la fonctionnalité [Mesh](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Mesh) décode automatiquement le fichier de maillage :

```py
>>> from datasets import load_dataset, Mesh

>>> dataset = load_dataset("VINAY-UMRETHE/My-Mesh-Dataset", split="train")
>>> dataset[0]["mesh"]
<trimesh.Scene(len(geometry)=33)>
```

Selon le contenu du fichier, `trimesh` peut retourner un objet `trimesh.Trimesh` ou un objet `trimesh.Scene`.

> [!WARNING]
> Accédez à un jeu de données de maillage en utilisant d'abord l'index de ligne, puis la colonne `mesh` - `dataset[0]["mesh"]` - afin d'éviter de décoder tous les fichiers de maillage du jeu de données. Sinon, cela peut être un processus lent et chronophage si vous disposez d'un jeu de données volumineux.

Avec `decode=False`, le type [Mesh](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Mesh) vous fournit le chemin ou les octets du fichier de maillage sans le décoder avec `trimesh` :

```py
>>> dataset = load_dataset("VINAY-UMRETHE/My-Mesh-Dataset", split="train").cast_column("mesh", Mesh(decode=False))
>>> dataset[0]["mesh"]
{'bytes': b'...',
 'path': '00001.glb'}
```

La fonctionnalité [Mesh](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Mesh) prend en charge les fichiers `.glb`, `.gltf`, `.ply` et `.stl`. Pour les octets intégrés, le `path` stocké est utilisé pour déduire le type de fichier de maillage.

## Fonctionnalité Json

Les jeux de données sont basés sur Arrow, un format en colonnes, et s'attendent donc à ce que chaque exemple ait le même type et les mêmes sous-types, et que les dictionnaires aient les mêmes clés et les mêmes types de valeurs. Le chargement d'un jeu de données provoque une erreur lorsque les types des champs ne correspondent pas, et remplit les champs manquants dans les dictionnaires avec None afin que tous les dictionnaires aient les mêmes clés et les mêmes types de valeurs.

Pour éviter cela et autoriser les types mixtes sans erreur, vous pouvez utiliser `on_mixed_types="use_json"` ou spécifier `features=` avec un type [Json](/docs/datasets/v5.2.0/fr/package_reference/loading_methods#datasets.Json) :

```python
>>> ds = Dataset.from_dict({"a": [0, "foo", {"subfield": "bar"}]})
Traceback (most recent call last):
  ...
  File "pyarrow/error.pxi", line 92, in pyarrow.lib.check_status
pyarrow.lib.ArrowInvalid: Could not convert 'foo' with type str: tried to convert to int64

>>> features = Features({"a": Json()})
>>> ds = Dataset.from_dict({"a": [0, "foo", {"subfield": "bar"}]}, features=features)
>>> ds.features
{'a': Json()}
>>> list(ds["a"])
[0, "foo", {"subfield": "bar"}]
```

Ceci est également utile pour les listes de dictionnaires avec des clés et des valeurs arbitraires, afin d'éviter de remplir les champs manquants avec None :

```python
>>> ds = Dataset.from_dict({"a": [[{"b": 0}, {"c": 0}]]})
>>> ds.features
{'a': List({'b': Value('int64'), 'c': Value('int64')})}
>>> list(ds["a"])
[[{'b': 0, 'c': None}, {'b': None, 'c': 0}]]  # missing fields are filled with None

>>> features = Features({"a": List(Json())})
>>> ds = Dataset.from_dict({"a": [[{"b": 0}, {"c": 0}]]}, features=features)
>>> ds.features
{'a': List(Json())}
>>> list(ds["a"])
[[{'b': 0}, {'c': 0}]]  # OK
```

Un autre exemple avec des données d’appel d’outils et l’argument `on_mixed_types="use_json"` (utile pour ne pas avoir à spécifier `features=` manuellement) :

```python
>>> messages = [
...     {"role": "user", "content": "Turn on the living room lights and play my electronic music playlist."},
...     {"role": "assistant", "tool_calls": [
...         {"type": "function", "function": {
...             "name": "control_light",
...             "arguments": {"room": "living room", "state": "on"}
...         }},
...         {"type": "function", "function": {
...             "name": "play_music",
...             "arguments": {"playlist": "electronic"}  # mixed-type here since keys ["playlist"] and ["room", "state"] are different
...         }}]
...     },
...     {"role": "tool", "name": "control_light", "content": "The lights in the living room are now on."},
...     {"role": "tool", "name": "play_music", "content": "The music is now playing."},
...     {"role": "assistant", "content": "Done!"}
... ]
>>> ds = Dataset.from_dict({"messages": [messages]}, on_mixed_types="use_json")
>>> ds.features
{'messages': List({'role': Value('string'), 'content': Value('string'), 'tool_calls': List(Json()), 'name': Value('string')})}
>>> ds[0][1]["tool_calls"][0]["function"]["arguments"]
{"room": "living room", "state": "on"}
```

