Реализация обучения подкреплению свободной энергией

Я пытался реализовать алгоритм, описанный здесь , а затем протестировать его на описанной «задаче большого действия». в той же газете.

Обзор алгоритма:

enter image description here

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

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

Обзор задачи большого действия:

enter image description here

Обзор рекомендаций автора по реализации:

Ограниченная машина Больцмана с 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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Что я прошу:

Итак, если кто-то из вас сможет заставить этот алгоритм работать должным образом (авторы утверждают, что в среднем ~40 вознаграждений после 12000 итераций), я буду очень благодарен.

Если мой код делает что-то явно неправильное, то обратить на это внимание тоже будет отличным ответом.

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

8
задан Sicco 30 August 2012 в 11:58
поделиться