开发者博客 – IT技术 尽在开发者博客

开发者博客 – 科技是第一生产力


  • 首页

  • 归档

  • 搜索

论文笔记:CodeSearchNet Challenge E

发表于 2023-01-09

导语

本文记录了GitHub 团队在2019年发布的CodeSearchNet 语料库论文的学习笔记,该语料库旨在为代码搜索领域提供基准数据集,提升代码搜索结果的质量。

  • 会议:Arxiv 2019
  • 链接:arxiv.org/abs/1909.09…

1 简介

尽管深度学习模型已经能够帮助人们处理非常多的任务,但在面对高度结构化数据(编程代码)的任务,如代码语义搜索时,其性能仍有待提升。标准的信息检索方法在代码搜索领域效果不佳,因为搜索词和结果之间通常很少共享词汇表(例如,考虑一个名为deserialize_JSON_obj_from_stream的方法,它可能是查询“read JSON data”的正确结果)。更具挑战的是,评估这项任务的方法非常困难,因为没有为这项任务创建实质性的数据集。

为了解决这个问题,本文发布了一个名为CodeSearchNet的语料库,并基于此构建了该任务的基准:CodeSearchNet挑战。CodeSearchNet语料库是通过编程方式获取的,方法是抓取开源存储库,并将单个函数与其(经过处理的)文档作为自然语言注释进行配对。它有着约200万个数据示例,可以在任务上训练高容量的深度神经模型。

CodeSearchNet挑战由99条自然语言查询组成,并与六种编程语言(Go, Java, JavaScript, PHP, Python和Ruby)的可能相关结果配对。每个查询/结果对都由人类专家标记,表明结果与查询的相关性。最后,本文也给出了一些该基准上的简单Baseline模型。

2 CodeSearchNet语料库

由于大规模标注是不现实的,因而作者将开源软件中的函数与各自文档中出现的自然语言配对作为一种标注信息。详细步骤如下:

数据收集

作者从公开可用的开源非fork GitHub存储库收集语料库,删除许可证模糊的项目。然后,使用TreeSitter (GitHub的通用解析器)标记所有Go、Java、JavaScript、Python、PHP和Ruby函数(或方法),并在可用的情况下,使用启发式正则表达式标记它们各自的文档文本。

数据过滤

作者只使用那些具有文档描述的函数示例,并使用如下的启发式规则对函数cic_ici和检索到的文档did_idi进行过滤:

  • 截断did_idi,只使用第一段;
  • 删除掉cic_ici小于3行或did_idi少于3个token的示例;
  • 删除掉函数名中包含’test’子字符串的示例;
  • 去除重复的示例;

数据集统计

经过过滤后的数据集统计指标如下:

image.png

局限性

自动化收集的数据有以下局限性:

  1. 文档从根本上不同于查询,因此使用其他形式的语言。与搜索查询不同,它通常与文档代码在同一时间由同一作者编写,因此倾向于使用相同的词汇表。
  2. 尽管进行了数据清理,但无法知道每个文档准确描述其相关代码片段的程度。例如,许多注释对于它们所描述的代码来说已经过时了。
  3. 一些文档是用其他语言编写的,而CodeSearchNet Challenge评估数据集主要关注英语查询。

3 CodeSearchNet挑战

为了在CodeSearchNet Challenge上进行评估,作者为一个方法必须为99个预定义的自然语言查询中的每一个返回一组来自CodeSearchNet语料库的相关结果。注意,这个任务在某种程度上简化了一般的代码搜索任务,只允许完整的函数/方法作为结果,而不允许任意的代码块。

Query收集

本文从Bing上获得了一些常见的搜索查询,这些查询的代码点击率很高,并将这些查询用StaQC模型进行重写。

image.png

专家标注

显然,不能注释所有的查询/函数对(数据量太大)。作者首先使用基线方法的实现并集成它们(参见第4节),为每个查询和编程语言生成10个候选结果(即可能的相关代码)。使用web界面进行标注(参见图1),每次显示一个查询/函数对,如图2所示。

image.png

实验表明,一些标注者发现检查代码片段的上下文有助于判断相关性。显示给用户的查询/代码对的顺序是随机的,这样允许用户单独对每对的相关性进行评分。

标注统计

本文收集了6种编程语言中的4026个标注,统计数值如下。

image.png

定性观察

作者发现了标注过程中的一下问题:

  • 代码质量。有很多代码(即使是知名的repo)是低效、不安全的实现方式,为此,标注者也打了低分;
  • Query歧义性。有些问题本身就是不明确的,如how to determine if a string is a valid word?这里的valid word具体定义不明确。
  • 使用特定库函数。
  • 上下文。有些结果在语义上是正确的,但不依赖于相关的辅助函数。
  • 方向性。实验结果中的一个常见问题是函数实现了查询的反向功能,例如“convert int to string”得到stringToInt回答。

3.1 模型评估

由于结果是一个有序的查询列表,所以评估指标使用normalized discounted cumulative gain (NDCG),并在两种语料库规模上进行评估:

  1. 只在专家标注的数据上;
  2. 在全部数据上。

对该指标不明确的同学可以参考:zhuanlan.zhihu.com/p/136199536

4 Baseline方法

4.1 联合向量空间编码

本文的训练目标是将代码和相应的语言映射到彼此接近的向量(也就是指代码文本和问题文本都在同一个嵌入空间中)上,因为我们可以通过嵌入查询来实现搜索方法,然后返回嵌入空间中“接近”的代码片段集。

image.png

模型如图3所示。编码器使用下列模型:

  • Neural Bag of Words。
  • Bidirectional RNN models。这里使用GRU。
  • 1D卷积网络。
  • Self-attention。

在训练过程中,我们得到了一组N对(ci,di)(c_i, d_i)(ci,di)的代码和自然语言描述,并实例化了一个代码编码器EcE_cEc和一个查询编码器EqE_qEq。我们通过最小化损失来训练:

image.png

4.2 Elasticsearch基线方法

作者也采用了ES作为一种搜索的基线方法。

4.3 评估

下表展示了实验结果(前面说的用NDCG,这里表格又使用了MRR作为评估指标,有些迷惑):

image.png

5 相关工作

略

6 总结

本文发布CodeSearchNet语料库,并提出CodeSearchNet挑战,其中包括99个自然语言查询,以及来自CodeSearchNet语料库的大约4k专家相关注释。该语料库包含了大约600万个来自六种编程语言(Go、Java、JavaScript、PHP、Python和Ruby)的开源代码函数。CodeSearchNet语料库还为200万个函数包含自动生成的类似查询的自然语言,这些语言是通过机械抓取和预处理相关的函数文档获得的。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

【若川视野 x 源码共读】第41期 vant 4 正式发

发表于 2023-01-09

源码共读前言

为了能帮助到更多对源码感兴趣、想学会看源码、提升自己写作和前端技术能力的同学。 帮助读者夯实基础,查漏补缺,开阔眼界,拓宽视野,知其然知其所以然。

我倾力组织了每周一起学200行左右的源码共读活动。我写有《学习源码整体架构系列》20余篇,走过路过的小伙伴可以点击关注下这个目前是掘金关注数最多的专栏。

欢迎点此扫码加我微信 ruochuan02 交流,参与 源码共读 活动,每周大家一起学习200行左右的源码,共同进步。可以持续关注我@若川。

从易到难推荐学习顺序

活动介绍和顺序具体看这里从易到难推荐学习顺序

提交笔记

提交笔记方式,具体的看这里
简言之:看任务,看辅助文章、看源码,交流讨论,在掘金写笔记,写好后提交到本文评论区。

为了给大家谋福利,另外给大家的文章带来更多阅读量,便于搜索,从2022年3月27日起,笔记可以直接发布在掘金,以《标题自取》标题不限,可以取个好标题,容易被掘金推荐。

笔记文章开头加两句话:

  • 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
  • 这是源码共读的第xx期,链接:xxx。

笔记文章最后,建议写上总结、收获、感受等。

  • 开头第一句作用是:方便每月统计评优,掘金赞助送小礼物。顺便帮忙宣传推广,让更多人参与进来,一起学习。
  • 开头第二句作用是:加上是多少期,当前任务说明的链接,方便读者知道这是什么活动。

笔记写完后,到当前期活动的文章评论区留言自己的文章和笔记特点。方便大家查阅学习交流讨论。

任务发布时间

2023年1月9日 - 2023年3月5日。可以按照自己节奏学习,提交笔记即可(不一定要严格按照我规定的时间)。往期共读也可以及时复习,笔记未完成可以继续完成。

语雀本期任务说明链接

语雀有树形菜单,更方便查看,所以也放下语雀的这一期链接

学习任务

    1. 学会 vant 组件库暗黑主题的原理和实现
    1. 学会使用 vue-devtools 打开组件文件,并可以学会其原理
    1. 学会 iframe postMessage 和 addEventListener 通信
    1. 学会 ConfigProvider 组件 CSS 变量实现对主题的深度定制原理
    1. 学会使用 @vue/babel-plugin-jsx 编写 jsx 组件
    1. 等等
  • 参考我的文章
  • juejin.cn/post/715823…

