©PaperWeekly 原创 · 作者|苏剑林

单位|追一科技

研究方向|NLP、神经网络

▲ 中国象棋

不知道读者有没有看过量子位年初的文章《最强写作AI竟然学会象棋和作曲,语言模型跨界操作引热议,在线求战》,里边提到有网友用 GPT2 模型训练了一个下国际象棋的模型。

笔者一直在想,这么有趣的事情怎么可以没有中文版呢?对于国际象棋来说,其中文版自然就是中国象棋了,于是我一直有想着把它的结果在中国象棋上面复现一下。拖了大半年,在最近几天终于把这个事情完成了,在此跟大家分享一下。

象棋谱式:

将军不离九宫内,士止相随不出官。象飞四方营四角,马行一步一尖冲。炮须隔子打一子,车行直路任西东。唯卒只能行一步,过河横进退无踪。

背棋谱

其实,简单看看量子位的文章,就能理解 GPT2 下象棋的原理了,无非就是“背棋谱”。简单来说,就是象棋的棋谱可以表示为一个连续的文本字符串,而 GPT2 正是擅长于背诵文本,因此可以用 GPT2 把人类的棋谱都背诵下来,而对于下棋来说,就可以看成是根据已经走的部分棋谱背诵下一步棋谱了,因此整个任务理论上确实是可以用 GPT2 完成。

为了完成这个任务,我们就需要了解计算机是如何记谱的。关于记谱的标准,比较通用的是 ICCS 记谱法和 FEN 局面表示法,其细节可以参考文章《中国象棋电脑应用规范(二):着法表示》[1] 和《中国象棋电脑应用规范(二):FEN文件格式》[2]。

1.1 ICCS记谱

简单来说,ICCS 记谱就是将棋盘用如下图的横纵坐标表示,每一步走法只需要记录起始坐标,比如“h2e2”就是指将原来位于坐标(h, 2)的子移动到(e, 2),如果是当前局面是新开局,那么这就对应着走法“炮二平五”。这样一来每一步就只需要 4 个字符来记录了,n 步的棋谱就变成了 4n 长度的字符串了。

当然,如果要输入到模型的话,不一定非得要按照这样的方式来,比如我也可以把“h2”只用一个 id 表示、“e2”用另一个 id 表示,也就是每个格点都用一个坐标而不是两个坐标来描述,这样每一步的只需要两个 id 来记录,以此来缩小棋谱的序列长度,这没有什么定法,有兴趣大家自己改进着完就好。

▲ 中国象棋棋盘ICCS坐标示意图

1.2 FEN局面

至于 FEN 局面表示法,则是用来表示当前局面有哪些子,轮到谁走。本文所建模的棋谱实际上都是全局棋谱,所以实际上本文的模型不需要用到它(局面都是默认的新开局面),不过为了方便有兴趣的读者做出改进,这里也简单介绍下。

所谓 FEN 表示法,主要就是想办法表示出每一行有哪些子,比如开局表示为“rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1”。其中红色部分表示局面,小写表示黑方,大写表示红方,不同行之间用/隔开,字母含义如下表。

这样,“rnbakabnr”就表示第一行为黑子的“車馬象士將士象馬車”,“9”表示第二行 9 个点都是空白的,“1c5c1”表示第三行是“1个空白 +1 个黑砲 +5 个空白 +1 个黑砲 +1个空白”,等等;绿色部分表示轮到哪一方走子,“w”表示红方,“b”表示黑方;剩下部分一般不大重要,有兴趣的读者自己去看链接就行。

建模型

看了上述对记谱表示的介绍,我们知道,不管是每步的走法还是局面的表示,都被我们转化为了一串文本了,而对于象棋的推演都是以局面与走法作为输入输出的,所以理论上来说象棋的建模完全就是一个“文本处理”问题!这便是 GPT2 下象棋的理论依据了。本质上来讲,GPT 也就是 BERT 加上语言模型的 Attention Mask,所以这样的做法我们说是 BERT 下象棋或者 GPT 下象棋都行。

2.1 代码分享

