本章包括:

  • 利用优势使强化学习更有效率
  • 用actor-critic方法来实现自我提升AI
  • 设计和训练Keras的多输出神经网络

如果你正在学习下围棋,最好的改进方法之一是让一个水平更高的棋手给你复盘。有时候,最有用的反馈只是指出你在哪里赢棋或输棋。复盘的人可能会给出这样的评论,“你下了30步后已经远远落后了”或“在下了110步后,你有一个获胜的局面,但你的对手在130时扭转了局面。”

为什么这种反馈是有帮助的?你可能没有时间仔细检查一个对局中的所有300个落子,但你可以把全部注意力集中在10或20个落子序列上。复盘的人可以让你知道对局中的哪些部分是重要的。

强化学习研究人员将这一原则应用于actor-critic学习,它是策略学习(如第10章所述)和价值学习(如第11章所述)的结合。策略函数在其中扮演着演员的角色:它选择要下的落子点。价值函数在其中是批评家:它跟踪代理在游戏过程中是领先还是落后。这种反馈指导着训练过程,就像游戏复盘一样指导你的学习。

本章描述了如何用actor-critic学习来做自我提升的游戏AI。让其工作的核心概念就是优势(advantage),时实际游戏结果和预期结果之间的区别。我们首先要说明怎样让优势去改进训练过程。在那之后,我们准备构建一个actor-critic游戏AI。首先,我们将展示如何实现落子选择,然后我们要实现新的训练过程。在这两个函数中,我们大量借鉴了第10章和11章中的代码示例,最终的结果是最好的:它将策略学习和价值学习的好处结合成一个代理。

12.1 advantage 教你哪个决策是重要的

在第十章中,我们简要提到了信度分配问题。假设你的学习代理下了一个200步的对局,最终取胜。因为它赢了,你可以假设它是至少选择了一些好的落子点,但它可能也选择了一些不好的落子点。信度分配没有把你想要强化的好落子和你想要忽视的坏落子分开。本节介绍了优势的概念,这是一个估计某一特定决策对最终结果贡献的公式。首先,我们描述了优势如何帮助信度分配;然后我们提供代码样本来说明如何去计算。

12.1.1. 什么是advantage?

想象一下,你正在看一场篮球比赛;当第四节快结束的时候,你最喜欢的球员却投出了一个三分球。你有多兴奋是取决于游戏状态的。如果分数是80比78,你可能要从座位上跳起来,而如果分数是110比80,你就会无动于衷。这有什么区别?在一场快结束的比赛中,三分球造成了游戏预期结果的巨大变化。另一方面,如果游戏是一种吊打的局面,那一个单独的动作不会影响任何的结果。当游戏结果还未定时,这时的动作是最重要的。在强化学习方面,advantage就是一个量化这一概念的公式。

为了计算advantage,您首先需要对状态的价值进行估计,我们将其表示为V(s)。这是代理将要看到的预期回报,给出一个特定状态s下的已经做到的地方。在游戏中,你可以认为V(s)可以指示当前局面对黑方有利还是白方有利。如果V(s)接近于1,就说明当前局面非常有利;如果V(s)接近于-1,你的代理人就会输棋。

如果你回忆起上一章中的action-value函数Q(s,a),可以知道这个概念是相似的。不同之处在于V(s)表示在你选择落子之前,棋局是多么有利;Q(s,a)表示在你选择落子之后棋局是多么有利。

优势的定义通常规定如下:

A=Q(s,a)-V(s)

可以这样思考这个公式:如果你处于一个好的状态(也就是说,V(S)是高的),但你下了一个差的落子(也就是说Q(s,a)是低的),此时计算是负的,因此你的优势就会消失。然而,这个公式的问题是,你不知道如何去计算Q(s,a)。但你可以认为你在游戏结束时得到的回报就是对真实Q的无偏估计。所以你可以在得到你的回报R后再估计优势,公式如下:

A=R-V(S)

这是你将在本章中用来估计优势的公式。让我们看看这个值是怎样用的。

