Q-learning

Q-learning — это метод обучения с подкреплением, направленный на нахождение оптимальной политики поведения агента в среде. Алгоритм стремится приблизить Q-функцию, которая отображает ожидаемое вознаграждение за выполнение действия в данном состоянии. Библиотека ConvNetJS позволяет реализовать Q-learning, используя нейронные сети для аппроксимации Q-функции, что особенно полезно при работе с большим количеством состояний.

Q-функция и аппроксимация нейронной сетью

Классическая Q-функция (Q(s, a)) описывает ценность действия (a) в состоянии (s). Для сред с большим или непрерывным пространством состояний хранение таблицы Q невозможна, поэтому используется функциональная аппроксимация:

[ Q(s, a; ) (s, a)]

где () — веса нейронной сети. В ConvNetJS создается сеть с полносвязными слоями, входной слой принимает вектор состояния, а выходной — значения Q для всех действий.

Пример создания сети:

var layer_defs = [];
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:state_dim});
layer_defs.push({type:'fc', num_neurons:64, activation:'relu'});
layer_defs.push({type:'fc', num_neurons:64, activation:'relu'});
layer_defs.push({type:'regression', num_neurons:num_actions});

var net = new convnetjs.Net();
net.makeLayers(layer_defs);

var trainer = new convnetjs.SGDTrainer(net, {
    learning_rate: 0.01,
    momentum: 0.9,
    batch_size: 32,
    l2_decay: 0.001
});

Здесь state_dim — размерность состояния, num_actions — количество возможных действий.

Выбор действия: ε-жадная стратегия

Для балансировки между исследованием среды и использованием уже изученных знаний применяется ε-жадная стратегия:

[ a = ]

В ConvNetJS это реализуется через выбор максимального значения выхода сети для текущего состояния с вероятностью (1-) и случайное действие с вероятностью ().

function selectAction(state, epsilon) {
    if (Math.random() < epsilon) {
        return Math.floor(Math.random() * num_actions);
    } else {
        var q_values = net.forward(state).w;
        return q_values.indexOf(Math.max(...q_values));
    }
}

Обновление Q-функции через нейронную сеть

Обновление весов сети основано на минимизации ошибки между текущей оценкой Q и целевым значением (y):

[ y = r + _{a’} Q(s’, a’; )]

где (r) — вознаграждение, () — коэффициент дисконтирования, (s’) — следующее состояние.

В ConvNetJS процедура выглядит так:

function trainStep(state, action, reward, next_state, gamma) {
    var q_values_next = net.forward(next_state).w;
    var target = net.forward(state).w.slice();
    target[action] = reward + gamma * Math.max(...q_values_next);
    trainer.train(state, target);
}

Таким образом, сеть корректирует свои предсказания Q-функции в направлении уменьшения ошибки между текущими значениями и целевыми.

Использование памяти воспоминаний (Experience Replay)

Для улучшения стабильности обучения применяется буфер experience replay, который хранит прошлые переходы ((s, a, r, s’)). Из него случайным образом формируются мини-батчи для тренировки, что уменьшает корреляцию между последовательными шагами среды.

var memory = [];
var memory_size = 5000;

function remember(transition) {
    if (memory.length >= memory_size) memory.shift();
    memory.push(transition);
}

function sampleBatch(batch_size) {
    var batch = [];
    for (var i = 0; i < batch_size; i++) {
        batch.push(memory[Math.floor(Math.random() * memory.length)]);
    }
    return batch;
}

Цикл обучения агента

Обучение агента включает следующие шаги:

  1. Инициализация состояния среды.
  2. Выбор действия по ε-жадной стратегии.
  3. Выполнение действия и получение нового состояния и вознаграждения.
  4. Сохранение перехода в память воспоминаний.
  5. Выбор случайного батча из памяти и обновление сети через градиентный спуск.
  6. Повторение до окончания эпизода.
for (var episode = 0; episode < max_episodes; episode++) {
    var state = env.reset();
    while (!done) {
        var action = selectAction(state, epsilon);
        var {next_state, reward, done} = env.step(action);
        remember({state, action, reward, next_state});
        
        var batch = sampleBatch(batch_size);
        batch.forEach(t => trainStep(t.state, t.action, t.reward, t.next_state, gamma));

        state = next_state;
    }
}

Настройка гиперпараметров

  • learning_rate — скорость обновления весов сети, обычно 0.001–0.01.
  • gamma — коэффициент дисконтирования, задает, насколько важны будущие вознаграждения (0.9–0.99).
  • epsilon — вероятность случайного действия, постепенно уменьшается от 1 до 0.01.
  • batch_size — размер мини-батча для тренировки, обычно 32–64.
  • memory_size — объем памяти воспоминаний, влияет на разнообразие обучающих примеров.

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

Применение ConvNetJS для сложных сред

ConvNetJS позволяет строить глубокие нейронные сети для аппроксимации Q-функции даже в средах с высокоразмерными входами, таких как изображения или сенсорные массивы. Использование нескольких полносвязных слоев и функций активации ReLU повышает способность сети к нелинейной аппроксимации, обеспечивая эффективное обучение агента в сложных сценариях.