我们在学习过程中离开不了老师的指导,老师除了传授知识外,另外一个很重要的作用是指出问题。我们或多或少有这样的经验,在训练某种技能时一开始进步很快,但不久就进入瓶颈期,这段时期无论你做什么都很难产生明显的突破。此时如果有个水平较高,经验老到的老师给你指条出路,或是告诉你哪一步做出了,你根据它的指导去践行后,水平又会出现新的提升。

本节我们就要把这种‘高手指点’的效应引入到围棋机器人的训练过程中从而提升机器人的训练效果。在前面章节说到基于政策的训练算法时,我们先让两个机器人自我对弈,假设下了200步棋后机器人A获得了胜利,然后我们会把A下的200步棋和对应的棋盘状况收集起来作为训练数据,把棋盘当做输入,把每一步落子当做结果,训练网络在给定棋盘状况时,学会按照给定结果去落子。这种方法其实是告诉网络说,这200步落子方式都是好走法,事实上这200步落子中,可能只有十几步是好棋,其他的都是臭棋,因此以前的训练方法实际上会让网络把某些臭棋当做好棋来学习。

本节我们要引入一个”高手“,它会告诉网络这200步棋中,哪几步是好棋,哪几步是坏棋,这样的话网络在训练时就不会被坏棋误导,从而得到更好的训练效果。本节我们要找到一种算法,它能评估那200步棋的好坏,从而将里面的好棋和坏棋区分开来。

我们如何评估一步走法的好坏呢。设想你最喜欢的NBA球员是库里,比赛到了第四节快结束时库里投了一个三分球,那么他这次投篮成功价值有好呢?这取决于当前比分状况,如果库里所在球队与对手的差距在命中前是77比78,命中后变成80比78,那么这记三分球就非常重要,如果此时比分是77比110,那么这记三分球就显得无足轻重,所以这记三分球的重要程度取决于当前局面的具体情况。

同样的道理,一步棋是好是坏也取决于当前的棋盘状况。因此我们需要先对当前局面进行评估,假设s代表当前棋盘,我们有一个函数V,V(s)返回当前棋盘对机器人A的有利程度,V(s)的值越接近1表明情况对机器人A越有利,越接近-1表明棋盘对机器人A越不利。这个函数与前几节的评估函数Q(s,a)很像,不同在于V(s)评估行动前局面的好坏,Q(s,a)评估采取行动后局面的好坏。

于是我们评估一步棋是好是坏时可以这么计算A = Q(s,a) - V(s)。数值A表示机器人落子后所获得的优势,如果原来局面有利,但走了一步臭棋,A的值变小,也就是局面相比于原来变得不利了,这时A是负值。问题在于Q(s,a)如何计算,如果对弈200步后机器人A获得了胜利,那么s对应着两百步棋的棋盘,a对应200步走法,那么我们直接将Q(s,a)设置为1,如果最终输了,我们就将Q(s,a)设置成-1.

当然此时我们也不知道如何计算V(s),但我们可以用网络训练处准确评估V(s)的能力。我们看一个具体例子,在一开局时s对应空棋盘,所以V(s)=0,它表示当前局面对机器人A没有好处,当然也没有坏处。直到下完200步后,如果机器人A输了,由此A下完第一步棋后,对应的Q(s,a)=-1,于是我们得出A=-1-0=-1,由此认为在空棋盘状况下,第一步落子让机器人A处于非常不利的局面

假设在对弈快结束时,V(s)对棋盘进行评估后的值是0.95,最后机器人A赢了,那么机器人A在给定棋盘上落子后的得分Q(s,a)就设定为1,于是得出它落子后收获的优势A=1-0.95=0.05。如果A最后输了,那么在给定棋盘上A落子后收获的优势就是A=-1-0.95=-1.95。通过对当前棋盘状况的评估,在结合落子后的结果,我们就可以从数值上判断这步棋的好坏。

