Гиперболический тангенс

Гиперболический тангенс (tanh) является одной из ключевых функций активации, используемых в нейронных сетях. В библиотеке ConvNetJS эта функция часто применяется в скрытых слоях для нормализации выходных значений нейронов, что ускоряет обучение и улучшает сходимость модели.

Определение функции

Функция гиперболического тангенса определяется как:

[ (x) = ]

Основные свойства:

  • Выходные значения лежат в диапазоне от -1 до 1.
  • Функция является непрерывной и дифференцируемой на всей числовой оси.
  • Симметрична относительно начала координат (центральная симметрия), что улучшает баланс градиентов при обучении.

Использование в ConvNetJS

ConvNetJS предоставляет встроенную реализацию функции tanh через слой tanhLayer. Пример создания слоя с использованием tanh:

var layer_defs = [];
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:10});
layer_defs.push({type:'fc', num_neurons:20, activation:'tanh'});
layer_defs.push({type:'softmax', num_classes:5});

var net = new convnetjs.Net();
net.makeLayers(layer_defs);

В данном примере:

  • Первый слой — входной с размерностью 10.
  • Второй слой — полносвязный с 20 нейронами и активацией tanh.
  • Третий слой — softmax для классификации на 5 классов.

Градиенты и обратное распространение

Для функции tanh производная вычисляется как:

[ ’(x) = 1 - ^2(x)]

Это ключевой момент для backpropagation. ConvNetJS автоматически рассчитывает градиенты для tanh при обучении, используя указанное выражение. Поскольку значения tanh находятся в диапазоне [-1, 1], производная также ограничена, что предотвращает слишком большие градиенты и снижает риск взрыва градиентов.

Пример вручную вычисленного градиента для одного нейрона:

var x = 0.5;
var y = Math.tanh(x);
var dy_dx = 1 - y*y; // производная tanh

Сравнение с другими функциями активации

  • Sigmoid: диапазон [0,1], центр около 0.5, склонна к проблеме затухающего градиента.
  • ReLU: диапазон [0,∞), несимметричная, часто приводит к “мертвым” нейронам.
  • Tanh: диапазон [-1,1], центрирован на 0, сохраняет градиенты лучше для скрытых слоев.

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

Практические советы по обучению

  • Инициализация весов: для tanh рекомендуется использовать Xavier initialization, чтобы начальные значения нейронов не были слишком большими или маленькими.
  • Скорость обучения: значение learning rate должно быть умеренным, так как производные tanh ограничены, что может замедлять обновление весов при слишком малом шаге.
  • Регуляризация: комбинация tanh с dropout слоями улучшает устойчивость сети к переобучению.

Пример тренировки сети с tanh

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

for(var i=0;i<1000;i++){
    var x = new convnetjs.Vol(1,1,10);
    for(var j=0;j<10;j++) x.w[j] = Math.random();
    var y = Math.floor(Math.random()*5);
    trainer.train(x, y);
}

Особенности:

  • SGDTrainer автоматически применяет backpropagation через tanh слои.
  • Случайные входные данные демонстрируют процесс градиентного обновления.
  • При обучении на реальных данных tanh помогает скрытым слоям быстрее достигать стабильного распределения активаций.

Визуализация активаций

Активации tanh можно визуализировать для анализа поведения сети:

var x = new convnetjs.Vol([0.1, -0.2, 0.5, -0.7, 0.3, 0.9, -0.1, 0.4, -0.5, 0.2]);
var output = net.forward(x);

console.log(output.w); // значения после прохождения через tanh

Наблюдается, что значения нейронов ограничены диапазоном [-1,1], что делает активации более стабильными по сравнению с ReLU или сигмоидой на начальных этапах обучения.

Оптимизация и тонкая настройка

  • При большом количестве скрытых слоев tanh может привести к затухающим градиентам. В таких случаях полезно комбинировать tanh с batch normalization.
  • Для небольших сетей tanh часто показывает лучшую сходимость по сравнению с sigmoid из-за центрирования вокруг нуля.
  • При использовании convnetjs стоит учитывать, что tanh добавляет небольшую вычислительную нагрузку по сравнению с ReLU, так как требует вычисления экспоненты, но выигрывает в стабильности.