参考文章

  • juejin.cn/post/715823…
  • 看文章,看源码,交流讨论,写笔记发布在掘金。再在掘金这篇文章下评论放上提交笔记的链接。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

低代码平台组件间通信方案复盘

发表于 2023-01-04

背景介绍

3年前我开发了一款零代码搭建平台 H5-Dooring, 主要目的是想用更低的成本, 更快的效率, 上线 web 页面(其实是不想写重复的代码了,写麻了). 好在陆陆续续折腾了3年, 目前已经可以满足基本的页面设计和搭建能力, 并能快速上线页面.

之前也在社区分享了很多低代码和零代码的技术实现, 接下来继续和大家聊聊低代码平台中组件与组件之间的通信方案设计.

可视化搭建平台的基本能力

根据我自己设计可视化搭建平台的经验, 其需要具备最最基本的两个能力:

  • 静态页面设计能力(也就是可以用可视化平台制作我们想要的页面的能力)
  • 组件交互能力(制作好静态页面之后, 页面元素能具备一定的交互, 比如跳转链接, 打开弹窗等)

以上的能力可以让我们将页面通过拖拽的方式搭建出来:

虽然这已经可以满足很多展示型的需求, 但是仍然存在局限性, 比如可视化平台的组件与组件之间, 没办法相互通信.

更灵活自主的可视化搭建平台

这里给大家举一个实际的场景, 比如我们要做一个转盘H5页面, 它由转盘组件和按钮组件组成, 当点击按钮时, 转盘开始运动:

这种场景就需要转盘组件和按钮组件相互通信, 来实现交互功能. 所以在可视化搭建平台中, 如果能实现组件间的通信, 那将覆盖更多的业务场景, 从而为个人或者企业带来更大的价值.

接下来我将和大家分享一下低代码平台中组件间通信的几种方案, 共大家学习参考.

组件间通信的几种实现方案

说到组件通信我们也许并不陌生, 比如在 vue 或者 React 框架中, 经常会涉及到父子组件通信以及组件与组件间的通信, 常用的方案也有很多, 比如:

  1. props/$emit
  2. 子组件向父组件传值
  3. eventBus($emit/$on)
  4. vuex / redux
  5. $attrs/$listeners
  6. provide/inject

当然还有很多方式能帮我们实现传统组件间的通信, 那我们在低代码组件中, 也可以参考类似的方式来实现, 但是唯一的区别是需要设计一套规则, 来保证组件间通信可以通过用户配置的方式来运转.

接下来我们来分析几种低代码组件间的通信方案.

1.websocket

在设计组件通信方案前, 我们需全局维护一个公共的状态, 拿 H5-Dooring可视化平台 举例, 我们用 redux 管理公共状态, 组件间通信本质就是触发公共状态的更新:

为了保证低代码组件库足够纯净, 比如不应该在组件里连接 redux, 所以我们需要把 redux 触发器 dispatch 放在页面的全局, 这里就可以用 websocket, 在组件里触发 socket 指令, 在页面全局来监听, 并触发 dispatch :

当然使用 socket 的方式仍然会让低代码组件库负重前行(虽然能实现更自由的通信场景, 比如组件自更新, 生命周期回调, 控制业务钩子等), 因为我们不得不为其搭建 socket 服务, 并且需要为其设计稳定的通信桥梁, 比如 socket 心跳连接等.

2.iframe通信 postmessage

利用 iframe 的 postmessage 等 API 虽然也能实现组件间通信, 但是我们需要设计一套通信机制, 保证 iframe 能接受组件传送的指令, 并对外暴露共享状态:

我们从 Iframe 的通信模式可以发现它不仅可以作为中间桥梁起到通信作用, 有点类似于 eventBus的模式, 而且还可以实现页面间的通信, 比如目前很多微前端架构的底层支持也有采用 iframe 来设计的. 但是对于更细粒度的低代码组件来说, 有点小题大作了.

接下来给大家分享一下 iframe 通信的基本代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
js复制代码// 父页面和子页面通信
// A.html (父)
<iframe src="http://h5.dooring.cn/h5_plus" frameborder="1" id="Bframe"></iframe>
const msg = {
name: "H5-Dooring"
}
window.onload = () => {
// 自动调用必须放在onload中,通过事件调用则不用
// let frame = document.querySelector("#Bframe").contentWindow
let frame = window.frames[0]
frame.postMessage(msg, "http://h5.dooring.cn/preview")
}

// B.html
window.addEventListener("message", (e) => {
console.log(e.data)
console.log(e.origin)
console.log(e.source)
})

// 子页面和父页面通信
// A.html (父)
<iframe src="http://h5.dooring.cn/h5_plus" frameborder="1" id="Bframe"></iframe>
window.addEventListener("message", (e) => {
console.log(e.data)
console.log(e.origin)
console.log(e.source)
})

// B.html
const msg = {
name: "Dooring H5"
}
window.top.postMessage(msg, "http://h5.dooring.cn/preview")

3.Event Emitters

Event Emitters 的方式我觉得是最适合低代码组件间通信的方案, 类似于 js 里的事件监听机制, 我们可以给 dom 绑定监听, 并暴露事件给用户来实现手动触发机制. (虽然不一定是用户手动触发, 也有一种情况是逻辑触发, 比如当页面某个组件到达某一状态的时候, 后自动触发事件, 来改变其他组件的状态)

Event Emitters 类似一种观察者模式, 我们可以利用 javascript 的设计模式来实现它, 并在组件内部来监听或者触发, 一个简单的实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
js复制代码interface Events {
[key: string]: Function[];
}

export class EventEmitter {
public events: Events;
constructor(events?: Events) {
this.events = events || {};
}

public subscribe(name: string, cb: Function) {
(this.events[name] || (this.events[name] = [])).push(cb);

return {
unsubscribe: () =>
this.events[name] && this.events[name].splice(this.events[name].indexOf(cb) >>> 0, 1)
};
}

public emit(name: string, ...args: any[]): void {
(this.events[name] || []).forEach(fn => fn(...args));
}
}

具体设计流程有点像我之前设计的 iframe 通信架构, 不过使用起来会更简单:

低代码组件事件队列设计

以上只实现了组件的通信, 并没有将通信和实际的应用场景结合起来, 比如低代码用户需要如何操作,才能实现组件通信. 这里我之前也设计了一套模型:

每个组件都有一套事件列表, 用户可以给一个组件添加多个交互事件, 在第代码内部通过循环遍历来依次触发事件队列:

事件通信就可以用上面介绍的 Event Emitters来实现, 具体的低代码模式可以参考我之前的项目:

H5-Dooring可视化低代码平台

总结

后续我会继续和大家分享一下 H5-Dooring 低代码的更多实践和思考, 如果大家对可视化低代码感兴趣也可以参考我的低代码可视化专栏.

下一篇文章我会和大家分享一下低代码印章组件的实现方案, 大家有更多好的建议也可以随时和我反馈.

:::: column
::: column-left

H5-dooring低代码

H5-dooring低代码

:::
::: column-right

V6.Dooring可视化大屏搭建平台

V6.Dooring可视化大屏搭建平台

:::
::::

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

论文笔记:CodeGen An Open Large La

发表于 2023-01-03

导语

  • 会议:ICLR 2023在投
  • 链接:arxiv.org/abs/2203.13…

1 简介

程序合成(program synthesis)的目标是使编码过程自动化,并生成满足用户指定意图的计算机程序。该任务有两个关键挑战:

  1. 难以处理的搜索空间;
  2. 正确指定用户意图的困难。

为了成功地实现程序合成,用户必须采用一些方法将其意图传达给模型,例如逻辑表达式(指定程序输入和输出之间的逻辑关系)、伪代码、输入-输出示例或自然语言的语言化规范。一方面,完整的正式规范具有用户意图的确切规范,但可能需要用户的领域专业知识和努力来将意图转换为这样的形式。另一方面,仅仅基于输入-输出示例的规范成本较低,但可能没有详细说明意图,导致不准确的解决方案。

image.png

为了克服这些挑战,本文提出了一种多轮次程序合成方法(如图1),其中用户通过逐步用自然语言提供规范来与合成系统交互,同时以合成子程序的形式接收系统的响应,这样用户和系统一起在多个步骤中完成完整的程序合成。以下两个考虑因素激发了这种方法:

  1. 将一个潜在的长而复杂的规范分解为多个步骤将简化模型的理解,能够增强模型的程序合成能力;
  2. 代码表现出自然语言和编程语言交错的弱模式,这可能是可利用的。如果将一个单轮的复杂问题分解为若干多轮的子问题后,用户意图可以在多个轮次中表达,即意图可以部分分解和实现,而每个回合都可以很容易地用自然语言表达。

为此,作者还发布了一个多轮次程序合成数据基准MTPB (Multi-Turn Programming Benchmark)来衡量模型的多轮次程序合成能力。本文的主要贡献如下:

  • 研究了不同size自回归模型中在多轮次程序合成任务中的emerging现象(参考);
  • 利用这种emerging能力引入多轮次程序合成范式;
  • 利用一种新的多轮次程序合成基准来定量研究它的性质;
  • 开源了模型checkpoint和自定义训练库:JAXFORMER。

