tf.data.array и tf.data.generator

TensorFlow.js предоставляет высокоуровневые инструменты для подготовки и обработки данных, среди которых ключевое место занимает модуль tf.data. Он позволяет создавать эффективные конвейеры данных, которые поддерживают ленивую загрузку, батчинг и трансформации, что особенно важно при работе с большими наборами данных в браузере и на сервере Node.js.


tf.data.array

Метод tf.data.array предназначен для создания объекта Dataset на основе обычного JavaScript-массива. Этот способ удобен для небольших наборов данных, которые можно полностью загрузить в память.

Синтаксис:

const dataset = tf.data.array([1, 2, 3, 4, 5]);

После создания Dataset можно применять к нему разнообразные методы для трансформации данных:

  • map — функция, применяемая к каждому элементу:

    const squared = dataset.map(x => x * x);
  • batch — группировка элементов в батчи:

    const batched = dataset.batch(2);
  • shuffle — перемешивание элементов для обучения модели:

    const shuffled = dataset.shuffle(5);

Особенности:

  • Работает с массивами любого типа: числа, объекты, тензоры.
  • Для больших массивов в памяти может потребоваться оптимизация или использование tf.data.generator.
  • Поддерживает ленивую обработку, элементы вычисляются только при вызове forEachAsync, toArray или при передаче в модель через fitDataset.

Пример использования с обучением модели:

const xs = tf.data.array([1, 2, 3, 4]);
const ys = tf.data.array([1, 4, 9, 16]);

const dataset = tf.data.zip({xs, ys}).batch(2);

const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

await model.fitDataset(dataset, {epochs: 10});

Здесь создаются батчи по 2 элемента, которые подаются на вход модели.


tf.data.generator

Метод tf.data.generator используется для создания Dataset на основе генератора JavaScript. Это особенно полезно при работе с потоковыми данными или наборами данных, которые не помещаются полностью в память.

Синтаксис:

function* dataGenerator() {
  for (let i = 0; i < 10; i++) {
    yield i * i;
  }
}

const dataset = tf.data.generator(dataGenerator);

Ключевые возможности:

  • Позволяет использовать бесконечные потоки данных.
  • Поддерживает ленивую генерацию элементов по мере необходимости.
  • Идеален для динамического преобразования и аугментации данных перед подачей на модель.

Примеры трансформаций:

  • map для генератора:

    const datasetSquared = dataset.map(x => x + 1);
  • batch и shuffle работают аналогично tf.data.array.

Использование генератора с асинхронными операциями:

async function* asyncDataGenerator() {
  for (let i = 0; i < 5; i++) {
    const tensor = await tf.tensor([i, i * 2]);
    yield tensor;
  }
}

const asyncDataset = tf.data.generator(asyncDataGenerator).batch(2);

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


Объединение массивов и генераторов

Для удобства обработки данных можно комбинировать Dataset от массива и генератора с помощью tf.data.zip:

const arrayDataset = tf.data.array([1, 2, 3]);
function* gen() { yield* [4, 5, 6]; }
const genDataset = tf.data.generator(gen);

const combined = tf.data.zip({a: arrayDataset, b: genDataset});

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


Особенности и оптимизации

  • Ленивая загрузка: Dataset не хранит все данные в памяти, элементы вычисляются по мере необходимости.
  • Эффективность: Методы batch и shuffle позволяют уменьшить накладные расходы при обучении модели.
  • Совместимость: Dataset, созданный через array или generator, можно напрямую передавать в model.fitDataset.
  • Потоковая обработка: generator позволяет работать с потоковыми данными и интегрироваться с асинхронными источниками.

Использование tf.data.array и tf.data.generator формирует основу для построения масштабируемых и гибких конвейеров данных в TensorFlow.js, обеспечивая эффективную подготовку и трансформацию данных перед обучением моделей.