赞
踩
目录
这段时间学习深度强化学习的总结。
强化学习是做出最佳决策的科学。它可以帮助我们制定活的物种所表现出的奖励动机行为。比方说,你想让一个孩子坐下来学习考试。要做到这一点非常困难,但是如果每次完成一章/主题时都给他一块巧克力,他就会明白,如果他继续学习,他会得到更多的巧克力棒。所以他会有一些学习考试的动机。
孩子代表着Agent代理 。奖励制度和考试代表了Environment环境。今天的题目是类似于强化学习的States状态。所以,孩子必须决定哪些话题更重要(即计算每种行为的价值)。这将是我们的工作的 Value-Function价值方程。所以,每次他从一个国家到另一个国家旅行时,他都会得到Reward奖励,他用来在时间内完成主题的方法就是我们的Policy决策。
马尔科夫链是用来描述智能体和环境互动的过程。
马尔科夫链包含三要素:state,action,reward
智能体在一个状态(S)下,选择了某个动作(A),进入了另外一个状态,并获得奖励(用R代表)的过程。
所以,我们希望通过让智能体在环境里获取最多的奖励,把智能体训练成我们想要的样子——就是能完成某些特定的任务。
马尔科夫链,其实应该叫马尔科夫树
S到A是agent的选择 ,而A到S时环境的随机性。
马尔科夫链具有不确定性。
Q和V:
评估动作的价值,称为Q值:它代表了选择这个动作后,一直到最终状态奖励总和的期望;
评估状态的价值,称为V值:它代表了在这个状态下,一直到最终状态的奖励总和的期望。
算上奖励R,Q和V之间的关系:
V就是子节点的Q的期望,Q就是子节点的V的期望.
蒙地卡罗:
我们把agent放到环境的任意状态;从这个状态开始按照策略进行选择动作,并进入新的状态。
重复上一步,直到最终状态;我们从最终状态开始向前回溯:计算每个状态的G值。
重复前面多次,然后平均每个状态的G值,这就是我们需要求的V值。
缺点: 每一次都需要先从头走到尾,再进行回溯更新。如果最终状态很难达到,可能每一次都要转很久很久才能更新一次G值。就是说如果环境的状态空间非常大,或者最终状态只有非常小的概率达到。
TD算法对蒙地卡罗(MC)进行了改进:
1. 和蒙地卡罗(MC)不同:TD算法只需要走N步。就可以开始回溯更新。
2. 和蒙地卡罗(MC)一样:小猴需要先走N步,每经过一个状态,把奖励记录下来。然后开始回溯。
3. 状态的V值计算:和蒙地卡罗一样,假设N步之后,就到达了最终状态了。
可以简单来说就是,TD不走完整段路程,而是半路就截断。用半路的路牌,更新当前的路牌。就是说不需要一直到最后,我们可以先用后面的估算,然后调整当前状态。
在MC,G是更新目标,而在TD,把更新目标从G,改成r+gamma*V
S:start,出发点。 G:target,终点。 F:可以走的路,但偶尔你会因为滑到,自动往前滑一格。 H:hole:是陷阱。
FrozenLake-v0是一个4*4的网络格子,每个格子可以是起始块,目标块、冻结块或者危险块。 我们的目标是让agent学习从开始块如何行动到目标块上,而不是移动到危险块上。 agent可以选择向上、向下、向左或者向右移动,同时游戏中还有可能吹来一阵风,将agent吹到任意的方块上。
我们的任务就是让我们的agent,从起点,走到终点。
V(St+1)的意义是,在St+1到最终状态获得的奖励期望值。 Q(St,At)的意义是,在Q(St,At)到最终状态获得的奖励期望值。 所以我们可以把V(St+1)看成是下山途中的一个路牌,这个路牌告诉我们下山到底还有多远,然后加上R这一段路,就知道Q(St,At)离山脚有多长的路。
因为从状态St+1到动作At+1之间没有奖励反馈,所以我们直接用At+1的Q价值,代替St+1的V价值。
在St+1下,可能有很多动作At+1。不同动作的Q值自然是不同的。 所以Q(St+1,At+1)并不能等价于V(St+1)。
虽然不相等,但不代表不能用其中一个来代表V(St+1)。人们认为有个可能的动作产生的Q值能够一定程度代表V(St+1)。
Qlearning和SARSA唯一的不同,就是用什么动作的Q值替代St+1的V值。SARSA 选择的是在St同一个策略产生的动作。Qlearning 选择的是能够产生最大的Q值的动作。
Qleanring的更新流程。 我们将会在任意的state出发
1. 我们将会用noisy-greedy的策略选定动作A
2. 在完成动作后,我们将会进入新状态St+1;
3. 检查St+1中所有动作,看看哪个动作的Q值最大;
4. 用以下的公式更新当前动作A的Q值;
5. 继续从s'出发,进行下一步更新 1-6步我们作为一个EP,进行N个EP的迭代。
- """Q-Table learning algorithm.
- Non deep learning - TD Learning, Off-Policy, e-Greedy Exploration
- Q(S, A) <- Q(S, A) + alpha * (R + lambda * Q(newS, newA) - Q(S, A))
- See David Silver RL Tutorial Lecture 5 - Q-Learning for more details.
- For Q-Network, see tutorial_frozenlake_q_network.py
- EN: https://medium.com/emergent-future/simple-reinforcement-learning-with-tensorflow-part-0-q-learning-with-tables-and-neural-networks-d195264329d0#.5m3361vlw
- CN: https://zhuanlan.zhihu.com/p/25710327
- tensorflow==2.0.0a0
- tensorlayer==2.0.0
- """
-
- import argparse
- import os
- import time
-
- import gym
- import matplotlib.pyplot as plt
- import numpy as np
-
- parser = argparse.ArgumentParser()
- parser.add_argument('--train', dest='train', action='store_true', default=True)
- parser.add_argument('--test', dest='test', action='store_true', default=True)
-
- parser.add_argument(
- '--save_path', default=None, help='folder to save if mode == train else model path,'
- 'qnet will be saved once target net update'
- )
- parser.add_argument('--seed', help='random seed', type=int, default=0)
- parser.add_argument('--env_id', default='FrozenLake-v0')
- args = parser.parse_args()
-
- ## Load the environment
- alg_name = 'Qlearning'
- env_id = args.env_id
- env = gym.make(env_id)
- render = False # display the game environment
-
- ##================= Implement Q-Table learning algorithm =====================##
- ## Initialize table with all zeros
- Q = np.zeros([env.observation_space.n, env.action_space.n])
- ## Set learning parameters
- lr = .85 # alpha, if use value function approximation, we can ignore it
- lambd = .99 # decay factor
- num_episodes = 10000
- t0 = time.time()
-
- if args.train:
- all_episode_reward = []
- for i in range(num_episodes):
- ## Reset environment and get first new observation
- s = env.reset()
- rAll = 0
- ## The Q-Table learning algorithm
- for j in range(99):
- if render: env.render()
- ## Choose an action by greedily (with noise) picking from Q table
- a = np.argmax(Q[s, :] + np.random.randn(1, env.action_space.n) * (1. / (i + 1)))
- ## Get new state and reward from environment
- s1, r, d, _ = env.step(a)
- ## Update Q-Table with new knowledge
- Q[s, a] = Q[s, a] + lr * (r + lambd * np.max(Q[s1, :]) - Q[s, a])
- rAll += r
- s = s1
- if d is True:
- break
- print(
- 'Training | Episode: {}/{} | Episode Reward: {:.4f} | Running Time: {:.4f}'.format(
- i + 1, num_episodes, rAll,
- time.time() - t0
- )
- )
- if i == 0:
- all_episode_reward.append(rAll)
- else:
- all_episode_reward.append(all_episode_reward[-1] * 0.9 + rAll * 0.1)
-
- # save
- path = os.path.join('model', '_'.join([alg_name, env_id]))
- if not os.path.exists(path):
- os.makedirs(path)
- np.save(os.path.join(path, 'Q_table.npy'), Q)
-
- plt.plot(all_episode_reward)
- if not os.path.exists('image'):
- os.makedirs('image')
- plt.savefig(os.path.join('image', '_'.join([alg_name, env_id])))
-
- # print("Final Q-Table Values:/n %s" % Q)
-
- if args.test:
- path = os.path.join('model', '_'.join([alg_name, env_id]))
- Q = np.load(os.path.join(path, 'Q_table.npy'))
- for i in range(num_episodes):
- ## Reset environment and get first new observation
- s = env.reset()
- rAll = 0
- ## The Q-Table learning algorithm
- for j in range(99):
- ## Choose an action by greedily (with noise) picking from Q table
- a = np.argmax(Q[s, :])
- ## Get new state and reward from environment
- s1, r, d, _ = env.step(a)
- ## Update Q-Table with new knowledge
- rAll += r
- s = s1
- if d is True:
- break
- print(
- 'Testing | Episode: {}/{} | Episode Reward: {:.4f} | Running Time: {:.4f}'.format(
- i + 1, num_episodes, rAll,
- time.time() - t0
- )
- )
在Qlearning中,有一个Qtable,记录着在每一个状态下,各个动作的Q值。
Qtable的作用是当输入状态S,通过查表返回能够获得最大Q值的动作A。也就是需要找一个S-A的对应关系。
这种方式很适合格子游戏。因为格子游戏中的每一个格子就是一个状态,但在现实生活中,很多状态并不是离散而是连续的。
例如在GYM中经典的CartPole游戏,杆子的角度是连续而不是离散的。在Atari游戏中,状态也是连续的。
遇到这些情况,Qtable就没有办法解决。
Qtable的作用就是找一个S-A的对应关系。所以我们就可以用一个函数F表示,我们有F(S) = A。这样我们就可以不用查表了,而且还有个好处,函数允许连续状态的表示。
这时候,我们深度神经网络就可以派上用场了。因为神经网络可以看成一个万能的函数。
这个万能函数接受输入一个状态S,它能告诉我,每个动作的Q值是怎样的。
Qlearning和DQN并没有根本的区别。只是DQN用神经网络,也就是一个函数替代了原来Qtable而已。解决连续问题。
更新当前状态St下的某动作A的Q值:Q(S,A),我们可以这样做:
1. 执行A,往前一步,到达St+1;
2. 把St+1输入Q网络,计算St+1下所有动作的Q值;
3. 获得最大的Q值加上奖励R作为更新目标;
4. 计算损失 - Q(S,A)相当于有监督学习中的logits - maxQ(St+1) + R 相当于有监督学习中的lables - 用mse函数,得出两者的loss
5. 用loss更新Q网络。
用Q网络估算出来的两个相邻状态的Q值,他们之间的距离,就是一个r的距离。
和有监督学习不同,深度强化学习中,我们需要自己找更新目标。通常在马尔科夫链体系下,两个相邻状态状态差一个奖励r,经常能被利用。
- """
- Deep Q-Network Q(a, s)
- -----------------------
- TD Learning, Off-Policy, e-Greedy Exploration (GLIE).
- Q(S, A) <- Q(S, A) + alpha * (R + lambda * Q(newS, newA) - Q(S, A))
- delta_w = R + lambda * Q(newS, newA)
- See David Silver RL Tutorial Lecture 5 - Q-Learning for more details.
- Reference
- ----------
- original paper: https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf
- EN: https://medium.com/emergent-future/simple-reinforcement-learning-with-tensorflow-part-0-q-learning-with-tables-and-neural-networks-d195264329d0#.5m3361vlw
- CN: https://zhuanlan.zhihu.com/p/25710327
- Note: Policy Network has been proved to be better than Q-Learning, see tutorial_atari_pong.py
- Environment
- -----------
- # The FrozenLake v0 environment
- https://gym.openai.com/envs/FrozenLake-v0
- The agent controls the movement of a character in a grid world. Some tiles of
- the grid are walkable, and others lead to the agent falling into the water.
- Additionally, the movement direction of the agent is uncertain and only partially
- depends on the chosen direction. The agent is rewarded for finding a walkable
- path to a goal tile.
- SFFF (S: starting point, safe)
- FHFH (F: frozen surface, safe)
- FFFH (H: hole, fall to your doom)
- HFFG (G: goal, where the frisbee is located)
- The episode ends when you reach the goal or fall in a hole. You receive a reward
- of 1 if you reach the goal, and zero otherwise.
- Prerequisites
- --------------
- tensorflow>=2.0.0a0
- tensorlayer>=2.0.0
- To run
- -------
- python tutorial_DQN.py --train/test
- """
- import argparse
- import os
- import time
-
- import gym
- import matplotlib.pyplot as plt
- import numpy as np
- import tensorflow as tf
-
- import tensorlayer as tl
-
- # add arguments in command --train/test
- parser = argparse.ArgumentParser(description='Train or test neural net motor controller.')
- parser.add_argument('--train', dest='train', action='store_true', default=True)
- parser.add_argument('--test', dest='test', action='store_true', default=True)
- args = parser.parse_args()
-
- tl.logging.set_verbosity(tl.logging.DEBUG)
-
- ##################### hyper parameters ####################
- env_id = 'FrozenLake-v0'
- alg_name = 'DQN'
- lambd = .99 # decay factor
- e = 0.1 # e-Greedy Exploration, the larger the more random
- num_episodes = 10000
- render = False # display the game environment
-
- ##################### DQN ##########################
-
-
- def to_one_hot(i, n_classes=None):
- a = np.zeros(n_classes, 'uint8')
- a[i] = 1
- return a
-
-
- ## Define Q-network q(a,s) that ouput the rewards of 4 actions by given state, i.e. Action-Value Function.
- # encoding for state: 4x4 grid can be represented by one-hot vector with 16 integers.
- def get_model(inputs_shape):
- ni = tl.layers.Input(inputs_shape, name='observation')
- nn = tl.layers.Dense(4, act=None, W_init=tf.random_uniform_initializer(0, 0.01), b_init=None, name='q_a_s')(ni)
- return tl.models.Model(inputs=ni, outputs=nn, name="Q-Network")
-
-
- def save_ckpt(model): # save trained weights
- path = os.path.join('model', '_'.join([alg_name, env_id]))
- if not os.path.exists(path):
- os.makedirs(path)
- tl.files.save_weights_to_hdf5(os.path.join(path, 'dqn_model.hdf5'), model)
-
-
- def load_ckpt(model): # load trained weights
- path = os.path.join('model', '_'.join([alg_name, env_id]))
- tl.files.save_weights_to_hdf5(os.path.join(path, 'dqn_model.hdf5'), model)
-
-
- if __name__ == '__main__':
-
- qnetwork = get_model([None, 16])
- qnetwork.train()
- train_weights = qnetwork.trainable_weights
-
- optimizer = tf.optimizers.SGD(learning_rate=0.1)
- env = gym.make(env_id)
-
- t0 = time.time()
- if args.train:
- all_episode_reward = []
- for i in range(num_episodes):
- ## Reset environment and get first new observation
- s = env.reset() # observation is state, integer 0 ~ 15
- rAll = 0
- if render: env.render()
- for j in range(99): # step index, maximum step is 99
- ## Choose an action by greedily (with e chance of random action) from the Q-network
- allQ = qnetwork(np.asarray([to_one_hot(s, 16)], dtype=np.float32)).numpy()
- a = np.argmax(allQ, 1)
-
- ## e-Greedy Exploration !!! sample random action
- if np.random.rand(1) < e:
- a[0] = env.action_space.sample()
- ## Get new state and reward from environment
- s1, r, d, _ = env.step(a[0])
- if render: env.render()
- ## Obtain the Q' values by feeding the new state through our network
- Q1 = qnetwork(np.asarray([to_one_hot(s1, 16)], dtype=np.float32)).numpy()
-
- ## Obtain maxQ' and set our target value for chosen action.
- maxQ1 = np.max(Q1) # in Q-Learning, policy is greedy, so we use "max" to select the next action.
- targetQ = allQ
- targetQ[0, a[0]] = r + lambd * maxQ1
- ## Train network using target and predicted Q values
- # it is not real target Q value, it is just an estimation,
- # but check the Q-Learning update formula:
- # Q'(s,a) <- Q(s,a) + alpha(r + lambd * maxQ(s',a') - Q(s, a))
- # minimizing |r + lambd * maxQ(s',a') - Q(s, a)|^2 equals to force Q'(s,a) ≈ Q(s,a)
- with tf.GradientTape() as tape:
- _qvalues = qnetwork(np.asarray([to_one_hot(s, 16)], dtype=np.float32))
- _loss = tl.cost.mean_squared_error(targetQ, _qvalues, is_mean=False)
- grad = tape.gradient(_loss, train_weights)
- optimizer.apply_gradients(zip(grad, train_weights))
-
- rAll += r
- s = s1
- ## Reduce chance of random action if an episode is done.
- if d ==True:
- e = 1. / ((i / 50) + 10) # reduce e, GLIE: Greey in the limit with infinite Exploration
- break
-
- ## Note that, the rewards here with random action
- print('Training | Episode: {}/{} | Episode Reward: {:.4f} | Running Time: {:.4f}' \
- .format(i, num_episodes, rAll, time.time() - t0))
-
- if i == 0:
- all_episode_reward.append(rAll)
- else:
- all_episode_reward.append(all_episode_reward[-1] * 0.9 + rAll * 0.1)
-
- save_ckpt(qnetwork) # save model
- plt.plot(all_episode_reward)
- if not os.path.exists('image'):
- os.makedirs('image')
- plt.savefig(os.path.join('image', '_'.join([alg_name, env_id])))
-
- if args.test:
- load_ckpt(qnetwork) # load model
- for i in range(num_episodes):
- ## Reset environment and get first new observation
- s = env.reset() # observation is state, integer 0 ~ 15
- rAll = 0
- if render: env.render()
- for j in range(99): # step index, maximum step is 99
- ## Choose an action by greedily (with e chance of random action) from the Q-network
- allQ = qnetwork(np.asarray([to_one_hot(s, 16)], dtype=np.float32)).numpy()
- a = np.argmax(allQ, 1) # no epsilon, only greedy for testing
-
- ## Get new state and reward from environment
- s1, r, d, _ = env.step(a[0])
- rAll += r
- s = s1
- if render: env.render()
- ## Reduce chance of random action if an episode is done.
- if d: break
-
- print('Testing | Episode: {}/{} | Episode Reward: {:.4f} | Running Time: {:.4f}' \
- .format(i, num_episodes, rAll, time.time() - t0))
对深度强化学习的初步学习,从强化学习到深度强化学习,学习了一下算法,之后还需要深入实验,如GYM等。加油加油。
好的参考:
强化学习极简入门:通俗理解MDP、DP MC TC和Q学习、策略梯度、PPO_强化学习极简入门:通俗理解mdp、dpmc-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。