В библиотеке Brain.js нейронные сети строятся как последовательность слоёв, каждый из которых содержит веса и смещения, определяющие поведение сети при обработке входных данных. Иногда возникает необходимость частичного обучения сети: обновлять только некоторые слои, оставляя другие неизменными. Для этого применяется техника замораживания слоёв (layer freezing).
Замораживание слоёв позволяет:
В Brain.js замораживание слоёв реализуется через прямой доступ к
весам и смещениям слоёв, а также контроль над их обновлением во время
вызова train().
Сеть в Brain.js, особенно тип feedforward или
recurrent, состоит из массива объектов, каждый из которых
представляет слой:
{
weights: [...], // Матрица весов для текущего слоя
biases: [...], // Смещения для нейронов слоя
activation: 'sigmoid', // Функция активации
}
Каждый слой имеет:
[число_нейронов_текущего_слоя, число_нейронов_предыдущего_слоя].Для того чтобы слой не обновлялся во время обучения, необходимо
блокировать изменение его weights и
biases. Brain.js не предоставляет встроенной функции
типа freezeLayer(), поэтому решение осуществляется через
переопределение градиентов или отключение их обновления
вручную.
Перед тренировкой создаются копии текущих весов и смещений слоёв, которые нужно заморозить:
const frozenLayers = [];
for (let i = 0; i < network.layers.length; i++) {
if (i < 2) { // Замораживаем первые два слоя
frozenLayers[i] = {
weights: JSON.parse(JSON.stringify(network.layers[i].weights)),
biases: JSON.parse(JSON.stringify(network.layers[i].biases))
};
}
}
network.train(trainingData, {
iterations: 1000,
learningRate: 0.01,
log: true,
logPeriod: 100,
callback: () => {
for (let i in frozenLayers) {
network.layers[i].weights = frozenLayers[i].weights;
network.layers[i].biases = frozenLayers[i].biases;
}
}
});
Ключевые моменты:
Для более точного контроля можно изменить поведение метода обновления весов в слое. При тренировке используется функция обратного распространения ошибки, которая формирует градиенты. Замороженные слои просто пропускаются:
network.train = function(data, options) {
const frozenIndexes = [0, 1]; // Индексы слоёв для заморозки
const originalBackward = this._backpropagate;
this._backpropagate = function(target) {
const gradients = originalBackward.call(this, target);
frozenIndexes.forEach(idx => {
gradients[idx].weights.fill(0);
gradients[idx].biases.fill(0);
});
return gradients;
};
return BrainJSOriginalTrain.call(this, data, options);
};
Пояснения:
_backpropagate генерирует градиенты для всех
слоёв.Для рекуррентных сетей (LSTM, GRU)
замораживание слоёв усложняется, так как градиенты распространяются во
времени. В этом случае:
inputWeights, hiddenWeights).Замораживание слоёв работает независимо от функции активации
(sigmoid, tanh, relu). Однако при
использовании ReLU важно проверять, что замороженные
веса не приводят к “мертвым нейронам” после переноса в новую задачу,
поскольку они не будут адаптироваться к изменяющемуся диапазону входных
данных.