Проверка весов и активаций вручную

Brain.js — это библиотека для работы с нейронными сетями на JavaScript, ориентированная на простое обучение и предсказание. Одним из важных аспектов работы с нейронными сетями является понимание того, как изменяются веса и как вычисляются активации на каждом слое. Это особенно полезно при отладке или обучении сети на малых данных.

Структура нейронной сети в Brain.js

Нейронные сети в Brain.js строятся на основе слоев нейронов, каждый из которых имеет следующие ключевые элементы:

  • Веса (weights) — числовые коэффициенты, определяющие силу связи между нейронами предыдущего слоя и текущего.
  • Смещения (biases) — сдвиги, которые добавляются к сумме взвешенных входов перед применением функции активации.
  • Функция активации — преобразует линейную комбинацию входов и смещения в значение выхода нейрона.

Для примера рассмотрим простую сеть с одним скрытым слоем:

const brain = require('brain.js');

const net = new brain.NeuralNetwork({
  hiddenLayers: [3], // один скрытый слой с тремя нейронами
});

После обучения с помощью net.train(data) можно получить веса и смещения сети через свойство net.toJSON().

Доступ к весам и смещениям

Метод toJSON() возвращает объект, который содержит структуру сети в формате:

{
  "sizes": [2,3,1],
  "layers": {
    "0": {"0":{}, "1":{}, "2":{}},
    "1": {"0":{}}
  },
  "outputLookup": true,
  "inputLookup": true,
  "trainOpts": {...}
}
  • sizes — массив, где каждый элемент соответствует количеству нейронов в слое.
  • layers — объект с индексами слоев и нейронов. Каждый нейрон содержит поля bias и weights.

Пример доступа к весам:

const json = net.toJSON();
const firstHiddenNeuron = json.layers[0][0];
console.log("Bias:", firstHiddenNeuron.bias);
console.log("Weights:", firstHiddenNeuron.weights);

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

Проверка активаций вручную

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

  1. Вычисление взвешенной суммы входов:

Для нейрона ( j ) в слое ( l ):

[ z_j = i w{ij} x_i + b_j]

где ( w_{ij} ) — вес от нейрона ( i ) предыдущего слоя к нейрону ( j ), ( x_i ) — выход нейрона предыдущего слоя, а ( b_j ) — смещение.

  1. Применение функции активации:

Brain.js по умолчанию использует sigmoid или relu, в зависимости от конфигурации сети:

function sigmoid(x) {
  return 1 / (1 + Math.exp(-x));
}

Пример пошагового вычисления:

const input = [0.5, 0.8];
const neuron = json.layers[0][0]; // первый нейрон скрытого слоя

let z = neuron.bias;
for (const [key, weight] of Object.entries(neuron.weights)) {
  z += input[key] * weight;
}

const output = 1 / (1 + Math.exp(-z)); // sigmoid
console.log("Активация нейрона:", output);

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

Итоговая проверка по всем слоям

Для проверки всей сети можно пройтись по всем слоям:

function forwardPass(input, layers) {
  let activations = input;
  for (let l = 0; l < layers.length; l++) {
    const layer = layers[l];
    const nextActivations = [];
    for (const key in layer) {
      const neuron = layer[key];
      let z = neuron.bias;
      for (const [i, w] of Object.entries(neuron.weights)) {
        z += activations[i] * w;
      }
      nextActivations.push(1 / (1 + Math.exp(-z)));
    }
    activations = nextActivations;
  }
  return activations;
}

console.log("Выход сети вручную:", forwardPass([0.5, 0.8], json.layers));
console.log("Выход сети Brain.js:", net.run([0.5, 0.8]));

Этот подход позволяет:

  • Проверить корректность обучения сети.
  • Проанализировать, какие веса влияют сильнее на результат.
  • Выявить нейроны с аномальными активациями или слишком большими смещениями.

Практическая ценность

  • Отладка сети: ручная проверка весов помогает обнаружить, почему сеть делает неправильные предсказания.
  • Понимание обучения: позволяет увидеть, как градиенты корректируют веса.
  • Образовательная цель: укрепляет интуицию о внутренней работе нейронной сети.

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