强化学习鱼书(8)——DQN
DQN:Deep Q-network
监督学习从训练用的数据集中随机取出一部分 数据。取出的这部分数据叫作小批量(mini-batch)。算法使用小批量来更新神经网络的参数(不相关)
Q学习使用在某个时刻得到的 Et =(St,At,Rt,St+1)更新Q函数(Et和Et+1强相关)
因此Q学习需要优化成 不相关的:经验回放
经验回放
能够使用经验回放的仅限于异策略型的算法。同策略型的算法只能使用从现在的策略得到的数据。也就是说,由于不能使用过去收集的经验数据,因此就不能使用经验回放。
采样后state=[(s,a,r,s),(s,a,r,s),(s,a,r,s)],next_state=[(s,a,r,s),(s,a,r,s),(s,a,r,s)]
action=[a,a,a],reward=[r,r,r]
经验回放的测试代码如下:只采取行动0,从10次组成的缓冲区中取出一个batch的数据
目标网络
下面具体说明一下目标网络的实现方法。首先,准备一个表示Q函数的原始网络(这个网络叫作qnet),然后,再准备了一个具有相同结构的网络(这个网络叫作qnet_target),定期与qnet的权重同步,在其余的时间里保持权重参数固定。
使用qnet_target计算TD目标的值,就能抑制作为监督标签的TD目标的变动了。
class DQNAgent:def __init__(self):...self.replay_buffer = ReplayBuffer(self.buffer_size, self.batch_size)self.qnet = QNet(self.action_size)self.qnet_target = QNet(self.action_size)self.optimizer = optimizers.Adam(self.lr)self.optimizer.setup(self.qnet) #优化器中只注册self.qnet
def sync_qnet(self):self.qnet_target = copy.deepcopy(self.qnet) #同步权重到qnet_targetdef get_action(self, state): #e-greedyif np.random.rand() < self.epsilon:return np.random.choice(self.action_size)else:state = state[np.newaxis, :]qs = self.qnet(state)return qs.data.argmax()
def update(self, state, action, reward, next_state, done):self.replay_buffer.add(state, action, reward, next_state, done)if len(self.replay_buffer) < self.batch_size: #缓冲区大小到batch_size才会取出returnstate, action, reward, next_state, done = self.replay_buffer.get_batch()qs = self.qnet(state) #state是[(s,a,r,s),(s,a,r,s),(s,a,r,s)],qs是[(action=左,q),[action=右,q]]q = qs[np.arange(self.batch_size), action] #取action对应的qnext_qs = self.qnet_target(next_state) #用qnet_target来获取TD目标next_q = next_qs.max(axis=1)next_q.unchain()target = reward + (1 - done) * self.gamma * next_qloss = F.mean_squared_error(q, target)#loss是实际q(qnet)和TD目标(qnet_target)的误差self.qnet.cleargrads()loss.backward()self.optimizer.update()
注意:为什么qs的维度是2?见下图
这一句是根据实际行动获取q:q = qs[np.arange(self.batch_size), action] #取对应的q
训练过程如下:
注意每次行动后的update,都会取出一个batch的数据,用来更新神经网络的参数
DQN的扩展
double DQN
优先级经验回放
batch数据(用来更新参数)的选择不是随机的,而是根据优先级进行的——信息量越大越好
Dueling DQN
上A下V,分别训练优势函数和价值函数的优点在哪里呢?这主要是在无论采取什么样的行动,结果都几乎没有变化的状态下有优势。
在图8-14的情况下,无论采取什么样的行动,结果都是输(负的奖励)。对于在某个状态s下实际采取的行动a, DQN会训练Q。如果发现A不能优化Q,会选择不采取行动,也不会训练Q
而Dueling DQN用到了价值函数V。价值函数是某个状态s的价值(不考虑行动)。因此,如果经历图8-14所示的状态,那么就会训练V,这样就算不尝试其他行动,Q的近似性能也会得到改善。这有助于提高训练效率