Отслеживание весов

ConvNetJS — это полностью клиентская библиотека для построения и обучения нейронных сетей на JavaScript. Она ориентирована на сверточные нейронные сети (CNN), но поддерживает и стандартные полносвязные сети. Основным объектом для работы является Net, который содержит архитектуру сети, веса и методы обучения.

Инициализация сети

Сеть создаётся с помощью конструктора convnetjs.Net(). После создания объект сети пуст и требует конфигурации слоёв через makeLayers(layer_defs). Конфигурация задаётся массивом объектов, каждый из которых описывает слой:

var layer_defs = [];
layer_defs.push({type:'input', out_sx:32, out_sy:32, out_depth:3}); // входной слой
layer_defs.push({type:'conv', sx:5, filters:8, stride:1, pad:2, activation:'relu'}); // сверточный слой
layer_defs.push({type:'pool', sx:2, stride:2}); // слой подвыборки
layer_defs.push({type:'softmax', num_classes:10}); // выходной слой

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

net.makeLayers(layer_defs);

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


Структура весов и смещений

Каждый слой сети хранит свои веса и смещения в виде объекта vol (объект класса Vol). Для сверточного слоя веса представляют собой 4-мерный тензор [sx, sy, depth, filters], где:

  • sx, sy — размеры фильтра по ширине и высоте
  • depth — глубина входного объёма
  • filters — количество фильтров

Смещения хранятся в отдельном векторе размерности равной количеству фильтров. Для полносвязного слоя веса хранятся в форме матрицы [num_inputs, num_neurons], а смещения — в виде вектора [num_neurons].

Пример доступа к весам сверточного слоя:

var conv_layer = net.layers[1];
console.log(conv_layer.filters[0].w); // массив весов первого фильтра
console.log(conv_layer.filters[0].dw); // массив градиентов по весам

Инициализация и распределение весов

ConvNetJS использует небольшое случайное распределение для инициализации весов, что предотвращает «затухание градиентов». Значения обычно находятся в диапазоне [-0.01, 0.01]. Смещения инициализируются нулями.

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

for(var i=0;i

Обновление весов

Обучение в ConvNetJS реализуется через стохастический градиентный спуск (SGD) и другие оптимизаторы (adagrad, adam). Метод train принимает входные данные и правильный класс, автоматически вычисляет градиенты и обновляет веса:

var trainer = new convnetjs.SGDTrainer(net, {learning_rate:0.01, momentum:0.9, batch_size:20});
trainer.train(x, y); // x — Vol, y — правильная метка

Каждый шаг обучения вычисляет dw для каждого фильтра и смещения. После этого веса обновляются по формуле:

[ w = w - dw]

где η — скорость обучения, dw — градиент. При использовании момента учитывается накопленный предыдущий градиент:

[ v = v - dw] [ w = w + v]

где μ — коэффициент момента.


Сохранение и загрузка весов

ConvNetJS поддерживает экспорт и импорт весов в JSON-формате. Это удобно для сохранения состояния сети и повторного использования:

var json = net.toJSON(); // экспорт сети и весов
var net2 = new convnetjs.Net();
net2.fromJSON(json); // загрузка сети с весами

В JSON сохраняются все параметры слоёв, включая веса, смещения и типы активаций.


Нюансы работы с весами

  1. Инициализация: малые случайные значения предотвращают «мертвые нейроны» в ReLU.
  2. Регуляризация: L1 и L2 можно добавить через trainer для предотвращения переобучения.
  3. Масштабирование входов: нормализация входных данных помогает ускорить сходимость и стабилизирует распределение градиентов.
  4. Поддержка батчей: обновление весов на мини-батчах улучшает стабильность градиентов и уменьшает переобучение.

Работа с Vol

В ConvNetJS основным контейнером для весов, смещений и активаций является класс Vol. Он поддерживает:

  • многомерные массивы
  • операции над весами и градиентами
  • методы для копирования и масштабирования

Пример создания собственного объёма весов:

var v = new convnetjs.Vol(3,3,2); // 3x3 фильтр, глубина 2
v.w[0] = 0.1; // присвоение конкретного веса

Использование Vol позволяет легко манипулировать весами и интегрировать их в вычисления сети.


Прямое редактирование весов

ConvNetJS допускает прямое вмешательство в веса для экспериментов или тонкой настройки:

var fc_layer = net.layers[2]; // полносвязный слой
for(var i=0;i

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

javascript42 — изучаем JavaScript вместе