翻译Deep Learning and the Game of Go(8)第六章:给围棋数据设计神经网络(上)

本章介绍如何使用深度学习预测围棋下一步落子,通过树搜索生成训练数据,用Keras构建神经网络。首先,创建Encoder将棋盘局面转换为向量,接着利用MCTS生成训练数据。然后,引入Keras深度学习库,了解其设计原则并安装。最后,展示了使用Keras的初步模型进行落子预测。
摘要由CSDN通过智能技术生成

本章包括(篇幅关系,本文章介绍前两个,后两个放在下个文章)

  • 构建一个深度学习应用程序从数据出发来预测下一步的围棋落子点
  • 引入Keras深度学习框架
  • 了解卷积神经网络
  • 构建分析空间围棋数据的神经网络

在前一章中,您看到了神经网络在行动中的基本原理,并从零开始实现了前馈网络。在本章中,你将把注意力转回到围棋游戏,并可以解决如何使用深度学习技术来预测在给定任何围棋盘面的情况下的下一步落子的问题。特别是,您将使用在第4章中运用的树搜索技术来生成围棋数据,并可以使用这个数据来训练神经网络。图6.1给出了您将在本章中构建的应用程序的概述。

 如图6.1所示,要利用到你上一章的神经网络工作知识,您必须首先解决几个关键步骤:

  1. 在第3章中,你把重点放在实现围棋棋盘上的数据结构,第4章使用这些结构进行树搜索。但在第5章中,你看到了神经网络需要数值的输入;对于你实现的前馈网络,向量是需要的。
  2. 要将围棋棋盘局面转换为向量输入到神经网络中,您必须创建一个Encoder类来完成这项工作。图中6.1,我们勾画了一个简单的编码器,这会在6.1节中实现;围棋棋盘会被编码为一个棋盘大小的矩阵,白色的棋子表示为-1,黑色的棋子表示为1,空点表示为0。其矩阵可以被展开化为向量,就像你在前一章中对MNIST数据集所做的那样。虽然这种表示有点太简单了,不能为落子预测提供出色的结果,但这是朝着正确方向迈出的第一步。在第7章中,您将看到更复杂和更有用的方法来编码棋盘局面。
  3. 要训练一个神经网络来预测下一步落子点,你必须先得到要输入到神经网络的数据。在6.2节中,您将使用第4章的技术来生成游戏记录。您将编码每个棋盘的局面,如刚才讨论的,这将作为您的特征,并将每个局面的下一步存储为标签。
  4. 虽然你在第5章中实现的一个神经网络是有用的,但同样重要的是我们需要获得更多的速度和可靠性,因此我们引入一个更成熟的深度学习库。为此,在第6.3节介绍了Keras,一个用Python编写的流行深度学习库。您将使用Keras来构建预测落子的网络
  5. 在这一点上,你可能会想,为什么你完全放弃了围棋棋盘的空间结构,把编码的棋盘展平到一个向量。在第6.4节中,你将了解到一个新的层类型称为卷积层,它更适合您的用例。您将使用这些层来构建一个名为卷积神经网络的新体系结构。
  6. 本章即将结束时,您将了解更多的现代深度学习的关键概念,这些概念将进一步提高落子预测的准确性,例如在第6.5节或第6.5节中使用Softmax有效地预测概率。在6.6节中建立更深层次的神经网络,并具有一个有趣的激活函数,称为校正线性单元(ReLU)。

6.1.给棋盘局面进行编码

在第三章中,您构建了一个Python类库,该库表示围棋游戏中的所有实体:Player、Board、GameState等。现在您想将机器学习应用于解决围棋中的一些问题。但是神经网络无法不能在像GameState类这样的高级对象上工作;它们只能处理数学对象,比如向量和矩阵。因此在本节中,我们将创建一个Encoder类,该类将你的本地游戏对象转换为数学形式。在本章的其余部分,您可以将该数学形式提供给你的机器学习工具。

建立围棋落子点预测的深度学习模型的第一步是加载可以输入神经网络的数据。通过为围棋棋盘定义一个简单的编码器来做到这一点,这在上图中已经介绍了。编码器是以合适的方式转换您在第3章中实现的围棋棋盘的一种方法。你所学到的神经网络,多层感知器,会作为输入的向量,但在6.4节中,您将看到另一个基于高维数据的网络体系结构。图6.2给出了如何定义这样一个编码器的想法。

 其核心思想就是,编码器必须知道如何编码一个完整的围棋游戏状态。特别是,它应该定义如何在围棋板上对单点进行编码。有时反过来看也很有趣:如果你用网络预测下一步落子,该落子将被编码,您需要将其转换回围棋实际的落子。这个操作叫做解码,对于应用预测落子很重要

考虑到这些,您现在可以定义Encoder类,这是您将在本章和下一章中将要创建的编码器的接口。您将在dlgo中定义一个名为Encoder的新模块。您将使用一个空的__init__.py进行初始化,并将文件base.py放入其中。然后,您将在下面的内容放入到文件中。

# 编码器接口
class Encoder:
    # 允许您支持日志记录或保存你的模型中正在使用的编码器的名称
    def name(self):
        raise NotImplementedError()

    # 把棋盘棋盘转化成数字数据
    def encode(self, game_state):
        raise NotImplementedError()

    # 将围棋棋盘点转换为整数索引
    def encode_point(self, point):
        raise NotImplementedError()

    # 将整数索引转换为围棋棋盘落子点
    def decode_point_index(self, index):
        raise NotImplementedError()

    #围棋棋盘上的交叉点的数目 - 棋盘宽度乘以棋盘高度
    def num_points(self):
        raise NotImplementedError()

    # 已经编码的棋盘结构外形
    def shape(self):
        raise NotImplementedError()

编码器的定义很简单,但是我们希望在base.py中增加一个更方便的特性:一个函数,用它的名字创建一个编码器,一个字符串,而不是创建一个对象。你可以使用下面的get_encoder_by_name函数进行此操作

# 用来导入模块的库
import importlib


# 通过名字返回相应的编码器
def get_encoder_by_name(name, board_size):
    if isinstance(board_size, int):
        board_size = (board_size, board_size)
    # 获取名字对应的模块
    module = importlib.import_module('dlgo.Encoder.' + name)
    # 得到该模块用来初始化的create方法
    constructor = getattr(module, 'create')
    return constructor(board_size)

现在您知道了编码器是什么,以及如何构建一个编码器,让我们实现第一个编码器:一种颜色表示为1,另一种颜色表示为-1,空点表示为0。为了得到准确的预测,模型也需要知道现在该轮到谁下了。因此,不要用1表示黑棋和-1表示白棋,你将使用1表示下一回合落子方,并用-1表示对手。你将把这种编码称为OnePlaneEncoder,因为您将要把围棋棋盘编码成与棋盘相同大小的单个矩阵或平面。在第7章中,您将看到具有更多特征平面的编码器;例如,您将实现这样一个编码器,一个平面放每个黑棋和白棋,一个平面用来识别劫。现在,您将在oneplane.py中实现的最简单的one-plane编码思想。下面的列表显示了第一部分。


                
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值