Q-learning — это метод обучения с подкреплением, направленный на нахождение оптимальной политики поведения агента в среде. Алгоритм стремится приблизить Q-функцию, которая отображает ожидаемое вознаграждение за выполнение действия в данном состоянии. Библиотека ConvNetJS позволяет реализовать Q-learning, используя нейронные сети для аппроксимации 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 и целевым значением (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, который хранит прошлые переходы ((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;
}
Обучение агента включает следующие шаги:
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 позволяет строить глубокие нейронные сети для аппроксимации Q-функции даже в средах с высокоразмерными входами, таких как изображения или сенсорные массивы. Использование нескольких полносвязных слоев и функций активации ReLU повышает способность сети к нелинейной аппроксимации, обеспечивая эффективное обучение агента в сложных сценариях.