为了说明目的,你会假装你已经有了一个准确的方法来估计V(s)。实际上,你的代理人会同时学习价值估计函数和策略函数。下一节将要介绍这是如何运作的。

让我们来举几个例子:

  • 在游戏开始时,V(s)=0:两个棋手有着近乎相同的机会。假设你的代理赢了比赛,那么它的回报将是1,所以它第一次移动的优势是1-0=1。
  • 想象一下游戏快结束了,你的代理几乎要锁定胜局了,假定V(S)=0.95。如果你的代理赢得对局,那么优势就是1-0.95=0.05。
  • 现在想象一下你的代理有另一个获胜的局面,其中再次出现V(S)=0.95。但在这个游戏中,你的AI不知何故输掉了对局,给了它一个回报-1,那么这时advantage就是-1-0.95=-1.95

图12.1和12.2说明了假想游戏的优势计算。在这个游戏中,你的学习代理在前几步慢慢领先;然后它犯了一些大错误,然后一路落后直到快要输棋。在150步落子之前的某个地方,它突然设法逆转了比赛,最终获得了胜利。在第10章的策略梯度技术下,游戏中每一步的权重都是相等的。在actor-critic学习中,你想找到最重要的落子并给予它们更大的权重。

 图12.1 假定游戏过程中的估计价值。这场比赛持续了200步。起初,学习AI稍微领先,然后它远远落后,然后它突然停止落后逆转了比赛,取得了胜利

由于学习AI获胜,利用A(s)=1-V(s)公式可以计算出优势。在图12.2中,您可以看到优势曲线与估值曲线具有相同的形状,但是做了翻转。最大的优势来自于代理人远远落后的时候,因为大多数棋手在如此糟糕的情况下都会输,所以AI一定在某个地方做了一个很好的落子。

图12.2  一个假设游戏中每个落子的优势。学习代理赢了这场比赛,所以它的最后回报是1,导致恢复局势的落子有接近2的优势,所以他们会在训练期间得到有力的加强。在比赛结束时,当比赛结果已经决定时,他们的优势就接近0,所以他们在训练中几乎会被忽略。 

在代理已经扭转局面到先前时,大约下了160步左右,它的决策已不再有趣:游戏已经结束了,这时的优势就接近于0。

本章稍后,我们就展示了如何根据优势调整训练过程。在此之前,你需要通过你的自我对弈过程来计算和存储优势。

12.1.2. 在自我对弈中计算优势

为了计算优势,您将更新您在第9章中定义的ExperienceCollector。最初,一个ExperienceBuffer跟踪三个并行数组:states、actions和rewards。你可以添加第四个并行数组来跟踪优势。要填充此数组,您需要每个状态下的估计值和最终游戏结果。直到游戏结束你才会有后者,所以在中间的时候中,你可以积累估计值,当游戏结束后,你可以把它们转化为优势。

    def __init__(self):self.states = []self.actions = []self.rewards = []self.advantages = []self.current_episode_states = []self.current_episode_actions = []self.current_episode_estimated_values = [] # 存当前局的所有估值

同样,您需要更新record_decision方法以接受估计值、状态和操作。

    # 记录当前的决定和行动def record_decision(self, state, action, estimated_value):self.current_episode_states.append(state)self.current_episode_actions.append(action)self.current_episode_estimated_values.append(estimated_value)

然后,在complete_episode方法中,您就可以计算代理所做的每个决策的优势。

    def complete_episode(self, reward):num_states = len(self.current_episode_states)# +=用在列表表示连接列表self.states += self.current_episode_statesself.actions += self.current_episode_actions# 给游戏中从episode开始到结束时的每一个动作都分配最后的回报(赢是1,输是-1)self.rewards += [reward for _ in range(num_states)]#计算优势,利用R-V(s)for i in range(num_states):advantage = reward-self.current_episode_estimated_values[i]self.advantages.append(advantage)#一局结束后重置self.current_episode_states = []self.current_episode_actions = []self.current_episode_estimated_values = []

您还需要更新ExperienceBuffer类和combine_Experience来处理这些优点。

