Keras.js — это библиотека, позволяющая запускать предобученные модели Keras в браузере на JavaScript, используя WebGL для ускорения вычислений. Одной из ключевых возможностей является расширение функциональности через создание пользовательских слоёв. Пользовательские слои позволяют реализовать нестандартные операции и интегрировать их в граф модели.
Для создания собственного слоя необходимо определить класс,
наследующий от базового класса Layer. Минимальные элементы,
которые требуется реализовать:
call(inputs) — основная логика
вычислений. Принимает входные данные в виде массива Tensor
и возвращает результат работы слоя.computeOutputShape(inputShape) —
определяет форму выходного тензора на основе формы входного.Пример базового шаблона:
class CustomLayer extends KerasJS.Layer {
constructor(config) {
super(config);
this.units = config.units || 1;
this.activation = config.activation || null;
}
computeOutputShape(inputShape) {
return [inputShape[0], this.units];
}
call(inputs) {
const input = inputs[0]; // inputs всегда массив
// Простейшая линейная операция: output = input * weight + bias
let output = input.map(x => x * this.units + 1); // пример
if (this.activation) {
output = this.activation(output);
}
return output;
}
}
Ключевые моменты:
inputs всегда массив, даже если слой имеет один
вход.KerasJS.activations.relu,
KerasJS.activations.sigmoid и др.).Пользовательские слои часто требуют своих параметров (весов и
смещений). В Keras.js веса хранятся в объекте this.weights.
Чтобы слой корректно работал, необходимо:
Пример инициализации весов:
class DenseCustom extends KerasJS.Layer {
constructor(config) {
super(config);
this.units = config.units;
this.inputDim = config.inputDim;
// Инициализация весов
this.weights = [
{ name: 'W', data: new Float32Array(this.inputDim * this.units).fill(0.01) },
{ name: 'b', data: new Float32Array(this.units).fill(0) }
];
}
call(inputs) {
const input = inputs[0];
const W = this.weights[0].data;
const b = this.weights[1].data;
const output = new Float32Array(this.units);
for (let i = 0; i < this.units; i++) {
let sum = b[i];
for (let j = 0; j < this.inputDim; j++) {
sum += input[j] * W[j * this.units + i];
}
output[i] = sum;
}
return output;
}
computeOutputShape(inputShape) {
return [inputShape[0], this.units];
}
}
Особенности:
this.weights.После создания слоя его можно интегрировать в модель так же, как
стандартный слой Keras.js. Модель строится с помощью объекта
Sequential или Model:
const model = new KerasJS.Sequential();
model.add(new DenseCustom({ units: 4, inputDim: 3 }));
model.add(new KerasJS.layers.Activation({ activation: 'relu' }));
Особенности интеграции:
inputDim обязателен для первого слоя, чтобы
модель знала форму входа.call возвращает массив тензоров.Для нестандартных функций активации или комбинаций слоев можно
реализовать логику напрямую в методе call. Например, слой с
умножением матриц и применением нестандартной функции:
call(inputs) {
const x = inputs[0];
const y = inputs[1];
const output = new Float32Array(x.length);
for (let i = 0; i < x.length; i++) {
output[i] = Math.tanh(x[i] * y[i] + 0.5);
}
return output;
}
Рекомендации:
TypedArray для повышения производительности.Пользовательский слой может принимать несколько входов и возвращать несколько выходов. В этом случае:
inputs всегда массив: каждый элемент — отдельный
вход.call должен возвращать массив соответствующей
длины.Пример слоя с двумя входами:
call(inputs) {
const [input1, input2] = inputs;
const output = input1.map((v, i) => v + input2[i]);
return [output];
}
Keras.js поддерживает загрузку предобученных моделей, включая веса пользовательских слоев, при условии, что:
Для сериализации можно реализовать методы getConfig и
fromConfig:
getConfig() {
return { units: this.units, activation: this.activation };
}
static fromConfig(config) {
return new CustomLayer(config);
}
Это позволяет интегрировать пользовательские слои в JSON модели и загружать их без ошибок.
Float32Array для всех числовых
данных.call для
экономии ресурсов.Пользовательские слои в Keras.js дают полный контроль над архитектурой модели и вычислительными процессами, позволяя создавать уникальные решения прямо в браузере без серверной части. Их грамотная реализация требует аккуратного управления весами, формами тензоров и оптимизацией под WebGL.