2 模型训练

作者主要在模型规模(四种size:350M, 2.7B, 6.1B, 16.1B)和预训练数据(The PILE, BigQuery,BigPython)方面对多轮次程序合成任务进行了实验探究。

2.1 数据集

作者提出的CodeGen模型主要在以下三个数据集上按顺序进行预训练:

image.png

  • The Pile:拥有825GiB的英语文本和代码,曾被GPT-Neo、GPT-J等模型预训练采用。在该数据集上训练得到的模型称为CodeGen-NL;
  • BigQuery:作者采用了BigQuery数据集中的以下六种编程语言,即C, C++, Go, Java, JavaScript,Python的代码数据继续预训练,得到的模型称为CodeGen-Multi;
  • BigPython:该数据集只包含了Python语言的文件(主要是为了下游任务),在该数据集上继续预训练得到的模型称为CodeGen-Mono。

2.2 模型

CodeGen模型采用自回归Transformer的形式,将next-token prediction语言建模作为学习目标。CodeGen有350M、2.7B、6.1B和16.1B参数的size。前三种参数大小配置可以与文本语料库上训练的开源大型语言模型进行直接比较,如GPT-Neo (350M, 2.7B) 和GPT-J (6B)。训练超参设置如下表:

image.png

以自然语言描述为条件的程序合成的emergence可能源于模型和数据的大小、训练目标和训练数据本身的性质。emergence指的是大规模的无监督语言模型可以以zero-shot的方式解决未见过的任务。这种现象的出现往往归因于模型和数据的大尺度。

数据由来自GitHub,其中一些数据呈现自然语言和编程语言交错的模式,作者认为由于next token prediction的训练目标,为程序合成能力提供了一个有噪声的监督信号。影响程序综合能力的主要因素有两个:1)模型规模和数据规模大,2)训练数据中有噪声信号。

3 单轮次评估

作者首先在HumanEval上进行了评估,也被称为单轮次评估。

3.1 不同参数和预训练数据规模的模型表现

整体结果如下表所示:

image.png

从单轮结果来看,作者使用的按顺序的预训练对最终结果是有帮助的(如Multi模型比NL模型好,Mono模型比Multi模型好)。

3.2 对用户意图更好的理解有助于程序合成

作者认为,程序合成系统的成功在很大程度上取决于它对用户意图的理解程度。为此,作者比较了4种不同size的CodeGen-Mono模型在预测正确和预测不正确的问题上的perplexity,对比结果如下表:

image.png

可以看到,模型对这些预测错误的样例的理解差于对预测正确样例的理解(错误样例的ppl更高)。因此,作者推测,类似于这种模式的用户意图规范将更好地被模型理解,从而导致更好的程序合成。受到这种模式的启发,作者提出在多个轮次中指定用户意图,这样模型一次只关注部分问题,这将使模型更容易理解用户意图。

4 多轮次评估

4.1 数据集构建

作者提出并研究了一种多步骤程序合成范式,该范式将程序合成分解为多个步骤,系统在每个步骤中合成一个子程序。为此,作者首先开发了一个多回合编程基准(MTPB)。MTPB由专家编写的115个问题组成,每个问题都包含自然语言(提示)的多步骤描述。为了解决问题,模型需要合成功能正确的子程序(1)遵循当前步骤的描述,(2)考虑前面步骤的描述和合成子程序(例如,对前面步骤中定义的函数和/或变量的正确反向引用)。图1显示了一个说明性示例。

4.2 执行环境

HumanEval的程序段是在一个完整的程序中填入部分函数代码,因此整体框架是比较完整的,易于执行和评估。而在MTPB中,不能保证生成这样的入口点(或返回值)。为了解决这个问题,作者强制对程序的最后一步进行print操作,以此来检验执行结果。

4.3 不同参数和预训练数据规模的模型表现

同样,作者比较了不同预训练数据下的不同参数规模的模型的实验表现,可以看到,CodeGen-Mono在多轮情况下表现非常好。

image.png

4.4 使用问题分解来更好的理解用户意图

作者认为,多轮次分解增强了模型对用户意图规范的理解,从而导致更好的程序合成能力。为了验证这个假设,作者将多轮问题拼接成一个prompt文本,比较了多轮次prompt和串联单轮次prompt的PPL。

实验结果如表4所示,对所有模型而言,单轮次比多轮次具有更高的平均PPL。因此,将用户规范分解为多个步骤,并利用大型语言模型的emergence能力,似乎可以让模型更容易地理解,更成功地合成程序。

image.png

此外,作者根据问题的平均通过率按难度级别对问题进行分类,分析不同模型在不同难度下的多轮次与单轮次性能差异。如图2所示(纵轴的值指的是多轮次比单轮次性能高的百分点数),在几乎所有模型尺寸和难度级别中,多轮次提示都比单轮次提示有显著改进,大多数改进接近或高于10个百分点。有趣的是,较大的模型(6.1B和16.1B)对于简单问题的多轮次分解后性能是不变的(参见图2中的两个短条,0.19%和- 0.25%)。这意味着当问题可以很容易地被模型理解时(由于问题的简单性和较大模型的高容量的共同作用),对规范进行因式分解是没有必要的。这实际上与作者的动机假设是一致的,即分解复杂的规范可以简化问题的理解并改进程序的综合。

4.5 定性分析

作者也给出了一些16.1B的最大模型在某些情况下不如小模型(2.7B)灵活的例子,如下图:

image.png

image.png

大模型初始化一个数字总是得到一个整数,尽管提示要求转换为字符串(图3),或者提示中的“return”关键字触发了一个函数定义,而目的是直接生成一个可执行程序(图4)。

image.png

image.png

然而,一般来说,大型模型克服了由于较小模型提示错误解释而导致的错误,包括同时分配多个变量(图5)或理解任何比较的概念(图6)。

5 相关工作

略

6 总结

本文利用在大量代码数据语料库上训练的大型因果语言模型来研究程序合成。随着模型大小和数据大小的增加,从简单的语言建模中获得理解长上下文和生成一致响应的能力。利用这种能力,并观察到更好的用户意图理解会带来更好的程序合成,作者提出了一种多步骤程序综合方法,其中程序合成是通过多轮次规范和代码生成来实现的。此外,本文发布了多回合编程基准(MTPB)来研究模型在这种多步范式下合成程序的能力。实验表明,多轮次程序合成能力是模型大小和数据大小的函数。在多个步骤中指定的意图规范更容易被模型消化,并帮助模型进行更准确的程序合成。作者开放了训练代码和模型checkpoint,以促进该领域未来的研究和实际应用。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

回首2022,展望2023 回首2022,展望2023

发表于 2023-01-02
  • 👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,Java领域新星创作者
  • 📕系列专栏:Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙
  • 📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
  • 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
  • 🍂博主正在努力完成2022计划中:以梦为马,扬帆起航,2022追梦人

回首2022,展望2023

当开始写这篇文章时,我意识到,2022结束了

说实话,回首自己的2022,感觉是不算成功的一年

这一年步履维艰,不仅是工作上还有生活上