class ExperienceBuffer:def __init__(self, states, actions, rewards,advantages):self.states = statesself.actions = actionsself.rewards = rewardsself.advantages = advantages# 序列化经验文件def serialize(self, h5file):h5file.create_group('experienceData')h5file['experienceData'].create_dataset('states', data=self.states)h5file['experienceData'].create_dataset('actions', data=self.actions)h5file['experienceData'].create_dataset('rewards', data=self.rewards)h5file['experienceData'].create_dataset('advantages', data=self.advantages)def combine_experience(collectors):combined_states = np.concatenate([np.array(c.states) for c in collectors])combined_actions = np.concatenate([np.array(c.actions) for c in collectors])combined_rewards = np.concatenate([np.array(c.rewards) for c in collectors])combined_advantages = np.concatenate([np.array(c.advantages) for c in collectors])return ExperienceBuffer(combined_states,combined_actions,combined_rewards,combined_advantages)# 加载经验文件
def load_experience(h5file):return ExperienceBuffer(states=np.array(h5file['experienceData']['states']),actions=np.array(h5file['experienceData']['actions']),rewards=np.array(h5file['experienceData']['rewards']),advantages=np.array(h5file['experienceData']['advantages']))

您的experience类现在已经准备好跟踪优势。您仍然可以不依赖优势去使用这些类;在训练时只需忽略优势缓冲区的内容即可

12.2.设计一种actor-critic学习神经网络

第11章介绍了如何在Keras中定义一个具有双输入的神经网络。这个Q-learning网络一个输入是棋盘,一个输入是建议落子。对于actor-critic来说,你想要学习一个输入和两个输出的网络。这个输入是棋盘状态的表示。一个输出是落子的概率分布,另一个输出表示当前局面的预测返回---点评。

建立一个具有两个输出的网络会带来一个令人惊讶的好处:每个输出在另一个输出上充当一种规范化。(回顾第6章,规范化技术是防止训练时您的模型过度拟合的确切数据集)。想象一下,棋盘上的一串棋子有被吃掉的危险。这个事实与价值输出有关,因为拥有弱棋子的玩家可能落后了。它也与落子输出相关,因为你可能想要攻击或防御薄弱的棋子。如果您的网络在早期层学习“弱棋子”检测器,那就会与两个输出都相关。对这两个输出训练迫使网络学习一个对两个目标都有用的表示。这往往可以提高泛化能力,有时甚至可以加快训练速度。

第11章介绍了Keras函数API,它使您有充分的自由在您的网络中连接层。您将在这里再次使用它来构建图12.3中描述的网络;此代码将在init_ac_agent.py脚本中进行。

from keras.models import Model
from keras.layers import Conv2D,Flatten,Dense,ZeroPadding2D,Input
from dlgo.Encoder.ElevenPlaneEncoder import ElevenPlaneEncoder
from dlgo.agent.ReinforcementLearning.ACAgent import ACAgentboard_size = 19
encoder = ElevenPlaneEncoder(board_size)
board_input = Input(encoder.shape(),name="board_input")
action_input = Input(encoder.num_points(),name="action_input")conv1 = Conv2D(64, (3, 3), padding='same', activation='relu')(board_input)
conv2 = Conv2D(64, (3, 3), padding='same', activation='relu')(conv1)
conv3 = Conv2D(64, (3, 3), padding='same', activation='relu')(conv2)# 此示例使用大小为512的隐藏层。实验寻找最佳尺寸,这三个隐藏层不需要是相同的大小。
flat= Flatten()(conv3)
processed_board = Dense(512)(flat)# 策略输出
policy_hidden_layer = Dense(512, activation='relu')(processed_board)
policy_output = Dense(encoder.num_points(), activation='softmax')(policy_hidden_layer)# 价值输出
value_hidden_layer = Dense(512, activation='relu')(processed_board)
value_output = Dense(1, activation='tanh')(value_hidden_layer)model = Model(inputs=board_input,outputs=[policy_output,value_output])agent = ACAgent(model,encoder)
initial_agent_filename = "initial_acAgent.h5"with open(initial_agent_filename,"w") as out_file:agent.serialize(out_file)