现在问题是,我们如何计算数值A,我们通过代码实现来讲解它的计算过程。我们前面几节曾经使用一个类ExperienceCollector来记录机器人对弈的信息。如果机器人A走了200步棋,那么该类就会记录200步棋的走法,以及每步棋落子时对应的棋盘以及最后的胜负结果,这里我们需要让它增加记录一种信息,也就是V(s),记录当前棋盘对机器人A的好坏,相关修改如下:

class  ExperienceCollector:def  __init__(self):self.states = []  #记录每一步棋对应的棋盘self.actions = []  #记录每一步落子self.rewards = []  #记录最终结果self.advatanges = []  #记录棋盘对应机器人的好坏self._current_episode_states = []  #记录当前对弈所产生的棋盘状况self._current_episode_actions = []  #记录当前对弈过程每一步落子self._current_episode_estimaged_values = [] #记录当前对弈过程所产生棋盘状况对机器人的有利程度

相比于以前的代码,我们增加了棋盘局面对机器人优劣的评估信息。在对弈过程中,每次落子,该类就得记录相应信息,代码如下:

def  record_decision(self, state, action, estimated_value = 0):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):  #如果胜利reward的值为1,失败则值为-1num_states = len(self._current_episode_states)self.states += self._current_episode_statesself.actions += self._current_episode_actionsself.rewards += [reward for _ in range(num_states)]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 = []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_advatages = np.concatenate([np.array(c.advantages) for c in collectors])return ExperienceBuffer(combined_states, combined_actions,combined_rewards, combined_advantages)

现在问题是,我们如何计算V(s)呢,此时我们需要训练一个神经网络来完成这个功能。这个网络的输入时当前棋盘状态,它将输出两个结果,一个是当前所有可落子方式的胜率评估,一个是当前棋盘对应的期望收益。接着我们看看网络的代码设计:

from keras import Model
from keras.layers import Conv2D, Dense, Flatten, Inputboard_input = Input(shape=encoder.shape(), name = 'board_input')
conv1 = Conv2D(64, (3, 3), padding = 'same', activation = 'relu')(board_input)
conv2 = Con2D(64, (3,3), padding = 'same', activation = 'relu')(conv1)
conv3 = Conv2D(64, (3, 3), padding = 'same', activation = 'relu')(conv2)
flat = Flatten()(conv3)
processed_board = Dense(512)(flat)
policy_hidden_layer = Dense(512, activation = 'relu')(processed_board)
policy_output = Dense(encoder.num_poits(), activation = 'softmax')(policy_hidden_layer) #给出每个落子位置的赢率
value_hidden_layer = Dense(512, activation = 'relu')(processed_board)
value_output = Dense(1, activation = 'tanh')(value_hidden_layer) #给出当前棋盘形势优劣的评估也就是V(s)
model = Model(inputs = board_input, outputs = (policy_output, value_output))

代码构造的网络会使用三个卷积层对棋盘进行扫描,最后给出两个结果,一个是当前棋盘下所有可以落子位置的赢率,第二个是当前棋盘对机器人优劣的量化评估,这里我们可以看到,当我们想计算某个数值,但又不知道如何以明确的方式或没有具体步骤或算法去计算时,我们就通过神经网络来完成对数值的评估,上面网络形成的结构如下:

接着我们看看机器人如何使用这个网络来决定落子位置:

class  ACAgent(Agent):def  select_move(self, game_state):num_moves = self.encoder.board_width * self.encoder.board_heightboard_tensor = self.encoder.encode(game_state)X = np.array([board_tensor])actions, values = self.model.predict(X) #根据当前棋盘评估落子赢率以及评估棋盘对本机器人的优劣mov_probs = actions[0] #获得所有可落子位置的赢率estimated_value = values[0][0] #获得棋盘优劣的评估值eps = 1e-6move_probs = np.clip(move_probs, eps, 1 - eps) #将概率过大或过下的落子位置忽略掉move_probs = move_probs / np.sum(move_probs)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_idx)move = goboard.Move.play(point)move_is_valid = game_state.is_valid_move(move)fills_own_eye = is_point_an_eye(game_state.board, point, game_state.next_player)if move_is_valid and not fills_own_eye:if self.collector is not None: #记录下当前落子和棋盘状况if self.collector.record_decision(state = board_tensor,action = point_idx,estimated_value = estimated_value):return goboard_Move.play(point)return goboard.Move.pass_turn()

