ReinforceJS库(动态展示DP、TD、DQN算法运行过程)
- 2019 年 11 月 21 日
- 筆記
深度强化学习报道
来源:REINFORCEjs
编辑:DeepRL
深度强化学习的发展让很多控制疑难问题有了新的发展思路,然而在大多数人的学习的过程中,尤其在基础DP、TD、MC等知识点的学习过程中有了很大的难度。“ReinforceJS”是一个实现了一些常见的RL算法的一个强化学习库,通过有趣的网络演示得到支持,目前由[@karpathy](https://twitter.com/karpathy)维护。该库目前包括:用于求解有限(而不是太大)确定性MDP的动态编程。
ReinforceJS在GridWorld、PuckWorld、WaterWorld环境中进行了动态的展示:
Part 1
DP动态演示
ReinforceJS的API使用DP,如果要对MDP使用ReinforceJS动态编程,则必须定义一个环境对象env,该环境对象env具有dp代理需要的一些方法:
- env.getNumStates()返回状态总数的整数
- env.getMaxNumActions()返回一个任意状态下操作数最大的整数。
- env.allowedactions接受整数s并返回可用操作的列表,该列表应为从零到maxNumActions的整数。
- env.nextStateDistribution(s,a)是一个误称,因为现在库假定确定性MDP,每个(状态、操作)对都有一个唯一的新状态。因此,函数应该返回一个整数,该整数标识世界的下一个状态
- env.奖励(s,a,ns),返回代理为s,a,ns转换所获得的奖励的浮点值。在最简单的情况下,奖励通常只基于状态S。
// create environment env = new Gridworld(); // create the agent, yay! Discount factor 0.9 agent = new RL.DPAgent(env, {'gamma':0.9}); // call this function repeatedly until convergence: agent.learn(); // once trained, get the agent's behavior with: var action = agent.act(); // returns the index of the chosen action
evaluatePolicy: function() { // perform a synchronous update of the value function var Vnew = zeros(this.ns); // initialize new value function array for each state for(var s=0;s < this.ns;s++) { var v = 0.0; var poss = this.env.allowedActions(s); // fetch all possible actions for(var i=0,n=poss.length;i < n;i++) { var a = poss[i]; var prob = this.P[a*this.ns+s]; // probability of taking action under current policy var ns = this.env.nextStateDistribution(s,a); // look up the next state var rs = this.env.reward(s,a,ns); // get reward for s->a->ns transition v += prob * (rs + this.gamma * this.V[ns]); } Vnew[s] = v; } this.V = Vnew; // swap },
updatePolicy: function() { // update policy to be greedy w.r.t. learned Value function // iterate over all states... for(var s=0;s < this.ns;s++) { var poss = this.env.allowedActions(s); // compute value of taking each allowed action var vmax, nmax; var vs = []; for(var i=0,n=poss.length;i < n;i++) { var a = poss[i]; // compute the value of taking action a var ns = this.env.nextStateDistribution(s,a); var rs = this.env.reward(s,a,ns); var v = rs + this.gamma * this.V[ns]; // bookeeping: store it and maintain max vs.push(v); if(i === 0 || v > vmax) { vmax = v; nmax = 1; } else if(v === vmax) { nmax += 1; } } // update policy smoothly across all argmaxy actions for(var i=0,n=poss.length;i < n;i++) { var a = poss[i]; this.P[a*this.ns+s] = (vs[i] === vmax) ? 1.0/nmax : 0.0; } } },

Part 2
TD动态演示
// agent parameter spec to play with (this gets eval()'d on Agent reset) var spec = {} spec.update = 'qlearn'; // 'qlearn' or 'sarsa' spec.gamma = 0.9; // discount factor, [0, 1) spec.epsilon = 0.2; // initial epsilon for epsilon-greedy policy, [0, 1) spec.alpha = 0.1; // value function learning rate spec.lambda = 0; // eligibility trace decay, [0,1). 0 = no eligibility traces spec.replacing_traces = true; // use replacing or accumulating traces spec.planN = 50; // number of planning steps per iteration. 0 = no planning spec.smooth_policy_update = true; // non-standard, updates policy smoothly to follow max_a Q spec.beta = 0.1; // learning rate for smooth policy update


// create environment env = new Gridworld(); // create the agent, yay! var spec = { alpha: 0.01 } // see full options on top of this page agent = new RL.TDAgent(env, spec); setInterval(function(){ // start the learning loop var action = agent.act(s); // s is an integer, action is integer // execute action in environment and get the reward agent.learn(reward); // the agent improves its Q,policy,model, etc. }, 0);

Part 1
DQN动态演示
(1)本演示是对PuckWorld:
- 状态空间现在大而连续:代理观察自己的位置(x,y)、速度(vx,vy)、绿色目标和红色目标的位置(总共8个数字)。
- 代理商可采取4种措施:向左侧、右侧、上方和下方施加推进器。这使代理可以控制其速度。
- Puckworld动力学整合了代理的速度来改变其位置。绿色目标偶尔移动到一个随机位置。红色目标总是缓慢地跟随代理。
- 对代理商的奖励是基于其与绿色目标的距离(低即好)。但是,如果代理位于红色目标附近(磁盘内),代理将获得与其到红色目标的距离成比例的负奖励。
代理的最佳策略是始终朝向绿色目标(这是常规的puckworld),但也要避免红色目标的影响区域。这使得事情变得更有趣,因为代理必须学会避免它。而且,有时看着红色目标把特工逼到角落是很有趣的。在这种情况下,最佳的做法是暂时支付价格,以便快速地进行缩放,而不是在这种情况下陷入困境并支付更多的奖励价格。
界面:代理当前体验到的奖励显示为其颜色(绿色=高,红色=低)。代理所采取的操作(移动的中等大小的圆)如箭头所示。其DQN的网络结构如下:

// create environment var env = {}; env.getNumStates = function() { return 8; } env.getMaxNumActions = function() { return 4; } // create the agent, yay! var spec = { alpha: 0.01 } // see full options on top of this page agent = new RL.DQNAgent(env, spec); setInterval(function(){ // start the learning loop var action = agent.act(s); // s is an array of length 8 // execute action in environment and get the reward agent.learn(reward); // the agent improves its Q,policy,model, etc. reward is a float }, 0);
(2)WaterWorld深度Q学习演示:
状态空间更大、更连续:代理有30个眼睛传感器指向各个方向,每个方向观察5个变量:范围、感测对象的类型(绿色、红色)和感测对象的速度。该代理的本体感受包括两个额外的传感器,以其自身的速度在X和Y方向。这是总共152维的状态空间。
- 代理商可采取4种措施:向左侧、右侧、上方和下方施加推进器。这使代理可以控制其速度。
- 动力学综合了物体的速度来改变它的位置。绿色和红色的目标反弹。
- 与任何红色目标(这些是苹果)接触的奖励是+1,与任何绿色目标(这是毒药)接触的奖励是-1。
该代理的最佳策略是巡航,远离绿色目标,吃红色目标。这个演示有趣的是,状态空间是如此的高维,而且被感知的变量是与代理相关的。它们不仅仅是前一个演示中固定数量目标的玩具x,y坐标。
// agent parameter spec to play with (this gets eval()'d on Agent reset) var spec = {} spec.update = 'qlearn'; // qlearn | sarsa spec.gamma = 0.9; // discount factor, [0, 1) spec.epsilon = 0.2; // initial epsilon for epsilon-greedy policy, [0, 1) spec.alpha = 0.005; // value function learning rate spec.experience_add_every = 5; // number of time steps before we add another experience to replay memory spec.experience_size = 10000; // size of experience spec.learning_steps_per_iteration = 5; spec.tderror_clamp = 1.0; // for robustness spec.num_hidden_units = 100 // number of neurons in hidden layer
在线页面:
https://cs.stanford.edu/people/karpathy/reinforcejs/index.html
Github: https://github.com/karpathy/reinforcejs