Недообучение и способы борьбы с ним

Недообучение (underfitting) возникает, когда нейронная сеть не способна уловить закономерности в обучающих данных и демонстрирует низкую точность как на тренировочном, так и на тестовом наборе. В контексте Brain.js, библиотеки для создания нейронных сетей на JavaScript, недообучение проявляется через слабую способность сети предсказывать значения даже для простых зависимостей.


Причины недообучения

  1. Слишком простая архитектура сети В Brain.js, при использовании NeuralNetwork, если количество скрытых слоев или нейронов в них недостаточно, сеть не может моделировать сложные зависимости. Например, для нелинейной зависимости между входом и выходом сеть с одним скрытым нейроном будет недостаточной.

  2. Недостаток обучающих данных Малое количество примеров не позволяет сети выявить закономерности. Особенно это критично для задач с высокой вариативностью входных данных.

  3. Слишком маленькое количество итераций обучения Методы train и trainAsync в Brain.js требуют достаточного числа эпох (iterations). Недообучение может проявляться, если количество итераций слишком мало.

  4. Слишком высокий коэффициент регуляризации при неправильной настройке В Brain.js есть параметр learningRate. Слишком низкое значение приводит к медленной корректировке весов, что может вызвать недообучение.


Методы борьбы с недообучением

  1. Увеличение сложности сети

    • Добавление скрытых слоев:

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

      Увеличение числа нейронов и слоев позволяет сети лучше моделировать сложные функции.

  2. Увеличение объема обучающих данных

    • Дополнительные примеры повышают способность сети выявлять закономерности.

    • Использование техник data augmentation, например, добавление случайного шума к числовым данным или небольшие вариации для категориальных данных:

      trainingData.forEach(item => {
        trainingData.push({
          input: item.input.map(x => x + Math.random() * 0.01),
          output: item.output
        });
      });
  3. Увеличение числа эпох обучения

    • Параметры iterations и errorThresh в методе train:

      net.train(trainingData, {
        iterations: 20000,
        errorThresh: 0.005,
        learningRate: 0.05
      });
      • iterations — максимальное количество итераций обучения.
      • errorThresh — целевой уровень ошибки.
  4. Оптимизация функции обучения

    • Изменение learningRate:

      learningRate: 0.1

      Более высокий learningRate ускоряет обучение, но может вызвать нестабильность. Баланс между скоростью и точностью критически важен.

  5. Нормализация входных данных

    • Недообучение часто возникает, когда диапазоны входов слишком велики или различаются по масштабу:

      const normalizedData = trainingData.map(item => ({
        input: item.input.map(x => x / 100),
        output: item.output
      }));

      Нормализация помогает сети быстрее находить оптимальные веса.

  6. Использование рекуррентных сетей для последовательностей

    • В задачах предсказания временных рядов или последовательностей обычная NeuralNetwork может недообучаться. Использование recurrent.LSTM в Brain.js улучшает способность сети выявлять временные зависимости:

      const net = new brain.recurrent.LSTM();
      net.train([
        { input: "привет", output: "здравствуйте" },
        { input: "как дела", output: "в порядке" }
      ]);

Примеры диагностики недообучения

  1. Сравнение ошибок на тренировочном и тестовом наборе

    • Если ошибка на тренировочном наборе высокая, а на тестовом схожа — классический случай недообучения.
  2. Визуализация функции потерь

    • Brain.js позволяет отслеживать прогресс через log:

      net.train(trainingData, {
        log: true,
        logPeriod: 100
      });

      Постепенное снижение ошибки указывает на успешное обучение. Плоская кривая с высокой ошибкой — сигнал недообучения.

  3. Проверка производительности на известных примерах

    • Простая проверка:

      console.log(net.run([0,1]));

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


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

  • Всегда начинать с простой архитектуры и постепенно увеличивать сложность.
  • Проверять данные на масштаб и качество перед обучением.
  • Использовать нормализацию или стандартизацию входных значений.
  • Следить за логами функции потерь и корректировать параметры обучения.
  • Применять техники data augmentation, если набор данных ограничен.
  • Для последовательных данных использовать рекуррентные сети (LSTM или GRU) вместо обычных нейронных сетей.

Недообучение в Brain.js — это сигнал того, что модель еще не достигла своей способности к обобщению. Адекватная настройка архитектуры, параметров обучения и качества данных позволяет устранить недообучение и добиться высокой точности предсказаний.