强化学习入门DQN详解

Deep Q Network

参考资料:

B站莫烦:https://www.bilibili.com/video/BV13W411Y75P/?spm_id_from=333.337.search-card.all.click&vd_source=a8e8676617fb04db42af59b530b145fd

github(tensorflow):https://github.com/MorvanZhou/Reinforcement-learning-with-tensorflow

pytorch版本:https://github.com/ClownW/Reinforcement-learning-with-PyTorch

1、先验知识:

(1)Q-learning

    Q-learning使用Q表存储状态-动作-价值对应关系。

    用这种办法进行尝试遍历制作Q表再根据损失函数进行训练逼近,虽然非常直观但是当状态与动作种类非常多时,Q表将会非常巨大,不利于计算效率的提升甚至会无法完成。

    Deep-Qlearning引入神经网络通过训练得到Q值,将状态和动作组合作为神经网络的输入,无需构造Q表,借助神经网络生成相应的Q值。也可以指输入状态,通过神经网络生成采取相应动作后对应的价值,直接通过强化学习选取价值最大的动作。

(2)Deep Learning

  那么在强化学习中我们是如何训练神经网络的呢?

在这里插入图片描述

新 N N = 老 N N + α ∗ ( Q 现实 − Q 估计 ) 新NN=老NN+\alpha*(Q现实-Q估计) NN=NN+α(Q现实Q估计)

(3)Experience replay and fixed Q target

经验回放机制,DQN是一种离线学习法,它存在一个记忆库,用于存放之前的经历。训练的时候会随机抽取一些之前的经历,以此打乱经历之间的相关性使神经网络的更新更有效率。

​ Fixed Q target,在DQN中使用两个结构相同但是参数不同的神经网络,用一个不断更新的网络来预测Q估计的值,用一个比较老的神经网络来预测Q现实的值,这样可以加快算法的收敛速度,达到更好的效果。

2、 DQN算法更新循环思路

​    关键思路:DQN采用经验回放机制,所以一开始先不学习,首先建造一个记忆库,这里用step记录,当step大于200以后,再每五步学习一次(RL.learn)。每个回合的更新流程是

①从环境导入智能体此时的状态

②更新环境,根据e-greedy策略选择动作

③得到并存储该动作产生的下一状态以及获得的奖励(存储很重要,在RL-brain中编写)

④更新状态

⑤判断状态是否是最终状态,到达最终状态跳出循环

def run_maze():
	step = 0
	for episode in range(300):
		print("episode: {}".format(episode))
		observation = env.reset()
		while True:
			print("step: {}".format(step))
			env.render()
			action = RL.choose_action(observation)
			observation_, reward, done = env.step(action)
			RL.store_transition(observation, action, reward, observation_)
			if (step>200) and (step%5==0):
				RL.learn()
			observation = observation_
			if done:
				break
			step += 1
	print('game over')
	env.destroy()                  

3、神经网络搭建

    由于采用fixed Q target方法,我们需要搭建两个结构相同而参数不同的神经网络(这里分别记为eval和target,eval不断更新,target保持过去的参数),将两个网络得到的结果比较,加快算法的收敛速度,pytorch版的代码如下。这里莫烦老师教程采用的是tensorflow,可以在github获取。

(1)定义网络结构

class Net(nn.Module):
	def __init__(self, n_feature, n_hidden, n_output):
		super(Net, self).__init__()
		self.el = nn.Linear(n_feature, n_hidden)
		self.q = nn.Linear(n_hidden, n_output)

	def forward(self, x):
		x = self.el(x)
		x = F.relu(x)
		x = self.q(x)
		return x

(2)拿出两个网络中的Q值

def _build_net(self):
   self.q_eval = Net(self.n_features, self.n_hidden, self.n_actions)
   self.q_target = Net(self.n_features, self.n_hidden, self.n_actions)
   self.optimizer = torch.optim.RMSprop(self.q_eval.parameters(), lr=self.lr)

4、基本参数定义(DQN初始化部分)

​    定义并初始化可选动作、状态特征、神经网络层数、学习率、折扣因子、神经网络更新周期、记忆库大小、抽取样本大小等强化学习需要的基本参数。并设置learn_step_counter来记录目前学习的步数,方便观察结果和测试。
    初始化记忆库(pandas),我们首先将记忆库初始化为全零矩阵,高度是记忆库的大小memory_size。其宽度就是每条记忆的大小取决于run-maze中定义的结构,一共有几个变量需要存储。在这里就是RL.store_transition(observation, action, reward, observation_)结构,这里两个状态observation、observation_加上action和reward所以数据长度是n_features*2+2,注意这里action虽然上下左右四个选项,但是每次只选取一个。
    这个顺序也比较关键,在后面抽取数据的时候要记住上一步和下一步的状态分别在哪个位置,可以通过切片索引的方法拿到需要的数据。

