CodeBERT、GraphCodeBERT和CodeT5是代码智能领域的里程碑预训练模型,奠定了代码理解的技术基础。本文讲清楚它们的预训练任务、数据流图融合策略和架构差异,以及各自擅长的下游任务。你将学到如何选择和微调这些模型用于代码搜索、摘要和生成,并理解它们的训练数据特点。适用于构建代码智能产品的算法工程师和做代码理解研究的人员。

学习提示

需要学习代码预训练模型(CodeBERT/GraphCodeBERT/CodeT5),世界模型、空间智能等前沿方向定义了CV的未来。本篇涵盖AGI/世界模型/脑机接口/前沿论文,帮助你跟踪AI前沿趋势。

目录
  1. 可视化演示
  2. AI 应用场景
  3. Python 演示
  4. 常见误区
  5. 面试题

可视化演示

状态—

CodeBERT、GraphCodeBERT和CodeT5是代码智能领域的里程碑预训练模型,奠定了代码理解的技术基础。本文讲清楚它们的预训练任务、数据流图融合策略和架构差异,以及各自擅长的下游任务。你将学到如何选择和微调...

预训练范式:先上"代码学院"再上岗

想象一位程序员学徒的成长路径:他先在一所"代码学院"里泡了几个月,每天翻阅数以亿计的开源代码——有的抄录、有的填空、有的默写——等他毕业时,对"代码长什么样"已经形成了肌肉记忆。这就是预训练范式:先用海量无标签数据教出通用理解能力,再针对具体工作做少量"岗前特训"(微调)。

传统做法是拿人工标注数据从零训练一个代码模型,可标注数据又贵又少,模型学不到通用规律。预训练模型的做法反过来:先从GitHub等平台免费获取海量代码,用自监督方式学习——无需人工标注,让模型自己跟自己练。

最经典的自监督任务是掩码语言建模(Masked Language Modeling,MLM):随机把15%的token用[MASK]盖住,让模型根据上下文猜出被盖住的词。对代码来说,这不是简单的完形填空,因为代码语法严格、语义敏感,换一个符号或错一个名称都会让人看不懂——这逼着模型学到比自然语言更精确的语法和语义关联。

这个公式度量模型对"被遮住的词"预测得有多准:预测越准,损失越小。

LMLM=−∑xi∈Mlog⁡P(xi∣x∖M)\displaystyle \mathcal{L}_{\text{MLM}} = -\sum_{x_i \in M} \log P(x_i \mid x_{\setminus M})
  1. 遮蔽集合训练时随机挑一些token放入集合M,相当于老师在书本上贴便签,盖住关键词让学生填空。
    M⊆input tokens\displaystyle M \subseteq \text{input tokens}
  2. 条件概率给定被挖空后的上下文(去掉M中的词),模型预测每个被盖住的词语原本是什么。
    P(xi∣x∖M)\displaystyle P(x_i \mid x_{\setminus M})
  3. 求和取负对数对所有被盖住的位置求预测概率的负对数并累加,模型越有把握,这个值越小。 所以你看,"学院教育"赋予学徒通用语感,"岗位特训"让他胜任具体工作。接下来的三位学长,只是在这套学习范式下各自选修了不同课程。
    −∑xi∈Mlog⁡P(xi∣x∖M)\displaystyle -\sum_{x_i \in M} \log P(x_i \mid x_{\setminus M})

CodeBERT:只会精读的学徒

学院里第一位学长CodeBERT,是典型的"精读型"学徒。他能把代码逐字读得很细,理解每行的意思,但让他默写一段新代码,他就抓瞎。这对应CodeBERT的定位:一个纯理解模型。

技术上,CodeBERT基于RoBERTa改造,属于"仅编码器"(encoder-only)架构。它的输入是两段拼接的多模态片段:代码序列和自然语言注释(比如"计算两个数的和"这种说明)。输出不是新代码,而是一串向量——就像学徒读完代码后在脑海里形成的综合印象。

