中国经济观察网 | 手机客户端 |
当前位置: 首页 > 新闻

基于深度NLP模型的现代程序综合以微调特定任务的性能

作者:柳暮雪    栏目:新闻    来源:TechWeb   发布时间:2022-06-13 14:47   阅读量:13202   

内容摘要:Copilot,Codex和AlphaCode:计算机程序自动编程的现状 最近几年来,由于自然语言处理领域转换器的兴起,我们看到了一系列令人震惊的代码编写深度学习模型可以编写计算机程序的计算机程序,通常称为程序合成,至少从20世纪60年代...

Copilot,Codex和AlphaCode:计算机程序自动编程的现状

最近几年来,由于自然语言处理领域转换器的兴起,我们看到了一系列令人震惊的代码编写深度学习模型可以编写计算机程序的计算机程序,通常称为程序合成,至少从20世纪60年代末和70年代初就已经被研究了

在20世纪10年代和20年代,基于注意的模型在其他领域的成功再次刺激了程序合成研究的动机,即在数百GB的文本上预先训练具有数百万或数十亿参数的大规模基于注意的神经模型的策略。

预训练模型在元学习方面表现出令人印象深刻的能力,这是由于它们的注意机制,并且它们似乎可以实际应用于文本开发mdash提示内容中只提供了几个例子

基于深度NLP模型的现代程序综合

NLP模型可以用特殊的数据集进一步训练,以微调特定任务的性能对于这个应用程序来说,编写代码是一个特别有趣的使用场景

GitHub上的Copilot项目,对外宣传为你的人工智能编程伙伴,2021年推出时引起了不小的争议这在很大程度上是由于训练数据集中使用了所有的公共GitHub代码根据说明,这些代码库包括具有Copyleft许可证的项目,该许可证可能不允许代码用于Copilot等项目,除非Copilot本身是开源的

Copilot是OpenAI和微软公司之间关系的产物,基于GPT—3的代码训练版本OpenAI演示并通过其API提供的版本称为Codex使用Copex的正式实验描述在陈先生等人2021年发表的论文中有详细介绍

2022年初,DeepMind开发了自己的深度NLP系统:AlphaCode。

新的挑战者:AlphaCode

与之前的Codex和Copilot一样,AlphaCode是一个大型的NLP模型,被设计和训练用来编写代码与Copilot一样,AlphaCode不是为软件工程师开发的生产力工具,而是为了在竞争性编程任务中挑战人类的编程性能

训练和评估AlphaCode的竞赛编码挑战的难度介于之前数据集的难度和真实世界软件工程的难度之间。

对于那些不熟悉竞赛编程挑战网站的人来说,这个任务有点像简化版的测试驱动开发根据一些给定的文字描述和几个例程,这个挑战的主要内容是编写一个通过一组测试的程序mdashmdash这些测试中的大多数对程序员是隐藏的

理想情况下,隐藏测试应该是全面的,通过所有测试意味着给定问题已经成功解决可是,用单元测试覆盖每一个边缘是一个难题对程序合成领域的一个重要贡献其实是CodeContests数据集本身,因为DeepMind团队付出了巨大的努力mdashmdash他们通过变异过程产生额外的测试,以降低假阳性率和慢阳性率

Alpha的表现是根据大赛网站CodeForces上的大赛编程挑战赛内容来评估的整体来看,AlphaCode在参赛程序员中的平均表现为前54.3% ,

请注意,这个指标可能有点误导,因为它实际上相当于45.7%的性能不可思议的是,AlphaCode系统可以写出任何通过所有隐藏测试的算法但是,请注意:AlphaCode使用了与人类完全不同的策略来解决编程问题

虽然人类的竞争对手可能会编写一个算法来解决大多数例程mdashmdash结合运行早期版本解决方案的见解,持续改进,直到通过所有测试,但是,AlphaCode采用了一种更广泛的方法,即每个问题生成多个样本,然后选择10个样本提交。

Alpha在CodeContests数据集上性能的一大贡献是生成后过滤和聚类的结果:在它生成约100万个候选解后,开始过滤候选解以删除问题描述中未通过示例测试的候选解,从而淘汰约99%的候选群体。

然后,通过聚类将剩余的候选人筛选为10个或更少的提交简而言之,他们训练了另一个模型,根据问题描述生成额外的测试输入

剩余的候选解决方案根据它们在生成的测试输入上的输出进行聚类从最大到最小,从每个集群中选择一个候选人进行提交如果聚类数小于10,则对聚类进行多次采样