模型原理就没什么好写的了,之前就有文章从语言模型到 Seq2Seq:Transformer 如戏,全靠 Mask 介绍,相关的例子有基于 Conditional Layer Normalization 的条件文本生成、BERT 可以上几年级了?Seq2Seq“硬刚”小学数学应用题等,读者可以自行翻看。本文的处理其实很简单,就是只保留全局棋谱,将棋谱的 ICCS 记法当成一个长句子,然后训练一个语言模型。

项目链接:

https://github.com/bojone/gpt_cchess

训练过程使用渐进式训练,即逐步增加序列长度,而不是一次性使用同一的长度,有些文章将这种做法称之为“课程学习(Curriculum Learning)”。

这种做法能提高模型的训练速度和收敛速度(一开始序列更短,训练速度更快,也更容易收敛),直观来看就是让模型先学习“开局”,然后再学习“开局+中局”,最后学习“开局+中局+残局”,逐步增加难度。

训练前加载了 BERT 的权重,可能读者会疑问 BERT 的权重还能跟棋谱有关系?其实没什么关系,但是不管怎么说,用 BERT 的权重比完全随机初始化的权重要好点,收敛会快一点点。

2.2 测试一下

模型脚本还包含了一个可以跟模型交互式下棋的实现,读者可以自行体验一下,这个交互式下棋使用了 python 的 cchess 模块 [3] 来辅助实现,在此表示感谢。

GPT 本身是一个生成模型,但是在决定下一步棋走什么的时候,笔者并不是用生成式方法(因为无约束生成有可能输出不可行的走法),而是用打分式的方法,即直接生成当前局面的所有可行走法,然后输入到模型打分,取分数最高的那个走法,这样就保证模型输出的每一步都是可行的,保证了可以跟 AI 一直对局下去,直到分出输赢。

▲ 交互式下期效果

也许读者可能会有疑问,枚举所有可行走法计算量会不会很大?其实,对于每个局面来说,可行走法并不多,可以通过简单论证它不会超过 111 种(是不是有点意外?中国象棋每一步的候选走法不超过 111 种,而不是一个非常大的数字),所以这一步的 batch_size 不会超过111,因此是可以接受的。

推导过程很简单:1 个车或炮最多有 17 种走法,2 车 2 炮最多有 68 种走法;兵如果都过河了,那么每个兵最多有3种走法,5 个兵最多有 15 种走法;1 个马最多有8种走法,2 个马就是 16 种;2 个相最多有 6 种走法(1 个在中间,1 个在边,4+2);1 个士在花心最多有 4 种走法(2 个士反而相互堵塞);最后的帅最多有 2 种走法。因此结果是 68+15+16+6+4+2=111。具体局面设计可以参考数学研发论坛的《一个中国象棋局面设计难题》[4]。

大家最关心的可能就是这样弄出来的模型棋力究竟怎样?笔者简单跟它测了一下,大概的结论是:基本上可以开一个比较好的局,开局的时候具有不错的应变能力,不过一旦到了中局之后,应变能力会大大下降。对于吃子不是很敏感,也就是说当你乱吃它的子的时候,它可能不会应对。可以看出这些其实都是纯背棋谱的缺点。当然,前面说了每一步的输出都是可行,因此你可以跟它一直玩下去,直到把棋下完。

谈改进

应该有读者会问能不能自己跟自己对弈来提高棋力?理论上当然是可以的,但很遗憾这里没有实现,一是没那个心思实现,二是没那个算力实现。

此外,增加模型大小应该也能进一步提升棋力,要注意笔者上述结果只用了 Base 版本(1 亿参数)的模型,本文开头提到的网友用 GPT2 下国际象棋可是用了 15 亿参数的 GPT2,是我们的 15 倍。

还有一个改进的地方,那就是上面的建模中我们直接学习了整个对局棋谱,按道理为了更好的棋力我们可以只学习赢家的走法,不能学习输家的走法。

