一种基于迭代对比学习的代码重排方法及系统转让专利

申请号 : CN202310199939.4

文献号 : CN116048454B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 聂帅怡黄琨瑜董颖佳

申请人 : 山东师范大学

摘要 :

本发明提出了一种基于迭代对比学习的代码重排方法及系统,包括:获取编程问题对应的待排序候选代码;利用程序转换技术扩增候选代码;将扩增后的候选代码输入至训练后的排序模型中,对每个代码进行排序;取所得序列中,排序得分最高的代码作为所述编程问题的最后推荐的代码。本发明通过迭代训练两个损失,即鉴别损失和对齐损失,能够发挥对比学习的能力增强代码排序模型的性能,相比于先前基于单元测试执行的方法,避免了执行代码执行的安全问题和用户提供单元测试的困难;相比于先前简单的基于分类的方法,迭代训练使得本发明的排序模型不仅注意代码的表现形式,更加习得代码的语义特征,进而排名更精确。

权利要求 :

1.一种基于迭代对比学习的代码重排方法,其特征在于,包括:获取自然语言问题描述对应的待排序的原始候选代码;

利用语义等价的程序转换程序技术扩增所述原始候选代码;

将原始候选代码和扩增后的代码同时输入至训练后的排序模型中,对每个代码进行排序;

取所得序列中,排序得分最高的原始候选代码作为所述自然语言问题描述的最后推荐的代码;

所述排序模型的训练步骤包括:

利用生成模型构建自然语言问题描述的原始代码集;

分别利用语义等价的程序转换程序技术和错误注入的程序转换技术扩增原始代码集;

利用错误注入的程序转换技术扩增原始代码集,包括:通过统计分析错误代码的常见异常类型,利用错误注入的程序转换技术为原始代码集中的正样本代码构建多个语义不同但表面形式相似的负样本代码;

利用原始代码集以及扩增后的代码集对排序模型进行迭代对比训练,得到训练后的排序模型;

所述利用原始代码集以及扩增后的代码集对排序模型进行迭代对比训练,包括:利用生成模型生成的正样本代码和负样本代码训练排序模型,计算鉴别损失L1:其中, 是从集合 中选择 的概率,它通过在排序得分上使用Softmax函数计算得到:

其中, 表示一条负样本, 表示正样本; 表示排序模型对于负样本的评分;

表示排序模型对于正样本的评分;

利用扩增后的正样本代码和负样本代码训练排序模型,计算对齐损失L2:其中, 分别代表锚点代码、正样本和负样本的语义表征向量;

表示余弦相似度函数;

迭代训练鉴别损失L1和对齐损失L2,更新排序模型参数,得到训练后的排序模型。

2.如权利要求1所述的一种基于迭代对比学习的代码重排方法,其特征在于,所述利用生成模型构建自然语言问题描述的原始代码集,包括:使用生成模型为数据集中的每一个自然语言问题描述产生N个候选代码,使用对应的单元测试执行采样得到的候选代码来生成对应的标签,完全通过单元测试的候选代码被视为正样本,未能通过任一单元测试的样本被视为负样本。

3.如权利要求1所述的一种基于迭代对比学习的代码重排方法,其特征在于,所述错误代码的常见异常类型包括:EOFError异常、Valueerror/TypeError异常、IndexError异常以及NameError异常。

4.如权利要求3所述的一种基于迭代对比学习的代码重排方法,其特征在于,所述利用错误注入的程序转换技术为原始代码集中的正样本代码构建多个语义不同但表面形式相似的负样本代码,包括:针对EOFError异常:在正样本代码行中随机插入input输入语句,并保持转换后代码的可编译性来构建负样本代码;针对Valueerror/TypeError异常:随机更改正样本代码中函数调用时参数的顺序、随机更改操作符左右参数的顺序、增加或者减少函数调用时的参数以及增加或者减少赋值语句左侧变量的个数来构建负样本代码;针对IndexError异常:通过在正样本代码列表和字符串序列对象的下标索引上随机加或者减一个数来构建负样本代码;

