Обучение автоэнкодера

Autoencoder в ConvNetJS строится на основе двух ключевых компонентов: кодировщика (encoder) и декодировщика (decoder). Кодировщик сжимает входные данные в скрытое представление (latent space), а декодировщик восстанавливает данные из этого представления.

В ConvNetJS сеть создается через объект convnetjs.Net(). Слои добавляются методом makeLayers, где каждый слой описывается объектом с полями type, num_neurons, activation, stride, pad и другими. Для автоэнкодера часто используют полностью связанные слои (fc) с активацией ReLU или Sigmoid.

Пример структуры:

var layer_defs = [];
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:784}); // 28x28 пикселей
layer_defs.push({type:'fc', num_neurons:128, activation:'relu'});
layer_defs.push({type:'fc', num_neurons:64, activation:'relu'}); // скрытое пространство
layer_defs.push({type:'fc', num_neurons:128, activation:'relu'});
layer_defs.push({type:'fc', num_neurons:784, activation:'sigmoid'});
var net = new convnetjs.Net();
net.makeLayers(layer_defs);

Ключевой момент: скрытый слой должен быть меньше входного, чтобы сеть действительно училась сжимать информацию.


Подготовка данных

ConvNetJS работает с массивами чисел, поэтому изображения 28x28 преобразуются в одномерный массив длиной 784. Входные данные нормализуются в диапазон [0,1] для стабильного обучения.

function normalizeImage(img) {
    var x = [];
    for(var i=0;i

Входные данные подаются в виде Vol:

var x = new convnetjs.Vol(normalizeImage(image));

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

Для автоэнкодеров используется среднеквадратичная ошибка (MSE), поскольку цель — восстановление входа. В ConvNetJS функция потерь задается через RegressionLayer:

layer_defs.push({type:'regression', num_neurons:784});

Оптимизатор выбирается из convnetjs.SGD:

var trainer = new convnetjs.SGDTrainer(net, {learning_rate:0.01, momentum:0.9, batch_size:20, l2_decay:0.001});

Важная деталь: размер батча влияет на стабильность градиентного спуска. Малые батчи позволяют быстрее обновлять веса, но могут вносить шум, большие — дают более плавное обучение.


Процесс обучения

Обучение автоэнкодера заключается в подаче входных данных и обратного распространения ошибки. В ConvNetJS это выглядит так:

for(var epoch=0; epoch<10; epoch++) {
    for(var i=0; i

Особенность: вход и целевой выход идентичны, поэтому целевая Vol совпадает с входной.


Визуализация скрытого слоя

После обучения важно проверить качество скрытых представлений. Скрытый слой можно извлечь так:

var x = new convnetjs.Vol(normalizeImage(image));
net.forward(x);
var hidden = net.layers[2].out_act; // выход скрытого слоя

Для визуализации часто используют тепловые карты или уменьшают размерность с помощью PCA или t-SNE.


Регуляризация и предотвращение переобучения

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

  • Dropout: добавляется на скрытые слои через {type:'dropout', drop_prob:0.2}.
  • L2-регуляризация: задается параметром l2_decay в SGDTrainer.
  • Шум в данных: можно добавлять случайные шумы в входной сигнал, что делает автоэнкодер denoising.

Модификации автоэнкодера

ConvNetJS позволяет экспериментировать с различными архитектурами:

  • Denoising Autoencoder: шум добавляется к входу, а сеть обучается восстанавливать исходное изображение.
  • Sparse Autoencoder: в скрытых слоях активируются лишь отдельные нейроны, достигается через регуляризацию на активность.
  • Variational Autoencoder (VAE): более сложная структура с вероятностной интерпретацией, хотя ConvNetJS требует ручного кодирования латентного распределения.

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

ConvNetJS предоставляет методы сериализации:

var json = net.toJSON();
var net2 = new convnetjs.Net();
net2.fromJSON(json);

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


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

Скрытое пространство можно использовать как компактное представление для:

  • Классификации с последующим fc-слоем.
  • Кластеризации с K-Means или DBSCAN.
  • Визуализации сложных данных в 2D или 3D.

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

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