图12.3  适合actor-critic学习的神经网络。这个网络有一个单一的输入,它表示当前的棋局。网络产生两个输出:一个输出指示哪些棋子应该下,这是策略输出,或者叫演员。另一个输出指示哪个棋手在游戏中处于领先,这是价值输出,或者称为评论家。评论家不用于下棋,但可以在训练过程起到帮助。

这个网络有三个卷积层,每个有64个过滤器。这是针对一个较小尺寸的棋盘,但有优势。一如既往,我们鼓励你尝试不同的网络结构。

策略输出表示可能落子的概率分布。维度等于棋盘上的交叉点数,您可以使用softmax激活函数,以确保策略总和为1。

价值输出是-1到1范围内的一个数字。此输出具有维度1,您可以使用tanh激活函数来限制该值的范围。

12.3 和一个actor-critic代理进行对局

选择落子几乎与第10章中的策略代理完全相同。你做了两个改变。首先,由于模型现在产生两个输出,所以需要一些额外的代码来解压缩结果。第二,您需要将估计价值传递给经验收集器,当然还有状态和行动。从概率分布中选择落子的过程是相同的。下面就展示了更新的select_move实现。我们已经指出了它与第10章策略代理的实施不同的地方。

 def select_move(self, game_state):num_moves = self.encoder.board_width * self.encoder.board_heightboard_tensor = self.encoder.encode(game_state)input_tensor = np.array([board_tensor])# 因为这是一个双输出模型,预测返回一个包含两个NumPy矩阵的元组。actions,values = self.model.predict(input_tensor)# 预测是一个批量调用,可以同时处理几个棋盘,因此您必须选择矩阵的第一个元素来获得您想要的概率分布。move_probs = actions[0]# 价值被表示为一维向量,因此必须拉出第一个元素以获得作为普通浮点数estimated_value = values[0][0]# 裁剪概率分布move_probs = self.clip_probs(move_probs)# 把概率转成一个排序列表(0-360)candidates = np.arange(num_moves)# 按照落子概率进行采样,不允许取相同的落子ranked_moves = np.random.choice(candidates, num_moves, replace=False, p=move_probs)# 从最高层开始,找到一个有效的落子,不会减少视野空间for point_index in ranked_moves:point = self.encoder.decode_point_index(point_index)if game_state.is_valid(goboard.Move.play(point)) and \not is_point_true_eye(game_state.board, point, game_state.current_player):# 当它选择到了合法落子时,将决定通知给收集器,多了估计值if self.collector is not None:self.collector.record_decision(state=board_tensor,action=point_index,estimated_value = estimated_value)return goboard.Move.play(point)return goboard.Move.pass_turn()

12.4 用经验数据训练actor-critic代理

训练你的actor-critic网络看起来就像是第十章中训练策略网络和第十一章中训练actor-value网络的组合。为了训练一个双输出网络,你为每个输出分别设立了训练目标,并为每个输出分别选择了一个损失函数。本节就介绍如何将经验数据转换为训练目标,以及如何使用Keras的FIT函数用于多输出。

回想一下如何编码策略梯度学习的训练数据。对于任何的游戏局面,训练目标是一个与棋盘相同大小的向量,-1或1对应于选择的落子;1表示赢,-1表示输。在你的actor-critic学习中,你将使用对训练数据使用相同的编码方案,但是你1或-1替换为棋子的优势。优势将具有与最终回报相同的符号,因此游戏决策的概率将向与简单策略学习相同的方向移动。但它会更进一步去做那些被认为很重要的行动,而对于那些优势接近于零的行动只需稍微移动一点

对于价值输出,训练目标是总体的回报。这看起来完全像是Q-learning的训练目标。图12.4说明了训练设置。

图12.4  actor-critic学习的训练设置。神经网络有两个输出:一个用于策略,一个用于价值。每个人都有自己的训练目标。策略产出通过一个与棋盘相同大小的向量训练。向量单元格中与所选落子点对应的地方被填充为该落子点计算的优势;其余为零。价值输出是反映比赛的最终结果。

