以简单游戏为例培养人工智能



在本文中,我将分享使用遗传算法发展简单人工智能(AI)的经验,还将讨论形成任何行为所需的最少命令集。

这项工作的结果是,不了解规则的AI独立掌握了井字游戏,并发现了与之对抗的机器人的弱点。 但是我从一个更简单的任务开始。

指令集


一切始于准备一套AI可能具有的命令。 高级语言包含数百种不同的运算符。 为了突出显示必要的最低限度,我决定转向汇编语言。 但是,事实证明它包含许多命令。

我需要AI读取和输出数据,使用内存,执行计算和逻辑运算,进行转换和循环。 我遇到了Brainfuck语言,该语言仅包含8条命令,可以执行任何计算(即Turing完成)。 原则上,它适合于基因编程,但我走得更远。

我想知道:实现任何算法所需的最少命令数量是多少? 事实证明-一个!

URISC处理器仅包含一个命令:如果相减的结果大于减量的结果,则减去并跳过下一条指令。 这足以构建任何算法。

Oleg Mazonka走得更远,他开发了BitBitJump团队,并根据Turing证明了它的完成。 该命令包含三个地址,将一个位从第一个地址复制到第二个地址,并将控制权转移到第三个地址。

借用了Oleg的想法,以简化工作,我建立了SumIfJump团队。 该命令包含四个操作数:A,B,C,D并执行以下操作:将单元格中的数据添加到地址A到地址B,如果该值大于指定的*,它将到达地址C,否则将到达地址D。

注意事项
*在这种情况下,使用了128个-基因组长度的一半。

当操作数A访问存储单元N0时,正在输入数据,而当操作数A进入存储单元N1时,则输出数据。

以下是FreePascal(Delphi的免费类似物)上的SumIfJump代码。

procedure RunProg(s: TData); var a, b, c, d: TData; begin Inc(NStep); if NStep > MaxStep then begin ProgResult := 'MaxStep'; Exit; end; a := s; b := s + 1; c := s + 2; d := s + 3; a := Prog[a]; b := Prog[b]; c := Prog[c]; d := Prog[d]; if a = 0 then begin ProgResult := 'Input'; Exit; end; if a = 1 then begin ProgResult := 'Output'; Exit; end; Prog[b] := Prog[b] + Prog[a]; if Prog[b] < ProgLength div 2 then RunProg(c) else RunProg(d); end; 

SumIfJump实现自修改代码。 它可以执行常规编程语言中可用的任何算法。 该代码易于修改,并且可以承受任何操作。

简单的任务


因此,我们的AI只有一支团队。 虽然井字游戏对他来说是非常困难的游戏,但我还是从一个简单的游戏开始。



机器人给出一个随机数,而AI应该读取数据并给出答案。 如果数字大于平均值(在随机数范围内),则AI给出的数字应小于平均值,反之亦然。

我们AI的基因组由256个细胞组成,值从0到255。每个值是一个内存,一个代码和一个地址。 代码执行步骤的数量限制为256。操作数一个接一个地读取。

最初,基因组是由一组随机数组成的,因此AI不知道它需要发挥什么作用。 而且,他不知道自己需要按顺序输入和输出数据,以响应机器人。

人口与选择


第一批人口包括开始使用该机器人的256个AI。 如果AI执行正确的操作(例如,请求输入数据,然后显示某些内容),则AI会收到积分。 正确的动作越多,得分就越高。

得分最高的16个AI提供了15个后代,并继续参与游戏。 后代是突变体。 通过用随机值替换父副本中的一个随机单元格来发生突变。



如果在第一个总体中没有AI得分,则形成下一个总体。 依此类推,直到某些AI开始执行正确的操作并提供“正确的”后代。

发展历程


ñ大事记
1个AI什么也没做。 该程序需要256个步骤并结束。
2开始请求数据。
3他开始请求数据并输出一些东西。 请求和响应的顺序很混乱。
4数据输入和输出顺序发生,有时会发生错误。 在一半的情况下,人工智能给出了正确的答案。
5定期给出正确答案,但有时会发生错误。
6在3万次迭代中给出正确的答案。 选择已上传。

在重大事件之间,数千代人过去了。 该程序在Core i7的多个线程中启动。 计算耗时约15分钟。



有趣的地方


  1. 当AI“领导者”犯了一个随机错误并且没有获得足够的分数时,人口开始下降,因为 由“次生”父母组成的后代。
  2. 碰巧的是,在外部人在打发时间的流中,成功进行了一次突变,从而使累积的积分急剧增加。 此后,此流程成为领导者。
  3. 有时很长一段时间没有成功的突变发生,甚至50万代都不足以完成选择。


结论


总之,我在井字游戏中也这样做。 与第一种情况一样,使用基因组大小。 步骤数增加到1024,而总体大小增加到64(以便进行更快的计算)。 计算花费了更长的时间。 一切都根据相同的情况发生。

最初,AI与“随机化器”对抗。 我称它为随机行走的机器人。 很快,AI开始打败他,排成一列。 此外,我通过给随机化器添加一些理由来使任务复杂化:如果可能的话,占据优势或者保卫。 但是,在这种情况下,人工智能发现了机器人的弱点并开始击败他。 也许有关此的故事是另一篇文章的主题。

儿子要求我编写一个程序,以便AI相互之间而不是与机器人一起玩。 有一些想法可以玩跳棋或走棋,但是为此,我已经没有足够的时间了。

我用来获得新个体的唯一方法是突变。 您还可以使用交叉和反转。 也许这些方法将加快获得所需结果的速度。

最终,这个想法诞生了:使AI能够管理PC上的所有进程并争夺计算机资源。 将PC连接到Internet,并将旧的比特币农场池用作计算能力...

如前所述,博客作者Mikhail Tsarkov进行了类似的实验:
也许他们会接管世界,但是如果呢?

参考文献


  1. 遗传算法
  2. 复制位-最简单的计算机/ Oleg Mazonka
  3. URISC-维基百科
  4. 图灵完整性-维基百科

Source: https://habr.com/ru/post/zh-CN406673/


All Articles