接下来还有一个很重要的问题是,我们如何训练网络,让它知道怎么评估当前棋盘的优劣。假设机器人A下了200步棋,最后赢得胜利,那么我们把200步棋对应的棋盘优势值全部设置成1,然后训练时把棋盘输入网络,让网络调整自己内部参数,以便它自己输出的优劣评估值尽可能接近1,如果机器人A最终输了,那么200步棋对应的棋盘优势值全部设置成-1,于是网络在接收棋盘后,调整内部参数让输出的评估值尽可能接近-1,相应代码如下:

 def  train(self, experience, lr = 0.1, batch_size = 128):opt = SGD(lr = lr)#因为网络有两个输出所有要对两头分别使用不同损失函数self.model.compile(optimizer = opt, loss = ['categorical_crossentropy', 'mse'])#左边输出的重要性是右边的2倍loss_weights = [1.0 , 0.5]n = experience.states.shape[0]num_moves = self.encoder.num_points()policy_target = np.zeros((n, num_moves))value_target = np.zeros((n))for i in range(n):action = experience.action[i]policy_target[i][action] = experience.advantages[i]reward = experience.rewards[i]value_target[i] = rewardself.model.fit(experience.states, [policy_target, value_target],batch_size = batch_size, epochs = 1)

上面所给代码就是本节所说的”高手指点“原理。网络内部参数在训练时受到两个方面影响,一是给定棋盘状态后网络选择的落子位置与棋盘对应的获得胜利的落子位置的差异,二是网络给出的棋盘优劣评估与我们在train函数中设置的棋盘优劣分值差异的影响。在train函数中,我们将所有棋盘的优劣分值设置成1或-1,这取决于网络在对弈时是胜利还是失败。

上面的代码需要足够的算力才能运行,普通电脑不可能训练出合适的网络,因此我们可以通过代码来了解算法原理,在没有GPU算力下,上面的代码依然难以通过运行来得以检验。

更详细的讲解和代码调试演示过程,请点击链接

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:

新书上架,请诸位朋友多多支持:

