Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/datasets/tfless_tfds.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

TFDS para Jax y PyTorch

TFDS siempre ha sido independiente del framework. Por ejemplo, puede cargar fácilmente conjuntos de datos en formato NumPy para utilizarlos en Jax y PyTorch.

TensorFlow y su solución de carga de datos ( tf.data ) son ciudadanos de primera clase en nuestra API por diseño.

Hemos extendido TFDS para soportar la carga de datos sólo NumPy sin TensorFlow. Esto puede ser conveniente para el uso en marcos de ML como Jax y PyTorch. De hecho, para estos últimos usuarios, TensorFlow puede:

  • Reservar memoria GPU/TPU;

  • Aumentar el tiempo de compilación en CI/CD;

  • Tardan en importarse en tiempo de ejecución.

TensorFlow ya no es una dependencia para leer conjuntos de datos.

Las tuberías de aprendizaje automático necesitan un cargador de datos para cargar ejemplos, descodificarlos y presentarlos al modelo. Los cargadores de datos utilizan el paradigma "fuente/muestreador/cargador":

Conjunto de datos TFDS ┌────────────────┐ en disco │ │ ┌──────────►│ Datos │ |..|... │ | │ fuente ├─┐ ├──┼────┴─────┤ │ │ │ 12│imagen12 ──┐ ├──┼──────────┤ │ │ │ │13│imagen13 │ ├───►│ Datos ├───► Tubería de aprendizaje automático ├──┼──────────┤ │ │ cargador │ │14│imagen14 │ ┌────────────────┐ │ │ │ ├──┼──────────┤ │ │ │ └────────────────┘ |..|... | │ Índice ├─┘ │ muestrario │ │ │ └────────────────┘
  • La fuente de datos es responsable de acceder y decodificar ejemplos de un conjunto de datos TFDS sobre la marcha.

  • El muestreador de índices es responsable de determinar el orden en que se procesan los registros. Esto es importante para implementar transformaciones globales (por ejemplo, barajado global, fragmentación, repetición para múltiples épocas) antes de leer cualquier registro.

  • El cargador de datos orquesta la carga aprovechando la fuente de datos y el muestreador de índices. Permite optimizar el rendimiento (por ejemplo, precarga, multiprocesamiento o multihilo).

TL;DR

tfds.data_source es una API para crear fuentes de datos:

  1. Para la creación rápida de prototipos en tuberías puramente de Python

  2. Para gestionar procesos de aprendizaje automático con gran cantidad de datos a gran escala.

Instalación

Vamos a instalar e importar las dependencias necesarias:

!pip install array_record !pip install tfds-nightly import os os.environ.pop('TFDS_DATA_DIR', None) import tensorflow_datasets as tfds

Fuentes de datos

Las fuentes de datos son básicamente secuencias de Python. Entonces necesitan implementar el siguiente protocolo:

class RandomAccessDataSource(Protocol): """Interfaz para fuentes de datos en las que el almacenamiento admite un acceso aleatorio eficiente.""" def __len__(self) -> int: """Numero de registros del conjunto de datos.""" def __getitem__(self, record_key: int) -> Sequence[Any]: """Recupera los registros para las record_keys dadas."""

Advertencia: la API todavía está en desarrollo continuo. En particular, en este momento, __getitem__ debe soportar tanto int como list[int] en la entrada. En el futuro, probablemente sólo soportará int según el estándar.

El formato de archivo subyacente debe permitir un acceso aleatorio eficaz. Actualmente, TFDS depende de array_record.

array_record es un nuevo formato de archivo derivado de Riegeli, que alcanza una nueva frontera de eficiencia de E/S. En concreto, ArrayRecord admite la lectura, escritura y acceso aleatorio en paralelo por índice de registro. ArrayRecord se basa en Riegeli y admite los mismos algoritmos de compresión.

fashion_mnist es un conjunto de datos habitual para la visión por ordenador. Para recuperar una fuente de datos basada en ArrayRecord con TFDS, basta con utilizar:

ds = tfds.data_source('fashion_mnist')

tfds.data_source es un contenedor conveniente. es equivalente a:

builder = tfds.builder('fashion_mnist', file_format='array_record') builder.download_and_prepare() ds = builder.as_data_source()

Esto genera un diccionario de fuentes de datos:

{ 'train': DataSource(name=fashion_mnist, split='train', decoders=None), 'test': DataSource(name=fashion_mnist, split='test', decoders=None), }