针对NameError异常:通过随机变换正样本代码中的变量名来构建负样本代码。

5.如权利要求1所述的一种基于迭代对比学习的代码重排方法,其特征在于,利用语义等价的程序转换技术扩增原始代码集包括:利用死代码插入、循环转换、变量重命名以及操作符/操作数交换方法为代码集中的正样本代码构建多个语义不变但表面形式变化的代码。

6.如权利要求1所述的一种基于迭代对比学习的代码重排方法,其特征在于,所述利用生成模型生成的正样本代码和负样本代码训练排序模型,计算鉴别损失L1,包括:通过排序模型计算排序得分;

利用Softmax函数以及排序得分计算从正样本和负样本代码集中鉴别出正样本代码的概率;

利用计算出的正样本代码的概率构建鉴别损失L1。

7.如权利要求1所述的一种基于迭代对比学习的代码重排方法,其特征在于,利用语义等价的程序转换技术扩增后的正样本代码和错误注入的程序转换技术扩增后负样本代码训练排序模型,包括:获取扩增后的正样本代码和负样本代码的表征,并以对比学习的方式,拉近正样本代码的表征而拉远负样本代码的表征。

8.如权利要求1所述的一种基于迭代对比学习的代码重排方法,其特征在于,所述迭代训练鉴别损失L1和对齐损失L2包括:最小化鉴别损失L1和对齐损失L2。

9.一种基于迭代对比学习的代码重排系统,其特征在于,包括:代码获取模块,被配置为:获取自然语言问题描述对应的待排序的原始候选代码;

代码扩增模块,被配置为:利用语义等价的程序转换程序技术扩增所述原始候选代码;

排序模型训练模块,被配置为:所述排序模型的训练步骤包括:利用生成模型构建自然语言问题描述的原始代码集;

分别利用语义等价的程序转换程序技术和错误注入的程序转换技术扩增原始代码集;

利用错误注入的程序转换技术扩增原始代码集,包括:通过统计分析错误代码的常见异常类型,利用错误注入的程序转换技术为原始代码集中的正样本代码构建多个语义不同但表面形式相似的负样本代码;

利用原始代码集以及扩增后的代码集对排序模型进行迭代对比训练,得到训练后的排序模型;

所述利用原始代码集以及扩增后的代码集对排序模型进行迭代对比训练,包括:利用生成模型生成的正样本代码和负样本代码训练排序模型,计算鉴别损失L1:其中, 是从集合 中选择 的概率,它通过在排序得分上使用Softmax函数计算得到:

其中, 表示一条负样本, 表示正样本; 表示排序模型对于负样本的评分;

表示排序模型对于正样本的评分;

利用扩增后的正样本代码和负样本代码训练排序模型,计算对齐损失L2:其中, 分别代表锚点代码、正样本和负样本的语义表征向量;

表示余弦相似度函数;

迭代训练鉴别损失L1和对齐损失L2,更新排序模型参数,得到训练后的排序模型;

代码排序模块,被配置为:将原始候选代码和扩增后的代码同时输入至训练后的排序模型中,对每个代码进行排序;

代码推荐模块,被配置为:取所得序列中,排序得分最高的原始候选代码作为所述自然语言问题描述的最后推荐的代码。

说明书 :

一种基于迭代对比学习的代码重排方法及系统

技术领域

[0001] 本发明属于计算机技术领域,尤其涉及一种基于迭代对比学习的代码重排方法及系统。

背景技术