预训练时它做两件事:一是MLM,分别对代码和注释做掩码预测;二是替换token检测(Replaced Token Detection,RTD),随机把一些词换成别的,让模型判断哪些位置被换过。最终损失是两者相加。训练完成后,模型每输入一段代码就吐出一个向量表示,后续的代码搜索、缺陷分类等任务都在这份"读后感"上加一个简单的分类头即可。

这个损失函数把"填空训练"和"找茬训练"放在一起:既要求模型会猜词,又要求它能分辨哪些词被动了手脚。

LCodeBERT=LMLM+LRTD\displaystyle \mathcal{L}_{\text{CodeBERT}} = \mathcal{L}_{\text{MLM}} + \mathcal{L}_{\text{RTD}}
  1. MLM掩码损失分别对代码片段和注释片段做掩码预测,两部分损失相加,让模型同时吸收两种语言的知识。
    LMLM=LMLMcode+LMLMdoc\displaystyle \mathcal{L}_{\text{MLM}} = \mathcal{L}_{\text{MLM}}^{code} + \mathcal{L}_{\text{MLM}}^{doc}
  2. RTD判别损失用另一个模型随机替换部分token,让主模型判断每个位置是否被替换过,训练它捕捉"词是否自然"。
    LRTD=−∑ilog⁡Di(x)\displaystyle \mathcal{L}_{\text{RTD}} = -\sum_{i} \log D_i(\mathbf{x})
  3. 联合优化把两个损失加起来,模型在一次训练中同时完成"理解语义"和"识别异常"两项作业。 精读学徒最擅长"阅读理解题"——代码搜索、代码分类、相似度比较。可他没法"写作文"。要生成代码,得等会写的学弟出场。
    LCodeBERT=LMLM+LRTD\displaystyle \mathcal{L}_{\text{CodeBERT}} = \mathcal{L}_{\text{MLM}} + \mathcal{L}_{\text{RTD}}

GraphCodeBERT:会画关系图的学徒

第二位学长GraphCodeBERT,在精读的功夫上多修了一门"关系追踪课"。他不满足于看懂每个token,还要把"变量从哪来、被谁用"的关系整理成一张像地铁线路图一样的数据流图。

代码里暗藏很多"暗线":变量a被赋值后可能在十行之外被使用,这两个token在文字上相距很远,但在"值传递"的意义上紧紧相邻。普通Transformer的自注意力很难捕捉这种长距离变量依赖。GraphCodeBERT的解法是:把代码转换成数据流图,图的边连接"变量定义"和"变量使用"。

技术上,它在CodeBERT之上做了三处改动。一是构建数据流:每个变量由哪次赋值定义、在哪次使用被引用,都用有向边标出。二是加GNN层:图神经网络(Graph Neural Network,GNN)把邻居的信息沿着数据流边聚合起来,更新每个token的表示。三是修改注意力掩码:让数据流可达的token对在注意力里能直接"看到"对方,绕过长距离的衰减。这些改动让标识符的语义更充分地被编码。

这是图神经网络更新节点表示的公式:每个节点把邻居的信息汇总起来,经过变换后变成自己新一轮的表示。可以理解为"你朋友的平均水平会影响你的新认识"。

hv(k+1)=ReLU(W∑u∈N(v)hu(k))\displaystyle h_v^{(k+1)} = \text{ReLU}\left(\mathbf{W} \sum_{u \in \mathcal{N}(v)} h_u^{(k)}\right)
  1. 邻居集合找出在数据流图上与节点v直接相连的所有邻居节点,记为N(v)。
    N(v)={u∣(u,v)∈E}\displaystyle \mathcal{N}(v) = \{ u \mid (u, v) \in E \}
  2. 邻居信息汇总把所有邻居节点的向量相加,相当于把大家的声音聚拢在一起。
    av=∑u∈N(v)hu(k)\displaystyle \mathbf{a}_v = \sum_{u \in \mathcal{N}(v)} h_u^{(k)}
  3. 线性变换与激活将汇总结果乘以权重矩阵W,再经过ReLU激活函数,得到节点v在第k+1层的新表示。 会画关系图的学徒,在排查"变量被错误复用"这类问题时,比只精读的学长看得更准。所以GraphCodeBERT在需要理解变量传播的代码场景(如缺陷定位)上表现更优。
    hv(k+1)=ReLU(Wav)\displaystyle h_v^{(k+1)} = \text{ReLU}\left(\mathbf{W} \mathbf{a}_v\right)