Una vez que download_and_prepare se ha ejecutado, y has generado los archivos de registro, ya no necesitamos TensorFlow. ¡Todo se hará en Python/NumPy!

Verifiquemos esto desinstalando TensorFlow y volviendo a cargar la fuente de datos en otro subproceso:

!pip uninstall -y tensorflow
%%writefile no_tensorflow.py import os os.environ.pop('TFDS_DATA_DIR', None) import tensorflow_datasets as tfds try: import tensorflow as tf except ImportError: print('No TensorFlow found...') ds = tfds.data_source('fashion_mnist') print('...but the data source could still be loaded...') ds['train'][0] print('...and the records can be decoded.')
!python no_tensorflow.py

En futuras versiones, también vamos a hacer que la preparación del conjunto de datos sea independiente de TensorFlow.

Una fuente de datos tiene una longitud:

len(ds['train'])

Accediendo al primer elemento del conjunto de datos:

%%timeit ds['train'][0]

...es tan barato como acceder a cualquier otro elemento. Esta es la definición de acceso aleatorio:

%%timeit ds['train'][1000]

Las funciones ahora utilizan NumPy DTypes (en lugar de TensorFlow DTypes). Puede inspeccionar las características con:

features = tfds.builder('fashion_mnist').info.features

Encontrará más información sobre las funciones en nuestra documentación. Aquí podemos recuperar notablemente la forma de las imágenes, y el número de clases:

shape = features['image'].shape num_classes = features['label'].num_classes

Uso en Python puro

Puedes utilizar fuentes de datos en Python iterando sobre ellas:

for example in ds['train']: print(example) break

Si inspeccionas los elementos, también notarás que todas las características ya están decodificadas usando NumPy. Entre bastidores, utilizamos OpenCV por defecto porque es rápido. Si no tienes OpenCV instalado, usamos por defecto Pillow para proporcionar una decodificación de imágenes ligera y rápida.

{ 'image': array([[[0], [0], ..., [0]], [[0], [0], ..., [0]]], dtype=uint8), 'label': 2, }

{Nota: Actualmente, la función sólo está disponible para las funciones Tensor, Image y Scalar. Las funciones Audio y Video estarán disponibles próximamente. Permanece atento.

Uso con PyTorch

PyTorch utiliza el paradigma fuente/muestreador/cargador. En Torch, las "fuentes de datos" se llaman " datasets". torch.utils.data contiene todos los detalles que necesita saber para construir tuberías de entrada eficientes en Torch.

Las fuentes de datos TFDS pueden utilizarse como conjuntos de datos tipo mapa normales.

Primero instalamos e importamos Torch:

!pip install torch from tqdm import tqdm import torch

Ya hemos definido las fuentes de datos para entrenamiento y prueba (respectivamente, ds['train'] y ds['test']). Ahora podemos definir el muestreador y los cargadores:

batch_size = 128 train_sampler = torch.utils.data.RandomSampler(ds['train'], num_samples=5_000) train_loader = torch.utils.data.DataLoader( ds['train'], sampler=train_sampler, batch_size=batch_size, ) test_loader = torch.utils.data.DataLoader( ds['test'], sampler=None, batch_size=batch_size, )

Utilizando PyTorch, entrenamos y evaluamos una regresión logística simple en los primeros ejemplos:

class LinearClassifier(torch.nn.Module): def __init__(self, shape, num_classes): super(LinearClassifier, self).__init__() height, width, channels = shape self.classifier = torch.nn.Linear(height * width * channels, num_classes) def forward(self, image): image = image.view(image.size()[0], -1).to(torch.float32) return self.classifier(image) model = LinearClassifier(shape, num_classes) optimizer = torch.optim.Adam(model.parameters()) loss_function = torch.nn.CrossEntropyLoss() print('Training...') model.train() for example in tqdm(train_loader): image, label = example['image'], example['label'] prediction = model(image) loss = loss_function(prediction, label) optimizer.zero_grad() loss.backward() optimizer.step() print('Testing...') model.eval() num_examples = 0 true_positives = 0 for example in tqdm(test_loader): image, label = example['image'], example['label'] prediction = model(image) num_examples += image.shape[0] predicted_label = prediction.argmax(dim=1) true_positives += (predicted_label == label).sum().item() print(f'\nAccuracy: {true_positives/num_examples * 100:.2f}%')

Próximamente: uso con JAX

Estamos trabajando estrechamente con Grain. Grain es un cargador de datos de código abierto, rápido y determinista para Python. Estén al tanto.

Más información

Para obtener más información, consulte tfds.data_source API doc.