当然,这些做法就算有提升,估计也是有限的,归根结底,这跟我们所理解的下棋原理不一样。我们下棋是根据局面形势往前推的,但上述的语言模型做法则没有局面这个概念,或者说它的局面需要用已经走的所有步骤来确定,这对于中后局来说历史步数太多,确实有点强模型所难了。

改进方法其实也很简单,改为“以局面为输入、以走法为输出”就好了,前面我们说了,局面也可以用 FEN 表示法表示为一个文本,因此这也是只是个 Seq2Seq 任务而已。

除此之外,还有一些别的做法,比如我们可以把赢家的每一个局面都当作正样本,输家的每一个局面都当作负样本,那么就可以训练一个二分类模型,来判断局面优劣,有了这个判断函数,我们也可以直接枚举每一个可行走法,根据判断函数的结果来选择最优下法。而局面可以表示为文本,这就意味这我们将下棋变成了一个文本分类任务了。

总之,得益于 Transformer 模型对文本的强大的建模能力,这使得我们对下棋的建模思路也变得简单多样起来了。

总小结

本文尝试了通过 bert4keras 用 GPT 来下中国象棋的做法,主要思路是通过“语言模型背棋谱”的方式来让模型具有预测下一步的能力,并谈及了一些改进思路。尽管本文的做法并非对下棋这个任务进行建模的标准做法,但通过这样的方式,能让我们进一步体会到语言模型的强大之处。

欢迎大家报告自己所训练的下棋模型的棋力智商,哈哈。

参考文献

[1] https://www.xqbase.com/protocol/cchess_move.htm

[2] https://www.xqbase.com/protocol/cchess_fen.htm

[3] https://github.com/walker8088/cchess

[4] https://bbs.emath.ac.cn/thread-17051-1-1.html

更多阅读

#投 稿 通 道#

 让你的论文被更多人看到 

如何才能让更多的优质内容以更短路径到达读者群体,缩短读者寻找优质内容的成本呢?答案就是:你不认识的人。

总有一些你不认识的人,知道你想知道的东西。PaperWeekly 或许可以成为一座桥梁,促使不同背景、不同方向的学者和学术灵感相互碰撞,迸发出更多的可能性。

PaperWeekly 鼓励高校实验室或个人,在我们的平台上分享各类优质内容,可以是最新论文解读,也可以是学习心得技术干货。我们的目的只有一个,让知识真正流动起来。

???? 来稿标准:

• 稿件确系个人原创作品,来稿需注明作者个人信息(姓名+学校/工作单位+学历/职位+研究方向)

• 如果文章并非首发,请在投稿时提醒并附上所有已发布链接

• PaperWeekly 默认每篇文章都是首发,均会添加“原创”标志

???? 投稿邮箱:

• 投稿邮箱:hr@paperweekly.site

• 所有文章配图,请单独在附件中发送

• 请留下即时联系方式(微信或手机),以便我们在编辑发布时和作者沟通

????

现在,在「知乎」也能找到我们了

进入知乎首页搜索「PaperWeekly」

点击「关注」订阅我们的专栏吧

关于PaperWeekly

PaperWeekly 是一个推荐、解读、讨论、报道人工智能前沿论文成果的学术平台。如果你研究或从事 AI 领域,欢迎在公众号后台点击「交流群」,小助手将把你带入 PaperWeekly 的交流群里。

