Datasets documentation

Mapeo por lotes

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Mapeo por lotes

Combinar la utilidad de Dataset.map() con el modo por lotes es muy potente. Te permite acelerar el procesamiento y controlar libremente el tamaño del conjunto de datos generado.

Necesidad de velocidad

El objetivo principal del mapeo por lotes es acelerar el procesamiento. A menudo, es más rápido trabajar con lotes de datos que con ejemplos individuales. Naturalmente, el mapeo por lotes se presta a la tokenización. Por ejemplo, la biblioteca 🤗 Tokenizers funciona más rápido con lotes porque paraleliza la tokenización de todos los ejemplos de un lote.

Tamaño de entrada != tamaño de salida

La capacidad de controlar el tamaño del conjunto de datos generado puede aprovecharse para muchos casos de uso interesantes. En la sección map de la guía, hay ejemplos de uso del mapeo por lotes para:

  • Divide las oraciones largas en fragmentos más cortos.
  • Ampliar un conjunto de datos con tokens adicionales.

Es útil entender cómo funciona esto para que puedas idear tus propias formas de usar el mapeo por lotes. En este punto, es posible que te preguntes cómo puedes controlar el tamaño del conjunto de datos generado. La respuesta es: la función mapeada no tiene que devolver un lote de salida del mismo tamaño.

En otras palabras, la entrada de su función mapeada puede ser un lote de tamaño N y devolver un lote de tamaño M. La salida M puede ser mayor o menor que N. Esto significa que puede concatenar sus ejemplos, dividirlos e incluso añadir más ejemplos.

Sin embargo, recuerda que todos los valores del diccionario de salida deben contener el mismo número de elementos que los demás campos del diccionario de salida. De lo contrario, no es posible definir el número de ejemplos en la salida devuelta por la función mapeada. El número puede variar entre lotes sucesivos procesados por la función mapeada. Sin embargo, para un solo lote, todos los valores del diccionario de salida deben tener la misma longitud (es decir, el mismo número de elementos).

Por ejemplo, a partir de un conjunto de datos de 1 columna y 3 filas, si usas map para devolver una nueva columna con el doble de filas, obtendrás un error. En este caso, terminarás con una columna de 3 filas y otra de 6 filas. Como puedes ver, la tabla no será válida:

>>> from datasets import Dataset
>>> dataset = Dataset.from_dict({"a": [0, 1, 2]})
>>> dataset.map(lambda batch: {"b": batch["a"] * 2}, batched=True)  # new column with 6 elements: [0, 1, 2, 0, 1, 2]
'ArrowInvalid: Column 1 named b expected length 3 but got length 6'

Para que sea válido, debe eliminar una de las columnas:

>>> from datasets import Dataset
>>> dataset = Dataset.from_dict({"a": [0, 1, 2]})
>>> dataset_with_duplicates = dataset.map(lambda batch: {"b": batch["a"] * 2}, remove_columns=["a"], batched=True)
>>> len(dataset_with_duplicates)
6

Alternativamente, puede sobrescribir la columna existente para lograr el mismo resultado. Por ejemplo, así se duplica cada fila del conjunto de datos sobrescribiendo la columna "a":

>>> from datasets import Dataset
>>> dataset = Dataset.from_dict({"a": [0, 1, 2]})
# overwrites the existing "a" column with duplicated values
>>> duplicated_dataset = dataset.map(
...     lambda batch: {"a": [x for x in batch["a"] for _ in range(2)]},
...     batched=True
... )
>>> duplicated_dataset
Dataset({
    features: ['a'],
    num_rows: 6
})
>>> duplicated_dataset["a"]
[0, 0, 1, 1, 2, 2]
Update on GitHub