CodeT5:既会读又会写的工程师

第三位学长CodeT5,是学院里的"全能学霸"。他不仅精读,还跟着写作课练出了"默写能力"——给一个函数名和一段注释,他能把函数体从头写出来。这股"生成"的本事,靠的是他把学习方法从"只读"换成了"读写一体"。

结构上,CodeT5把只读的编码器换成了编码器-解码器(encoder-decoder)框架:编码器读代码(理解),解码器写代码(生成)。它继承T5的设计,把文本序列先转化为token序列,输出端用自回归方式一个token一个token地"写"下去——写完第1个,再看已经写出的内容决定第2个,就像人写作文一样。

预训练任务也不再是MLM+RTD,而是更贴合生成的跨度去噪(span denoising):随机把代码里的连续片段用几个哨兵token替换掉,让模型把整段还原。模型还要学会识别特殊标识符(如函数名),按需要保留或改写。这个"还原连续片段"的训练方式,让它在需要"续写、补全、生成完整实现"的下游任务上发挥出色。

这个公式描述解码器如何"写代码":每写一个token,都要保证它在前文和输入条件下的整体概率最大。

LCodeT5=−∑t=1Tlog⁡P(yt∣y<t,x)\displaystyle \mathcal{L}_{\text{CodeT5}} = -\sum_{t=1}^{T} \log P(y_t \mid y_{<t}, x)
  1. 目标序列长度T是目标序列的token数量,例如要生成的函数体长度,代表解码器要写多少步。
    T=∣y∣\displaystyle T = |\mathbf{y}|
  2. 逐位置条件概率第t个输出token的概率依赖两部分:已经写出的前t-1个token,以及编码器读到的原始输入x。
    P(yt∣y<t,x)\displaystyle P(y_t \mid y_{<t}, x)
  3. 累加负对数似然把每个位置的负对数概率加起来,整体预测越准,损失越小;解码时模型就按这个目标逐字生成。 如果说CodeBERT是理解型选手,GraphCodeBERT是关系挖掘专家,那CodeT5就是既能看懂需求文档、又能动手实现的全能工程师。代码摘要、代码补全、代码翻译这些"要动笔"的活,是它的主场。
    −∑t=1Tlog⁡P(yt∣y<t,x)\displaystyle -\sum_{t=1}^{T} \log P(y_t \mid y_{<t}, x)

数据工程:学院里的教材质量

学院的教育再先进,也得有好教材。预训练模型学得怎么样,很大程度上取决于喂给它的代码质量。如果教材里一半是"hello world"和复制粘贴的垃圾代码,学徒的语感就会被带偏。

CodeBERT用的是CodeSearchNet数据集,包含数百万对"代码-注释"样本,覆盖Python、Java、JavaScript等多种语言。CodeT5进一步使用更大规模的CodeSearchNet+等语料,并补充了代码生成、翻译等任务数据;为了不让学徒被噪声干扰,数据工程阶段要清洗代码:去掉重复文件、过滤超长或格式混乱的样本、删除不可编译或禁用的文件。

衡量教材"可读性"的一个指标是困惑度(Perplexity,PPL):让一个已有语言模型读这段代码,它越"惊讶",PPL越高,说明这段代码越不规范;设定阈值,把PPL过高的"天书"样本直接扔掉。此外还要做代码-注释对齐:确保注释确实在描述旁边的代码,而不是离题万里。