GPT v.s. 中国象棋:写过文章解过题,要不再来下盘棋?相关推荐

  1. 美国教授对中国学生写英文文章的建议

    最常见的英文写作问题 --源自200多篇由中国科技类研究生撰写的英文论文 作者:Felicia Brittman  本文目的 中国学者的英文科技论文写作中,最常见的写作问题:语法错误.口语化.格式组织 ...

  2. 用 Python 的 tkinter 模块编写一个好看又强大的中国象棋

    继上次我的第一版的<中国象棋>程序之后,我又编写了第二版的<中国象棋>程序,关注我的粉丝知道,我在第一篇<中国象棋>的文章末尾说了,我会出第二版的,对第一版感兴趣的 ...

  3. c# - 作业4:中国象棋

    c# - 作业4:中国象棋 总体视图 & 废话集结区 资源下载 代码(全) FormMain.cs Program.cs Chess.cs 现存bug 总体视图 & 废话集结区 印象里 ...

  4. 朋友写的一个中国象棋游戏,JAVA代码

    朋友写的一个中国象棋游戏,JAVA代码.有兴趣的可以这里下载:中国象棋下载 (1)地址,不知现在还能下否....中国象棋历史悠久,吸引了无数的人研究,现对中国象棋的对战和实现棋谱的制作做如下的设计和说 ...

  5. 使用C++写的中国象棋(单机版)

    C++在游戏领域应用很广,其最大有点是运行效率高,对内存的操作比较直接,因此,我利用此有点写了中国象棋的简洁版,来进行一些简单的下棋操作.接下来是代码 #ifndef PUTTEXT_H_ #defi ...

  6. 【181008】VC++写的中国象棋游戏源程序

    VC++写的中国象棋游戏源程序,界面看上去挺不错,可以选择人与电脑对战,通过网络人与人对战,程序虽小,不过考验的编程水平是多方面的,因此通过游戏我们有学习不少实用的技巧.简要说明一下:游戏网络运行方法 ...

  7. 分享一个java写的中国象棋代码以及相关视频

    注意:相关资料链接地址:http://pan.baidu.com/share/link?shareid=493847&uk=3223420628 若要详细视频请到该链接直接下载: http:/ ...

  8. 中国象棋程序的设计与实现(四)-- 一次“流产”的写书计划

    2019独角兽企业重金招聘Python工程师标准>>> 1.写书缘由 2010年写完中国象棋程序(代码)后,我想认真完善下这个项目. 在写代码过程中,我已经加入了大量的注释. 写完后 ...

  9. Cocos2d-X开发中国象棋《九》走棋规则

    在上一节中实现了走棋,这篇博客将介绍中国象棋中的走棋规则 在写博客前先可能一下象棋的走棋规则: 1)将 将的坐标关系:横坐标相等,纵坐标相减绝对值等于1,或者纵坐标相等,横坐标相减绝对值等于1 将的特 ...

最新文章

  1. 汇编语言第五到八章总结
  2. 为了让16岁的儿子从轮椅上站起来,这位机器人工程师父亲打造了一套外骨骼装置...
  3. 09.20类类型random
  4. 2008 r2彻底删除 server sql_mysql添加列、删除列,创建主键、备份等常用操作总结...
  5. .NET 6 中的 ConfigurationManager
  6. LeetCode 966. 元音拼写检查器(哈希)
  7. 菜单固定随滚动条滑动
  8. 数据3分钟丨Apache Doris谴责DorisDB违背开源精神;HC2021下周召开;openGauss训练营第二期圆满落幕
  9. Apache ab 测试结果的分析
  10. Chrome去广告插件-Adblock Plus
  11. 【C++】1079:计算分数加减表达式的值(信息学奥赛)
  12. 台湾成功大学起诉苹果Siri专利侵权 库克哥凌乱了
  13. 深入理解8583协议
  14. 前端工程师面试问题归纳(一、问答类html/css/js基础)
  15. 爬虫学习经验分享-------某点评网站
  16. 互动百科与百度的百科大战对网络营销的影响
  17. 伪指令-宏定义:使用#define定义一个宏,宏体中包含命名空间信息导致vs大量报红,但编译和运行却正常
  18. 选择杠杆炒股的原因是什么?
  19. 用C语言求1到10 阶乘的和
  20. BAD PASSWORD: it is too simplistic/systematic

热门文章

  1. java getmethod类_Java getMethod类型参数
  2. wps出现安装installer_判断本机是否安装Microsoft Office或者wps
  3. Android 接入baceBook
  4. 不小心删除了某个包的一部分,重新安装方法
  5. 17. Merge Two Binary Trees 融合二叉树
  6. elasticsearch 基本配置
  7. spring零碎知识点(二)
  8. Spark SQL之External DataSource外部数据源(二)源代码分析
  9. hibernate07--关联映射
  10. 上学路线 (Standard IO)