我一直在尝试实现此处描述的算法,然后在同一篇论文中描述的“大型动作任务”上对其进行测试。
算法概述:
简而言之,该算法使用如下所示形式的 RBM 通过更改其权重来解决强化学习问题,使得网络配置的自由能等于为该状态动作对给出的奖励信号。
为了选择一个动作,该算法在保持状态变量固定的同时执行吉布斯采样。如果有足够的时间,这会产生具有最低自由能的动作,从而产生给定状态的最高奖励。
大动作任务概述:
作者的实施指南概述:
具有 13 个隐藏变量的受限玻尔兹曼机在具有 12 位状态空间和 40 位动作空间的大型动作任务的实例化上进行了训练。随机选择了 13 个关键状态。该网络运行了 12000 个动作,学习率从 0.1 到 0.01,温度从 1.0 到 0.1 在训练过程中呈指数增长。每次迭代都以随机状态初始化。每个动作选择由 100 次 Gibbs 抽样迭代组成。
重要省略的细节:
- 是否需要偏置单元?
- 需要减重吗?如果是这样,L1 还是 L2?
- 权重和/或激活是否需要稀疏约束?
- 梯度下降是否有修改?(例如动量)
- 这些附加机制需要哪些元参数?
我的实现:
我最初假设作者没有使用指南中描述的机制,所以我尝试在没有偏差单元的情况下训练网络。这导致了近乎偶然的表现,并且是我的第一个线索,即使用的某些机制必须被作者认为是“显而易见的”,因此被忽略了。
我玩弄了上面提到的各种省略的机制,并通过使用获得了最好的结果:
- softmax 隐藏单元
- 0.9 的动量(0.5 直到第 5 次迭代)
- 隐藏层和可见层的偏置单元
- 学习率是作者列出的学习率的 1/100。
- l2 重量衰减 0.0002
但即使进行了所有这些修改,在 12000 次迭代后,我在任务上的表现通常在平均奖励 28 左右。
每次迭代的代码:
%%%%%%%%% 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 个奖励),我将非常感激。
如果我的代码似乎在做一些明显错误的事情,那么引起注意也将构成一个很好的答案。
我希望作者遗漏的内容对于比我有更多基于能量的学习经验的人来说确实是显而易见的,在这种情况下,只需指出工作实施中需要包含的内容。