Построение нестандартных топологий вручную

Библиотека Synaptic предоставляет возможность создавать нейронные сети произвольной структуры, выходя за рамки стандартных полносвязных слоёв. Основной элемент в этом подходе — нейрон, а сеть формируется как граф из нейронов, связанных синапсами. Каждый нейрон обладает свойствами activation, bias и набором входящих и исходящих соединений.

const synaptic = require('synaptic');
const { Neuron, Layer, Network } = synaptic;

Нейроны можно связывать вручную через метод project:

let inputNeuron = new Neuron();
let hiddenNeuron = new Neuron();

inputNeuron.project(hiddenNeuron);

При этом создаётся синапс, который соединяет выход inputNeuron с входом hiddenNeuron. Можно задавать вес синапса вручную:

let connection = inputNeuron.project(hiddenNeuron);
connection.weight = 0.5;

Создание собственных слоёв

Слой в Synaptic — это коллекция нейронов с набором удобных методов для массовых операций. Создание нестандартного слоя:

let customLayer = new Layer(3); // три нейрона в слое

Можно напрямую добавлять нейроны:

customLayer.add(new Neuron());

Все нейроны слоя можно соединять с другим слоем через project:

customLayer.project(anotherLayer);

Для полного контроля над структурой можно соединять отдельные нейроны между слоями или внутри слоя.

Соединение нейронов и контроль потоков

Метод project поддерживает несколько вариантов:

  • Neuron → Neuron: одиночное соединение.
  • Neuron → Layer: нейрон соединяется со всеми нейронами слоя.
  • Layer → Layer: полное соединение всех нейронов двух слоёв.
  • Layer → Neuron: каждый нейрон слоя подключается к конкретному нейрону.

Пример создания асимметричной топологии:

let inputLayer = new Layer(2);
let hiddenLayer = new Layer(3);
let outputNeuron = new Neuron();

// соединяем только первый нейрон inputLayer с outputNeuron
inputLayer.neurons()[0].project(outputNeuron);

// соединяем все нейроны hiddenLayer с outputNeuron
hiddenLayer.project(outputNeuron);

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

Настройка весов и функций активации

Каждый нейрон по умолчанию использует сигмоидальную функцию активации, но её можно изменять через переопределение метода activate:

let neuron = new Neuron();
neuron.squash = Neuron.squash.TANH; // гиперболический тангенс

Вес синапса можно динамически изменять во время работы сети для реализации адаптивного поведения:

connection.weight += 0.1; // корректировка веса

Создание рекуррентных связей

Рекуррентные нейронные сети в Synaptic строятся путем соединения нейронов слоя с самим собой или с предыдущими слоями:

hiddenLayer.neurons().forEach(neuron => {
    neuron.project(hiddenLayer); // самосвязь
});

Такая структура позволяет хранить состояние и учитывать прошлые значения при вычислениях.

Композиция сетей

Можно объединять несколько отдельных сетей в одну более крупную, создавая сложные архитектуры. Для этого используется метод Network:

let inputLayer = new Layer(2);
let hiddenLayer = new Layer(3);
let outputLayer = new Layer(1);

inputLayer.project(hiddenLayer);
hiddenLayer.project(outputLayer);

let network = new Network({
    input: inputLayer,
    hidden: [hiddenLayer],
    output: outputLayer
});

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

Обработка сигналов и обучение

Для нестандартных сетей важно правильно формировать маски входов и выходов. Активация сети выполняется через метод activate:

let output = network.activate([0.5, 0.2]);

Обратное распространение ошибки (propagate) работает на уровне сети независимо от топологии, если корректно указаны входы и выходы:

network.propagate(0.3, [1]); // обучение с целевым выходом

Для рекуррентных или частично соединённых структур стоит вручную контролировать последовательность активаций нейронов.

Практические рекомендации

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

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