困惑度可以理解为"模型平均要在多少个词里犹豫一次":数值越小,说明这段代码越接近模型见过的正常代码。

PPL(x)=exp⁡(−1N∑i=1Nlog⁡P(xi∣x<i))\displaystyle \text{PPL}(x) = \exp\left(-\frac{1}{N} \sum_{i=1}^{N} \log P(x_i \mid x_{<i})\right)
  1. 平均对数概率让语言模型依次预测语料中每个token,把所有预测概率的对数取平均。
    −1N∑i=1Nlog⁡P(xi∣x<i)\displaystyle -\frac{1}{N} \sum_{i=1}^{N} \log P(x_i \mid x_{<i})
  2. 取指数还原对平均对数概率取指数,把结果还原成"平均猜测次数"的量纲,便于设定过滤阈值。
    exp⁡(−1N∑i=1Nlog⁡P(xi∣x<i))\displaystyle \exp\left(-\frac{1}{N} \sum_{i=1}^{N} \log P(x_i \mid x_{<i})\right)
  3. 阈值筛选保留困惑度低于阈值的样本作为高质量教材,数值上等价于"教材要挑读起来顺畅的"。 好教材让学徒学得快、学得正。这解释了为什么每个新模型的发布都会伴随更大的数据集——模型的进化,一半靠架构创新,一半靠"教材升级"。
    PPL(x)≤τ\displaystyle \text{PPL}(x) \leq \tau

下游应用:学徒的实习岗位

学徒毕业要找实习,不同岗位需要不同技能,这正是预训练模型在下游任务的"微调上岗"。同样是代码智能,代码搜索、代码摘要、代码生成三个岗位,对学徒的考核方式完全不同。

代码搜索更像"阅读理解+联想"。把查询语句映射成向量,代码库里的每段代码也映射成向量,然后算余弦相似度,相似度高的就是候选。这活儿用CodeBERT或GraphCodeBERT微调后干最好。代码摘要则要"写",要输入一段代码输出一句注释——这是生成任务,CodeT5更在行。

代码补全是在用户写了一半的代码处续写出后续片段,属于条件生成,同样是CodeT5的主场。代码翻译(把Python翻译成Java)也同理。理解型任务里,如果特别依赖变量之间关系(比如找未初始化变量),GraphCodeBERT比CodeBERT更合适。实际落地时,这些模型都经过任务数据微调:代码搜索要用"查询-相关代码"对训练,摘要要用"代码-注释"对训练。

这是代码搜索最常用的相似度公式:查询向量和代码向量的夹角越小,说明它们在语义空间里越"投缘"。

sim(q,c)=q⋅c∥q∥⋅∥c∥\displaystyle \text{sim}(q, c) = \frac{\mathbf{q} \cdot \mathbf{c}}{\|\mathbf{q}\| \cdot \|\mathbf{c}\|}
  1. 向量点积把查询向量与代码向量逐元素相乘后求和,数值越大说明两个向量的方向越一致。
    q⋅c=∑kqkck\displaystyle \mathbf{q} \cdot \mathbf{c} = \sum_{k} q_k c_k
  2. 模长归一化用两个向量的长度分别去除点积,把结果缩放到-1到1之间,防止"长向量"天然占便宜。
    q⋅c∥q∥⋅∥c∥\displaystyle \frac{\mathbf{q} \cdot \mathbf{c}}{\|\mathbf{q}\| \cdot \|\mathbf{c}\|}
  3. 相似度解读值越接近1表示语义越相近,排序后取Top-K作为搜索结果返回给用户。 给学徒安排对口的实习,他才能快速成为骨干。选错岗位——比如让只会精读的CodeBERT去写函数体——结果只能是一堆语法不通的"胡言乱语"。
    sim(q,c)→1\displaystyle \text{sim}(q, c) \to 1

选型指南:招哪一位学徒

