英特尔实验室的两位研究人员,利用遗传算法和图灵完备语言,号称实现了首个能够自动编程的AI系统“AI Programmer”。文章共三篇,以下是网络翻译的详细内容:
介绍
计算机程序有可能自己编写程序吗?人类的软件开发者有一天会被他们掌握的电脑所取代吗?就像农民、装配线工人和电话接线员一样,下一个会是软件开发人员吗?虽然这种想法看起来有些牵强,但实际上可能比我们想象的更接近。本文描述了一个实验,以产生一个人工智能程序,能够开发自己的程序,使用遗传算法实现自我修改和自我改进的代码。
“hello”
上面的编程代码是由一个人工智能程序创建的,设计用来编写具有自我修改和自我改进代码的程序。程序在29分钟内生成了上述结果。编程语言是脑残的。为什么是这种编程语言?继续读下去。
所有人工智能程序的代码都可以在GitHub上找到。
人工智能写代码
近年来,随着计算机技术、硬件、内存和CPU速度的进步,人工智能一直在稳步发展。随着计算机速度的提高,可以进行更多的计算,从而提高许多人工智能算法所需的计算密集型处理能力。
人工智能爱好
这对我来说有点像是一种爱好,我涉猎人工智能程序,试图编写一个本身就可以编写程序的程序。当然,我并不是指那些将程序指令或代码块的子集组合在一起或以其他方式优化以产生最终结果的程序。我指的是从头开始,人工智能完全不知道如何用目标语言编程。人工智能必须自己学习如何为特定目的创建一个功能完备的程序。
我最初是在20世纪90年代末开始这项冒险的,当时我试图用简单的if/then/else语句创建程序,用BASIC编程语言输出程序。这是一项艰巨的任务,原因很多。首先,使用if/then/else条件来编写随机程序似乎一点也不聪明。第二,BASIC中可用的计算机指令太多了。更麻烦的是,有些指令非常危险(Shell(“format c:”)!我还尝试用C、C++和其他几种语言生成程序。然而,这种天真的方法从来没有产生一个工作的孩子计划。尽管这不仅仅是因为使用简单的if/then/else语句,还因为所选的编程语言是为了供人类使用而不是计算机,因此,对于人工智能来说,自动化要复杂得多。
虽然最终的目标是产生一个能够编写自己的文字处理软件、图像编辑工具、网络浏览器或磁盘碎片整理程序的计算机程序,但我更感兴趣的是一个简单的概念证明,证明这个想法是可能的。
足够多的猴子和破打字机
我最初的动机来自于【无限猴子】定理,它说如果你有1000多只猴子在打字机上敲打足够长的时间,它们最终会重演莎士比亚写的剧本。这听起来很荒谬,但如果有足够的时间,猴子们最终肯定会碰到“一些”随机的字符序列,最终产生书面作品。简化这个想法,其中一只猴子肯定会在键盘的敲击声中敲出莎士比亚戏剧的第一个字母;这当然是可能的。
如果你能引导猴子呢?每次一只猴子按正确的顺序按正确的键,你就用香蕉奖励他?经过足够长的时间,也许猴子会开始发现一个模式?如果他真的很犀利,也许他甚至会开始学习英语中哪些字母通常一起组成单词,从而比同龄人利用更多的香蕉。
关于遗传算法的切线
这是遗传算法的基本思想。遗传算法是一种模仿生物进化的人工智能,除了可用的工具和有效的指令外,它一开始对这个学科一无所知。人工智能随机挑选一系列指令(作为一段DNA)并检查结果的适用性。它是在人口众多的情况下完成的,比如说100个项目。当然,有些节目比其他节目好。那些身体最健康的人被交配在一起产生后代。每一代人都从轮盘赌选择、交叉和变异等进化技术中获得了一点额外的多样性。每个子代都会重复这个过程,希望产生越来越好的结果,直到找到目标解决方案。遗传算法是适者生存的编程实现。他们也可以被归类为人工智能搜索算法,就他们如何搜索一个巨大的问题空间的具体解决方案。
好,但是为什么选择brainf ck呢?
虽然使用BASIC、C、C++和其他语言的原始实验未能产生结果,但我能够成功地通过将一个自组织的编程语言(包括加法、减法、循环等)与遗传算法和神经网络结合来生成人工智能编写的程序。虽然这很有趣,但最终的结果是简单的数学计算和编程语言本身,是未知的,并且对它最终能产生什么有严重的限制。
我开始寻找一种简单的编程语言,指令数量有限,可以训练人工智能程序使用。汇编(ASM)很接近,但仍然包含了太多的排列。虽然听起来很幽默,但我最终还是尝试了brainf ck,并最终成功地生成了上面显示的代码。
虽然brainf ck被设计成一种笑话编程语言,但由于人类使用它有多困难,它实际上对计算机有几个明显的优势。
Brainf ck作为人工智能编程语言的优势
1。它是图灵完备的
图灵完全编程语言意味着它在理论上能够解决宇宙中的任何计算问题。一种具有这种能力的编程语言提供了大量的可能性。毕竟,大多数(如果不是所有的话)计算机程序的设计都是为了执行某种计算并以某种方式输出结果。
2。它只由一组简化的8条指令组成
简化的指令集减少了可以找到目标程序代码的搜索空间。随着计算机越来越快,可以搜索更大的问题空间。然而,在个人计算机上,搜索空间需要受到限制。通过将编程指令集限制为8个不同的字符,AI可以更快地运行,并在合理的时间内(即,分钟、小时,甚至可能是一天)获得最佳适应度分数。
3。建立一个解释器很容易
指令集有很好的文档记录,易于理解。因此,创建一个可以执行程序的简单解释器非常简单。通过将解释器包含在AI程序+遗传算法本身中,代码可以优化为比调用外部编译器来执行每个子程序快得多。这也提供了安全约束,因为子程序是在人工智能程序的受控环境中运行的。AI还可以访问解释器的内部组件,例如内存、指令和输出。这在计算健康评分时很有用。然而,使用第三方编译器,这些组件将更难访问。
4。每条指令为1字节
本文中使用的人工智能程序是在C#.NET中设计的,它使用一个双倍数组作为基因组。基因组中的每个double(基因)对应于编程语言中的一条指令。因为每条指令只有1个字节,所以很容易将每个基因映射到一个编程代码(注意,1 double=8字节;仍然相当于数组中的一个插槽)。
5。存在扩展指令的可能性
大多数编程语言的解释器只是执行代码,维护内存值,并支持控制台输入/输出。但是,可以扩展解释器以包括对生成图形、网络功能、文件系统访问等的支持。想想你能给人工智能开发自己程序的能力吧!;)
工作原理
人工智能程序的工作原理如下:
1 一个基因组由一系列双倍体组成。
2 每个基因对应于brainf ck编程语言中的一条指令。
3 从一群随机的基因组开始。
4 通过将每个double转换成相应的指令并执行程序,将每个基因组解码成结果程序。
5 根据每个程序写入控制台的输出(如果有),获取每个程序的适应度得分,并对它们进行排序。
6 使用轮盘赌选择、交叉和变异将最好的基因组配对,产生新一代。
7 对新一代重复此过程,直到达到目标适应度分数。
由于适应度方法fitness是计算成本最高的部分(它必须为人口中的每个成员执行程序代码,这可能包括无限循环和其他讨厌的东西),人工智能程序使用Parallel.ForEach方法,可在.NET4.5中找到。以这种方式,它可以在每一代对群体中的多个基因组执行多个适应度算法。这允许程序利用最大的CPU资源并利用多个CPU核。程序还每隔10000代保存一次状态,以防程序或PC关闭,并且可以从停止的位置继续搜索。
适应度法
适应度方法的工作原理是对生成的程序的输出进行评分。通过查看程序输出的每个字符(如果产生任何输出)并从所需字符中减去其值来计算分数:
fitness += 256 - Math.Abs(console[i] - targetString[i]);
当然,最初大多数生成的程序甚至不会编译,更不用说将文本输出到控制台了。这些都被简单地丢弃,偏向于至少输出一些东西的程序;并进一步引导和进化,直到输出结果越来越接近所需的解决方案。
解释器指令集
Brainf ck由以下指令集组成:
结果?
输出Hi
人工智能在大约1分钟内成功地编写了一个程序,在5700代之后输出“hi”。它产生了以下代码:
尽管上面的代码包含解析错误(例如不匹配的括号),但是我们的仿真解释器会一直计算结果,直到程序失败为止,因此在上述情况下,语法错误(在找到解决方案之后,在代码中稍后进行介绍) )不会影响健康度。
您可以尝试将上面的代码粘贴到brainf-ck解释器中。 单击“启动调试器”,忽略警告,然后单击“运行到断点”。 注意输出。
如果我们剪裁多余的代码,则会看到以下语法上有效的代码:
您可以在程序运行时查看以下屏幕截图:
这是历史图表,绘制了一段时间内的体能得分。您可以看到人工智能是如何学习如何用目标语言编程并实现所需的解决方案的。
输出hello
人工智能在大约29分钟内成功地编写了一个程序,在2520000代之后输出“hello”。它产生了以下代码:
+-+-+>-<[++++>+++++<+<>++]>[-[---.--[[-.++++[+++..].+]],]<-+<+,.+>[[.,],+<.+-<,--+.]],+]
[[[.+.,,+].-
在生成过程中,人工智能非常接近于一个解决方案,但是两个字母在一个循环中相互绑定。人工智能通过在有问题的循环中创建一个内部循环,成功地输出正确的字符,并继续处理,从而克服了这个问题。
Hi程序
他成功地写了一个程序输出“嗨!“经过大约2小时7分钟的1219400代。它产生了以下代码:
-----------<++[[++>++<+][]>-.+[+++++++++++++++++++++++++++++><+++.<><-->>>+].]
这其实是我最喜欢的。运行它,您可以看到原因(单击启动调试器并运行到断点)。就好像电脑知道它在做什么。有趣的是,生成这个程序要比前两个程序花费更长的时间。这可能是由于使用的字符,其中包括大写字母和符号。另外两个例子使用的字符在ASCII系统中的值更接近,这对AI来说更容易找到。
输出reddit
人工智能在大约22分钟内成功地编写了一个程序,在19.5万代之后输出“reddit”。它产生了以下代码:
+[+++++>++<]+>++++++[[++++++.-------------.-.-+.+++++.+++++],.,+,-+-,+>+.++<<+<><+]
-[-<>.]>+.-.+..]<
这次是个挑战。这可能是由于它的长度,或可能是由于d的位置棘手。人工智能会反复陷入局部最大值。局部极大值是指当遗传算法在其当前参数内找到它能看到的最佳适应度时,即使可能存在更好的适应度。人工智能无法跳出洞来获得更好的适应度,因为这样做需要适应度先下降,然后再增加,这通常违反遗传算法的规则。
我能够通过在突变功能中加入额外的多样性来解决这个问题。以前,这种突变只是通过改变基因组中的一条指令来实现的。突变被增强,不仅包括单个位的突变(替换突变),还包括位的上移(插入突变)和下移(缺失突变)。这种额外的多样性使人工智能能够继续前进。
输出hello world
这是在大约2小时内经过580900代之后产生的。它产生了以下代码:
-><[>-<+++]->>++++[++++++++++++++++++<+]>.---.+-+++++++..+++.+>+<><+[+><><>+++++++++.+-<
-++++[++[.--------.+++.------],.-----],,.>.+<<<[><<>]<++>+.[]+[.[+]],[[.]..,<]]],]<+]],[
]],[[+[,+[]-<.,.],--+]-++-[,<.+-<[-<]-><>-]-<>+[-,-[<.>][--+<>+<><++<><-,,-,[,[.>]]<-+[.
+[<.<],]<<<>].[--+[<<->--],-+>]-,[,
如果去掉多余的部分,打印文本的实际代码就会短得多:
-><[>-<+++]->>++++[++++++++++++++++++<+]>.---.+-+++++++..+++.+>+<><+[+><><>+++++++++.+-<
-++++[++[.--------.+++.------],.-----]]
输出 I love all humans
这是6057200代后在大约10小时内产生的。它产生了以下代码:
+[>+<+++]+>------------.+<+++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++
++++.+++.+++++++.-----------------.--<.>--.+++++++++++..---<.>-.+++++++++++++.--------.--
----------.+++++++++++++.+++++.]-+,.-<[><[[[[[[<-[+[>[<-<-[+[,]-,,-[>[+[-<-,.<]]]<-+<[]+<
.,,>[<,<[.]>[<,<<-.]><,,,--[.--.-
如果删去多余的部分,打印文本的实际代码将变短:
+[>+<+++]+>------------.+<+++++++++++++++++++++++++++++++.>++++++++++++++++++++++++++++++
++++.+++.+++++++.-----------------.--<.>--.+++++++++++..---<.>-.+++++++++++++.--------.--
----------.+++++++++++++.+++++.
在上面的运行中,为AI提供了300条指令的起始程序数组大小(即300字节,或者更确切地说是2400字节,因为1 double=8字节)。人工智能不需要完整的程序代码。它能用209条指令编写程序。
注意,此解决方案需要10小时才能完成。但是,请记住,如果是人工智能程序而不是人来编程,那么完成一个程序所需的时间就不那么重要了。人工智能可以简单地在后台运行,而人工智能可以处理其他任务。我还预计,随着未来几年计算机速度的提高,计算时间将大大缩短。
未来
这个实验是一个概念证明,一个AI程序可以开发自己的计算机程序来执行特定任务。在这方面,它是成功的。 AI完全可以在不了解目标编程语言的情况下启动,并成功学习了如何生成有效的计算机程序,该程序在执行时可以解决特定任务。
与所有遗传算法一样,设计适应度函数也涉及很多工作。适应性功能等效于向AI描述您要查找的内容。这样,创建适应性函数本身就有点像编程(代表人类)。如果AI有可能开发自己的适应功能,这将是向前迈出的一步。同时,可能仍可以扩展该项目以创建更复杂的子程序,例如那些接受用户输入并计算结果的子程序。
十年前,该计划在任何合理的时间内都不会成功。五年前,该计划可能要花费几天到几周的时间,甚至可能更长。今天,执行只花了几分钟。明天,该程序可能会在几毫秒内运行。随着计算机变得越来越快,功能越来越强大,可以计算出越来越大的搜索空间。我等不及了
如果您发现这很有趣并且想了解更多信息,请在GitHub上下载完整的源代码或联系Kory Becker。阅读我的有关在C#.NET中使用遗传算法和神经网络的教程。本文中的程序可执行文件是使用Brainfuck.NET编译器编译的。
2015年1月5日更新
是否想了解AI还能做什么?我也是!在后续文章中阅读更多内容:突破自我编程人工智能的极限和自我编程人工智能学习使用功能。
关于作者
本文由软件开发人员和架构师Kory Becker撰写,他们精通多种技术,包括Web应用程序开发,机器学习,人工智能和数据科学。