Нормализация данных через датасет

В TensorFlow.js обработка и подготовка данных для обучения моделей осуществляется через объект tf.data.Dataset. Этот объект позволяет создавать конвейеры данных, обеспечивающие эффективную загрузку, трансформацию и нормализацию данных. Датасеты могут быть построены из массивов, файлов или потоков данных, а также комбинироваться и преобразовываться с использованием встроенных методов.

const xs = tf.tensor2d([[1], [2], [3], [4]]);
const ys = tf.tensor2d([[1], [3], [5], [7]]);

const dataset = tf.data.array([{x: xs, y: ys}]);

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


Нормализация данных

Нормализация — это процесс приведения данных к единому масштабу, что улучшает сходимость градиентного спуска и качество обучения моделей. В TensorFlow.js данные чаще всего нормализуются к диапазону [0, 1] или стандартизируются с нулевым средним и единичной дисперсией.

Масштабирование значений

Простейшая форма нормализации — деление всех значений на максимальное значение:

function normalize(tensor) {
    const maxVal = tensor.max();
    const minVal = tensor.min();
    return tensor.sub(minVal).div(maxVal.sub(minVal));
}

const normalizedXs = normalize(xs);
  • tensor.sub(minVal) — смещает все значения так, чтобы минимальное стало равным нулю.
  • div(maxVal.sub(minVal)) — масштабирует значения до диапазона [0, 1].

Стандартизация

Стандартизация перемещает данные так, чтобы их среднее было равно 0, а стандартное отклонение — 1:

function standardize(tensor) {
    const mean = tensor.mean();
    const std = tensor.sub(mean).square().mean().sqrt();
    return tensor.sub(mean).div(std);
}

const standardizedXs = standardize(xs);
  • tensor.sub(mean) смещает данные относительно среднего.
  • div(std) масштабирует данные с учетом дисперсии, улучшая стабильность обучения.

Интеграция нормализации с Dataset

Для работы с конвейерами данных нормализация выполняется через метод map объекта Dataset. Это позволяет автоматически преобразовывать каждую партию данных перед подачей в модель:

const normalizedDataset = dataset.map(({x, y}) => {
    const xNorm = normalize(x);
    const yNorm = y; // целевые значения могут оставаться без изменений
    return {x: xNorm, y: yNorm};
});

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


Батчинг и перемешивание данных

Обучение модели становится более устойчивым при разбиении данных на батчи и их перемешивании. Для этого используются методы batch и shuffle:

const batchedDataset = normalizedDataset.shuffle(100).batch(16);
  • shuffle(bufferSize) случайным образом перемешивает элементы в пределах указанного буфера.
  • batch(batchSize) объединяет элементы в группы указанного размера, оптимизируя работу GPU или CPU.

Примеры использования с моделью

Нормализованный и разбитый на батчи датасет подается в метод fit модели:

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

await model.fitDataset(batchedDataset, {
    epochs: 50
});

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


Практические рекомендации

  1. Всегда нормализовать входные данные. Модели быстрее сходятся при единых диапазонах значений.
  2. Целевые значения нормализуются только при необходимости. Для регрессии с физическими величинами часто оставляют оригинальный масштаб.
  3. Комбинировать трансформации через map. Можно одновременно применять нормализацию, аугментацию и фильтрацию.
  4. Использовать shuffle перед batch. Это улучшает качество обучения за счет случайного порядка данных.
  5. Проверять значения после нормализации. Методы min, max и mean позволяют убедиться в корректности преобразований.

Особенности работы с изображениями

Для изображений нормализация часто производится делением на 255, переводя пиксели в диапазон [0, 1]:

const imageDataset = tf.data.array([imageTensor1, imageTensor2]);
const normalizedImages = imageDataset.map(img => img.div(255));

При этом можно комбинировать нормализацию с аугментацией:

const augmentedDataset = normalizedImages.map(img => tf.image.randomFlipLeftRight(img));

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