如果你是技术负责人,要在项目里选一个预训练模型,就好比招聘:先看岗位职责(任务类型),再看薪资预算(资源约束),最后看试用期表现(评估指标)。

先定任务:纯理解型(分类、检索、相似度)选CodeBERT或GraphCodeBERT;生成型(补全、摘要、翻译)选CodeT5。再确认资源:CodeBERT约1.25亿参数,CodeT5-base约2.2亿参数,如果线上对延迟和显存敏感,大模型不一定合适,甚至要考虑蒸馏或小模型。最后看数据:现有标注数据的规模决定微调策略——数据少就多用预训练模型自带的表示做冻结特征,数据多就全面微调或再加一层任务头。

评估指标也要配套:分类任务看F1(精确率和召回率的调和平均),生成任务看BLEU或CodeBLEU,检索任务看MRR。选型不能只盯指标,还要看是否与业务痛点匹配:变量间关系敏感的缺陷检测,GraphCodeBERT的"关系追踪"能力就是加分项。

F1是精确率和召回率的"综合评分":两者都高,F1才高;任何一项偏科都会被惩罚。

F1=2⋅Precision⋅RecallPrecision+Recall\displaystyle F_1 = \frac{2 \cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}
  1. 精确率模型预测为"有缺陷"的样本里,真正有缺陷的比例,衡量"抓得准不准"。
    Precision=TPTP+FP\displaystyle \text{Precision} = \frac{TP}{TP + FP}
  2. 召回率所有真实有缺陷的样本里,被模型找回来的比例,衡量"抓得全不全"。
    Recall=TPTP+FN\displaystyle \text{Recall} = \frac{TP}{TP + FN}
  3. 调和平均把两者取调和平均,任何一个值太低都会明显拉低总分,避免模型靠偏科刷分。 最贵的不一定最合适。一个能力匹配、资源友好的模型,远比"更大的模型"更有价值——这句话在AI选型里和招聘一样成立。
    F1=2⋅Precision⋅RecallPrecision+Recall\displaystyle F_1 = \frac{2 \cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}

AI 应用场景

代码搜索引擎

阶段:模型微调与部署

解决的问题:传统代码搜索靠关键词文本匹配,搜"求两个数之和"匹配不到"def add(a, b): return a + b"。CodeBERT把自然语言查询和代码映射到同一语义空间,用余弦相似度检索,让"人话"能找到"代码"。

具体案例:某技术团队对内部百万行代码库建立向量索引,用CodeBERT微调后,开发者用自然语言描述功能即可找到对应实现,检索命中率提升约35%。

相关角色:算法工程师、搜索推荐工程师

智能代码补全

阶段:生成式预训练 + 任务微调

解决的问题:传统IDE补全基于模板或语法规则,遇到没见过的上下文就失效。CodeT5基于编码器-解码器框架,可以根据函数签名和注释预测完整函数体,是Copilot类产品的核心原理。

具体案例:IDE插件根据函数签名和上方注释自动生成函数体骨架,辅助程序员完成样板代码,实测减少约30%的键盘输入,尤其对重复性高的初始化代码效果明显。

相关角色:NLP算法工程师、IDE工具链开发者

代码安全审计

阶段:数据流特征提取 + 分类微调

解决的问题:传统静态分析工具产生大量误报,人工排查成本高。GraphCodeBERT利用数据流图追踪变量定义与使用路径,帮助定位未初始化变量、空指针等风险点,把"暗线"变成"明线"。

具体案例:安全团队用GraphCodeBERT对开源C语言项目做缺陷预测,在漏洞数据集上能精准定位危险变量传播链,辅助安全审计人员把排查范围缩小到关键路径。

相关角色:安全算法工程师、DevSecOps工程师

Python 演示

