October 9, 2024

Пример реализации ИИ на JS

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

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

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

const NUM_TRAINING_POINTS = 100;
const TRAINING_DATA = [];
for (let i = 0; i < NUM_TRAINING_POINTS; ++i) {
  const x = i / NUM_TRAINING_POINTS;
  const y = x + Math.random() * 0.2 - 0.1; // добавляем шум от -0.1 до +0.1
  TRAINING_DATA.push([x, y]);
}

console.log("Training Data: ", TRAINING_DATA);

Реализация функции активации ReLU

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

function relu(x) {
  return Math.max(0, x);
}

Архитектура нейронной сети

Создадим архитектуру нейронной сети с одним скрытым слоем. У нас есть входные данные, которые представляют собой вектор [x], промежуточный слой с весами w1, который преобразует вход в скрытое состояние, и выходной слой с весом w2, который преобразует скрытое состояние в результат.

class NeuralNetwork {
  constructor(nInputs, nHiddenNodes, nOutputs) {
    this.nInputs = nInputs;
    this.nHiddenNodes = nHiddenNodes;
    this.nOutputs = nOutputs;

    this.initializeWeights();
  }

  initializeWeights() {
    this.weights1 = Array.from({ length: this.nHiddenNodes }, () => Math.random());
    this.weights2 = Array.from({ length: this.nOutputs }, () => Math.random());
  }

  predict(input) {
    const hiddenState = this.weights1.map((weight, index) => weight * input[index]).reduce((sum, val) => sum + relu(val), 0);
    const output = this.weights2.map((weight, index) => weight * hiddenState).reduce((sum, val) => sum + val, 0);
    return output;
  }

  train(trainingData, numEpochs, learningRate) {
    for (let epoch = 0; epoch < numEpochs; ++epoch) {
      trainingData.forEach(([input, desiredOutput]) => {
        const predictedOutput = this.predict(input);
        const error = desiredOutput - predictedOutput;
        this.updateWeights(input, error, learningRate);
      });
    }
  }

  updateWeights(input, error, learningRate) {
    const hiddenState = this.weights1.map((weight, index) => weight * input[index]).reduce((sum, val) => sum + relu(val), 0);
    const dOutputErrorWrtHidden = this.weights2.map((weight, index) => weight * error).reduce((sum, val) => sum + val, 0);

    this.weights1 = this.weights1.map((weight, index) => weight + learningRate * (error * input[index] * (hiddenState > 0 ? 1 : 0)));
    this.weights2 = this.weights2.map((weight, index) => weight + learningRate * dOutputErrorWrtHidden * hiddenState);
  }
}

Тренировка модели

Запустим процесс тренировки модели на наших обучающих данных.

const NETWORK = new NeuralNetwork(1, 10, 1);
NETWORK.train(TRAINING_DATA, 1000, 0.01);

Оценка модели

Теперь проверим модель на тестовых данных, чтобы увидеть её производительность.

const TEST_DATA = [];

for (let i = 0; i < 10; ++i) {
  const x = i / 10;
  const y = x + Math.random() * 0.2 - 0.1;
  TEST_DATA.push([x, y]);
}

TEST_DATA.forEach(([input, expected]) => {
  const actual = NETWORK.predict(input);
  console.log(`Actual Output: ${actual}, Expected Output: ${expected}`);
});

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