Написание пользовательской функции активации

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


Структура функции активации

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

Пример базовой структуры:

function customActivation(x) {
    let y = new Float32Array(x.length);
    for (let i = 0; i < x.length; i++) {
        y[i] = Math.tanh(x[i]); // пример активации
    }
    return y;
}
  • x — одномерный массив чисел (Float32Array), представляющий значения активаций на входе слоя.
  • y — массив такой же длины, содержащий результат функции активации.

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


Подключение пользовательской функции к модели

В Keras.js при загрузке модели из формата .json функции активации передаются в объект custom:

import KerasJS from 'keras-js';

const model = new KerasJS.Model({
    filepath: 'model.json',
    gpu: true,
    custom: {
        'custom_activation': customActivation
    }
});

Здесь 'custom_activation' — имя функции, указанное в Keras при сохранении модели. Оно должно совпадать с ключом в объекте custom. Keras.js при инициализации модели автоматически подставляет эту функцию для соответствующего слоя.


Применение кастомной активации в слоях модели

Для корректной работы модели с пользовательской функцией активации необходимо:

  1. В Keras указать имя функции активации при создании слоя:
from keras.layers import Dense
from keras.models import Sequential
from keras.utils.generic_utils import get_custom_objects
import keras.backend as K

def custom_activation(x):
    return K.tanh(x) + 0.1 * x

get_custom_objects().update({'custom_activation': custom_activation})

model = Sequential()
model.add(Dense(64, input_shape=(100,), activation='custom_activation'))
  1. Сохранить модель в формате JSON (model.to_json()) и весах (model.save_weights()), чтобы Keras.js мог их загрузить.

  2. В Keras.js передать функцию через объект custom, как показано выше.


Советы по оптимизации пользовательских функций

  1. Векторизация вычислений: избегать циклов for для больших массивов, использовать возможности Float32Array и встроенные математические функции, такие как Math.exp или Math.max.

  2. Стабильность чисел: при использовании функций типа sigmoid или softplus контролировать диапазон входных значений для предотвращения переполнений. Например, ограничение входа сигмоиды:

x = Math.max(-20, Math.min(20, x));
  1. Совместимость с WebGL: при включении GPU-режима Keras.js выполняет вычисления через WebGL, поэтому функции должны быть простыми и без побочных эффектов.

  2. Кэширование промежуточных вычислений: при сложных выражениях можно предварительно вычислять константы вне цикла, чтобы уменьшить нагрузку на GPU или CPU.


Примеры распространённых пользовательских функций

  1. Leaky ReLU:
function leakyReLU(x, alpha = 0.01) {
    let y = new Float32Array(x.length);
    for (let i = 0; i < x.length; i++) {
        y[i] = x[i] > 0 ? x[i] : alpha * x[i];
    }
    return y;
}
  1. Swish:
function swish(x) {
    let y = new Float32Array(x.length);
    for (let i = 0; i < x.length; i++) {
        y[i] = x[i] / (1 + Math.exp(-x[i]));
    }
    return y;
}
  1. Custom bounded activation:
function bounded(x) {
    let y = new Float32Array(x.length);
    for (let i = 0; i < x.length; i++) {
        y[i] = Math.max(-1, Math.min(1, x[i]));
    }
    return y;
}

Отладка и тестирование

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

const input = new Float32Array([0.5, -0.5, 1.2, -2.3]);
console.log(customActivation(input));

Это позволяет убедиться, что функция возвращает массив правильной длины и значения соответствуют ожидаемым. Ошибки в размерности массива или типе данных — самая частая причина сбоев при запуске модели в Keras.js.