Narx: нелинейная авторегрессионная сеть

Библиотека Synaptic — это мощный инструмент для построения, обучения и тестирования нейронных сетей в JavaScript. Она предоставляет низкоуровневый доступ к структурам сети, позволяя создавать как простые перцептроны, так и сложные рекуррентные сети. В основе Synaptic лежат три ключевых компонента: Neuron, Layer и Network.

  • Neuron — отдельный нейрон с возможностью настраивать веса входов и функции активации.
  • Layer — слой нейронов, объединяющий несколько нейронов и обеспечивающий возможность прямого или рекуррентного соединения.
  • Network — полная нейронная сеть, которая может состоять из одного или нескольких слоев, с возможностью обучения методом обратного распространения ошибки.

Моделирование Narx-сети

Narx (Nonlinear AutoRegressive with eXogenous inputs) — это тип рекуррентной сети, ориентированной на предсказание временных рядов. Она использует прошлые значения сигнала (авторегрессия) и внешние входные данные (exogenous inputs) для построения прогноза текущего состояния.

Ключевая особенность Narx-сети: наличие обратных связей с задержкой, которые позволяют сети учитывать динамику временного ряда.

Структура Narx в Synaptic

Narx-сеть можно реализовать в Synaptic через комбинацию следующих элементов:

  1. Входной слой: принимает текущее значение сигнала и внешние параметры.
  2. Скрытые слои: несколько слоев нейронов, где каждый слой выполняет нелинейное преобразование входных данных.
  3. Выходной слой: формирует предсказание для текущего момента времени.
  4. Механизм задержек (taps): реализуется путем подачи прошлых значений сигнала и внешних входов на входной слой сети.

Пример концептуальной схемы Narx-сети в Synaptic:

[input(t), input(t-1), ..., exog(t), exog(t-1), ...] --> [Hidden Layer] --> [Output(t)]

Создание нейронов и слоев

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

let inputLayer = new Layer(5); // 3 прошлых значения сигнала + 2 внешних входа
let hiddenLayer = new Layer(10);
let outputLayer = new Layer(1);

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

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

Особенности конфигурации

  • Размер входного слоя зависит от числа задержек и числа экзогенных переменных.
  • Скрытые слои рекомендуется подбирать через эксперименты: слишком маленький слой не позволит сети уловить нелинейности, слишком большой — приведет к переобучению.
  • Функции активации нейронов: по умолчанию Synaptic использует сигмоидную функцию, но можно заменить на tanh или ReLU через модификацию класса Neuron.

Реализация задержек

Для Narx важно хранить историю сигналов. Можно использовать очередь фиксированной длины:

class DelayBuffer {
    constructor(size) {
        this.buffer = [];
        this.size = size;
    }
    push(value) {
        this.buffer.push(value);
        if (this.buffer.length > this.size) {
            this.buffer.shift();
        }
    }
    getValues() {
        return this.buffer;
    }
}

Использование буфера позволяет формировать вектор входов сети:

let delay = new DelayBuffer(3);
delay.push(currentSignal);
let networkInput = [...delay.getValues(), ...exogenousInput];
narxNetwork.activate(networkInput);

Обучение Narx-сети

Synaptic поддерживает обучение методом обратного распространения ошибки через Trainer.

const trainer = new synaptic.Trainer(narxNetwork);

trainer.train(trainingSet, {
    rate: 0.01,
    iterations: 20000,
    error: 0.005,
    shuffle: true,
    log: 1000
});
  • rate — скорость обучения.
  • iterations — максимальное количество эпох.
  • error — целевой порог ошибки.
  • shuffle — случайное перемешивание обучающих примеров для повышения обобщающей способности сети.

Подготовка обучающих данных

Данные для Narx-сети требуют формирования входных и выходных векторов с учетом задержек:

let trainingSet = [];
for (let t = maxDelay; t < series.length; t++) {
    let inputVector = series.slice(t - maxDelay, t).concat(exogenousSeries.slice(t - maxDelay, t));
    let outputVector = [series[t]];
    trainingSet.push({ input: inputVector, output: outputVector });
}

Применение сети к прогнозированию

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

let predictionBuffer = new DelayBuffer(maxDelay);
series.slice(0, maxDelay).forEach(v => predictionBuffer.push(v));

for (let t = maxDelay; t < futureSteps; t++) {
    let inputVector = [...predictionBuffer.getValues(), ...futureExogenous[t]];
    let prediction = narxNetwork.activate(inputVector)[0];
    predictionBuffer.push(prediction);
}

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

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

  • Регуляризация: можно применять уменьшение весов через прямую модификацию нейронов для снижения переобучения.
  • Адаптивная скорость обучения: Synaptic позволяет динамически менять параметр rate в процессе обучения.
  • Раннее завершение (early stopping): контроль ошибки на валидационном наборе помогает остановить обучение до переобучения.

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