[0002] 本部分的陈述仅仅是提供了与本发明相关的背景技术信息,不必然构成在先技术。
[0003] 程序合成任务旨在自动生成满足问题规范的可执行计算机程序,因其对软件行业的重大影响而备受关注。现有的代码生成模型都采用了一种基于采样的策略来生成多样的解决方案,这可以显著提高生成正确代码的概率,例如,尽管在HumanEval数据集上Codex的pass@1 (仅产生一个候选答案的通过率) 仅仅可以达到33.5%,但是它的pass@100 (如果针对给定问题生成的100个解决方案中的一个或多个能够通过相应的测试用例,则认为通过) 可以达到 77.4%。然而,在实际代码生成应用中(如Copilot),让用户从许多外观相似且可能包含微妙错误的候选中选出正确解决方案却是不现实的,这一问题使我们必须探索如何给众多候选排序来帮助选择最好的解决方案,以弥补pass@1和pass@100的差距。
[0004] 现有的代码候选排序的方法可以归纳为两类。一类是基于执行的方法。这种方法通过执行问题描述对应的单元测试重排候选代码。但是这一方法存在很大的问题:首先,由于环境依赖不满足、候选片段不完整以及执行模型生成的候选存在潜在的安全风险(读写磁盘)等问题,代码候选本身不被允许执行,在CoPilot这样的插件中采用基于执行的方法是不切实际的;其次,提供单元测试会给用户增加很多负担。另一类工作使用一个神经网络来为采样得到的程序排序。现有的方法将此视作一个多分类问题,然而简单的分类损失函数难以促使模型对微妙的程序错误做出区分。

发明内容

[0005] 为克服上述现有技术的不足,本发明提供了一种基于迭代对比学习的代码重排方法及系统,可以作为灵活方便地直接应用到现有的代码自动生成系统(如Copilot)中,且区别于先前的方法,该方法保证了代码重排时的及时性与安全性,并通过迭代的对比学习达到更高的准确性,为用户提供了巨大便利。
[0006] 为实现上述目的,本发明的一个或多个实施例提供了如下技术方案:
[0007] 本发明第一方面提供了一种基于迭代对比学习的代码重排方法,包括:
[0008] 获取自然语言问题描述对应的待排序的原始候选代码;
[0009] 利用语义等价的程序转换程序技术扩增所述原始候选代码;
[0010] 将原始候选代码和扩增后的代码同时输入至训练后的排序模型中,对每个代码进行排序;
[0011] 取所得序列中,排序得分最高的原始候选代码作为所述自然语言问题描述的最后推荐的代码;
[0012] 所述排序模型的训练步骤包括:
[0013] 利用生成模型构建自然语言问题描述的原始代码集;
[0014] 分别利用语义等价的程序转换程序技术和错误注入的程序转换技术扩增原始代码集;
[0015] 利用错误注入的程序转换技术扩增原始代码集,包括:通过统计分析错误代码的常见异常类型,利用错误注入的程序转换技术为原始代码集中的正样本代码构建多个语义不同但表面形式相似的负样本代码;
[0016] 利用原始代码集以及扩增后的代码集对排序模型进行迭代对比训练,得到训练后的排序模型。
[0017] 本发明第二方面提供了一种基于迭代对比学习的代码重排系统,包括:
[0018] 代码获取模块,被配置为:获取自然语言问题描述对应的待排序的原始候选代码;
[0019] 代码扩增模块,被配置为:利用语义等价的程序转换程序技术扩增所述原始候选代码;
[0020] 排序模型训练模块,被配置为:所述排序模型的训练步骤包括:
[0021] 利用生成模型构建自然语言问题描述的原始代码集;
[0022] 分别利用语义等价的程序转换程序技术和错误注入的程序转换技术扩增原始代码集;
[0023] 利用错误注入的程序转换技术扩增原始代码集,包括:通过统计分析错误代码的常见异常类型,利用错误注入的程序转换技术为原始代码集中的正样本代码构建多个语义不同但表面形式相似的负样本代码;
[0024] 利用原始代码集以及扩增后的代码集对排序模型进行迭代对比训练,得到训练后的排序模型;
[0025] 代码排序模块,被配置为:将原始候选代码和扩增后的代码同时输入至训练后的排序模型中,对每个代码进行排序;
[0026] 代码推荐模块,被配置为:取所得序列中,排序得分最高的原始候选代码作为所述自然语言问题描述的最后推荐的代码。
[0027] 以上一个或多个技术方案存在以下有益效果:
[0028] (1)本发明通过利用对比学习训练得到的代码排序模型对候选代码进行排序,相比于先前基于单元测试执行的方法,避免了执行代码执行的安全问题和用户提供单元测试的困难;相比于先前简单的基于分类的方法,迭代训练鉴别损失和对齐损失使得本发明的排序模型不仅关注代码的表面形式,更加学习到代码的本质语义特征,进而使得排名更精确,更快速高效。
[0029] (2)本发明通过生成和变换两种方式获得对比学习的正、负样本代码集:基于代码生成模型的预测结果以及基于生成结果的错误分布人工构造负样本。这两种难度更大的负样本可以促进对比学习的性能,能将代码生成模型在推理阶段的错误暴露在排序器之中,同时无需人工标注,可以快速便捷地大量生成。
[0030] (3)本发明对比学习包括:通过鉴别损失函数(The Discrimination Loss)训练,采用与生成模型推理时所生成分布相同的负样本进行训练,训练使得排序模型习得从大量生成模型产生的错误候选中鉴别出正确候选的能力;以及通过对齐损失函数(The Alignment Loss)训练,采用错误注入的程序转换技术构造与正确候选表面相似但语义不同的负样本代码进行对比学习,使得排序模型不仅关注候选代码的表面形式,而且学习到代码的本质语义特征,并同时增强排序模型区分微妙错误的能力。该训练方法可以使得模型更精确,且更具鲁棒性。
[0031] (4)在推理阶段,通过语义等价转换的的程序转换技术为每个生成的候选生成多个语义不变但语法改变的转换,然后计算这些转换上的平均排序得分,以减小训练时的过拟合并增强鲁棒性。
[0032] 本发明附加方面的优点将在下面的描述中部分给出,部分将从下面的描述中变得明显,或通过本发明的实践了解到。