当您在一个网络中有多个输出时,您可以为每个输出选择不同的损失函数。策略输出将使用分类交叉熵损失函数,价值输出采用均方误差损失函数(请参阅第10章和第11章,解释为何这些损失函数对这些目标有意义)。

你将要使用的一个新的Keras特征是损失权重。默认情况下,Keras会将把每个输出的损失函数加起来得到整体的损失函数。如果您指定损失权重,Keras将在求和之前会缩放每个单独的损失函数,这样可以允许你调整每个输出的相关性。在我们的实验中,我们发现与策略损失相比,价值损失比较多,所以我们将价值损失缩小了一半。根据你的确切网络和训练数据,你可能需要稍微调整一下损失权重。

每当你调用fit时,Keras都会打印出计算的损失值。对于双输出网络,它将分别打印出这两个损失。你可以查看大小是否可比。如果一个损失远大于另一个损失,请考虑调整权重,别担心变得太精确。

下面的列表显示了如何将经验数据编码为训练数据,然后调用fit在这个训练目标上。该结构类似于第10章和第11章中的训练实现。

既然你已经拥有了所有的片段,让我们端到端地尝试actor-critic学习。你将从一个9×9机器人开始,这样你就可以快速地看到结果。循环就会这样进行:

  1. 在游戏中生成自我对弈游戏块5000局。
  2. 在每局之后,训练代理并将其与之前版本的AI进行比较。
  3. 如果新的AI能在100场比赛中击败之前的机器人60场,那么你就已经成功地改进了你的代理。请开始这个过程
  4. 如果新的AI不能在100场比赛中击败之前的机器人60场,那么请生成新的自我对弈数据,并再次训练。持续训练直到新的AI足够强大

在100场中,更新的AI获得60场获胜的基准有点武断;但这是一个很好的轮数,让你有合理的信心任务你的机器人真的更强大,而不仅仅是幸运。

请开始使用init_ac_agent脚本来初始化机器人(如清单12.5所示):

from dlgo.agent.FastRandomAgent.goboard_fast import GameState, Player
from dlgo.agent.ReinforcementLearning.ExperienceCollector import ExperienceCollector
from dlgo.utils import print_board
from dlgo.ComputeWinner import compute_game_result
from dlgo.agent.ReinforcementLearning.ExperienceCollector import combine_experience
from collections import namedtuple
from dlgo.agent.ReinforcementLearning.ACAgent.ACAgent import load_policy_agent
import h5pyclass GameRecord(namedtuple('GameRecord', 'moves winner margin')):passdef simulate_game(black_player, white_player,board_size):moves = []game = GameState.new_game(board_size)agents = {Player.black: black_player,Player.white: white_player,}while not game.is_over():next_move = agents[game.current_player].select_move(game)moves.append(next_move)game = game.apply_move(next_move)print_board(game.board)game_result = compute_game_result(game)print(game_result)return GameRecord(moves=moves,winner=game_result.winner,margin=game_result.winning_margin,)def main():board_size = 9num_games = 5000experience_filename = "exp_9_0001.h5"agent1 = load_policy_agent(h5py.File("initial_acAgent_9.h5"))agent2 = load_policy_agent(h5py.File("initial_acAgent_9.h5"))collector1 = ExperienceCollector()collector2 = ExperienceCollector()agent1.set_collector(collector1)agent2.set_collector(collector2)# 开始模拟对局for i in range(num_games):print("开始模拟对局%d/%d" %(i+1,num_games))collector1.begin_episode()collector2.begin_episode()game_record = simulate_game(agent1,agent2,board_size)# 黑棋赢了给第一个AI回报1,给第二个AI回报-1if game_record.winner == Player.black:collector1.complete_episode(reward=1)collector2.complete_episode(reward=-1)# 白棋赢了给第一个AI回报-1,给第二个AI回报1else:collector1.complete_episode(reward=-1)collector2.complete_episode(reward=1)experience = combine_experience([collector1, collector2])with h5py.File(experience_filename, 'w') as experience_outf:experience.serialize(experience_outf)if __name__ == '__main__':main()