class DeepQNetwork():
	def __init__(self, n_actions, n_features, n_hidden=20, learning_rate=0.01, reward_decay=0.9, e_greedy=0.9,
				replace_target_iter=200, memory_size=500, batch_size=32, e_greedy_increment=None,
				):
		self.n_actions = n_actions
		self.n_features = n_features
		self.n_hidden = n_hidden
		self.lr = learning_rate
		self.gamma = reward_decay
		self.epsilon_max = e_greedy
		self.replace_target_iter = replace_target_iter
		self.memory_size = memory_size
		self.batch_size = batch_size
		self.epsilon_increment = e_greedy_increment
		self.epsilon = 0 if e_greedy_increment is not None else self.epsilon_max

		# total learning step
		self.learn_step_counter = 0

		# initialize zero memory [s, a, r, s_]
		self.memory = np.zeros((self.memory_size, n_features*2+2))

		self.loss_func = nn.MSELoss()
		self.cost_his = []

		self._build_net()

5、存储记忆store_transition

​     定义存储记忆函数,这里的输入参数分别是当前状态s,选取动作a,获得奖励r,下一状态s_。

     通过self.memory_counter进行索引,找到记忆库的某一行,再插入此时的这条数据。当counter到记忆库大小时,归零,返回上去,从头开始按条替换,保证记忆库是最近的数据,循环往复,不断覆盖更新。

	def store_transition(self, s, a, r, s_):
		if not hasattr(self, 'memory_counter'):
			self.memory_counter = 0
		transition = np.hstack((s, [a, r], s_))
		# replace the old memory with new memory
		index = self.memory_counter % self.memory_size
		self.memory[index, :] = transition 
		self.memory_counter += 1

6、动作选择部分

​    将当前状态observation输入神经网络,输出在该状态下选取每一个动作的Q值,根据e_greedy策略,在90%(可任意设置)情况下选取Q值最大的动作,剩下10%随机探索,避免局部最优。

	def choose_action(self, observation):
		observation = torch.Tensor(observation[np.newaxis, :])
		if np.random.uniform() < self.epsilon:
			actions_value = self.q_eval(observation)

			action = np.argmax(actions_value.data.numpy())
		else:
			action = np.random.randint(0, self.n_actions)
		return action

7、fixed Q target(神经网络更新)

​    该部分比较简单,在开始训练之前,我们第一步要判断此时的神经网络是否需要更新。target_net中的各参数是冻结的(Fixed Q target),当到达一个更新周期(replace_target_iter)后,将eval网络中的参数传给target网络,以此来实现网络的更新,这样可以避免神经网络的参数一直变化,不稳定,收敛困难的问题,加速其收敛速度。

		# check to replace target parameters
		if self.learn_step_counter % self.replace_target_iter == 0:
			self.q_target.load_state_dict(self.q_eval.state_dict())
			print("\ntarget params replaced\n")

8、训练过程

    神经网络训练时,每一次参数的更新所需要损失函数并不是由一个单独的数据{data:label}获得的,而是由一组数据加权得到的,这一组数据的数量就是[batch size]。我们用随机梯度下降法对数据集进行批量训练,每次随机抽取记忆库中的样本,这里设置当抽取数量大于记忆库大小时,即抽取已经存入的所有记忆。

def learn(self):
   # check to replace target parameters
   if self.learn_step_counter % self.replace_target_iter == 0:
      self.q_target.load_state_dict(self.q_eval.state_dict())
      print("\ntarget params replaced\n")

   # sample batch memory from all memory
   if self.memory_counter > self.memory_size:
      sample_index = np.random.choice(self.memory_size, size=self.batch_size)
   else:
      sample_index = np.random.choice(self.memory_counter, size=self.batch_size)
   batch_memory = self.memory[sample_index, :]

    接下来运行两个神经网络,分别得到他们的估计值,冻结网络target的输出作为Q现实,eval网络输出值作为Q估计,从而实现迭代更新。切片索引时注意这里target网络的输入是下一状态,eval网络输入是当前状态。