附图说明

[0033] 构成本发明的一部分的说明书附图用来提供对本发明的进一步理解,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。
[0034] 图1为第一个实施例的一种基于迭代对比学习的代码重排方法流程图。
[0035] 图2为第一个实施例的Codex生成候选的运行时异常类型分布图。

具体实施方式

[0036] 实施例一
[0037] 如图1所示,本实施例公开了一种基于迭代对比学习的代码重排方法,包括:
[0038] 步骤S1:模型生成的负样本构建。本发明并非使用来自同一批(batch)中的对比样本,而是从生成模型 的预测中构建负样本。这种方法可以自动产生大量符合代码生成模型所产生的候选分布的的难负样本,且其在子词级别与正确候选相似但语义级别不同。而且,可方便快速地生成大量难负样本而无须人工标注;
[0039] 步骤S2:程序转换的正负样本构建。对于编程语言而言,微妙的错误即可导致语义的反转,这种微小的差别在排序问题中更为普遍。且对于排序问题而言,答案的搜索空间仅由生成模型采样得到的候选组成,正误候选之间高度相似的,所以模型难以区分这些表面相似但语义不同的代码。为了使得排序模型可以理解代码的本质语义而非仅关注其表面形式,在统计并分析了生成模型 采样得到的错误候选的运行时错误类型(如图2所示)后,受这些异常类型的启发,本发明设计了微妙错误注入的启发式方法来构建难负样本。一方面,由于这些错误参考了生成模型 产生的的实际错误,所以增强了排序模型区分这些典型错误的能力;同时,这些错误注入代码与原始代码在表面形式上尽可能相似,从而使排序模型更关注代码的本质语义而非表面形式,提升对含微小错误的代码的排序效果。同时,通过已有的正样本扩增方法,即变量重命名、死代码插入、For‑while转换等扩增了正样本;
[0040] 步骤S3:通过鉴别损失函数(The Discrimination Loss)训练。为训练排序模型从大量生成模型产生的错误候选中鉴别出正确候选的能力,本发明运用步骤S1构造的来自生成模型预测的负样本,通过一个鉴别损失函数,以对比学习的方式从训练模型从步骤S1构造的负样本中鉴别出正确代码。
[0041] 步骤S4:通过对齐损失函数(The Alignment Loss)训练。本发明运用步骤S2提到的程序转换的启发式方法,为数据集中的每个正确代码解决方案(即锚点代码)生成1个语义保护转换的正样本和 个错误注入转换的负样本。本发明通过对齐损失函数(The Alignment Loss),拉近锚点代码和其语义保护转换的正样本的距离,并且拉远锚点代码与其错误注入转换的负样本的距离。这样做的目的是:本发明认为,经过充分训练ranker应该为具有一致语义的代码提供相同的分数。通过对齐损失函数,使得排序模型在被错误注入代码的干扰的情况下,将锚点代码和其语义相同转换的代码在语义向量空间对齐,以使得排序模型为语义一致的代码打出相同的排序得分,而为语义不同但表面形式类似的代码打出不同的更低的排序得分。排序模型通过对齐损失函数更好地学习到代码的本质语义,并同时增强排序模型区分微妙错误的能力;
[0042] 步骤S5:为了使模型不仅关注代码的表面形式,而且进一步理解语法和语义,在鉴别损失后迭代训练对齐损失,两个损失函数交替进行训练,以层层递进的方式获得更好的语义表征。具体解释为:步骤S3中与生成模型推理产生的分布相同的负样本进行训练(即负样本由步骤S1得到),从而可增强排序器从错误候选结果分布中鉴别正确方案的能力;步骤S4中则通过错误注入转换技术构造表面相似但语义不同的负样本,使排序器更关注代码的本质语义而非表面形式,从而提升对含微妙程序错误代码的排序效果,并使得推理阶段更具有鲁棒性。
[0043] 步骤S6:在推理阶段,通过与训练时相同的语义保护程序转换技术为每个候选代码生成多个语义保护转换。然后,计算候选与其转换上的平均排序得分,以减小训练时的过拟合并增强鲁棒性。
[0044] 步骤S7:取所得序列中,排序得分最高的代码作为所述编程问题的最后推荐的代码。
[0045] 在步骤S1中,本发明为步骤S3的鉴别损失函数构建负样本。并非使用来自同一批(batch)中的对比样本,而是从生成模型的预测中构建负样本,具体为:
[0046] 训练数据集中一个样本包括以下条目:(1)编程问题(2)单元测试,即用于衡量编程问题的对应代码正确与否的测试样例。(3)标准答案(ground truth)即此编程问题对应的标准答案。本实施例使用的训练数据集是APPS数据集(自动化编程进度标准数据集, Automated Programming Progress Standard),共有5000个编程任务。使用代码生成模型为训练集中的每一个任务产生N个候选(在本发明的实验中,N=100)。然后使用对应的单元测试执行采样得到的代码候选来生成对应的标签,即正确或者错误。正确代表候选通过所有单元测试,为是正确解决方案;错误代表候选未通过任一单元测试,是错误候选。本发明将错误候选被视为难负样本。
[0047] 在步骤S2中,本发明为步骤S4的对齐损失函数构建正负样本。通过统计并分析代码生成模型生成的错误代码的常见错误类型,设计了错误注入的程序转换方法来构建难负样本。并参考已有的语义保护的程序转换方法,为步骤S4的对齐损失函数构造了所需的正样本。具体为:
[0048] (1)语义不同但表面形式相似的负样本构建。在统计代码生成模型中的运行时错误的分布情况后,本发明模拟这些错误类型,构建语义不同但表面相似的负样本。以下转换方法皆借助代码抽象语法树解析工具tree‑sitter实现:
[0049] (1‑1)针对EOFError异常(即当程序中存在多余的input()语句时程序所抛出的异常),在代码行中随机插入input语句(即输入语句),并保持转换后代码的可编译性。
[0050] (1‑2)针对Valueerror异常(即当函数参数具有正确的类型但不正确的数值时程序所抛出的异常)和TypeError(即当函数应用在不正确的参数类型时程序所抛出的异常),总而言之,以上两种异常类型多是由于函数参数不匹配的原因导致的。随机更改代码中函数调用时参数的顺序、随机更改操作符左右参数的顺序、增加或者减少函数调用时的参数、增加或者减少赋值语句左侧变量的个数来模拟这一类型的错误。
[0051] (1‑3)针对IndexError异常(即当当序列下标越界时程序所抛出的异常),通过在列表、字符串等序列对象的下标索引上随机加或者减一个数来模拟这种错误类型。具体来说,将源代码使用tree‑sitter解析为ast,然后遍历寻找其本身节点类型为整数并且其父节点的节点类型为下标的叶子节点,并将找到的叶子节点随机+或‑Random(n)[0052] (1‑4)针对NameError异常(即当当局部或者全局的变量名未找到时程序所抛出的异常),通过随机变换代码中的变量名来模拟这种错误。具体来说,为了保证变换后代码的可编译性并增加负样本的难度,首先使用tree‑sitter提取函数中所有的变量名,形成变量名列表,并对于代码中的变量,选择变量列表中随机的变量名进行替换。
[0053] (2)语义相同但表面形式不同的正样本构建。借助代码抽象语法树解析工具tree‑sitter实现以下转换方法:
[0054] (2‑1)循环转换:此方法将for循环修改为等价的while循环,反之亦然。
[0055] (2‑2)死代码插入:在原始代码中的随机位置注入死代码块。“死代码”是指出现在源代码中但从未执行的代码。
[0056] (2‑3)操作符操作数交换:改变二进制逻辑运算的操作符和操作数。例如,对于 if high>=low ,将其变换为if low<= high。
[0057] (2‑4)变量重命名:随机按一定比例将一些变量重命名为Var_i。例如,将 ans = b + c 变换为 ans = Var_1 +Var_2。
[0058] 在步骤S3中,通过鉴别损失函数(The Discrimination Loss)训练。为训练排序模型从大量生成模型产生的错误候选中鉴别出正确候选的能力,本发明运用步骤S1构造的来自生成模型预测的负样本,通过一个鉴别损失函数,以对比学习的方式从训练模型从步骤S1构造的负样本中鉴别出正确代码。具体为:
[0059] (3‑1)使用 表示编程问题。使用 表示其标准答案。首先通过生成模型 采样产生大量错误候选,并随机选择 个错误候选作为负样本, 是超参数,代表鉴别损失函数(The Discrimination Loss)中负样本的数量,一个编程问题在步骤S3的正样本表示为,而其负样本集合最终表示为 。本发明将候选与问题 拼接后送入排序模型。
[0060] (3‑2)首先通过排序模型计算排序分数 ,该分数表示排序模型给出的候选代码的质量:
[0061]
[0062] 表示排序模型,具体来说,使用在TransformerEncoder输出上方进行平均池化后加一层全连接层作为排序模型,具体为:
[0063]
[0064]
[0065]
[0066] 其中 用于提取语义 对应的 维语义表征向量 ,用于将 投射为一个常数值(即排序分数 )。
[0067] 可以通过最小化对比损失来训练:
[0068]
[0069] 此处 是从集合 中选择 的概率,它通过在排序得分上使用Softmax函数计算得到:
[0070]
[0071] 其中, 表示一条负样本; 表示模型对于负样本的评分; 表示模型对于正样本的评分;
[0072] 在步骤S4中,通过对齐损失函数(The Alignment Loss)训练。本发明运用步骤S2提到的程序转换的启发式方法,为数据集中的每个正确代码解决方案(即锚点代码)生成1个语义保护转换的正样本和m个错误注入转换的负样本。本发明通过对齐损失函数(The Alignment Loss),拉近锚点代码和其语义保护转换的正样本的距离,并且拉远锚点代码与其错误注入转换的负样本的距离。具体为:
[0073] 运用步骤S2提到的程序转换的启发式方法,为数据集中的每个正确代码解决方案(即锚点代码)生成1个语义保护转换的正样本和 个错误注入转换的负样本。其中 是超参数,表示这一步的负样本数量。因此,对齐损失函数可以表示为:
[0074]
[0075] 其中, 分别代表锚点代码、正样本和负样本的语义表征向量,即通过 得到; 表示余弦相似度函数;
[0076] 在步骤S5中,迭代训练 和 ,即在训练 后迭代训练 ,如此反复,两个损失交替训练,使模型不仅关注代码的表面形式,而且进一步理解语法和语义,训练过程如算法1所示。
[0077] 其迭代训练过程的原因解释为:通过步骤S3中与生成模型推理产生的分布相同的负样本进行训练(即负样本由步骤S1得到),从而可增强排序器从错误候选结果分布中鉴别正确方案的能力;步骤S4中则通过错误注入转换技术构造表面相似但语义不同的负样本(即负样本由步骤S2得到),并通过语义保护转换构造正样本,使排序器更关注代码的本质语义而非表面形式,从而提升对含微妙程序错误代码的排序效果,并使得推理阶段更具有鲁棒性。对于同一正确解决方案,本发明使其依次经过阶段1和阶段2,以一种层层递进的方式获将其投射到更好的表征空间。
[0078] 算法 1训练过程:
[0079] 定义:排序模型 ,生成模型 ,采样个数N,S3和S4的负样本个数 ;
[0080] 1)使用 为每个问题 采样N个候选解决方案,执行单元测试区分为正误候选;
[0081] 2)对于训练集中每个问题 ,正确解决方案 ,都进行步骤3)、4)、5)、6);
[0082] 3)从 生成的错误候选中随机抽取k个错误候选形成负样本集合 ;
[0083] 4)步骤S3中 的负样本集合为 ,用 更新模型参数;
[0084] 5)为锚点 随机产生1个语义保护转换的正样本和 个错误注入转换的负样本集合 ;
[0085] 6)步骤S4中 负样本集合为 ,用 更新模型参数;
[0086] 7)结束。
[0087] 在步骤S6中,在推理阶段,通过与训练时相同的语义保护转换技术为每个生成的候选生成a个语义不变但语法改变的转换,因此,每一种候选被拓展为(a+1)种表现形式,通过排序模型为这(a+1)种表现形式分别打分,并取其平均得分作为最终得分:
[0088]
[0089] 其中, 表示(a+1)中表现形式中的任意一种,即为原始候选或者原始候选的一种语义保护转换。
[0090] 通过平均得分,增强了最终得分的鲁棒性;
[0091] 需要说明的是,在推理阶段,利用语义等价转换技术扩增后的代码不参与最终的排序结果的输出,但是需要输入排序模型,语义等价转换的代码与原始代码一起输入排序模型,最后原始代码的排序得分由语义等价转换的代码和原始代码的平均得分获得;因为是平均分,所以这个分数更具有鲁棒性。
[0092] 例如,在实际代码自动生成应用场景中,用户输入以下问题:请用python语言书写一个判断是否为闰年的代码。代码生成模型通过采样,给出10个候选答案:
[0093] 候选答案①:
[0094] year=int(input("请输入年份:"))
[0095] if(year%4==0 and year%100 !=0):
[0096] print("是闰年!")
[0097] else:
[0098] print("不是闰年!")
[0099] 候选答案②:
[0100] year=int(input("请输入年份:"))
[0101] if(year%4==0 and year%100 !=0):
[0102] print("是闰年!")
[0103] elif(year%400==0):
[0104] print("是闰年!")
[0105] else:
[0106] print("不是闰年!")
[0107] 候选答案③:
[0108] year=int(input("请输入年份:"))
[0109] if(year%4=0 and year%100 !=0):
[0110] print("是闰年!")
[0111] elif(year%400=0):
[0112] print("是闰年!")
[0113] else:
[0114] print("不是闰年!")
[0115] ……
[0116] 候选答案⑩:
[0117] year=int(input("请输入年份:"))
[0118] if(year%4==0 or year%100 !=0):
[0119] print("是闰年!")
[0120] elif(year%400==0):
[0121] print("是闰年!")
[0122] else:
[0123] print("不是闰年!")
[0124] 其中,②号候选为正确候选,其余候选均包含了细微错误。如①号候选缺少判断每400年为一次闰年的特殊条件:elif(year%400==0):print("是闰年!");③号候选将elif(year%400 == 0):中的“==”错写为“=”;⑩号候选将if(year%4==0 and year%100 !=0)中的“and”错写为“or”。
[0125] 如果让用户直接从10个候选中选出正确候选,由于候选之间差异细微,所以甄别难度非常大,给用户带来的负担甚至会超过用户自己书写代码的负担,对用户极度不友好,代码自动生成应用也将难以普及并帮助提高生产力。
[0126] 然而,通过本发明的代码重排系统,每个候选的置信得分(排序得分)将由排序模型给出,如:
[0127] ①号候选:75;②号候选98;③号候选:85;……;⑩号候选:90。
[0128] 由此,用户发现②号候选得分最高,即其最有可能是正确候选,用户会率先尝试②,即找到正确答案。由此,减轻了用户从头鉴别正确候选的负担,使得代码自动生成应用更加方便友好。
[0129] 实施例二
[0130] 本实施例公开了一种基于迭代对比学习的代码重排系统,包括:
[0131] 代码获取模块,被配置为:获取自然语言问题描述对应的待排序的原始候选代码;
[0132] 代码扩增模块,被配置为:利用语义等价的程序转换程序技术扩增所述原始候选代码;
[0133] 排序模型训练模块,被配置为:所述排序模型的训练步骤包括:
[0134] 利用生成模型构建自然语言问题描述的原始代码集;
[0135] 分别利用语义等价的程序转换程序技术和错误注入的程序转换技术扩增原始代码集;
[0136] 利用所述的错误注入的程序转换技术扩增原始代码集,包括:通过统计分析错误代码的常见异常类型,利用错误注入的程序转换技术为原始代码集中的正样本代码构建多个语义不同但表面形式相似的负样本代码;
[0137] 利用原始代码集以及扩增后的代码集对排序模型进行迭代对比训练,得到训练后的排序模型;
[0138] 代码排序模块,被配置为:将原始候选代码和扩增后的代码同时输入至训练后的排序模型中,对每个代码进行排序;
[0139] 代码推荐模块,被配置为:取所得序列中,排序得分最高的原始候选代码作为所述自然语言问题描述的最后推荐的代码。
[0140] 本领域技术人员应该明白,上述本发明的各模块或各步骤可以用通用的计算机装置来实现,可选地,它们可以用计算装置可执行的程序代码来实现,从而,可以将它们存储在存储装置中由计算装置来执行,或者将它们分别制作成各个集成电路模块,或者将它们中的多个模块或步骤制作成单个集成电路模块来实现。本发明不限制于任何特定的硬件和软件的结合。
[0141] 上述虽然结合附图对本发明的具体实施方式进行了描述,但并非对本发明保护范围的限制,所属领域技术人员应该明白,在本发明的技术方案的基础上,本领域技术人员不需要付出创造性劳动即可做出的各种修改或变形仍在本发明的保护范围以内。