Я пытался реализовать алгоритм, описанный здесь, и затем протестируйте его на «большой задаче», описанной в той же статье.
Обзор алгоритма:
Вкратце, алгоритм использует RBM показанной ниже формы для решения задач обучения с подкреплением путем изменения его весов таким образом, чтобы свободная энергия сетевой конфигурации равнялась сигналу вознаграждения, заданному для этой пары действий состояния.
Чтобы выбрать действие, алгоритм выполняет выборку гиббса, сохраняя при этом переменные состояния фиксированными. Если у вас будет достаточно времени, это приведет к действию с наименьшей свободной энергией и, следовательно, наибольшей наградой за данное состояние.
Обзор большой задачи:
Обзор авторских рекомендаций по реализации:
Ограниченная машина Больцмана с 13 скрытыми переменными была обучена на создании экземпляра большой задачи действия с 12-битным пространством состояний и 40-битным пространством действий. Случайным образом были выбраны тринадцать ключевых состояний. Сеть была запущена для 12 000 действий со скоростью обучения от 0,1 до 0,01 и температурой, экспоненциально изменяющейся от 1,0 до 0,1 в процессе обучения. Каждая итерация инициализировалась случайным состоянием. Каждая выборка действий состояла из 100 итераций выборки Гиббса.
Важные пропущенные сведения:
- Были ли нужны блоки смещения?
- Было ли необходимо снижение веса? И если да, то L1 или L2?
- Требовалось ли ограничение разреженности для весов и / или активаций?
- Была ли модификация градиентного спуска? (например, импульс)
- Какие мета-параметры были необходимы для этих дополнительных механизмов?
Моя реализация:
Сначала я предположил, что авторы не использовали никаких механизмов, кроме описанных в руководстве, поэтому я попытался обучить сеть без единиц смещения. Это привело к почти случайному результату и было моим первым ключом к тому факту, что некоторые используемые механизмы должны были быть сочтены авторами «очевидными» и, следовательно, опущены.
Я поигрался с различными пропущенными механизмами, упомянутыми выше, и добился наилучших результатов, используя:
- softmax скрытые блоки
- импульс 0,9 (0,5 до 5-й итерации)
- единицы смещения для скрытых и видимых слоев
- скорость обучения составляет 1/100 от указанной авторами.
- l2 снижение веса на 0,0002
Но даже с учетом всех этих модификаций моя производительность при выполнении задачи была в среднем около 28 после 12000 итераций.
Код для каждой итерации:
%%%%%%%%% START POSITIVE PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
data = [batchdata(:,:,(batch)) rand(1,numactiondims)>.5];
poshidprobs = softmax(data*vishid + hidbiases);
%%%%%%%%% END OF POSITIVE PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
hidstates = softmax_sample(poshidprobs);
%%%%%%%%% START ACTION SELECTION PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if test
[negaction poshidprobs] = choose_factored_action(data(1:numdims),hidstates,vishid,hidbiases,visbiases,cdsteps,0);
else
[negaction poshidprobs] = choose_factored_action(data(1:numdims),hidstates,vishid,hidbiases,visbiases,cdsteps,temp);
end
data(numdims+1:end) = negaction > rand(numcases,numactiondims);
if mod(batch,100) == 1
disp(poshidprobs);
disp(min(~xor(repmat(correct_action(:,(batch)),1,size(key_actions,2)), key_actions(:,:))));
end
posprods = data' * poshidprobs;
poshidact = poshidprobs;
posvisact = data;
%%%%%%%%% END OF ACTION SELECTION PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if batch>5,
momentum=.9;
else
momentum=.5;
end;
%%%%%%%%% UPDATE WEIGHTS AND BIASES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
F = calcF_softmax2(data,vishid,hidbiases,visbiases,temp);
Q = -F;
action = data(numdims+1:end);
reward = maxreward - sum(abs(correct_action(:,(batch))' - action));
if correct_action(:,(batch)) == correct_action(:,1)
reward_dataA = [reward_dataA reward];
Q_A = [Q_A Q];
else
reward_dataB = [reward_dataB reward];
Q_B = [Q_B Q];
end
reward_error = sum(reward - Q);
rewardsum = rewardsum + reward;
errsum = errsum + abs(reward_error);
error_data(ind) = reward_error;
reward_data(ind) = reward;
Q_data(ind) = Q;
vishidinc = momentum*vishidinc + ...
epsilonw*( (posprods*reward_error)/numcases - weightcost*vishid);
visbiasinc = momentum*visbiasinc + (epsilonvb/numcases)*((posvisact)*reward_error - weightcost*visbiases);
hidbiasinc = momentum*hidbiasinc + (epsilonhb/numcases)*((poshidact)*reward_error - weightcost*hidbiases);
vishid = vishid + vishidinc;
hidbiases = hidbiases + hidbiasinc;
visbiases = visbiases + visbiasinc;
%%%%%%%%%%%%%%%% END OF UPDATES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Я прошу:
Так что, если кому-то из вас удастся заставить этот алгоритм работать должным образом (авторы утверждают, что в среднем за 12000 итераций получено ~ 40 вознаграждений), я был бы чрезвычайно благодарен.
Если кажется, что мой код делает что-то явно не так, то внимание к этому тоже будет отличным ответом.
Я надеюсь, что то, что упустили авторы, действительно очевидно для кого-то, у кого больше опыта в энергетическом обучении, чем у меня, и в этом случае просто укажите, что нужно включить в рабочую реализацию.