python29 行
from transformers import AutoTokenizer, AutoModelimport torchimport torch.nn.functional as F model_name = "microsoft/codebert-base"tokenizer = AutoTokenizer.from_pretrained(model_name)model = AutoModel.from_pretrained(model_name)  def encode(code: str):    inputs = tokenizer(code, return_tensors="pt", truncation=True, max_length=128)    with torch.no_grad():        hidden = model(**inputs).last_hidden_state    return hidden[:, 0, :]  code_lib = [    "def add(a, b): return a + b",    "def multiply(a, b): return a * b",    "total = sum(range(100))",    "def add(a, b): return a - b",] query = "add two numbers and return the sum"q_vec = encode(query)for code in code_lib:    c_vec = encode(code)    score = F.cosine_similarity(q_vec, c_vec).item()    print("%.3f %s" % (score, code))

常见误区

误区听到"BERT"就觉得它什么都能干,让CodeBERT直接生成代码,结果输出一堆乱码或报错,于是怀疑模型是坏的。

正解CodeBERT是"仅编码器"架构,本质上是个阅读理解高手,输出的是向量表示而不是新代码。会精读文章的人不等于会写文章,生成任务需要CodeT5那种"编码器-解码器"结构。选模型前先分清任务是要"理解"还是要"生成"。

为何常见:BERT名气太大,加上"预训练"三个字让人误以为它通用全能,忽略了架构对任务能力的根本限制。

误区看到"Graph"就以为模型用了完整的抽象语法树(AST),觉得它应该理解所有语法结构,遇到它答错复杂语法就认为模型不行。

正解GraphCodeBERT用的是轻量级的数据流图,只记录"变量在哪里定义、在哪里使用",并不包含完整的语法树信息。数据流图计算成本低,对代码搜索、克隆检测、变量关系类任务提升明显,但它不负责解析一切语法。

为何常见:一看到"图"就联想到语法树,是因为两者都长着"节点+边"的模样,却没意识到数据流只是语法树的一个投影。

误区以为CodeT5就是把CodeBERT的编码器输出接一个解码器,改动不大,预训练任务也应该一样。

正解CodeT5从模型初始化到预训练目标都重新设计,直接对齐T5框架,采用跨度去噪和标识符感知等生成式预训练任务,而不是BERT系的MLM+RTD。会读与会是两种能力的组合升级,不是"多张嘴巴"就能学会写文章。

为何常见:从CodeBERT到CodeT5的命名递进让人误以为只是小修小补,忽略了生成式预训练与判别式预训练的本质差异。

误区加载了预训练权重跑起来,发现效果还行,就直接部署到生产环境,结果在真实数据上一塌糊涂。

正解预训练只是"通识教育",要让模型在具体任务上好用,必须用任务数据微调。比如代码搜索需要"查询-相关代码"对做监督训练,否则embedding没有业务区分度。大学毕业生也要参加岗位培训才能胜任工作。

为何常见:模型在demo上惊艳的表现容易让人高估零样本能力,忽略了预训练与微调是完整的流水线。

误区选型时无脑挑参数量最大的模型,认为"大力出奇迹"在代码任务上也成立,结果上线时延迟和显存扛不住。

正解模型选择要匹配任务类型、推理延迟、显存预算。CodeBERT约1.25亿参数,CodeT5-base约2.2亿参数,在生成任务上性价比已经很高;对资源敏感的场景,还要考虑蒸馏或更小的变体,而不是盲目追大。

为何常见:"更大=更强"的直觉在通用NLP上经常成立,但工程落地是约束优化问题,资源成本也是重要维度。

面试题

Q1. CodeBERT的模型结构属于哪一类?

单选题 · easy

  • A.仅编码器架构← 正确答案
  • B.编码解码一体
  • C.纯解码器结构
  • D.图像分类网络

答案:A。CodeBERT基于RoBERTa改造,是典型的"仅编码器"架构,输入代码输出向量表示,擅长理解型任务。"编码解码一体"和"纯解码器"分别对应生成型模型和GPT系模型,而"图像分类网络"与代码理解无关。