虽然过滤/聚类步骤是独特的,并且AlphaCode在新的CodeContests数据集上进行了微调,但其初始训练方法与Codex或Copilot大致相同AlphaCode首先在GitHub的大型公开代码数据集上接受预训练他们训练了五个变种,参数数量从2.84亿增加到410亿

与AlphaGo系列的精神或AlphaStar机器人玩星际争霸2游戏一样,AlphaCode也是一个研究项目,旨在开发一个在专门任务领域接近人类能力的系统,在程序合成过程中开发的效用程序门槛更低。

从开发解决问题的实用工具来看,这方面机器人的代表是基于GPT—3的Codex和Copilot工具Codex是GPT—3的OpenAI变体,它是在公开可用的代码语料库上训练的根据随论文发表的HumanEval数据集,OpenAI报告Codex在中通过,docstring到code格式任务生成100个样本,可以解决70%以上的问题

接下来,我们将探索这种通过使用Codex自动生成代码的提示编程技术。我们也将使用下面给出的模型来开发约翰middot康威的生活游戏

GitCopilot采用代码自动完成的方式,目前的打包形式是Visual Studio,VSCode,Neovim,JetBrains等集成开发环境的扩展根据Copilot网页的描述,Copilot已经根据给定的描述成功重写了一组经过良好测试的Python函数,其中57%与HumanEval数据集相似

我们会研究Copilot的一些实际用例,比如使用VSCode特别beta版的Copilot扩展自动编写测试。

提示编程:用抄本写康威的生命游戏

在这一节,我们将介绍基于约翰middot的信息,康威的《生命的游戏》的任务是编写元胞自动机模拟器只要稍加修改,不用硬编码规则,我们的程序应该能够模拟任何一组栩栩如生的细胞自动机规则

我们将采用互动的方法,而不是产生100个例子并选择最好的一个当Codex给出一个糟糕的解决方案时,我们会做出调整,试图引导一个更好的答案当然,如果绝对必要,在Codex完全失效的情况下,我们可以继续修改代码,得到一个工作实例

编写一个真实的CA模拟器的第一步是提出一个计算邻居的函数。我们编写了下面的docstring提示,并提供给code—davinci—001,这是OpenAI API库中最大的Codex模型:

# prompt import numpy as NP def compute _ neighborhood—gt,np.array:" " "计算输入网格中每个像元的摩尔邻域中像元状态的总和摩尔邻域包括8个单元,与中心单元对角正交相邻,但不包括中心单元由1表示的单元对应于单元a的摩尔邻域:1 1 1 1 a 1 1 1 1如果单元a在网格的边缘,摩尔邻域绕到相对边缘的单元,即网格在圆环上args: grid,二进制值为0或1的numpy数组grid包含当前单元格的状态值Returns:neighborhood _ grid,一个numpy数组,包含从0到8的整数值

在上面的代码中,添加注释行# PROMPT和# GENERATED是为了让提示结束的地方更清楚。

上面那些相当全面的docstring技巧你仔细分析过了吗法典是怎么做的

# GENERATED # TODO:实现此函数pass

这对我们的小实验来说可能不是个好兆头即使在调整p值超参数以实现更宽松的内核采样后,Codex似乎仍然没有给出上述问题的答案

幸运的是,我们只需要在docstring提示符下添加类似下面的内容,Codex就会产生一个更有希望的输出。

#提示此函数已完成且不包含任何TODOs """#生成#获取网格的维度n_rows,n_cols = grid.shape #初始化输出数组neighborhood _ grid = NP . zeros,dtype=int) #在网格上循环for I in range(n _ rows):for j in range(n _ cols):#获取当前单元格值cell_val = grid(i,j) #获取当前单元格的摩尔邻域#使用get_neighborhood函数neighborhood = get _ neighborhood j) #对邻域中的像元值求和neighborhood _ sum = NP . sum(neighborhood)#在邻域网格中存储求和neighborhood_grid(i,j)= neighborhood _ sum return neighborhood _ grid

当然,这还不是一个好的解决方案,因为它引入了一个未使用的变量cell_val,并将其大部分工作委托给了它刚刚添加的另一个函数get_neighborhood但总的来说,这看起来是一个可行的开始

接下来,我们为上面提到的get_neighborhood函数编写了一个简单的docstring:

def get _ neighborhood—gt,np.array: """ get_neighborhood由compute_neighborhood用于返回位于坐标I,j处的单元的3x3 Moore邻域如果I,j坐标位于网格的边缘(即,I或j等于0,或者i grid.shape(0)—1或j grid.shape(1)),则Moore邻域应该环绕以包括相对边缘上的单元换句话说,网格可以被认为是一个圆环的表面,就像Pac—Manargs:grid,np.array,这是细胞自动机网格I,int的当前状态,该坐标对应于行j,int,坐标对应于列returns:moore _ neighborhood—NP . array,应该总是具有3×3的维度,并且包含网格中I,j处的单元的Moore邻域

上述程序的输出似乎也是可行的,但经过检查,它实际上包含了一个重要的错误。

在邻居坐标循环中,它使用与从网格中检索到的坐标相同的坐标来为摩尔邻居赋值。

我们没有找到明确的方法来提示Codex避免错误,因此,我们必须手动修改代码:

# FIXED循环遍历index的坐标,coord in enumerate: #获取坐标cell_val = grid(coord(0),coord(1)) # FIXED将单元格值存储在输出数组moore_neighborhood(index // 3,index % 3)= cell _ val return Moore _ neighborhood

另外在前面的代码中引入了另一个函数get_neighborhood_coordinates来处理的比较,Rdquo的一部分。

接下来,我们将为函数get_neighborhood_coordinates编写一个提示。

# PROMPT def get _ neighborhood _ coordinates—gt,列表:" " " get_neighborhood_coordinates由get_neighborhood用于返回位于坐标I,j的单元的3x3 Moore邻域的坐标如果I,j坐标位于网格的边缘(即I或j等于0,或者i grid.shape(0)—1或j grid.shape(1)),则Moore邻域应该环绕以包括相对边缘上的单元

这比我们预期的函数式编程深度要深一点,但看起来我们终于有了一组函数,可以返回邻居和。

更新函数是左的,其对应的docstring提示如下:

# PROMPTdef update _ grid—gt,np.array:" " "根据输入参数规则中包含的类生命规则更新输入参数网格rules是一个列表列表,第一个元素包含一个出生条件列表(单元格从0—gt,1)并且第二元素包含存活条件的列表(细胞不变)具有不在出生(B)或存活(S)规则中的邻域和的单元变为0此函数使用函数compute_neighborhood来计算网格中每个像元的邻域值args: grid,np.array. grid包含单元格值(0或1)规则,列表列表rules包含用于类似生命的细胞自动机的B/S规则,例如,为了模拟Conway的生命CA,rules = ((3),(2,3))`,即B3/S23没有死亡的生命具有规则B3/S012345678,因此` rules = ((3),(0,1,2,3,4,5,6,7,8))`如果规则包含大于8(摩尔邻域中活细胞的最大数量)或小于0的值,update_grid将引发异常

这似乎是解决上述问题的一个非常合理的方法,尽管我们明确建议,如果相邻格网包含错误的值,并且在生成的输出中找不到,将会抛出异常。

我们可以通过做一些修补,成功设计出完全可行的类生命元胞自动机模拟器:手动干预函数get_neighborhood,尝试给出一些提示。

上面的代码并不是一个特别快速的实现方案,但其质量类似于程序员在开始使用一门新语言时可能会犯的那种Hello World尽量相似值得注意的是,训练数据集中有很多例子可供研究者参考

在康威的《生命的游戏》中,我们可以想象这个程序在微型滑翔机开发中的成功。

虽然我们确实通过一组函数编写了CA模拟器,但这种方法对于日常软件工程来说并不是一种非常有用或现实的开发方法但另一方面,这并不能阻止SourceAI这样的创业公司将自己的服务宣传为给每个人创造有价值的定制软件的机会,

我们建立了一个独立的系统,可以开发世界上最熟练的工程师级软件可是,与Codex进行交互确实是一种潜在的有用的学习或实践编程的方式,尤其是对于CodeSignal,CodeForces或HackerRank等网站的编程问题

接下来,我们将尝试评估Codex/Copilot,以获得自动编写测试和docstring的更真实的用例。

任务2:编写一个测试

对于这个例子,我们选择使用VSCode开发工具的GitHub Copilot扩展来编写测试。

# PROMPT import numpy as NP def pythagorean(a:NP . float,b:NP . float)—gt,np.float:" " "使用勾股定理计算边长为a和b的三角形的斜边args: a,np.float,三角形的一边b,np.float,三角形的另一边return:c,np.float,斜边的长度" " " c = NP . sqrt(a * * 2+b * * 2)return cdef Test _ Pythagorean():# GENERATED(Copilot autocomplete)" " "测试勾股函数" " " a = np.array((3,4

虽然毕达哥拉斯定理函数可能过于简单,但Copilot建议进行合理的测试如果你运行它,它将通过您会注意到自动完成建议可以正确地获得测试的结构和数字内容

如果我们想用自己喜欢的框架,用一种更系统的方式来编写测试,该怎么办不用太担心,因为我们已经用numpy库和自动微分技术编写了大量的低级学习模型,供测试人员使用所以下面这个例子虽然不是100%真实的来自现实世界,但是效果还是接近真实情况的

在这个例子中,我们将通过使用unittest中的autograd和numpy以及TestCase类来设置一个简单的多层感知器正向传输,损失函数和梯度函数进行测试。

# prompt import unittest from autograd import numpy as NP from autograd import grad def forward _ MLP—gt,np.array:" " "计算多层感知器的正向传递层数等于权重列表的长度,权重列表必须与偏差列表相同args: input_x,np.array,输入数据权重,np.arrays列表,np.array矩阵列表,表示权重偏差:np.arrays列表,各层偏差列表返回:result,np.array,网络的输出" " " assert len(weights)len(bias)for layer _ index in range(len(weights)—1):input _ x = NP . tanh(NP . matmul(input _ x,weights(layer _ index))+bias(layer _ index))output = NPnp.float:计算具有权重和偏差的mlp相对于输入数据input_x和目标数组target的均方误差损失

Copilot的建议并不完美,但确实为测试类提供了一个合理的思路可是,如果您试图完整地运行代码,您将不会执行任何测试,更不用说通过测试了

输入数据与第一个权重矩阵的维数不匹配,数据类型错误,无法使用自动签名的梯度函数。

当然,以上问题并不难解决如果权重矩阵列表中的第一个条目被一个3×2矩阵所取代,那么正向传播应该可以工作为了让梯度计算测试顺利运行,需要在np.array定义的数字上加一个小数点或者显式定义数组数据类型

通过这些更改,测试可以成功执行,也可以失败,但期望值在数值表示上是不正确的。

任务3:自动文档字符串

Copilot在自动编写文档方面有很大的潜力,尤其是为已经编写好的函数填充docstring内容这方面几乎是实用的

对于毕达哥拉斯定理的示例程序,Copilot的运行结果非常接近,但它将问题描述为求两点A和B之间的距离,而不是求边长C到边长A和边长B的距离,不出所料,随Copilot分发的docstring中的示例也与函数的实际内容不符:它返回的是标量而不是C的值数组。

Copilot对前进MLP功能docstrings的建议也很接近,但不完全正确。

Copilot支持的自动文档字符串建议

机器能代替我的工作吗。

对于软件工程师来说,程序合成的每一个新发展都可能引起经济恐慌。

毕竟,如果计算机程序可以像程序员一样给计算机编程,不就意味着机器应该取代我们的工作真的吗在不久的将来会是这样吗

表面上看,答案似乎是还没有,可是,这并不意味着伴随着这些工具变得更加成熟,软件工程的本质可能会保持不变在未来,使用复杂的自动完成工具进行成功的推理可能与使用代码格式化工具一样重要

Copilot目前处于测试试用阶段,关于如何使用它的选项有限同样,Codex也可以通过OpenAI获得测试版中的应用编程接口试点项目的使用条款和隐私考虑确实限制了这项技术的潜在使用场景

根据目前的隐私政策,输入这些系统的任何代码都可以用于微调模型,并可以由GitHub/微软或OpenAI员工进行审查这排除了在敏感项目中使用Codex或Copilot的可能性

Copilot为它所基于的Codex模型增加了许多实用程序您可以为所需的代码编写一个框架或大纲,并将光标移动到大纲的中间,以获得合理的OK自动完成建议

目前,对于任何比简单的编码实践更复杂的问题,Copilot都不太可能建议正确完整的代码,但是,它通常可以创建一个合理的大纲,并节省一些手动输入。

还需要注意的是,Copilot运行在云中这意味着它不能离线工作,自动完成建议有点慢此时,您可以通过按Alt+在建议中循环,但有时只有几个建议可供选择,甚至只有一个建议可供选择

当副驾驶运行良好时mdashmdash其实已经足够好了有点危险unittest示例中建议的测试和为毕达哥拉斯函数建议的docstring乍一看是正确的,并且可能通过疲惫的软件工程师的检查

综上所述,尽管Copilot/Codex在目前的状态下更像是一个玩具或学习工具,但它实际上可以工作是令人难以置信的如果你遇到一只跳华尔兹的熊,我想它不会给你留下它跳得有多好的印象同样,如果你碰到一个智能代码补全工具,让你印象深刻的不应该是它写的代码有多完美

总之,伴随着自动编程NLP模型技术的进一步发展,以及人类程序员对NLP自动完成工具的大量调整,很可能在不久的将来会出现程序合成模型这一重大杀手级应用。

译者简介

郑重声明:此文内容为本网站转载企业宣传资讯,目的在于传播更多信息,与本站立场无关。仅供读者参考,并请自行核实相关内容。

相关阅读