在此之后,您应该有一个exp_0001.hdf5文件,其中包含一大块游戏记录。下一步是训练:

这将使用当前存储在ac_v1.hdf1中的神经网络,对exp_0001.hdf中的数据运行一个单一的训练,并将更新的代理保存到ac_v2.hdf5中。优化器将使用0.01的学习率,1024的训练集大小。你应该看到输出这样的东西:

Epoch 1/1 574234/574234 [==============================] ­ 15s 26us/step ­ loss: 1.0277 ­ dense_3_loss: 0.6403 ­ dense_5_loss: 0.7750

请注意,损失现在分为两个值:dense_3_loss和dense_5_loss,分别对应于策略输出和价值输出。

与早期版本对局100局,结果如下

... Simulating game 100/100...
9 oooxxxxx.
8 .oox.xxxx
7 ooxxxxxxx
6 .oxx.xxxx
5 oooxxx.xx
4 o.ox.xx.x
3 ooxxxxxxx
2 ooxx.xxxx
1 oxxxxxxx.ABCDEFGHJ
B+31.5
Agent 1 record: 60/100

在这种情况下,输出显示您准确地实现了100场中获得60场胜利的阈值:您可以有合理的信心相信您的机器人已经学到了一些有用的东西。(这只是一个例子,与你的实际结果会有点不同,这很好。因为ac_v2bot比ac_v1强得多,所以您可以使用ac_v2去生成游戏,然后再次进行训练和评估,这次情况不像之前那么成功。

Agent 1 record: 51/100

ac_v3机器人在100次中只击败了ac_v2机器人51次。有了这些结果,很难说ac_v3是否更强一点;最保险的结论是,它与ac_v2水平差不多,但不要绝望。您可以生成更多的训练数据,然后再试一次:

每增加一批游戏数据后,您可以再次与ac_v2进行对局。在我们的实验中,我们需要三批5000局对局-总共15000个对局-然后才能得到令人满意的结果。

Agent 1 record: 62/100

成功!战胜ac_v262场,现在你可以说ac_v3比ac_v2强。然后,你就可以切换到ac_v3去生成自我对弈游戏,然后再次重复这个循环过程。

虽然我们不是很清楚一个围棋机器人可以通过actor-critic得到多强的能力,但我们我们已经证明,你可以训练一个机器人来学习基本的战术,但它的力量一定会在某一时刻达到顶峰。通过将强化学习与树搜索进行深度整合,你可以训练一个AI让它比任何人类棋手更强,14章就展示了这个技术。

12.5 总结

  • actor-critic学习是一种强化学习技术,在这种技术中,你可以同时学习策略函数和价值函数。策略函数告诉你应该如何做决定,以及价值函数有助于改进训练过程。你可以将actor-critic学习应用于与策略梯度学习同样类型的问题,但是actor-critic学习通常更稳定。
  • 优势是一个代理人看到的实际回报和预期回报之间的差别。对于游戏来说,这就是游戏实际结果(输或赢)和期望值(由代理的价值模型估计)的差别。
  • 优势有助于识别游戏中的重要决策。如果一个学习代理人赢了一场比赛,那么当比赛快输的时候,所做的优势是最大的,而当比赛已经决定后,所做的动作优势的最小。
  • 一个Keras顺序网络可以有多个输出。在actor-critic学习中,这可以让您创建一个单一的网络来建模策略函数和价值函数。

翻译Deep Learning and the Game of Go(14)第十二章 采用actor-critic方法的强化学习相关推荐

  1. [论文翻译] Deep Learning

    [论文翻译] Deep Learning 论文题目:Deep Learning 论文来源:Deep learning Nature 2015 翻译人:BDML@CQUT实验室 Deep learnin ...

  2. 李弘毅机器学习笔记:第十二章—Recipe of Deep Learning

    李弘毅机器学习笔记:第十二章-Recipe of Deep Learning 神经网络的表现 如何改进神经网络? 新的激活函数 梯度消失 怎么样去解决梯度消失? Adaptive Learning R ...

  3. Gradle 2.0 用户指南翻译——第二十二章. 标准的 Gradle 插件

    翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc 本文翻译所在分支: https://github.com/msdx/gradledoc/tre ...

  4. [论文翻译]Deep Learning 翻译及阅读笔记

    论文题目:Deep Learning 论文来源:Deep Learning_2015_Nature 翻译人:BDML@CQUT实验室 Deep Learning Yann LeCun∗ Yoshua ...

  5. [论文翻译]Deep learning

    [论文翻译]Deep learning 论文题目:Deep Learning 论文来源:Deep Learning_2015_Nature 翻译人:BDML@CQUT实验室 Deep learning ...

  6. 文献翻译 Deep Learning

    该篇文章为18年图灵奖得主,被誉为"深度学习之父"的Lecun.Bengio.Hinton三位业界巨擘共同发表在Nature上的关于深度学习的综述,DOI:10.1038/natu ...

  7. 翻译Deep Learning and the Game of Go(2)第1章:面向深度学习

    第1章:面向深度学习 本章内容包括: 机器学习及其与传统编程的区别 机器学习无法解决的问题 机器学习与人工智能的关系 机器学习系统的结构 机器学习学科 只要存在计算机,程序员就对人工智能(AI)感兴趣 ...

  8. 翻译Deep Learning and the Game of Go(10)第八章:部署你的AI

    本章包括: 构建一个端到端的应用程序来训练和运行一个围棋机器人 在前端运行来对抗你的机器人 让你的机器人在本地与其他机器人对抗. 部署到在线围棋服务器 到目前为止,你已经知道如何为围棋落子预测去构建和 ...

  9. 翻译Deep Learning and the Game of Go(10)第七章:从数据中学习:一个深度学习AI

    本章包括 下载和处理实际的围棋游戏记录 了解存储围棋游戏的标准格式 训练一个使用这样的数据进行落子预测的深度学习模型 运行自己的实验并评估它们 在前一章中,您看到了构建深度学习应用程序的许多基本要素, ...

最新文章

  1. 采访Jesús Fernandes(QA主管)
  2. 动态规划实现斐波那契数列求解
  3. 【产品】腾讯内部的顶级产品课:灵动在细节
  4. 【人物】养车点点费岸:给O2O产品经理的四点意见
  5. java map按照value排序_基础:Java集合需要注意的 5 个问题
  6. Linux 启动失败 磁盘阵列,组建RAID5重启系统,出现md127的解决办法
  7. MFC中CString.Format的详细用法
  8. Windows Phone 模拟器 (WPR Alpha 0.0.1 WP7/8模拟器) XAP XNA文件使用教程
  9. linux sqluldr2命令,sqluldr2 linux64
  10. 层次分析法(AHP)详细步骤
  11. Git 合并单个文件
  12. 图扑软件数字孪生 SMT 产线,智能工业可视化管理
  13. JIRA统计工时,我们用Tempo
  14. 怎么添加校园邮箱到Outlook?
  15. 【模型 6.0】以前的你遇事不知所措,现在的你可以镇定自若,靠它!
  16. ILM --interface logic model
  17. Simulink 3D Animation的使用(V_realm builder2.0)
  18. 思科模拟器出现Translating XXXX...domain server (255.255.255.255) 解决办法
  19. fread函数和fwrite函数详解
  20. 李建忠设计模式——策略模式Strategy

热门文章

  1. codeforces 963B Destruction of a Tree
  2. 路由器的基本配置和单臂路由配置
  3. Word水印为计算机红色水平,2017年9月计算机一级MS Office基础预习题(四)
  4. 医药流通企业如何安全访问医药ERP?无需公网IP和改变现有IT架构
  5. 排序算法总结和java实现
  6. DQN(deep Q-network)算法简述
  7. box-shadow属性分析
  8. linux内核奇遇记之md源代码解读之八阵列同步二
  9. 温州医科大学oracle期末试题,系统解剖学期末复习(温州医科大学)系解试题A卷.doc...
  10. 循环嵌套问题:为什么大循环在内,小循环在外可以提高程序的运行效率