Q2. 与CodeBERT相比,CodeT5的关键结构变化是什么?

单选题 · easy

  • A.采用编码解码框架← 正确答案
  • B.加入循环网络模块
  • C.使用图神经网络
  • D.增加注意力头数

答案:A。CodeT5最大的变化是采用编码器-解码器框架,使模型既能读代码也能生成代码。循环网络不是CodeT5的设计,图神经网络是GraphCodeBERT的特点,增加注意力头数属于细节调优而非结构性变化。

Q3. 与CodeBERT相比,GraphCodeBERT主要引入了什么?

单选题 · easy

  • A.更大规模训练语料
  • B.数据流图信息← 正确答案
  • C.更深的隐藏层数
  • D.全新的分词器

答案:B。GraphCodeBERT的核心贡献是引入数据流图,用有向边连接变量的定义与使用位置。更大语料、更深网络、新分词器都不是它相对CodeBERT的主要区别,模型本质变化在输入结构上。

Q4. CodeBERT的多模态输入片段组合包含哪些?

多选题 · mid

  • A.代码片段← 正确答案
  • B.注释文本← 正确答案
  • C.数据流图
  • D.语音信号

答案:AB。CodeBERT的输入由代码序列和自然语言注释拼接而成,目的是让模型学习"代码-注释"的对齐关系。数据流图是GraphCodeBERT的输入,语音信号与代码预训练无关。

Q5. GraphCodeBERT中的数据流图主要捕捉什么关系?

单选题 · mid

  • A.变量定义与引用← 正确答案
  • B.函数调用的层级
  • C.代码缩进层级
  • D.注释与代码联系

答案:A。数据流图记录"变量在哪里被定义、在哪里被使用",这正是GraphCodeBERT提升代码理解能力的关键。函数调用层级属于调用图,缩进层级是格式信息,注释与代码的联系属于多模态对齐。

Q6. CodeT5的跨度去噪预训练任务核心是什么?

单选题 · mid

  • A.遮蔽片段并复原← 正确答案
  • B.检测替换的token
  • C.随机交换词顺序
  • D.预测下一句语句

答案:A。跨度去噪是随机遮蔽一段连续的token片段,让模型还原完整内容。检测替换token是CodeBERT的RTD任务,随机交换词顺序和预测下一句都不是CodeT5的预训练目标。

Q7. 下列哪些属于代码模型常用预训练任务?

多选题 · mid

  • A.掩码语言建模← 正确答案
  • B.替换token检测← 正确答案
  • C.跨度去噪复原← 正确答案
  • D.手写数字识别

答案:ABC。掩码语言建模(MLM)是CodeBERT的基础任务,替换token检测(RTD)是CodeBERT的判别任务,跨度去噪是CodeT5的生成式任务。手写数字识别属于计算机视觉领域,与代码预训练无关。

Q8. 关于CodeBERT的替换token检测任务,正确的是哪项?

单选题 · hard

  • A.判别词是否被替换← 正确答案
  • B.预测被遮蔽的词
  • C.生成替换后的词
  • D.删除低质量词对

答案:A。RTD任务是让模型判断输入中哪些位置被替换成了别的token,本质上是判别任务。预测被遮蔽的词是MLM,生成替换后的词意味着任务是生成式的,删除词对更是与RTD无关。

Q9. GraphCodeBERT相对CodeBERT的改动包含哪些?

多选题 · hard

  • A.引入数据流图信息
  • B.增加GNN编码层← 正确答案
  • C.修改注意力掩码
  • D.改用解码器架构
  • E.嵌入层与编码层之间
  • F.所有Transformer之上
  • G.输出层之后的位置
  • H.每层Transformer的中间

答案:B。GraphCodeBERT在BERT的所有Transformer层之上叠加GNN层,让图信息聚合发生在深层语义表示形成之后。若放在嵌入层与编码层之间,则图信息过早介入会损失语义抽象;放在输出层之后或每层之间都不是论文的原始设计。