# Особенности набора данных

[Features](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Features) определяет внутреннюю структуру набора данных. Он используется для указания базового формата сериализации. Однако для вас более интересным является то, что [Features](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Features) содержит высокоуровневую информацию обо всем: от имен и типов столбцов до [ClassLabel](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.ClassLabel). Можно считать [Features](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Features) основой набора данных.

Формат [Features](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Features) прост: `dict[column_name, column_type]`. Это словарь пар «имя столбца» и «тип столбца». Тип столбца предоставляет широкий набор вариантов для описания типа имеющихся данных.

Рассмотрим характеристики набора данных MRPC из бенчмарка 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'),
}
```

Функция [Value](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Value) сообщает 🤗 Datasets:

- Тип данных `idx` — `int32`.
- Типы данных `sentence1` и `sentence2` — это `string`.

🤗 Datasets поддерживает многие другие типы данных, такие как `bool`, `float32` и `binary`, чтобы назвать лишь некоторые из них.

> [!TIP]
> Список поддерживаемых типов данных см. в [Value](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Value).

Функция [ClassLabel](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.ClassLabel) сообщает 🤗 Datasets, что столбец `label` содержит два класса. Классы обозначены как `not_equivalent` и `equivalent`. Метки хранятся в наборе данных в виде целых чисел. При извлечении меток методы [ClassLabel.int2str()](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.ClassLabel.int2str) и [ClassLabel.str2int()](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.ClassLabel.str2int) выполняют преобразование из целочисленного значения в имя метки и обратно.

Если ваш тип данных содержит список объектов, вам следует использовать функцию [List](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.List). Помните датасет 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'))}}
```

Поле `answers` строится с использованием словаря признаков, поскольку и содержит два подполя, `text` и `answer_start`, которые являются списками `string` и `int32` соответственно.

> [!TIP]
> См. раздел [flatten](./process#flatten), чтобы узнать, как извлечь вложенные подполя в виде отдельных независимых столбцов.

Тип данных массива полезен для создания массивов различных размеров. Вы можете создавать двумерные массивы с помощью [Array2D](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Array2D), а также массивы с пятью измерениями с помощью [Array5D](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Array5D).

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

Тип массива также позволяет сделать первый размер массива динамическим. Это полезно для работы с последовательностями переменной длины, такими как предложения, без необходимости дополнять или укорачивать входные данные до единой формы.

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

## Аудио-функция

Наборы данных аудио содержат столбец типа [Audio](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Audio), в котором есть три важных поля:

- `array`: декодированные аудиоданные, представленные в виде одномерного массива.
- `path`: путь к скачанному аудиофайлу.
- `sampling_rate`: частота дискретизации аудиоданных.

При загрузке аудиодатасета и обращении к аудиоколонке функция [Audio](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.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]
> Обращайтесь к аудиодataset по индексу строки, а затем к колонке `audio` — `dataset[0]["audio"]` — чтобы избежать декодирования и ресемплинга всех аудиофайлов в датасете. В противном случае, если датасет большой, этот процесс может быть медленным и требовать много времени.

При `decode=False` тип [Audio](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Audio) просто возвращает путь или байты аудиофайла, не декодируя их в объект 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'}
```

## Функция изображения

Наборы данных изображений содержат столбец типа [Image](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Image), который загружает объекты `PIL.Image` из изображений, хранящихся в виде байтов:

При загрузке набора данных изображений и обращении к столбцу с изображениями функция [Image](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.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]
> Обращайтесь к набору данных изображений сначала по индексу строки, а затем по столбцу `image` — `dataset[0]["image"]` — чтобы избежать декодирования всех файлов изображений в наборе. В противном случае, если набор данных большой, этот процесс может быть медленным и требовать много времени.

При `decode=False` тип [Image](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Image) просто возвращает путь или байты файла изображения, не декодируя их в `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'}
```

В зависимости от набора данных вы можете получить путь к локально загруженному изображению или содержимое изображения в виде байтов, если набор данных не состоит из отдельных файлов.

Вы также можете определить набор данных изображений из массивов numpy:

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

В этом случае массивы numpy кодируются в PNG (или в TIFF, если важна точность значений пикселей).

Для многоканальных массивов, таких как RGB или RGBA, поддерживается только uint8. Если вы используете более высокую точность, вы получите предупреждение, а массив будет приведён к uint8. Для изображений в оттенках серого вы можете использовать любую целочисленную или вещественную точность, совместимую с `Pillow`. Если точность целочисленных или вещественных значений вашего изображения слишком высока, выводится предупреждение, и в этом случае массив приводится к более низкой точности: массив int64 приводится к int32, а массив float64 — к float32.

## Функция Mesh

Наборы данных Mesh содержат столбец типа [Mesh](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Mesh), который загружает файлы 3D-сеток как объекты `trimesh`.

При загрузке набора данных с мешами и обращении к столбцу меша функция [Mesh](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Mesh) автоматически декодирует файл меша:

```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)>
```

В зависимости от содержимого файла `trimesh` может вернуть объект `trimesh.Trimesh` или объект `trimesh.Scene`.

> [!WARNING]
> Обращайтесь к набору данных мешей сначала по индексу строки, а затем по столбцу `mesh` — `dataset[0]["mesh"]` — чтобы избежать декодирования всех файлов мешей в наборе данных. В противном случае, если набор данных большой, этот процесс может быть медленным и требовать много времени.

При `decode=False` тип [Mesh](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Mesh) возвращает путь или байты файла меша без его декодирования с помощью `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'}
```

Функция [Mesh](/docs/datasets/v5.2.0/ru/package_reference/main_classes#datasets.Mesh) поддерживает файлы `.glb`, `.gltf`, `.ply` и `.stl`. Для встроенных байтов для определения типа файла меша используется сохранённый `path`.

## Функция Json

Датасеты основаны на Arrow, который является колоночным форматом, поэтому ожидается, что каждый пример имеет одинаковый тип и подтипы, а словари — одинаковые ключи и типы значений. При загрузке датасета возникает ошибка, если типы полей не совпадают, а отсутствующие поля в словарях заполняются значением None, чтобы все словари имели одинаковые ключи и типы значений.

Чтобы избежать этого и разрешить смешанные типы без ошибок, вы можете использовать `on_mixed_types="use_json"` или указать `features=` с типом [Json](/docs/datasets/v5.2.0/ru/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"}]
```

Это также полезно для списков словарей с произвольными ключами и значениями, чтобы избежать заполнения отсутствующих полей значением 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
```

Ещё один пример с данными для вызова инструментов и аргументом `on_mixed_types="use_json"` (полезно, чтобы не указывать `features=` вручную):

```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"}
```

