本章介绍
- 利用策略梯度学习来提升游戏对弈水平
- 使用Keras实现策略梯度学习
- 为策略梯度学习改变优化器
第9章向您展示了如何让一个下围棋的程序和自己对弈,并把结果保存在经验数据中这是强化学习的前半部分;下一步是运用经验数据来提升代理水平,以便让它可以更经常地获胜。来自上一章的代理使用神经网络来选择落子。作为一个思维实验,想象一下你随机改变神经网络的每个权重,然后代理将选择不同的落子。只要运气好,这些新落子中的一些会比旧落子更好;而另一些则会更糟。最终平衡下来,最新的代理可能会比以前的版本稍微强一点或弱一点。它走哪条路都是随机的。
你能改进一下吗?本章涵盖策略梯度学习的一种形式。为了使AI能更好地做任务,策略梯度方法提供了一组往哪个方向改变权重的方案。与随机改变权重不同,你可以分析经验数据来猜测是增加还是减少一个特定的权重。随机性仍然在起作用,但策略梯度学习会提高了你的希望。
回想第九章,你做决定依靠的是一个随机梯度----一个指定代理所能做的每一个可能的落子概率的函数。本章所涉及的策略学习方法工作方式就像这样:
- 1 当代理人获胜时,就增加它选择的每一个落子的概率。
- 2.当代理人输掉时,就减少它选择的每一个落子的概率。
首先,您将通过一个简化的示例来说明如何使用这种技术来改进策略,从而可以赢得更多的对局。接下来,您将看到如何使用梯度来做你想要的改变----提升或减少一个特定落子的概率----在一个神经网络中。在管理训练过程中,我们会总结一些实用的小技巧。
10.1 随机的游戏怎么一个决定是否是好的
为了引入策略学习,我们将从一个比围棋简单得多的游戏开始。让我们把这个游戏叫加起来。以下是规则:
- 在每个回合中,每个玩家选择一个介于1到5之间的数字。
- 一百回合以后,每个玩家把他们所选择的所有数字加起来。
- 总数较高的选手获胜。
是的,这意味着最佳策略是在每个回合中都选择5。不,这可能不是一个好游戏。但我们会使用这个游戏来说明策略学习,在这里,您可以根据游戏结果逐步改进随机策略。因为你知道这个游戏的正确策略,所以你可以看到策略是怎样学习从而可以完美地发挥。
加起来是一个简单的游戏,但我们可以用它来类比一个更严肃的游戏,比如围棋。就像在围棋中一样,加起来的游戏也可以玩很长,同一游戏中玩家有很多机会做出好的或错误的选择。为了根据游戏结果更新策略,您需要确定哪些落子应该为赢棋或输棋而受到表扬或指责。这是称为信度分配问题(credit assignment problem),这是强化学习的核心问题之一。本节就演示了如何平均许多游戏结果来分配信度给单个决定。在第12章中,您将在此技术的基础上创建一个更复杂和健壮的信度分配算法。
让我们从一个纯随机策略开始,在该策略中您在相同概率下从五个选项中选择(这样的政策叫做统一随机)。在一场完整的游戏中,你会期望政策选择1大约20次,2大约20次,3大约20次,等等。但你不会期望1正好出现20次;它将因游戏而异。下面的列表显示了一个Python函数,它模拟了一个代理将在游戏中所做的所有选择。图10.1显示了一些示例运行的结果;您可以尝试自己的代码片段几次,然后查看。
import numpy as np
count = {1:0,2:0,3:0,4:0,5:0}
for i in range(100):
choice = np.random.choice([1,2,3,4,5])
count[choice]+=1
print(count)
即使代理在每个游戏中都遵循完全相同的策略,策略的随机性也会导致游戏间的差异,而你可以利用这种差异来改进策略。
下面就显示了一个函数,它模拟了一个完整的加起来游戏,跟踪每个玩家做出的决定,并计算出赢家。
import numpy as np
class GameResult:
def __init__(self,winner_choice,losing_choice):
self.winner_choice = winner_choice;
self.losing_choice = losing_choice;
def show(self):
return (self.winner_choice,self.losing_choice)
def simulate_game(policy):
print("policy:"+str(policy))
player1_count = {1:0,2:0,3:0,4:0,5:0}
player1_total = 0
player2_count = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
player2_total = 0
for i in range(100):
player1_choice = np.random.choice([1,2,3,4,5],p=policy)
player1_count[player1_choice]+=1
player1_total+=player1_choice
player2_choice = np.random.choice([1, 2, 3, 4, 5], p=policy)
player2_count[player2_choice] += 1
player2_total += player2_choice
print("player1:"+str(player1_total))
print("player2:"+str(player2_total))
if player1_total>player2_total:
return GameResult(player1_count,player2_count)
else:
return GameResult(player2_count,player1_count)
print(stimulate_game([0.2,0.2,0.2,0.2,0.2]).show())
运行几次并查看结果;列表10.3显示了一些示例运行。通常情况下,获胜者会少选1,但并不总是这样。有时获胜者会多选5,但同样不能保证