AlphaGo增强式学习算法:实现‘高手指点’特效相关推荐

  1. 向AlphaGo进化,应用增强式学习技术打造超越人类的围棋机器人

    AlphaGo在与李世石或柯洁对弈过程中有个休息流程.此时人类选手利用这段时间充分放松思维,让自己从上一盘比赛的剧烈思维活动中抽身而出,让身体和思维获得恢复以便再战.但此时AlphaGo并没有休息,而 ...

  2. 2021 增强式学习RL 李宏毅

    到目前为止,我們講的幾乎都是 Supervised Learning.就算是我們在講 Self Supervised Learning 的時候.其实也是很类似Supervised Learning的方 ...

  3. origin中文版散点图拟合曲线_origin中两组数已经画出散点图,如何新增类似于excel中的趋势线?而且是幂函式的,求高手指点...

    origin中两组数已经画出散点图,如何新增类似于excel中的趋势线?而且是幂函式的,求高手指点以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让 ...

  4. 增强式学习:如何使用Q-Learning算法训练围棋机器人

    上一节我们构造出如下结构的神经网络: 本节我们看看如何使用该网络训练围棋机器人.我们在标题中提到Q-Learning,它实际上是一种使用上面网络进行训练的算法流程.首先我们先定义执行Q-Learnin ...

  5. 干货丨 从遗传算法到强化学习,一文介绍五大生物启发式学习算法

    文章来源:机器之心 本文是作者献上的一部「野外纪录片」,介绍了五个直接受大自然启发而产生的人工智能算法:人工神经网络.遗传算法.集群智能.强化学习和人工免疫系统. 在当今技术背景之下,人工智能的发展催 ...

  6. 十种深度学习算法要点及代码解析

    前言 谷歌董事长施密特曾说过:虽然谷歌的无人驾驶汽车和机器人受到了许多媒体关注,但是这家公司真正的未来在于机器学习,一种让计算机更聪明.更个性化的技术. 也许我们生活在人类历史上最关键的时期:从使用大 ...

  7. 十种深度学习算法要点及代码解析(转)

    前言 谷歌董事长施密特曾说过:虽然谷歌的无人驾驶汽车和机器人受到了许多媒体关注,但是这家公司真正的未来在于机器学习,一种让计算机更聪明.更个性化的技术. 也许我们生活在人类历史上最关键的时期:从使用大 ...

  8. 涨知识|最新十种深度学习算法要点及代码解析「精华」

    https://www.toutiao.com/i6634340699275788813/ 2018-12-13 13:10:15 摘要:前言 谷歌董事长施密特曾说过:虽然谷歌的无人驾驶汽车和机器人受 ...

  9. Ensemble_learning 集成学习算法 stacking 算法

    原文:https://herbertmj.wikispaces.com/stacking%E7%AE%97%E6%B3%95 stacked 产生方法是一种截然不同的组合多个模型的方法,它讲的是组合学 ...

  10. 模型精度再被提升,统一跨任务小样本学习算法 UPT 给出解法!

    近日,阿里云机器学习平台PAI与华东师范大学高明教授团队.达摩院机器智能技术NLP团队合作在自然语言处理顶级会议EMNLP2022上发表统一多NLP任务的预训练增强小样本学习算法UPT(Unified ...

最新文章

  1. WMI技术介绍和应用——WMI概述
  2. plotly自定义股票数据绘图
  3. java-多线程安全-锁
  4. java semaphore 等待时间_一个java同步工具类Semaphore的详解
  5. 数据库基础:什么是列?数据类型是什么?
  6. python 异常学习2
  7. android 缓存程序,Android轻量缓存框架--ASimpleCache
  8. unshift向数组添加自定义对象
  9. matlab求解外推法和黄金分割法
  10. Turtle图形绘制(绘制奥运五环)
  11. Python神经网络编程 | 专场送书活动
  12. 员工管理和激励的十个经典故事
  13. SQL 查询当前时间,已经设置时区
  14. java nanotime 转秒_[Java] System.nanoTime()返回结果nanoSeconds和seconds之间的转换
  15. 用计算机制作程序框图,流程图 结构图制作更轻松
  16. 2.整理华子面经--2
  17. 南航大二学生两年手搓火箭成功发射,全靠业余时间上网自学,稚晖君点赞
  18. 爱因斯坦曾出过这样一道数学题:有一条长阶梯,若每步跨2阶,最后剩下1阶;若每步跨3阶,最后剩下2阶;若每步跨5阶,最后剩下4阶;若每步跨6阶,则最后剩下5阶;只有每步跨7阶,最后才正好1阶不剩。参考例
  19. 2022-2028全球与中国盲侧辅助(BSA)市场现状及未来发展趋势
  20. 小羊驼和你一起学习cocos2d-x之六(lua、android.mk)

热门文章

  1. OI生涯回忆录(Part5:至初中竞赛生涯完)
  2. windows10系统下vue开发环境搭建
  3. 机器学习中的数学——激活函数(六):Parametric ReLU(PReLU)函数
  4. Freeimage-3.18.0编译(静态库)
  5. 威纶通触摸屏上传错误_威伦触摸屏程序上传方式
  6. 2020年计算机设计大赛参赛回顾与总结
  7. 从ResNet101到ResNet50
  8. JSP+MySQL基于ssm的物理竞赛管理系统
  9. (附源码)小程序 校园二手交易平台 毕业设计 191637
  10. 很牛的求职经历(转载)