浅谈强化学习原理(附代码&链接)
作者:Michel Kana
翻译:王琦
校对:王雨桐
本文约4900字,建议阅读15分钟。
本文介绍了强化学习的基本原理,并通过代码实例来讲解如何找到最优策略。
Google在2017年年底发布了AlphaZero,这个零基础的AI系统能够在4小时内自学并掌握国际象棋、围棋和将棋。
极短的训练时间是 AlphaZero击败世界顶级国际象棋程序的致命武器。
Andriy Popov / Alamy Stock 照片
最近,OpenAI 展示了强化学习不是一个仅限于虚拟任务的工具。Dactyl的类人机械手已经学会了如何独立解魔方(见下面链接)。
附链接:https://openai.com/blog/solving-rubiks-cube/
Google AlphaZero和OpenAI Dactyl的本质都是强化学习算法,它不基于任何相关领域的知识,我们只需要给定游戏的规则。一些AI专家认为这是实现人类或超人类的通用人工智能的最可行方法。
我们之前的文章介绍了强化学习的基础概念(见下面链接)。
附链接:
https://towardsdatascience.com/dont-ever-ignore-reinforcement-learning-again-4d026ee81371
现在让我们继续深入AI智能体的工作原理, 探索它是如何通过自学来采取恰当的行动流程,从而实现全局最优的目标。
什么是策略?
让我们假设一个OpenAI冰湖的简单情景,在此环境下智能体能够控制一个人物在坐标格上运动。网格里的一些是可走的,其他格子则意味着人物将掉进冰洞里。 当智能体发现一条可走的并且能达到目标地点(图中黄色星星)的路径时,它就会得到奖励。
在这种很简单的环境下,我们可以有很多策略。比如说,智能体可以一直向前移动,或者随机选择一个方向移动,还可以通过前车之鉴来学习如何绕过障碍,甚至可以原地转圈来娱乐。
从直观上来讲,策略可以被定义为一些能够控制智能体行为的规则集合。不同的策略会给我们不同的收益,因此找到一个好的策略很重要。
策略的正式定义是每个可能状态下采取的行为的概率分布:
最优策略
能够最大化预期的值函数 V:
区分于短期收益,值函数 V(s) 是状态s下含折扣的预期长期收益,它表示智能体所处状态的好坏。对一个从该状态开始的智能体来说,这相当于预期的总收益。换言之,这就是在状态s下采取行动a这一步的总收益,被定义为 V(s)。
如何选择最好的行动?
值函数取决于智能体选择行动所用的策略。学习最优策略需要使用所谓的Bellman方程。
让我们通过下面的例子来直观地了解一下Bellman方程。智能体能够执行行动1, 2, …, N,这会让它转移到未来的状态S1, S2, …, SN, 从而分别得到相应的收益 r1, r2, …, rN。对于未来各个状态来说,预期的长期收益是V1, V2, …, VN。
如果智能体采取行动 a=i,当其在状态S0时,对状态S0来说,预期的长期收益或价值可以用下面的方程来表示,方程中的γ 是常数。
最优策略能够帮助智能体选择最佳的可能行动。为了达到目的,智能体需要计算每个可能行动 a=1, 2, …, N所产生的收益。然后,我们会选择可能性最大的结果。
上面的方程被称为确定的Bellman方程。对一个给定的行动,如果智能体能够以不同的概率转移到多个未来状态,它就变成了一个随机方程。下图解释了这种情况。
对于这种一般情况,所得的随机Bellman方程如下所示。
我们提供了一种对Bellman方程的实现,这种实现可以在给定的状态 s 下选择最好的可能行动。此函数计算了每个行动的所得值并选择可能性最大的结果。在一切开始之前,你需要加载一些我们之前文章谈到的库(见下面链接)。
附链接:
https://towardsdatascience.com/dont-ever-ignore-reinforcement-learning-again-4d026ee81371
1. # using the Bellman equation, we find the action providing the highest value for the given state s. 2. # V is the list of values of all states 3. def choose_best_action(env, V, s, gamma): 4. a_best = None 5. q_best = float('-inf') 6. nb_actions = env.action_space.n 7. for a in range (0, nb_actions): 8. env.env.s = s # go to state s 9. s_next, r, done, info = env.step(a) #take the action a 10. q = r + gamma * V[s_next] # compute the value future value after taking action a 11. if q > q_best: 12. q_best = q 13. a_best = a 14. return a_best
AI智能体如何通过值迭代来学习?
我们已经解释了如何找到获得最大长期价值的最佳行为。如果我们对所有状态使用这个方法,就会得到值函数。我们也能知道在每个状态(最优状态)下应该采取什么行动。这个算法被称为值迭代。
值迭代算法随机选择一个初始值函数。然后在迭代过程中计算新的改进值函数,直到找到一个最优的值函数。最后,我们可以从最优的值函数中得到最优的策略。
在一个 4×4的冰湖环境下,值迭代算法会在16个状态下进行循环并采取4个可能的行动来探索给定行动的收益。此外,它还会计算可能性最大的行动/收益并将其存储在向量 V[s]中,持续迭代这个算法直到 V[s] 不再有显著的改进。
最优策略 P 每次会采取能够转移到最大V值状态的行动。
下面的函数实现了在 4×4的冰湖环境下的值迭代算法。
1. # value iteration algorithm 2. def compute_value_iteration(env = gym.make('FrozenLakeNotSlippery-v0'), 3. gamma=.9, v_delta_threshold=.01, 4. V = None, verbose=True): 5. env.reset() 6. nb_actions = env.action_space.n 7. nb_states = env.observation_space.n 8. # values vector 9. if V == None: 10. V = np.zeros([nb_states]) 11. # policy vector 12. P = np.zeros([nb_states], dtype=int) 13. iteration = 0 14. while True: 15. 16. v_delta = 0 17. for s in range (0, nb_states): 18. v_previous = V[s] 19. a_best = choose_best_action(env, V, s, gamma) # find an action with the highest future reward 20. env.env.s = s # go to the state s 21. s_next, r, done, info = env.step(a_best) #take the best action 22. V[s] = r + gamma * V[s_next] # update the value of the state 23. P[s] = a_best # store the best action in the policy vector for the state 24. v_delta = max(v_delta, np.abs(v_previous - V[s])) # calculate the rate of value improvment for the state 25. iteration += 1 26. if v_delta < v_delta_threshold: 27. if verbose: 28. print (iteration,' iterations done') 29. break 30. return V, P 31. 32.# compute values for a 4x4 board 33.V_4, P_4 = compute_value_iteration() 34.V_4
上面所得的数组解释了值迭代函数是如何成功地计算出16个状态的长期收益。此算法迭代了7次。
表示冰洞(H)的状态值为0,那些表示冰面的格子(F)的状态有更大的值,尤其是那些处在有希望到达目标G的路径上的格子。
下面的函数绘制了热力图将结果可视化。箭头展示了使用最优策略 P来获得最佳总收益的行动流程。
1. # function for displaying a heatmap 2. def display_value_iteration(P, env = gym.make('FrozenLakeNotSlippery-v0')): 3. nb_states = env.observation_space.n 4. visited_states = np.zeros(nb_states).astype(bool) 5. visited_states[0] = 1 6. states_labels = np.where(P==0, '<', 7. np.where(P==1, '>', 8. np.where(P==2, 'v', 9. np.where(P==3, '^', P) 10. ) 11. ) 12. ) 13. desc = env.unwrapped.desc.ravel().astype(str) 14. colors = np.where(desc=='S','y',np.where(desc=='F','b',np.where(desc=='H','r',np.where(desc=='G','g',desc)))) 15. states_labels = np.zeros(nb_states).astype(str) 16. states_labels[:] = '' 17. total_reward = 0 18. s = env.reset() 19. #env.render() 20. done = False 21. while done != True: 22. best_a = P[s] # select the best next action from the policy 23. states_labels[s] = '^' if best_a==0 else ('v' if best_a==1 else ('>' if best_a==2 else '<')) 24. #print(s, best_a) 25. s, rew, done, info = env.step(best_a) #take step using selected action 26. total_reward = total_reward + rew 27. visited_states[s] = 1 # mark the state as visited 28. #env.render() 29. ax = sns.heatmap(P.reshape(int(np.sqrt(nb_states)),int(np.sqrt(nb_states))), 30. linewidth=0.5, 31. annot=states_labels.reshape(int(np.sqrt(nb_states)),int(np.sqrt(nb_states))), 32. cmap=list(colors), 33. fmt = '', 34. cbar=False) 35. plt.show() 36. print("Total Reward: ", total_reward) 37. 38. # display heatmap for a 4x4 board 39. display_value_iteration(P_4)
下面我们在8×8的冰湖环境下运行了值迭代算法。
1. V_8, P_8 = compute_value_iteration(env = gym.make('FrozenLake8x8NotSlippery-v0')) 2. V_8 3. display_value_iteration(P_8, env = gym.make('FrozenLake8x8NotSlippery-v0'))
AI 智能体如何通过策略迭代来学习?
在前一小节,我们已经展示了值迭代算法并解释了一个智能体如何走过一个有洞的冰湖来达到目标。
在策略迭代的算法中,一开始我们使用的是一个随机策略而不是随机值函数,得到了该策略的值函数。接下来,我们可以基于之前的值函数得到新的(改进的)策略。经过多次迭代后,我们会得到一个最优策略。
下面的函数实现了策略迭代算法。
1. # function for performing policy iteration 2. def compute_policy_iteration(env = gym.make('FrozenLakeNotSlippery-v0'), 3. gamma=.9, v_delta_threshold=.01, 4. P = None, verbose=True): 5. env.reset() 6. nb_actions = env.action_space.n 7. nb_states = env.observation_space.n 8. # values vector 9. V = np.zeros([nb_states]) 10. # policy vector 11. if P == None: 12. P = np.random.choice(nb_actions, size=nb_states) 13. 14. max_iterations = 200000 15. iteration = 0 16. for i in range(max_iterations): 17. 18. # policy evaluation 19. while True: 20. v_delta = 0 21. for s in range (0, nb_states): 22. v_previous = V[s] 23. env.env.s = s # go to state s 24. s_next, r, done, info = env.step(P[s]) #take the action recommended by policy 25. V[s] = r + gamma * V[s_next] # update value after applying policy 26. v_delta = max(v_delta, np.abs(v_previous - V[s])) # calculate the rate of value improvment for the state 27. if v_delta < v_delta_threshold: 28. break 29. 30. # policy improvement 31. policy_stable = True 32. for s in range (0, nb_states): 33. a_old = P[s] # ask policy for action to perform 34. a_best = choose_best_action(env, V, s, gamma) # find an action with the highest future reward 35. P[s] = a_best # store the best action in the policy vector for the state 36. if a_old != a_best: 37. policy_stable = False 38. 39. if policy_stable: 40. break 41. 442. iteration += 1 43. if verbose: 44. print (iteration,' iterations done') 45. return V, P 46. 47. Vp_4, Pp_4 = compute_policy_iteration() 48. Vp_4 49. display_value_iteration(Pp_4)
正如我们所看到的那样,两个算法的结果相同。值迭代算法在每次迭代中不断地改进值
函数,直到值函数收敛。策略改进理论让我们确信策略迭代算法发现的策略比最初的随机策略要好。
两种方法都能实现相同的目标,但策略迭代的计算效率更高。
如何调整 AI 智能体的学习率?
值迭代算法和策略迭代算法都依赖于超参数γ(gamma),γ定义了值更新或策略更新的学习率。
让我们试试不同的gamma 值并讨论一下gamma值对训练的影响。
1. # function for performing value and policy iterations for given gamma 2. def gammas_training(method='value_iteration', 3. gammas = np.arange(0, 1, 0.1), 4. env=gym.make('FrozenLakeNotSlippery-v0')):5. df = pd.DataFrame(columns=['gamma','state','value']) 6. for gamma in gammas: 7. if method == 'value_iteration': 8. V, P = compute_value_iteration(env=env, gamma=gamma, verbose=False) 9. else: 10. V, P = compute_policy_iteration(env=env, gamma=gamma, verbose=False) 11. df = df.append(pd.DataFrame({'gamma':[gamma for i in range(0,env.observation_space.n)], 12. 'state':[i for i in range(0,env.observation_space.n)], 13. 'value': V})) 14. df.state=df.state.astype(int) 15. return df 16. 17. 18. # display the values for multiple gammas 19. 20. fig, ax = plt.subplots(2,2, figsize=(20,10)) 21. 22. df_4_v = gammas_training(method='value_iteration', env=gym.make('FrozenLakeNotSlippery-v0')) 23. sns.lineplot(data=df_4_v, x='gamma', y='value', hue='state', ax=ax[0][0]) 24. ax[0][0].set_title('4x4 - VALUE ITERATION - Values per gamma') 25. 26. df_4_i = gammas_training(method='policy_iteration', env=gym.make('FrozenLakeNotSlippery-v0')) 27. sns.lineplot(data=df_4_i, x='gamma', y='value', hue='state', ax=ax[0][1]) 28. ax[0][1].set_title('4x4 - POLICY ITERATION - Values per gamma') 29. 30. df_8_v = gammas_training(method='value_iteration', env=gym.make('FrozenLake8x8NotSlippery-v0')) 31. sns.lineplot(data=df_8_v, x='gamma', y='value', hue='state', ax=ax[1][0]) 32. ax[1][0].set_title('8x8 - VALUE ITERATION - Values per gamma') 33. 34. df_8_i = gammas_training(method='policy_iteration', env=gym.make('FrozenLake8x8NotSlippery-v0')) 35. sns.lineplot(data=df_8_i, x='gamma', y='value', hue='state', ax=ax[1][1]) 36. ax[1][1].set_title('8x8 - POLICY ITERATION - Values per gamma');
这些图展示了当gamma增加时,价值是如何增加的。不同的gamma值(0-10) 会产生不同的策略。较小的gamma值会赋予短期收益更多的权重,然而较大的gamma 值会给长期收益更多的权重。
Gamma的最优值取决于任务的领域。在冰湖的情况下,寻求短期收益是不合理的(例如:即使惩罚相同,但相比于走了很长的路但没掉进冰洞,掉进洞里导致的负面收益毫无意义)。因此,我们尽可能地将眼光放长远。
结论
在这篇文章中,我们介绍了强化学习中能够找到最优策略的值迭代和策略迭代算法的实践技术。
Andrej Kaparthy写的这个帖子提供了更好的见解(见下面链接)。
附链接:https://cs.stanford.edu/people/karpathy/reinforcejs/gridworld_dp.html
当智能体知道充足的与环境模型相关的信息时,值迭代算法和策略迭代算法都是有效的。在自动驾驶、医疗或股票交易等多种情况下,学习或提供一个转移模型(transition model)可能会很困难。在这种情况下,免模型(model-free)方法更合适,本文不细谈这个概念。
Q-学习是一种免模型学习,其适用于智能体不了解环境模型但又必须利用其与环境互动的历史进行反复试验来发现策略的情况。
SARSA (State–action–reward–state–action)是另一种智能体能够与环境互动并基于已采取的行动来更新策略的算法。这篇文章(见下面链接)提供了有关免模型算法的其他有趣见解。
附链接:
https://studywolf.wordpress.com/2013/07/01/reinforcement-learning-sarsa-vs-q-learning/
感谢阅读。
看得不过瘾?你可以在下面链接中查看我对深度学习最全面,最简单的介绍。
附链接:https://towardsdatascience.com/why-deep-learning-works-289f17cab01a
原文标题:
This Is How Reinforcement Learning Works
原文链接:
https://towardsdatascience.com/this-is-how-reinforcement-learning-works-5080b3a335d6
编辑:王菁
译者简介
王琦,中国科学院大学研一在读,研究方向是机器学习与数据挖掘。喜欢探索新事物,是一个热爱学习的人。
— 完 —
关注清华-青岛数据科学研究院官方微信公众平台“THU数据派”及姊妹号“数据派THU”获取更多讲座福利及优质内容。
— 完 —
关注清华-青岛数据科学研究院官方微信公众平台“THU数据派”及姊妹号“数据派THU”获取更多讲座福利及优质内容。