强化学习(DDPG,AC3,DPPO)

通过把Policy Based 和Value Based结合起来的Actor Critic,解决了Value Based如Q-Learning的无法解决连续和高维度问题,也解决了Policy Based的效率低速度慢的问题。但是同样的,像DQN一样,在使用神经网络进行值估计的时候,神经网络的相关性都太强了,梯度更新相互依赖,导致网络将会学不到东西。

有两种解决方法:DDPG和AC3。

DDPG
Actor-Critic+DQN=Deep Deterministic Policy Gradient。
先将这个词拆成三部分:

  • Deep:使用神经网络估计值。
  • Policy Gradient:根据学习到的策略分布输出筛选动作。
  • Deterministic:斩钉截铁的输出一个动作。因为以往的随机策略会先学习动作分布再随机进行筛选,在某些场景中的动作维度(动作多或联系性动作)可能极大,如果想精确的学习到概率分布需要很大的样本。但是不管动作维度怎么样,最大概率肯定是只有一个,所以确定性策略就直接输出概率最大的动作就可以了。

Actor-Critic+DQN,两者如何融合?
Actor-Critic:Actor网络学习动作策略,Critic网络用于评价动作。
DQN:记忆库,两套网络解决网络相关性。

DQN中的两套网络是为了计算价值函数,那么还是Value Based,现在加入了Policy Based后,同样也需要两套网络来计算策略函数。即使用双Actor神经网络和双Critic神经网络共有4套网络的方法来改善神经网络更新的收敛性。

对于Actor的双网络 ,有用来估计的新网络和延迟的旧网络。估计网络用来输出实时的动作,而旧网络则是用来更新价值网络系统的.。
对于Critic的双网络,也有估计的新网络和延迟的旧网络。它们都输出根据状态的输出相应的value价值,估计网络根据actor的动作进行输出,而旧网络会根据actor旧网络得到的动作进行输出。
太绕了,于是博主自己画了一张图:
在这里插入图片描述
即先从一个状态S出发,通过Actor新网络得到动作A并执行,存入记忆库。然后从记忆库中采样,得到Si,Ai,Si’,Si’通过Actor旧网络得到动作Ai’,用于给Critic更新参数,即输入到Critic旧网络中得到一个“现实目标值”Q’,即可以算出在这个状态下的动作总值y,和Critic的估计值进行均方误差就可以更新Critic网络了。(AC中是用前后V值差的均方来更新,现在使用了旧网络能够更加的客观)而actor的网络用Critic新网络得到的Q值来评价动作的好坏,即就用来更新了Actor网络。(AC中是用Reward的TD误差来更新,现在通过旧网络同样更客观了)

Critic 参数更新公式为:

L = 1 N ∑ i ( y i − Q ( s i , a i ∣ θ Q ) ) 2 L=\frac{1}{N}\sum_i(y_i-Q(s_i,a_i|\theta^Q))^2 L=N1i(yiQ(si,aiθQ))2

旧网络会依据下一状态, 用 Actor旧网络中的结果来选择动作,使用这种方法获得的值能像 DQN 那样切断相关性, 以更好的提高收敛性。

Actor参数更新公式为:

∇ θ μ J = 1 N ∑ i [ ∇ a Q ( s , a ∣ θ μ ) ∣ s = s i , a = μ ( s i ) ∇ θ μ π θ ( s ) ∣ s i ] \nabla_{\theta^\mu}J= \frac{1}{N}\sum\limits_{i}[\nabla_{a}Q_(s,a|\theta^\mu)|_{s=s_i,a=\mu(s_i)}\nabla_{\theta^\mu} \pi_{\theta(s)}|_{s_i}] θμJ=N1i[aQ(s,aθμ)s=si,a=μ(si)θμπθ(s)si]
前半部分从Critic新网络来的, 用于评价Actor的动作要怎么移动, 才能获得更大的 Q, 而后半部分是从 Actor 来的, 用于说明Actor 要怎么样修改自身参数, 使得 Actor 更有可能做这个动作. 所以两者合起来就是在说: Actor 要朝着更有可能获取大 Q 的方向修改动作参数。

