Интеграция с React: хуки и жизненный цикл

Для работы с Keras.js в React необходимо добавить библиотеку через npm или подключить напрямую через CDN. В современных приложениях предпочтителен вариант с npm:

npm install keras-js

После установки импорт производится стандартным способом:

import KerasJS from 'keras-js';

Важно учитывать, что Keras.js работает на стороне клиента и использует WebGL для ускорения вычислений. Следовательно, компоненты, где планируется использование модели, должны корректно обрабатывать асинхронную загрузку WebGL контекста.


Создание и загрузка модели

Keras.js работает с моделями, экспортированными из Python Keras в форматах .json и .bin. Для интеграции в React можно использовать асинхронную функцию с хуком useEffect для загрузки модели при монтировании компонента.

import { useState, useEffect } from 'react';
import KerasJS from 'keras-js';

function useKerasModel(modelPath) {
  const [model, setModel] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const kerasModel = new KerasJS.Model({ filepath: modelPath });
    kerasModel.ready()
      .then(() => {
        setModel(kerasModel);
        setLoading(false);
      })
      .catch(err => {
        console.error('Ошибка загрузки модели:', err);
        setLoading(false);
      });
  }, [modelPath]);

  return { model, loading };
}

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

  • Использование useEffect без зависимостей кроме пути модели обеспечивает однократную загрузку при монтировании.
  • kerasModel.ready() возвращает промис, который разрешается после готовности модели к предсказаниям.
  • Обработка ошибок обязательна, так как некорректный путь или несовместимая модель могут вызвать исключение.

Использование модели для предсказаний

После того как модель загружена, можно выполнять предсказания. Keras.js принимает входные данные в виде TypedArray (Float32Array, Uint8Array) или обычных массивов чисел.

function predict(model, inputData) {
  if (!model) return null;

  const inputTensor = new Float32Array(inputData);
  return model.predict({ input: inputTensor })
    .then(output => {
      return output.output; // ключ соответствует имени выхода модели
    })
    .catch(err => {
      console.error('Ошибка предсказания:', err);
      return null;
    });
}

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

  • Входной массив должен строго соответствовать форме (shape) слоя input модели.
  • Асинхронная природа predict требует обработки через then или async/await.
  • Результаты возвращаются в формате объекта, где ключи соответствуют именам выходных слоёв модели.

Интеграция с React-хуками

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

function useKerasPredict(modelPath) {
  const { model, loading } = useKerasModel(modelPath);
  const [result, setResult] = useState(null);
  const [error, setError] = useState(null);

  const runPrediction = async (inputData) => {
    if (!model) return;
    try {
      const output = await model.predict({ input: new Float32Array(inputData) });
      setResult(output.output);
    } catch (err) {
      setError(err);
      setResult(null);
    }
  };

  return { result, error, loading, runPrediction };
}

Преимущества подхода:

  • Полная асинхронная обработка без блокировки интерфейса.
  • Хук можно многократно использовать в разных компонентах.
  • Хранение состояния предсказания и ошибок локально упрощает отображение прогресса и результатов.

Управление жизненным циклом модели

React предоставляет несколько стратегий для корректного управления ресурсами Keras.js:

  1. Очистка модели при размонтировании При использовании больших моделей важно освобождать WebGL ресурсы:
useEffect(() => {
  return () => {
    if (model && model.gl) {
      model.gl.delete();
    }
  };
}, [model]);
  1. Отслеживание прогресса загрузки Можно использовать локальный стейт для отображения индикатора загрузки:
const [progress, setProgress] = useState(0);
kerasModel.ready().then(() => setProgress(100));
  1. Поддержка нескольких моделей одновременно Если приложение использует несколько моделей, каждая должна загружаться в отдельном хуке или компоненте, чтобы избежать конфликтов WebGL контекста.

Взаимодействие с пользовательским интерфейсом

Интеграция с React позволяет динамически обновлять интерфейс при работе модели. Примеры типичных решений:

  • Кнопка предсказания запускает runPrediction и блокируется во время вычислений.
  • Индикатор загрузки отображается пока loading равен true.
  • Вывод результатов можно привязать к состоянию result, обновляя DOM автоматически через реактивный рендер.

Оптимизация производительности

Keras.js использует WebGL, но в браузере есть ограничения на память и вычислительную мощность. Рекомендации:

  • Минимизировать размер модели для клиентской загрузки.
  • Использовать Float16 вместо Float32, если точность позволяет.
  • Пакетировать несколько предсказаний в один вызов predict, чтобы снизить накладные расходы на WebGL.
  • Кэшировать результаты модели, если одно и то же изображение или данные предсказываются многократно.

Асинхронная обработка больших данных

Для работы с массивами большого объёма стоит разбивать входные данные на чанки и выполнять предсказания по частям, чтобы не блокировать главный поток:

async function batchPredict(model, data, batchSize = 32) {
  const results = [];
  for (let i = 0; i < data.length; i += batchSize) {
    const batch = data.slice(i, i + batchSize);
    const batchResult = await model.predict({ input: new Float32Array(batch.flat()) });
    results.push(...batchResult.output);
  }
  return results;
}

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