Связывание слоёв и построение графа вычислений

Keras.js представляет собой JavaScript-реализацию высокоуровневого API Keras, позволяющую выполнять нейронные сети прямо в браузере с использованием WebGL для ускорения вычислений. Основой работы является граф вычислений, в котором каждый слой модели выступает как узел, а данные (тензоры) — как рёбра, связывающие слои.

Важной концепцией является разделение слоёв и их связей. В Keras.js слои не выполняются линейно сразу после определения, а сначала создаётся абстрактная структура сети — граф, где каждый слой хранит информацию о входах и выходах. Такой подход позволяет:

  • реализовывать модели с разветвлениями и петлями;
  • оптимизировать выполнение через WebGL, минимизируя копирование данных между слоями;
  • повторно использовать слои в разных частях сети без дублирования кода.

Создание и связывание слоёв

Слои создаются как объекты соответствующих классов, например:

const Dense = require('keras-js').Layers.Dense;
const Input = require('keras-js').Layers.Input;

const inputLayer = new Input({shape: [784]});
const hiddenLayer = new Dense({units: 128, activation: 'relu'});
const outputLayer = new Dense({units: 10, activation: 'softmax'});

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

hiddenLayer.setInput(inputLayer.output);
outputLayer.setInput(hiddenLayer.output);

Метод setInput гарантирует, что данные будут правильно переданы между слоями во время выполнения модели. В Keras.js каждый слой хранит ссылки на источники данных (inputs) и на слои, которые потребляют его выходы (outputs), что формирует направленный ациклический граф (DAG).

Работа с многовходовыми и многовыходными моделями

Keras.js поддерживает сложные архитектуры с несколькими входами и выходами. Например, модель с двумя входами и объединением их через конкатенацию реализуется через слой Merge:

const Merge = require('keras-js').Layers.Merge;

const inputA = new Input({shape: [64]});
const inputB = new Input({shape: [64]});

const merged = new Merge({mode: 'concat'}).setInput([inputA.output, inputB.output]);

Особенности работы с многовходовыми моделями:

  • входной массив setInput([...]) должен соответствовать порядку, используемому при обучении модели;
  • каждый слой может иметь несколько родителей, что позволяет строить DAG с развилками и повторным использованием слоёв.

Передача данных через граф

При вызове метода model.predict(inputData) Keras.js выполняет топологическую сортировку слоёв графа, чтобы гарантировать корректный порядок вычислений. Алгоритм выполняется следующим образом:

  1. Вычисляются все слои, не имеющие родителей (истоки графа).
  2. Для каждого слоя проверяется, готовы ли все входные данные; если да, выполняется операция слоя.
  3. Выход слоя передаётся на вход всех дочерних слоёв.
  4. Процесс повторяется до достижения всех выходных слоёв.

Такой подход позволяет эффективно использовать GPU через WebGL и избегать лишнего копирования данных.

Управление памятью и кэширование результатов

Keras.js кэширует результаты промежуточных слоёв для повторного использования, что особенно важно при многовыходных сетях:

  • Кэширование тензоров снижает нагрузку на память и повышает производительность;
  • Удаление временных данных происходит автоматически после того, как они перестают быть необходимыми для вычислений последующих слоёв;
  • Для оптимизации больших моделей можно вручную управлять памятью, вызывая методы dispose() на неиспользуемых тензорах.

Обработка условных и динамических путей

Хотя Keras.js ориентирован на статические графы, возможна организация условных ветвлений через условные слои или вычисления вне графа с последующей подачей данных в стандартные слои. Для этого используется сочетание слоёв Lambda и массивов входных данных:

const Lambda = require('keras-js').Layers.Lambda;

const conditionalLayer = new Lambda({
  function: x => x.greater(0.5).mul(x)
});
conditionalLayer.setInput(hiddenLayer.output);

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

Визуализация графа

Keras.js предоставляет возможности для отладки и анализа структуры сети. Основные методы включают:

  • model.toJSON() — выводит описание всех слоёв и их связей;
  • layer.getInboundLayers() — показывает список всех родительских слоёв;
  • layer.getOutboundLayers() — возвращает все дочерние слои, которые используют данный слой.

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

Ключевые моменты

  • Keras.js строит направленный ациклический граф для вычислений, что обеспечивает поддержку сложных архитектур;
  • Связывание слоёв осуществляется через setInput, а данные передаются по графу в порядке топологической сортировки;
  • Поддерживаются многовходовые и многовыходные модели, с возможностью объединения данных через слои Merge и Lambda;
  • Кэширование и управление памятью обеспечивают эффективное использование ресурсов браузера;
  • Визуализация и методы introspection позволяют детально анализировать граф и отлаживать модель.

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