# q_next is used for getting which action would be choosed by target network in state s_(t+1)
		q_next, q_eval = self.q_target(torch.Tensor(batch_memory[:, -self.n_features:])), self.q_eval(torch.Tensor(batch_memory[:, :self.n_features]))
		# used for calculating y, we need to copy for q_eval because this operation could keep the Q_value that has not been selected unchanged,
		# so when we do q_target - q_eval, these Q_value become zero and wouldn't affect the calculation of the loss 
		q_target = torch.Tensor(q_eval.data.numpy().copy())

    最后计算损失、反向传播、更新参数,这里计算损失比较关键,由于两个Q值都是二维数组,如果直接矩阵相减,对应关系不正确,需要首先找到eval中的状态和对应动作,再去找到target中的对应值,才可以进行相减计算损失。

	batch_index = np.arange(self.batch_size, dtype=np.int32)
	eval_act_index = batch_memory[:, self.n_features].astype(int)
	reward = torch.Tensor(batch_memory[:, self.n_features+1])
	q_target[batch_index, eval_act_index] = reward + self.gamma*torch.max(q_next, 1)[0]

		loss = self.loss_func(q_eval, q_target)
		self.optimizer.zero_grad()
		loss.backward()
		self.optimizer.step()
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: DQN(Deep Q-Network)是一种由深度神经网络(DNNs)支持的Q-learning算法,用于强化学习问题。它的目标是使函数逼近最优策略函数,以便在状态空间中涉及的每个状态下选择正确的动作。这使得DQN成为一种广泛用于游戏AI和机器人技术的强化学习方法。 在matlab中,可以通过编写DQN的代码来实现强化学习。首先,需要定义DNN的体系结构,其中包括输入层、隐层和输出层。在定义DNN的结构后,需要确定状态、行动和奖励,以便在每个状态下进行正向或反向传播。 在DQN中,还需要使用经验回放机制来提高学习效率。这意味着网络将保存先前成功学习到的状态和行动序列。然后,选择一个经验池来训练模型,并在随后的迭代中更新经验以进一步改进模型的精度。 在编写DQN代码时,还需要调整各种参数,例如学习率、随机探索率和折扣率等。这些值可以根据问题的要求和具体的应用场景进行优化。 总的来说,实现DQN的代码需要一定的编程经验和深入的数学知识,包括机器学习、优化算法和深度神经网络。但如果成功实现,该算法可以成为解决各种强化学习问题的有力工具。 ### 回答2: DQN是深度强化学习中非常流行的一种技术,它的主要优势是能够处理离散状态与动作空间。在MATLAB中,有很多可以使用的DQN代码包。下面让我们来讨论一下MATLAB中的DQN算法以及它的实现。 DQN算法 DQN是一种基于Q学习的强化学习策略,它主要是通过神经网络来逼近现实生活中的复杂环境,并通过使用经验回放的机制来优化神经网络DQN算法将Q学习与深度学习相结合,以实现更高效的搜索。在这种算法中,一个深度神经网络被用来逼近每个状态的价值函数,并使用经验回放技术来减少样本相关性。 DQN实现 在MATLAB中,一个DQN实现遵循一下几个步骤: 1. 状态表达 在DQN中,状态向量用来表示代理器所处的状态。这个向量可以包含任意的重要信息,比如位置、速度、方向等。在MATLAB中,可以使用预处理的数据或者深度神经网络来构建状态向量。 2. 神经网络构建 神经网络DQN中用来估计每个状态的价值函数。在MATLAB中,可以使用深度学习工具箱来构建神经网络,该工具箱提供了不同的神经网络模型。 3. 经验回放 由于DQN需要大量的样本数据才能训练神经网络,因此需要使用经验回放技术来减少样本相关性。在MATLAB中,可以使用ReplayBuffer类来实现经验回放。 4. 算法训练 在MATLAB中,可以使用TrainDQN方法来训练DQN算法,该方法会使用神经网络代替具体的深度神经网络。 总结 DQN是一种非常流行的强化学习方法,在MATLAB中也有非常好的支持。使用MATLAB可以轻松地构建DQN模型、训练深度神经网络和实现经验回放技术。使用MATLAB的DQN代码,可以更方便地研究、实现和优化DQN算法。 ### 回答3: DQN是深度强化学习中的一种算法,结合了深度学习强化学习的优点,能够处理高维复杂的状态和动作空间。Matlab是一种流行的数学软件,也可以用来编写DQN算法的代码。下面将介绍一些常用的Matlab强化学习代码DQN。 首先,需要导入一些必要的Matlab函数和工具箱。常用的包括Deep Learning Toolbox、Reinforcement Learning Toolbox等。 接着,需要定义神经网络的结构并将其编译。在DQN算法中,有两个神经网络:一个被称为“目标网络”,用于计算未来的奖励;另一个被称为“评估网络”,用于选择下一个动作。这两个网络的参数会逐渐改变,在每个epoch末尾更新“目标网络”的参数。 然后,需要定义强化学习环境。我们可以选择使用预先定义的环境,比如CartPole或MountainCar。也可以自定义环境,包括状态和动作空间、奖励函数等。 接下来,需要定义一些训练参数,比如学习率、回放缓冲区大小、mini-batch大小等。这些参数也需要根据实际情况进行调整。 在训练过程中,每个epoch开始时,需要执行一些预处理步骤,比如获取当前状态、执行动作并观察奖励、将状态转换成神经网络的输入格式等。然后,需要使用“评估网络”选择下一个动作,以及计算TD误差和损失函数。接着,需要更新“评估网络”的参数。每个epoch末尾,需要使用“目标网络”更新所有TD目标。 最后,需要定义一些测试参数,比如测试次数、测试最长时间等。使用学习后的“评估网络”对测试环境进行测试并计算平均测试分。 综上所述,Matlab强化学习代码DQN的实现方法是相对比较简单的,主要是需要借助一些基础的Matlab函数和工具箱,并根据实际情况进行参数的选择和调整。但是,具体实现过程中也需要注意一些细节和技巧,比如数据预处理、神经网络结构的选择、参数的调整等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝士就是力量蛙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值