再看下整体的算法流程:
在这里插入图片描述

  • 初始化四套神经网络的参数,θ,θ′,w,w′和记忆库R。
  • 对于每次迭代,初始化第一个状态S,得到其特征向量 ϕ ( S ) \phi(S) ϕ(S)
  • Actor网络根据状态S得到动作A(算法中的N为随机噪音,可以增加一些随机性)。执行动作A,得到新状态S’和奖励r,存入记忆库R。
  • 然后从R中采样N组,计算当前目标Q值y_i, y i = { r i i s _ e n d i    i s    t r u e r i + γ Q ′ ( ϕ ( S i ′ ) , π θ ′ ( ϕ ( s i ′ ) ) ∣ θ Q ′ ) i s _ e n d i    i s    f a l s e y_i= \begin{cases} r_i& {is\_end_i\; is \;true}\\ r_i + \gamma Q'(\phi(S'_i),\pi_{ \theta'}(\phi(s'_i))|\theta^{Q'})& {is\_end_i\; is \;false} \end{cases} yi={riri+γQ(ϕ(Si),πθ(ϕ(si))θQ)is_endiistrueis_endiisfalse其中要先从actor旧网络中得到策略 μ \mu μ,再结合状态输入到Critic旧网络中才是Q’,才能得到y_i
  • 使用均方误差更新Critic,梯度反向来更新Actor。
  • C步之后,更新旧网络的参数。直到结束。

使用keras实现DDPG

def Actor_network(self):
        inp = Input((self.env_dim)) #环境状态的维度

        x = Dense(256, activation='relu')(inp)
        x = GaussianNoise(1.0)(x) #随机变量以增加随机性,探索性

        x = Flatten()(x)
        x = Dense(128, activation='relu')(x) #relu激活
        x = GaussianNoise(1.0)(x)

        out = Dense(self.act_dim, activation='tanh', kernel_initializer=RandomUniform())(x)
        out = Lambda(lambda i: i * self.act_range)(out)

        return Model(inp, out)

def Critic_network(self):
        state = Input((self.env_dim))
        action = Input((self.act_dim,)) #输入s和a,计算value值
        x = Dense(256, activation='relu')(state)
        x = concatenate([Flatten()(x), action])
        x = Dense(128, activation='relu')(x)
        out = Dense(1, activation='linear', kernel_initializer=RandomUniform())(x)
        return Model([state, action], out)

def memorize(self, state, action, reward, done, new_state):
        self.buffer.memorize(state, action, reward, done, new_state)#记忆库

def update_models(self, states, actions, critic_target):#从采样中更新两个网络
        self.critic.train_on_batch(states, actions, critic_target)#训练Critic
        # 从当前策略计算Q
        actions = self.actor.model.predict(states)
        grads = self.critic.gradients(states, actions)

        self.actor.train(states, actions, np.array(grads).reshape((-1, self.act_dim)))#训练actor
        
        #隔一段时间就copy到旧网络中
        self.actor.transfer_weights()
        self.critic.transfer_weights()

time, cumul_reward, done = 0, 0, False
old_state = env.reset()
actions, states, rewards = [], [], []
noise = OrnsteinUhlenbeckProcess(size=self.act_dim)

while not done:
	if args.render: env.render()
    a = self.policy_action(old_state) #根据状态选确定的动作

    a = np.clip(a+noise.generate(time), -self.act_range, self.act_range)#clip限制在范围中
                
    new_state, r, done, _ = env.step(a) #得到新状态,奖励,是否终端

    self.memorize(old_state, a, r, done, new_state)#加入到记忆库

    states, actions, rewards, dones, new_states, _ = self.sample_batch(args.batch_size)#从记忆库采样

    q_values = self.critic.target_predict([new_states, self.actor.target_predict(new_states)]) #在旧网络预测Q

    critic_target = self.bellman(rewards, q_values, dones)

    self.update_models(states, actions, critic_target)#训练网络

    old_state = new_state #更新状态
    cumul_reward += r
    time += 1 #时间步控制旧网络的更新

A3C(Asynchronous Advantage Actor-Critic)
同样为了解决神经网络更新太依赖的问题,A3C的方法是使用了多线程并行计算,使不同的副本学习到不同的知识并相互通信共同的完成任务,这样网络之间也就没有那么的依赖,解决了不收敛的问题。

即有一个主线程负责更新Actor和Critic的参数,多个辅线程负责分别和环境交互,一定次数后能得到梯度更新值,但是不是更新自己而汇总一起更新主线程网络的参数。而所有的辅线程会定期从主线程更新网络参数。这些辅线程还是起到了类似DQN中经验回放的作用,但是效果更好,而且大大提高了速度。
在这里插入图片描述
DPPO
PPO(Proximal Policy Optimization)
主要是限制更新步长。因为学习速率慢时间就长,学习速率快就容易躁动。
限制的部分就在于actor的更新,A会乘一个新旧概率比,如果差距大优势大那么学习幅度就加大,同时还要减去一个新旧的分布的KL,做以惩罚项,让他们不要差距太大。
另外也可以不要KL的惩罚项,因为惩罚也是为了限制它的更新速度,那么直接对新旧比的出现幅度进行控制就可以了。(比如倍数不超过多少倍),即clip。

Distributed PPO
类似与AC3的多线程。

实现DPPO打Dota2
在这里插入图片描述

  • 12
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值