年初订的计划也没有完成(可能由于计划太多了,今年要理性一点订计划

不论如何,这一年还是过来的,随着时间的车轮回首一下2022吧

一、回首

回首必然要根据去年立的计划一起来看一下

1. 工作

计划:

保持更好的工作状态,逼迫自己做一些有挑战性的工作,将工作中的DDD架构研究透彻

现实:

2022年确实对项目理解更深了,不论项目整体的技术架构还是细枝末节,都比去年的我提升不少

今年自己也作为几个小项目的负责人,也给团队提供过技术方案,基本完成了当初导师对我的期望:独立负责项目,可惜导师走了看不到了(尬

完成指数:四颗星

2. 学习

计划:

  • 算法:明年力扣破1000题,周赛拿到 knight
  • 八股:中间件、分布式、408、Java系列学习一遍
  • 书籍:明年要看24本书
  • 文章:明年文章100篇

现实:

  • 算法:还是没有突破1000题,前面5个月保持的很好,后面就摆烂了(刷不下去了….在这里插入图片描述

在这里插入图片描述

  • 八股:自己的最后一篇文章基本涵盖了自己这一年的学习:操作系统 –> 计算机网络 –> Linux 通信 –> Java NIO –> Netty –> Kafka。自己最大的收获应该是 Netty 吧,用了4个月的时间学完了整个Netty 的源码,对网络通信的架构又进一步。
  • 书籍:这一年书籍其实读的挺少的,读了大概6本左右,让我印象最深的是 《程序员的自我修养》,但是很可惜的是,这本书没读完,读了一半读不下去了……
  • 文章:2022年一共发表了33篇文章,内容主要为:操作系统、Netty、kafka,虽然挺少,但令我比较满意的是,对于 Netty 和 Kafka 的文章的源码解读,基本上做到了全网最细。

完成指数:三颗星

3. 健身

计划:持续性跑步,一定坚持下来

现实:G,真没坚持下来

完成指数:一颗星

4. 公众号

计划:明年订一个小目标,粉丝数破200+

现实:自己上半年其实公众号发的挺少的,涨粉自然而然的也少了,下半年发了几篇,涨粉还不错。其实这个公众号就是满足自己的一点小小成就心罢了,不然写文章坚持下来十分困难…..

在这里插入图片描述

完成指数:二颗星

二、展望

今年的计划订的稍微低一些,看看明年的自己是否都完成了

1. 工作

保持更好的工作状态,承担起响应的责任,更深入的研究工作中的架构

2. 学习

算法:明年力扣破 1000 题,周赛拿到 knight

八股:MySQL、JVM、Kafka、Dubbo、Spring等源码级阅读

书籍:明年要看12本书,保持一月一本

文章:明年文章36篇,保持一月三更

3. 健身

持续性跑步,减肥至 130 斤

4. 公众号

粉丝数破300+

三、总结

不得不说,2022是经济严重下滑的一年,这一年,各行各业都不好过

不过,随着防疫政策的放开,2023年经济将会迎来复苏

这一年有的时候学习学着学着就会emo,但也坚持了下来

随着毕业年数的增加,越来越感觉焦虑

去年这个时候还能以毕业半年安慰自己,转眼间已经毕业一年半了,不能再以毕业年限作为技术差的借口了

正如:那些年欠下的债,未来总归是要还的!

希望2023生活会变得很好,2023年让我们一起成长,一起共勉!

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

论文笔记:InCoder A Generative Mod

发表于 2023-01-02

导语

  • 会议:ICLR 2023在投
  • 链接:arxiv.org/abs/2204.05…

1 简介

最近,大型的语言模型在代码生成等相关领域取得了令人印象深刻的进展。然而,这些left-to-right的自回归式模型不太直接适用于许多普遍存在的代码编辑任务,例如修复错误、添加注释或重命名变量。为了解决这个问题,本文提出InCoder模型,该模型通过学习使用一个sential token随机替换一段代码并将它们移动到序列的末尾来填充(这就是本文最核心的创新点,该灵感来源于CM3: A causal masked multimodal model of the Internet.),如图1所示。

image.png

在模型推理阶段,可以任意使用sential token来mask掉一段文本来让模型预测。同时,该模型也可以在没有sential token的情况下进行简单的生成,所以InCoder将程序合成(通过从左到右生成)和编辑(通过填充)任务完成了统一。

本文评估了一系列zero-shot的代码填充任务的性能,如类型预测、变量重命名、注释生成和完成缺失的代码行。实验发现:使用双向上下文的zero-shot填充在很大程度上优于基于仅从左到右模型的方法,并且在一些任务上获得了与在任务上经过微调的最先进模型相当的性能。 InCoder在现有的从左到右的程序合成任务上也取得了出色的表现,尽管它的训练目标更一般,但它与在类似规模下训练的现有代码语言模型相匹配。

模型在 sites.google.com/view/incode… 上公布。

2 通过Causal Masking的填充和合成

用于代码生成的神经模型要么利用了从左到右(因果)的自回归语言建模目标,要么像BERT那样,使用了掩蔽语言建模目标。这两种方法各有优缺点。因果模型只对所生成的标记左侧的上下文设置条件,从而防止填充,但它们可以自回归地生成整个文档。另一方面,遮罩语言模型可以同时使用左右上下文来填充屏蔽区域,但是,它们的训练目标通常仅限于生成文档的15%左右。在本文中,我们采用了最近提出的因果遮罩目标(causal masking objective),该目标旨在结合因果语言模型和掩蔽语言模型的优点。

2.1 训练

在训练时,首先在每个文档中采样一系列连续token来进行掩码(图1,左上)。为此,需要确定两个数字:

  • span的数目;
  • 每个span的长度(即遮盖的token个数)。

对于span的数目,本文从泊松分布中选取span的数量,设置均值为1,并截断值为256,因此通常存在少量的span(约50%的情况为1个span),但分布具有长尾(最多256个span)。

对于span的长度,本文从文档的长度中进行统一采样,如果有span重叠,则重新采样。

一旦span被采样,每个spankspan_kspank将被一个特殊的sential token Mask:kMask:kMask:k取代。然后将span中的token序列移动到文档的末尾(图1,右上),前置掩码sential token Mask:kMask:kMask:k和一个特殊的掩码结束token < EOS >。换句话说,当一个mask token第一次以从左到右的顺序出现时,它标记了span被移除的位置;当它第二次出现时,它标志着移动的span文本的开始。然后,我们最大化概率:

image.png

如果对多个span进行采样,则每个span将类似地按顺序追加到文档的末尾。与标准的从左到右生成语言建模一样,我们计算序列自回归的概率,并在除Mask:kMask:kMask:k;之外的所有标记上使用交叉熵损失来训练模型,以便模型在推理过程中不会生成这些token。

2.2 推理

在推断过程中,模型可以用标准的方式从左到右生成(通过从模型中进行自回归抽样,不使用任何特殊标记),也可以在现有文档的任意位置插入代码,方法是插入 Mask:kMask:kMask:k 标记在所需的位置,并在文档的末尾继续生成。为了简便起见,假设我们只想在单个位置插入文本,我们通过从分布中自回归抽样标记,生成一个span来插入该位置的左右上下文序列

image.png

直到< EOS >生成或实现任务相关的停止条件。一种更加通用的表示形式是多个mask,那么整个预测序列将表示为:[A;Mask:0;C;Mask:1;E;Mask:2;Mask:0;B;;Mask:1;D;][A; Mask:0; C; Mask:1; E; Mask:2; Mask:0; B; < EOM >; Mask:1; D; < EOM >][A;Mask:0;C;Mask:1;E;Mask:2;Mask:0;B;;Mask:1;D;],其中区域B和D是需要被填充的。

这里有一个脚注,即在实践中,作者从分布P(⋅∣[Left;Mask:0;Right;Mask:1;Mask:0]P(⋅∣[Left; Mask:0; Right; Mask:1; Mask:0]P(⋅∣[Left;Mask:0;Right;Mask:1;Mask:0] 中插入一个Mask:1Mask:1Mask:1token。如果不插入Mask:1Mask:1Mask:1,则会给模型一个隐式的大小提示,即Mask:0Mask:0Mask:0token应该展开以填充2048令牌上下文窗口的其余部分。相反,插入一个Mask:1Mask:1Mask:1token向模型表明在正确的上下文之后省略了文档的一部分。作者发现,使用这一点大大提高了模型预测。

当应用于代码时,这允许我们以零目标的方式执行从双向上下文中受益的任务,如图1底部所示,作者展示了四种情况下如何进行推理:

  • Type Inference
  • Variable Name Prediction
  • Docstring Generation
  • Multi-Region Infilling

3 训练数据

我们在一个语料库上训练我们的模型:

  1. 具有许可的、非copyleft的、开源许可的公共代码和
  2. StackOverflow问题、答案和注释。

数据量统计如下:

image.png

3.1 代码

代码源

代码数据主要来自于GitHub/GitLab,大约67万个公共非fork存储库,主要包含Python、JavaScript或Jupyter Notebook文件,并具有MIT、Apache 2.0、BSD-2或BSD-3条款许可。

去重

最近的研究表明,训练中的重复数据删除可以提高模型性能,并降低记忆训练数据的风险。作者也进行了去重操作。

排除训练数据

为了防止数据泄露,作者删除了CodeSearchNet的验证和测试集中包含的所有存储库,因为这些存储库用于为CodeXGLUE中的几个任务构建验证和测试集。

过滤

过滤掉一些过长或过短的文件。

3.2 StackOverflow

语料库的第二个组件由来自StackOverflow的问题、答案和评论组成。The Pile数据集(参考:juejin.cn/post/718390… )也包含这些问题和答案,但不包含注释。定性地说,作者发现注释,以及InCoder模型具备的填充能力,使其具有一些在语言指导下进行交互式代码编辑的能力(如下图11)。

image.png

3.3 Metadata

作者还保留了一些文件或者StackOverflow的元数据,例如文件名、拓展名、来源、StackOverflow的主题、标签等信息。为了允许该元数据在执行模型的从左到右提示时是可选的,作者以50%的概率将每个属性插入其文档的开头(允许模型学习元数据调节);否则,将其插入到文档的末尾(允许元数据预测)。

image.png

3.4 Tokenization

为了增加模型所依赖的上下文数量、模型可以生成的文档长度以及训练和推理的效率,作者训练了BPE Tokenizer,允许token跨越空格(不包括换行符)进行扩展,这样常见的代码习惯用法(例如,import numpy as np)在词汇表中表示为单个token。这极大地提高了标记器的效率——相对于GPT-2的字节级BPE标记器和词汇表,将编码训练语料库所需的token总数减少了45%。

4 训练

本文提出的主要模型是InCoder-6.7B,在248张V100上训练了24天。同时,也训练了一个1.3B版本的小模型。

image.png

5 填充实验

作者的主要评估实验是不同的编程任务的zero-shot实验。
为了评估InCoder在生成填充时如何从双向上下文中获益,作者比较了三种不同的推断方法:第2节中描述的因果掩蔽推断过程,标准的从左到右生成方法(left-to-right single),以及从左到右生成和重排序方法(left-to-right reranking)。

Left-to-right single

该Baseline根本不使用被mask位置右侧的上下文。它通过对左侧上下文进行条件处理,并从模型P(⋅∣left)P(⋅∣left)P(⋅∣left)中自回归采样token,直到达到特定于任务的停止条件(例如,对于注释生成,产生注释结束分隔符;对于多行填充,将生成指定的行数)。

Left-to-right reranking

该Baseline仅使用左侧上下文来给出填充空白的候选语句,但同时使用左侧和右侧上下文在这些候选语句中进行选择。

具体来说,首先为mask区域生成K=10种可能的补全,跨度为1。然后,通过将每个候选人代入空白并对完成的文档进行评分来评估每个候选人。我们使用完成文档的总日志概率logP([Left;Spank;Right])log P([Left; Span_k; Righ_t])logP([Left;Spank;Right]),或者使用完整文档的平均对数概率。

5.1 Infilling Lines of Code (HumanEval)

作者从HumanEval数据集为完整的代码行创建一个填充实验的基准,从HumanEval数据集构建了两个不同的填充任务,用于单行和多行:

  • 单行填充:即遮盖掉N行内容的某一行,让模型预测该行内容,共进行N次实验;
  • 多行填充:即遮盖掉若干行内容,让模型预测多行内容,共进行N(N+1)/2次实验(即CN+12C_{N+1}^2CN+12).

预测结果如下表所示:

image.png

同时,作者还比较了被mask掉的部分的右侧的上下文的多少对于实验结果的影响,结果如下图所示:

image.png

InCoder方法比L-R baseline有更大的改进,因为右侧有更多的上下文可用(即,当空白区域出现在函数的早期时)。

5.2 Docstring generation (CodeXGLUE)

接下来,作者展示了在CodeXGLUE(参考:)上的Docstring Generation任务的表现,InCoder模型在Zero-shot的条件下取得了和CodeBERT(参考:)类似的性能表现。

image.png

5.3 Code Cloze (CodeXGLUE)

在完形填空任务上的主要结果如下表所示。使用带有单个标记(包含min/max)作为屏蔽区域的模型比仅使用左侧上下文执行得更好,但不如从左到右对整个序列进行评分。屏蔽一个更大的区域(CM填充区域),其执行与对整个序列进行评分相当。填充区域长度和标记化可以影响性能。

image.png

5.4 Return Type Prediction

image.png

5.5 Variable Name Prediction

image.png

6 模型对比

6.1 Comparison to Left-to-Right Generative Models on Code Synthesis

所有模型都是Decoder-only模型,其在HumanEval和MBPP上的实验结果如下表:

image.png

可以看到,InCoder模型在HumanEval指标上实现了与CodeGen-Multi大致相当的性能,CodeGen-Multi也是一个用大致相同数量的Python代码训练的∼6B参数模型。

作者还进行了消融实验,比较从本文的训练语料库以及HumanEval和MBPP基准测试中获得的验证集的Python部分的模型性能。实验结果如下表所示:

image.png

7 Qualitative Examples

一些实验示例结果如下图:

image.png

image.png

image.png

8 相关工作

略

9 总结

本文证明了在训练生成式代码模型时使用因果掩蔽目标(causal masking objective)可以在许多具有挑战性和实用的代码填充和编辑任务中实现强大的Zero-shot性能。该模型的额外填充能力似乎并没有损害其进行标准的从左到右生成的能力:消融实验表明,InCoder模型在标准的从左到右语言到代码合成基准上具有与相似资源模型相当的性能。

展望未来,作者希望通过更多的参数、数据和训练步骤,使得模型性能继续提高。此外,微调将使InCoder能够更好地适应自然语言指令和人类意图的其他迹象。最后,本文为未来通过模型微调进行监督填充和编辑以及执行迭代解码的工作奠定了基础,其中模型可用于改进自己的输出。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

论文笔记:A Systematic Evaluation o

发表于 2023-01-02

导语

  • 会议:MAPS 2022
  • 链接:arxiv.org/abs/2202.13…

关键词

code language model, evaluation, pretraining, code generation, open-source

1 简介

最近,语言模型被广泛的应用到了AI辅助代码的相关任务上,比如最近OpenAI提出最大的模型的CodeX(GPT-3 Codex模型学习笔记)已经被应用到了Github Copilot工具上。尽管研究者们取得了这些成就,但是像CodeX这类模型并不公开,人们只能使用相关公司提供的付费API来进行调用,模型的内部细节都是一个黑盒,这无疑阻碍了相关研究的发展。

像GPT-Neo、GPT-J、GPT-NEoX等中大型的语言模型是公开的(注:由于GPT-3模型也是不公开的,所以这几个模型都是EleutherAI训练的公开的大型自回归模型),它们的训练数据集(The Pile数据集,有800GB的文本、代码等数据)包含了广泛的文本形式,也能够合理的生成代码。

image.png

考虑到这些模型中涉及的模型大小和训练方案的多样性,以及这些模型之间缺乏比较,许多建模和训练设计决策的影响仍不清楚。本文对现有的跨各种编程语言的代码模型——Codex、GPT-J、GPT-Neo、GPT-NeoX和CodeParrot——进行了系统评估并发布了PolyCoder模型,该模型基于 GPT-2 架构并在12种编程语言上进行预训练。

本文首先对PolyCoder、开源模型和Codex之间的训练和评估设置进行了广泛的比较。其次,作者在HumanEval基准上评估模型。最后,由于HumanEval只评估自然语言到Python合成,作者在12种语言中评估不同模型的perplexity。实验结果发现,尽管Codex据称专注于Python,但它在其他编程语言上的表现也令人惊讶地好,甚至比在Pile上训练的GPT-J和GPT-NeoX更好。尽管如此,在C编程语言中,我们的PolyCoder模型实现了比所有这些模型(包括Codex)更低的复杂性。

虽然目前大多数模型的表现不如Codex,但该研究有助于该领域未来的研究设计更高效和有效的模型。更重要的是,通过对不同模型的系统评估,作者鼓励社区研究并发布用于代码的中大型语言模型,以回应Hellendoorn和Sawant[18]所表达的担忧:

[…为了达到最先进的水平,成本呈爆炸式增长,这使得训练和测试这类模型的能力局限于少数几家大型科技公司,而且几乎所有学术实验室的资源都远远不够。

作者相信,本文的努力是迈向大型代码语言模型民主化的重要一步。

2 相关工作

本章节主要介绍预训练语言模型的相关方法和预训练数据集。

2.1 预训练方法

有三种形式的预训练方法(如下图所示):

  • Left-to-Right Language Models.该类模型即自回归式方法,典型的模型例如CodeGPT (124M), CodeParrot (1.5B), GPT-Neo (2.7B) , GPT-J (6B), Codex (12B), GPT-NeoX (20B)和Google’s (137B);
  • Masked Language Models.该类模型即只使用Transformer的Encoder部分,典型的模型如CodeBERT (125M)和 CuBERT (345M);
  • Encoder-decoder Models.该类模型即Encoder-decoder模型,典型的方法如CodeT5(220M)和PLBART(406M)。

image.png

2.2 预训练数据集

一些方法只在Github的代码数据上进行训练,如CodeT5或CodeParrot模型,它们的训练数据集要么是Google BigQuery’s GitHub数据集,要么是CodeSearchNet。其他的开源模型如GPT-Neo、GPT-J则是在自然语言和代码的混合文本上进行训练,典型的数据集为The Pile。还有一些不公开的数据集,如CodeX,Google’s 模型使用的数据集。

3 评估设定

分为外在评估(Extrinsic Evaluation)和内在评估(Intrinsic Evaluation)。外在评估指的是在HumanEval这个数据上的Pass@k表现,但由于该数据集只有Python代码的,所以作者又提出了内在评估。

所谓内在评估,则是评估本身语言模型在不同的程序语言文本上的PPL(即perplexity),这种评估方式很简单,但却很有效。

4 比较的模型

4.1 现存的模型

本文主要比较以下模型:

  • 不开源的模型:CodeX
  • 开源的通用模型:GPT-Neo, GPTJ 和 GPT-NeoX
  • 开源的单一语言模型:CodeParrot

4.2 PolyCoder的数据

原始数据收集

我们在2021年10月从GitHub克隆了12种至少有50颗星的流行编程语言的最受欢迎的存储库(每种语言停止在大约25K,以避免对流行编程语言的过度倾斜)。对于每个项目,提取属于该项目的大多数语言的每个文件,生成初始训练集。这个初始的、未经过滤的数据集包含631GB和389M个文件。

数据预处理

数据预处理流程如下表1

image.png

去重和过滤

像CodeX和CodeParrot那样,作者也过滤掉了过长和过短的数据,得到的最终数据集如下表所示:

image.png

本文收集的数据集包含比Codex或CodeParrot更少的Python代码(只有16G),而是涵盖了许多不同的编程语言。

Tokenizer

在包含所有语言的所有预训练数据的随机5%子集上训练一个GPT-2 Tokenizer(使用BPE)。

4.3 PolyCoder的训练

由于预算有限,作者采用了GPT-2作为自己的模型架构,并设置了130M,400M和2.7B三种不同的size。在单机8 Nvidia RTX 8000 GPU上训练2.7B模型大约耗时6周。

image.png

训练时的超参数设置如上表所示,由于训练资源有限,作者无法进行超参搜索,而是基本遵循了GPT-2的参数设定。而且由于训练资源的受限,模型似乎还没有完全收敛。

image.png

5 结果

5.1 外在评价

HumanEval测试基准上的实验结果如下表所示:

image.png

作者探讨了模型规模和softmax温度(可以参考 温度 )的影响:

Scaling Effect

HumanEval基准测试的性能随着模型中参数数量的大小(对数尺度)线性增加。在PolyCoder和GPT-Neo/J模型上也发现了类似的缩放效应。有趣的是,只在Python上训练的CodeParrot模型似乎随着参数数量的增加而达到了饱和性能,其中专注于Python的训练语料库可能会有一些效果。

image.png

在参数数较高(2.7B)的情况下,PolyCoder的性能趋向于GPT-Neo/J。比较在包含文本、Stack Exchange转储和GitHub数据的Pile数据集上训练的GPTNeo/J与仅在流行编程语言的GitHub存储库上训练的PolyCoder,作者认为添加的文本,特别是技术和软件工程领域的文本,可能对更大的模型提高性能至关重要。

Temperature Effect

Pass@1的总体趋势是温度越低越好。对于Pass@100,较高的温度有帮助,而对于Pass@10,中间的温度更适合。

image.png

5.2 内在评估

PPL结果如图6所示,PolyCoder在C语言中优于Codex和所有其他模型。仅比较开源模型,PolyCoder在C、JavaScript、Rust、Scala和TypeScript中的性能要优于类似大小的GPT-Neo 2.7B。

在除C语言之外的11种语言中,所有其他开源模型,包括PolyCoder,都明显比Codex更糟糕。这可能是因为PolyCoder是在不同语言的不平衡混合上训练的,C和C++密切相关,并且在整个训练语料库中占主导地位。因此,较大的总容量(因为长文件)使C语言成为PolyCoder最“青睐”的语言。PolyCoder在c++中表现不如Codex的原因可能是由于c++语言的复杂性和Codex的上下文窗口大小明显较长(4096,而PolyCoder的2048),或者因为Codex可能在更多的c++训练数据上进行训练。

image.png

使用相同的预训练语料库,从2.7B模型(GPT-Neo)到6B模型(GPT-J)的增益在所有语言上都是显著的。然而,当进一步增加模型大小到20B时,不同语言的改进有所不同。例如,当模型大小增加3倍时,Go、Java、Rust、Scala、TypeScript上的性能并没有显著提高。这表明对于某些编程语言,并且给定数据量,GPT-J的容量是足够的。有趣的是,这些语言似乎与PolyCoder优于在Pile上训练的类似大小模型的语言一致。这可能暗示,对于较大模型不能提供额外增益的语言,仅使用代码训练模型可能足够或比同时使用自然语言和代码训练更有帮助。

我们可以看到,比较不同的模型,Python的困惑度趋势与外部评估的HumanEval基准性能有很好的相关性(第5.1节)。这表明困惑度是评估其他下游指标的有用且低成本的指标。

6 总结

本文对现有的最大的代码语言模型进行了系统的评估,同时发布了PolyCoder,这是一个大型的开源代码语言模型,专门针对12种不同编程语言的代码进行训练。在C语言中,PolyCoder实现了比包括Codex在内的所有模型更低的复杂度。

虽然模型的性能通常受益于更大的模型和更长的训练时间,但小型(300M) Codex在HumanEval上优于所有其他模型的结果表明,模型大小并不是唯一的重要因素,使用其他技术,开源模型仍有很大的改进空间。作者还认为,GPT-Neo在某些语言中优于PolyCoder的结果表明,在自然语言文本和代码上的训练可以使代码建模受益。

为了鼓励未来在该领域的研究,本文在github.com/VHellendoor… 上公开了模型、代码、数据和数据挖掘脚本。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

论文笔记:CodeT5 Identifier-aware U

发表于 2023-01-02

导语

  • 会议:EMNLP 2021
  • 链接:arxiv.org/abs/2109.00…

1 简介

最近,很多研究尝试将NLP领域的PLM模型引入到编程语言领域,如CodeBERT等,但这类模型仅利用了Encoder或者Decoder,而且在预训练时使用的方法大多与训练自然语言的方法类似,无法很好的利用代码丰富的结构信息,导致模型无法很好的学到代码的语义。

image.png

本文提出了CodeT5模型,这是一个考虑代码token类型的encoder-decoder模型。除了最基本的denoising seq2seq预训练目标,作者还提出利用开发者在代码中指定的标识符(identifiers)和代码对应的注释作为NL-PL对齐语料。预训练语料与CodeBERT相同,既有双模态语料,也有代码的单模态语料。Fine-tune则是在CodeXGLUE的相应下游任务上进行。

本文的贡献如下:

  • 本文提出了CodeT5,以支持与编码相关的理解和生成任务,并且还允许多任务学习。
  • 文本提出了一种新颖的标识符感知预训练目标,该目标考虑了来自代码的关键标记类型信息(标识符)。此外,本文提出利用源代码中自然提供的NL-PL对来学习更好的跨模态对齐。
  • 大量的实验表明,CodeT5在CodeXGLUE的14个子任务上产生了最先进的结果。进一步的分析表明,CodeT5可以通过提出的识别标识符的预训练更好地捕获代码语义,双模态双向生成主要有利于NL↔PL任务。

2 相关工作

略

3 CodeT5

3.1 Encoding NL and PL

对于双模态数据,也是使用[SEP]来分隔开,其格式如下:

x=([CLS],w1,…,wn,[SEP],c1,…,cm,[SEP])x = ([CLS], w_1, …, w_n, [SEP], c_1, …, c_m, [SEP])x=([CLS],w1,…,wn,[SEP],c1,…,cm,[SEP])
对于PL单模态数据,NL部分则是空。

3.2 预训练任务

总共使用4种预训练任务。

  • MSP(Masked Span Predicion)
  • IT(Identifier Taggng)
  • MIP(Masked Identifier Prediction)
  • Bimodal Dual Generation

image.png

Masked Span Prediction

如图2(a),该任务以15%的概率随机MASK掉一个原输入中的span,该span的长度为1到5中的均匀抽样得到,并且采用whole word mask技术,以避免将一个完整词的部分token给mask掉。

image.png

Identifier Taggng

如图2(b),该任务目的是通知模型该代码标记是否是标识符(即用户定义的变量名),这与一些开发辅助工具中的语法突出显示精神相似。该任务即为一个二分类的Sequence labeling。

image.png

Masked Identifier Prediction

如图2(c),该任务屏蔽PL段中的所有标识符,并对所有出现的特定标识符使用唯一的标记 (obfuscation,混淆的思想,,即改变标识符名称不会影响代码语义)。然后将唯一标识符和sentinel tokens排列到目标序列I中再预测。

image.png

Bimodal Dual Generation

如图2(d),该任务即NL-PL的双向seq2seq生成,即由注释文本和代码字段进行相互转换。

3.3 Fine-tuning CodeT5

作者介绍了两种Fine-tune的方式:

  • Task-specific Transfer Learning
  • Multi-task Learning

Task-specific Transfer Learning

与代码相关的任务可以分为生成任务和理解任务。对于前者,CodeT5可以自然地使用Seq2Seq框架进行调整。为了理解任务,作者研究了两种方法,一种是将标签生成为unigram目标序列(就是seq2seq输出label,像原始T5那样),另一种是根据最后一个解码器隐藏状态,从类标签词汇表中预测它。

Multi-task Learning

本文还通过一次在多个任务上训练共享模型来探索多任务学习设置,为所有任务采用相同的统一模型,而不添加任何特定于任务的网络.为了通知模型它正在处理哪个任务,作者设计了任务控制代码的统一格式,并将其预先放入源输入中,如图1所示。例如,使用“Translate Java to CSharp:”作为从Java到CSharp的代码到代码转换任务的源提示符。

由于不同的任务有不同的数据集大小,作者采用平衡抽样策略。对于N个数据集(或任务),在概率{qi}i=1N{q_i}_{i=1}^N{qi}i=1N的情况下,定义以下抽样的多项分布:

image.png

其中nin_ini为第i个任务的样例数,α设为0.7。

4 实验设置

4.1 预训练数据集

与之前的工作如CodeBERT类似,采用CodeSearchNet作为预训练数据集。其统计指标如下图:

image.png

4.2 Code-specific Tokenizer

绝大多数PLM采用BPE形式的Tokenization策略,本文作者在自己的预训练数据集上重新训练了一个和原始T5 Tokenizer一样词表大小的BPE Tokenizer,作者发现相比于原始T5的Tokenizer,使用他们重新训练的BPE Tokenizer,可以大幅度减少下游任务的序列长度(30%-45%)。这将加速训练,特别是有助于生成任务,因为预测的序列更短。

4.3 下游任务和评价指标

作者主要在CodeXGLUE上进行实验,主要包括:

  • Code summarization
  • Code generation
  • Code translation
  • Code refinement
  • defect detection
  • clone detection

4.4 比较的模型

主要对比三种类型的模型:

  • Encoder-Only:ROBERTA、CodeBERT、GraphCodeBERT、DOBF等;
  • Decoder-Only:CodeGPT-2、CodeGPTadapted;
  • Encoder-decoder:PLBART;

4.5 模型配置

略

5 实验结果与分析

5.1 CodeXGLUE Downstream Tasks

实验结果如下图:

image.png

image.png

5.2 Effects of Bimodal Dual Generation and Multi-task Learning

双模态预训练为CodeT5-small和CodeT5-base上的代码摘要和生成任务带来了一致的改进。然而,这种预训练任务对PL-PL生成和理解任务没有帮助,甚至有时会略微影响其表现。作者预计这是因为双峰双生成学习了PL和NL之间更好的对齐,这自然有利于涉及PL和NL的前任务。作为一个副作用,这个目标可能会使模型偏向PL-NL任务,并影响其在PL-PL任务上的性能。

在多任务学习中,除了代码转换和缺陷检测外,它通常可以改进大部分的下游任务。特别是,它在很大程度上提高了代码摘要的性能,这并不奇怪,因为代码摘要占子任务的最大比例(13个子任务中的6个),因此从多任务学习中受益最多。此外,作者观察到多任务学习可以持续地提高代码细化的性能,这可能得益于中小细化数据的联合训练。另一个可能的原因是带有缺陷检测的多任务训练将使模型能够更好地理解用于缺陷检测的代码语义,这也是代码改进的必要中间步骤。

5.3 Identifier-aware预训练的分析

消融实验通过消除三个目标(掩码跨度预测(MSP)、标识符标记(IT)和掩码标识符预测(MIP))中的每一个来比较CodeT5-small在四个选定任务上的性能。如表6所示,删除一个目标会降低所有任务的性能。具体来说,删除MSP将大大降低所有生成任务的性能,但反而会提高缺陷检测的性能。这表明掩码跨度预测对于为生成任务捕获语法信息更为关键。相反,删除MIP将对缺陷检测任务造成最大的伤害,这表明它可能更多地关注代码语义理解。通过结合这些目标,CodeT5可以更好地从代码中捕获语法和语义信息。

image.png

图4进一步提供了来自CodeT5及其变体的输出。可以观察到CodeT5可以正确地生成准确的函数,而没有MIP和IT的模型无法恢复“s2”和“hasField”的标识符。这表明Identifier-aware预训练可以更好地区分和利用标识符信息。

image.png

作者还研究了identifier tagging性能,发现它对所有PLs都达到了超过99%的F1,这表明CodeT5可以自信地区分代码中的标识符。

然后我们检查MSP和MIP任务是否会有冲突,因为它们使用相同的哨点令牌进行屏蔽。在标识符屏蔽中,一个唯一标识符的所有出现都被替换为相同的哨兵标记,与span预测中的一对一映射相比,这导致多对一映射。我们比较了用MSP或MIP预训练的模型,以及表7中这两个任务的模型。我们报告了预测精度,以及它们生成与哨点令牌相同数量预测的频率之比。我们观察到,仅使用MIP或MSP进行预训练会使模型偏向该任务,当应用于其他任务时,预测的准确性较差,预测数量不匹配。有趣的是,我们发现MIP-only目标在MSP任务中比MSP-only目标在MIP任务中可以更好地恢复正确的预测数量,这意味着它更容易从多对一映射适应到一对一映射,而相反则很难。最后,将它们结合起来,可以帮助我们的模型在这两个任务之间做出很好的权衡。

6 总结

本文提出了CodeT5,这是一个预训练的编码器-解码器模型,它集成了来自代码的token类型信息。本文提出了一个新的识别预训练目标,以更好地利用标识符,并提出了一个双模态双向生成任务,以使用代码及其注释学习更好的NL-PL对齐。使用统一模型可以支持代码理解和生成任务,并允许多任务学习。实验表明,在大多数CodeXGLUE任务中,CodeT5明显优于所有先前的工作。进一步的分析还揭示了它在各种编程语言之间更好的代码理解能力。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

论文笔记:CodeBERT A Pre-Trained M

发表于 2022-12-29

导语

  • 会议:EMNLP 2020 Findings
  • 链接:arxiv.org/abs/2002.08…

1 前言

随着NLP大型预训练语言模型的广泛应用,越来越多的多模态PLM出现,例如ViLBERT、VideoBERT等。本文提出了CodeBERT,一个针对编程语言PL和自然语言NL的双模态预训练模型。CodeBERT捕获了自然语言和编程语言之间的语义联系,并生成通用表示,可以广泛支持NL-PL理解任务(例如自然语言代码搜索)和生成任务(例如代码文档生成)。CodeBERT在预训练时,除了利用了NL-PL的并行双模态数据外,也充分利用了大量PL、NL的单模态数据。整体来说,本文的主要贡献如下:

  • CodeBERT是第一个用于多种编程语言的大型NL-PL预训练模型。
  • 实验结果表明,CodeBERT在代码搜索和代码到文本生成任务中都是有效的。
  • 我们进一步创建了一个数据集,这是第一个调查基于代码的预训练模型的探测能力的数据集。

2 背景

略

3 CodeBERT

3.1 模型架构

模型整理框架与RoBERTa一致。

3.2 输入、输出表示

输入由NL和对应的PL拼接而成,中间使用[SEP]分隔开。

3.3 预训练数据

使用Husain et al.等人发布的一个数据集进行预训练,其中包括2.1M的双模态数据和6.4M的单模态数据。数据集的统计信息如下:

image.png

其中的一个数据示例如下图所示:

image.png

3.4 预训练CodeBERT

CodeBERT的预训练目标有两个:

  • Objective #1: Masked Language Modeling (MLM)

即传统的MLM任务,这里只有一种[MASK],不区分code的[MASK]和自然语句的[MASK]。

  • Objective #2: Replaced Token Detection (RTD)

这个借鉴了ELETRA模型的训练思路,即有一个Generator和Discriminator来共同训练,其训练流程如下图所示:NL和代码生成器都是语言模型,它们基于周围的上下文为mask位置生成合理的token。NL-code Discriminator是目标的预训练模型,它通过检测从NL和PL生成器采样的合理替代token来训练。NL-Code鉴别器用于在微调步骤中生成通用表示。在微调步骤中,只使用Discriminator。

image.png

3.5 Fine-tuning CodeBERT

在下游NL-PL任务中使用CodeBERT有不同的设置。例如,在自然语言代码搜索中,我们以与预训练阶段相同的方式提供输入,并使用[CLS]的表示来衡量代码与自然语言查询之间的语义相关性,而在代码到文本生成中,我们使用编码器-解码器框架,并使用CodeBERT初始化生成模型的编码器。细节在实验部分给出。

4 实验

4.1 Natural Language Code Search

给定一种自然语言作为输入,代码搜索的目标是从一组代码中找到语义上最相关的代码。本文在CodeSearchNet语料上进行实验。本文遵循官方评估度量来计算在固定的999个干扰码集合上的每对测试数据(c, w)的Mean Reciprocal Rank(MRR)。我们进一步计算所有语言的宏观平均MRR作为整体评估指标。

实验结果如下表所示:

image.png

其中,init=S表示train from scratch,init=R表示从RoBERTa初始化。

4.2 NL-PL Probing

本小节中,将进一步研究在不修改参数的情况下,在CodeBERT中学习什么类型的知识。

本文定义了NL-PL探测问题,并创建了数据集。给定一个NL-PL对(c, w), NL-PL探测的目标是测试模型在干扰物中正确预测/恢复感兴趣的掩码令牌(cic_ici或wjw_jwj)的能力。有两种主要类型的干扰因素:一种是用于掩蔽语言建模目标的整个目标词汇,另一种是基于专家对测试能力的理解筛选或策划的候选词汇。我们遵循第二个方向,将NL-PL探测制定为一个选择题回答任务,其中问题是完形填空式的,其中某个token被[MASK]取代,干扰者候选答案将根据我们的专业知识进行策划。

image.png

具体来说,我们分别在NL侧和PL侧进行评估。本文自动从CodeSearchNet的验证集和测试集中的NL-PL对中收集数据。为了在NL方面进行评估,选择关键字(max, min, less, greater)之一的NL-PL对,任务是要求PLM选择正确的一个。也就是说,这个设置中的输入包括完整的代码和屏蔽的NL文档。目标是从四个候选人中选出正确答案。对于PL方面,我们选择包含关键字max和min的代码,并将任务制定为一个两选答案选择问题。在这里,输入包括完整的NL文档和屏蔽的PL代码,目标是从两个候选项中选择正确答案。由于代码补全是一个重要的场景,我们想测试模型仅仅基于前面的PL上下文预测正确token的能力。因此,我们为PL端添加了一个额外的设置,其中输入包括完整的NL文档和前面的PL代码。

表3的前两行给出了数据统计。

image.png

4.3 Code Documentation Generation

本节涉及 code-to-NL 生成任务,报告了在 CodeSearchNet 语料库上六种编程语言的文档生成任务结果。
下表 5 展示了不同模型的代码-文档生成任务结果:

image.png

4.4 Generalization to Programming Languages NOT in Pre-training

这里作者测试一个不在预训练语料中出现的编程语言 C# 的数据集CodeNN来测试性能表现,得到Code-to-NL任务的性能表现如下:

image.png

5 总结

本文提出了CodeBERT,据我们所知,这是第一个用于自然语言和编程语言的大型双模态PLM。我们在双模态和单模态数据上训练CodeBERT,并展示了对CodeBERT进行微调在下游任务(包括自然语言代码搜索和代码到文档生成)上实现了最先进的性能。为了进一步研究预训练模型中包含的知识,我们制定了NL-PL探测任务,并创建了用于探测的数据集。我们将探测任务视为完形式的答案选择问题,并为NL和PL部分安排干扰。结果表明,当模型参数固定时,CodeBERT的性能优于RoBERTa和仅使用代码的连续训练模型。

这一领域有许多潜在的研究方向。首先,可以使用双模态或更复杂的神经结构来学习更好的生成器,以改进替换的token检测目标。其次,CodeBERT的损失函数主要针对NL-PL理解任务。尽管CodeBERT在代码到文档的生成方面获得了很高的BLEU分数,但CodeBERT本身可以通过与生成相关的学习目标进一步改进。如何成功地将AST融入到预训练步骤中也是一个很有吸引力的方向。第三,我们计划将CodeBERT应用于更多与NL-PL相关的任务,并将其扩展到更多的编程语言。灵活而强大的领域/语言适应方法是很好的泛化所必需的。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

DeepMind AlphaCode模型学习笔记 导语 1

发表于 2022-12-27

导语

AlphaCode是DeepMind在CodeX发表后紧随其后发表的一篇工作,该工作相比于CodeX可以接收更加长的输入和程序竞赛级别的题目难度,并在在线评测中打败了一半的人类参赛者。

  • 会议: arxiv
  • 链接: arxiv.org/pdf/2203.07…
  • 学习资料:OpenAI Codex 论文精读【论文精读】,跟李沐学AI,哔哩哔哩

1 简介

代码生成是一个有挑战性的任务,最近的一些工作在这方面取得了令人印象深刻的表现,但这些工作如CodeX只能处理简单的任务描述和简短的解决方案,远远没有现实世界编程的全部复杂性。

编程竞赛的题目则具有较高的复杂性,解决这类问题需要理解复杂的自然语言描述,推理以前未见过的问题,掌握广泛的算法和数据结构,并精确地实现跨越数百行的解决方案。最著名的国际大学生编程大赛(ICPC)和国际信息学奥林匹克竞赛(IOI)等活动被广泛认为是计算机科学领域最负盛名的比赛之一,吸引了来自世界各地的数十万参与者。使用人类从这种经过战斗考验的竞争中发现具有挑战性的问题,可以确保对捷径的鲁棒性,并为智能的许多方面提供有意义的基准。

image.png

本文提出了一个用于解决竞争性编程问题的代码生成系统AlphaCode。通过使用大型Transformer语言模型来生成代码,在选定的GitHub代码上对它们进行预训练,并对我们策划的竞争性编程问题进行微调。对于每一个看不见的问题,我们生成一个大的程序样本集,根据问题描述中的示例测试的执行结果对它们进行筛选,然后对剩余的样本进行聚类,以获得一个小的候选样本集,以便提交进行评估。在Codeforces编程竞赛平台上,AlphaCode被估计取得了1238分,超过了72%的人类参赛者。

2 问题建立

2.1 编程竞赛

一个编程竞赛的题目样例如下图所示:

image.png

相比于之前CodeX那种简单的题目,这里的难度和复杂度提高了很多。图3给出了AlphaCode给出的解法,可以看到还是非常的长的一段文本。

image.png

2.2 评估

评价指标采用 n@k,即“每个问题通过𝑘个样本的𝑛次提交解决的问题的百分比”(可以类比于CodeX那里的Pass@k,但这里的n是Pass@中的k)。

3 数据集

有两个数据集:

  1. 预训练数据集
  2. 微调数据集

3.1 预训练数据集

AlphaCode的预训练数据也是采样自Github,只不过它采样的时间比CodeX晚一年,而且采样的语言种类也多一些,最后得到了715.1GB的数据(CodeX应该是150GB左右)。

3.2 微调数据集

既然要做程序竞赛,那么微调数据集就要和其格式尽量相同,作者从Codeforce网站上爬取了一些数据作为辅助的微调数据集,并且命名为CodeContents,其统计指标如下:

image.png

表2展示了一些数据集中的质量。有时,模型生成的代码并不一定是完全正确的,但由于测试样例覆盖不全,导致“Flase Postive”现象的出现。 SlowRate则是说模型生成的可能是低效的算法,但由于测试样例中不存在大量数据的情况,导致没法判断出来的比例。作者比较了自己提出的CodeContents和之前的数据集的比较,可以看到作者提出的数据集(CodeContents Raw)在没有添加生成的隐藏样例时,FP也是很高的,在补充到200个左右的测样样例后,FP就会大大下降。

image.png

4 模型

4.1 模型架构

采用Encoder-Decoder的基础Transformer架构。表3展示不同size的AlphaCode模型的参数情况。这里可以看到,作者改进了Attention head中的Query和KV的数目,他们不相等。而且,Encoder和Decoder的数据也是不相等的。

编码器的长度是1536,解码器的长度是768也是非对称的。使用SentencePiece作为Tokenizer,词表大概有8000个token左右。

image.png

image.png

4.2 预训练

预训练时,解码器使用标准cross-entropy next token prediction loss,编码器使用masked language modeling loss。MLM loss对于提高编码器的表示学习能力至关重要。

4.3 微调

在微调阶段,作者使用了三个新的技术:

  • Tempering:

作者使用了一个小的温度 T=0.2

For high temperatures (τ→∞), all [samples] have nearly the same probability and the lower the temperature, the more expected rewards affect the probability. For a low temperature (τ→0+), the probability of the [sample] with the highest expected reward tends to 1.

from Wikipedia article on softmax function

  • Value conditioning & prediction:

作者同时利用了训练样例中的不正确的解,只是在训练时会加入一个前置字符串CORRECT SOLUTION等,如下图所示:

image.png

  • GOLD:

这是一个离线的强化学习方法,旨在让模型更加关注于正确的一个解。

4.4 大规模采样

AlphaCode提供了三种采样的策略:

  1. 生成一半Python,一半C++
  2. 通过修改图5中的提示,得到不同的解
  3. 采用更高的温度,生成更加多样的解

同时,作者也使用了CodeX中提到的TopK输出和nucleus sampling,发现没有太大必要去做。

4.5 过滤

作者使用程序题目中提供的样例输入和样例输出进行测试,如果测试通过则认为正确。这样就可以过滤掉99%的问题。

4.6 聚类

额外采用一个之前预训练好的一模一样的模型,这个模型在Fine-tune时用来生成一些测试样例(不一定正确),然后让模型生成过滤后的程序来接收这些测试样例,得到输出后,根据输出的结果进行聚类,每个类中的程序可以认为是语义相似的,只需要将聚类按大小排序,然后从大到小作为最终的提交次序来提交。

5 实验

在Codeforce平台上的成绩如下图所示:

image.png

最终的测试结果如下表所示:

image.png

一些不同设置的实验结果如下图所示:

image.png

可以看到,采样越多,效果越好;模型size越大,效果越好,且有参数量指数增长,性能线性增长的趋势。

image.png

作者还对比了不同模型的结构对于模型预测的影响:包括只用decoder、标准的Multi-head attention等。整体Performance没有太大变化,但是作者采用的这种是最快的。

image.png

下表展示了预训练的数据集对最终结果的影响:

image.png

最后,作者展示了不同技术加进去后的提升情况,

image.png

下图会更直观一些

image.png

6 分析

  1. 作者分析了模型会不会“抄袭”某些代码片段。

image.png
2. 作者分析了机器生成的代码中有一些无用的代码片段。

image.png

image.png

  1. 对问题的描述是不是很敏感:主要是说如果你把问题描述更加精简了,模型的性能会提升。这也说明,模型理解长文本可能还有待提升。其次,对标签的敏感程度,作者尝试了标签随机化,效果最好。

image.png

image.png

  1. 验证损失并没有太多的用:验证损失增加,Performance上升

image.png

7 相关工作

写的还是比较详细的,有兴趣的同学可以细读一下。

8 影响

略

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

1…808182…956

开发者博客

9558 日志
1953 标签
RSS
© 2025 开发者博客
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%