乐趣区

关于深度学习:代码的表示学习CodeBERT及其他相关模型介绍

什么是 CodeBert

CodeBERT 是微软在 2020 年开发的 BERT 模型的扩大。它是一个用于编程语言 (PL) 和自然语言 (NL) 的双峰预训练模型,能够执行上游的 (NL-PL) 工作,这个模型应用 6 种编程语言 (Python, Java, JavaScript, PHP, Ruby, Go) 进行 NL-PL 的匹配训练。

本文将对论文进行简要概述,并应用一个例子展现如何应用,无关模型背地的数学和具体架构的更多详细信息,请参阅原始论文。在最初除了 CodeBert 以外,还整顿了最近一些对于他的钻研之上的衍生模型。

在深入研究这篇论文之前,让咱们先介绍一下 CodeBERT 能够反对的上游工作用例和。这些用例中的一些曾经在 MS 工具中实现,例如 visual studio- IntelliCode。

CodeBert 的用例

代码转换或代码翻译:例如,当开发人员想要编写与现有 python 代码雷同的的 java 代码时,代码到代码翻译能够帮忙翻译此代码块。

代码主动正文:能够帮忙开发人员进行代码摘要。当开发人员看到不相熟的代码时,模型能够将代码翻译成自然语言并为开发人员进行总结。

文本到代码:相似代码搜寻的性能,这种搜寻能够帮忙用户检索基于自然语言查问的相干代码。除此以外还能够依据正文生成相应的代码。

文本到文本:能够帮忙将代码域文本翻译成不同的语言。

BERT 架构

BERT ((Bidirectional Encoder Representations from Transformers) 是谷歌在 2018 年提出的自监督模型。

BERT 实质上是由多个自注意力“头”组成的 Transformer 编码器层堆栈(Vaswani 等人,2017 年)。对于序列中的每个输出标记,每个头计算键、值和查问向量,用于创立加权示意 / 嵌入。同一层中所有头的输入被组合并通过一个全连贯层。每层都用跳过连贯相连,而后进行层规范化(LN)。BERT 的传统工作流程包含两个阶段:预训练和微调。预训练应用两个自监督工作:掩蔽语言建模(MLM,预测随机掩蔽的输出标记)和下一句预测(NSP,预测两个输出句子是否彼此相邻)。微调实用于上游应用程序,通常在最终编码器层之上增加一个或多个全连贯层。

CodeBert 架构

BERT 很容易扩大到多模态,即应用不同类型的数据集进行训练。CodeBert 是 Bert 的双模扩大。即 CodeBERT 同时应用自然语言和源代码作为其输出。(与次要关注自然语言的传统 BERT 和 RoBERTa 不同)

双峰 NL – PL 对:训练 CodeBERT 的典型输出是代码和明确定义的文本正文的组合。

CodeBERT 形容了两个预训练指标:掩码语言建模 (MLM) 和替换标记检测 (RTD)。

应用掩码语言建模训练 CodeBERT:为 NL 和 PL 抉择一组随机地位来屏蔽掉,而后用非凡的 [MASK] 标记替换所选地位。MLM 的指标是预测被覆盖的原始标记

带有替换标记检测的训练 CodeBERT:在原始 NL 序列和 PL 序列中,有很少的标记会被随机屏蔽掉。训练一个生成器模型,它是一个相似于 n-gram 的概率模型进行屏蔽词的生成。而后训练一个鉴别器模型来确定一个词是否是原始词(二元分类问题)。

CodeBERT 应用 12 层 Transformer 总计蕴含 125M 参数,在 FP16 精度上应用 NVIDIA DGX-2 上进行 250 小时的训,结果显示当 CodeBERT 与来自 RoBERTa 模型的预训练示意一起应用时(RoBERTa 模型已应用来自 Code-SearchNet 的代码进行训练)与从头开始训练时的比照。应用 RoBERTa 初始化 CodeBERT 性能更好。

应用 CodeBERT 进行微调

具体应用办法能够参考 CodeBERT 论文 在这里简要介绍如何应用 CodeBERT,并以代码文档生成为例。

装置相应的包

pip3 install torch==1.4.0
pip3 install transformers==2.5.0
pip3 install filelock

数据预处理

本工作中的数据预处理如下:

  • 删除代码中的正文
  • 删除代码无奈解析为形象语法树的示例。
  • 删除文档的 #tokens < 3 或 >256 的示例
  • 删除文档蕴含非凡标记的示例(例如 <img …> 或 https:…)
  • 删除文档不是英文的示例。
pip3 install gdown
mkdir-p data/code2nl
cd data/code2nl
gdown https://drive.google.com/uc?id=1rd2Tc6oUWBo7JouwexW3ksQ0PaOhUr6h
unzip Cleaned_CodeSearchNet.zip
rm Cleaned_CodeSearchNet.zip
cd ../..

应用 tree 命令能够看到如下目录构造:

tree data/code2nl/CodeSearchNet/
data/code2nl/CodeSearchNet/
├── go
│   ├── test.jsonl
│   ├── train.jsonl
│   └── valid.jsonl
├── java
│   ├── test.jsonl
│   ├── train.jsonl
│   └── valid.jsonl
├── javascript
│   ├── test.jsonl
│   ├── train.jsonl
│   └── valid.jsonl
├── php
│   ├── test.jsonl
│   ├── train.jsonl
│   └── valid.jsonl
├── python
│   ├── test.jsonl
│   ├── train.jsonl
│   └── valid.jsonl
└── ruby
    ├── test.jsonl
    ├── train.jsonl
    └── valid.jsonl

6 directories, 18 files

每种语言都有本人的训练、验证、测试数据文件。

运行程序

拜访 https://github.com/microsoft/… 并克隆 run.py、bleu.py、model.py 文件并将它们放入 data/code2nl 文件夹中。

运行以下命令。将 batch_size=128 改为 batch_size=4,这是因为 GPU 的内存不够,太大的 bs 会导致 OOM。

lang=php 
beam_size=10
batch_size=4
source_length=256
target_length=128
output_dir=model/$lang
data_dir=../data/code2nl/CodeSearchNet
dev_file=$data_dir/$lang/valid.jsonl
test_file=$data_dir/$lang/test.jsonl
test_model=$output_dir/checkpoint-best-bleu/pytorch_model.bin #checkpoint for test

python run.py --do_test --model_type roberta --model_name_or_path microsoft/codebert-base --load_model_path $test_model --dev_filename $dev_file --test_filename $test_file --output_dir $output_dir --max_source_length $source_length --max_target_length $target_length --beam_size $beam_size --eval_batch_size $batch_size

这样就开始训练了,训练实现后如何调用 CodeBERT 呢?

如果只想应用从 CodeBERT 转换的特色示意,能够应用以下示例代码:

from transformers import AutoTokenizer, AutoModel
import torch

# Init
tokenizer = AutoTokenizer.from_pretrained("microsoft/codebert-base")
model = AutoModel.from_pretrained("microsoft/codebert-base")

# Tokenization 
nl_tokens=tokenizer.tokenize("return maximum value")
code_tokens=tokenizer.tokenize("def max(a,b): if a>b: return a else return b")
tokens=[tokenizer.cls_token]+nl_tokens+[tokenizer.sep_token]+code_tokens+[tokenizer.sep_token]

# Convert tokens to ids
tokens_ids=tokenizer.convert_tokens_to_ids(tokens)
context_embeddings=model(torch.tensor(tokens_ids)[None,:])[0]

# Print
print(context)

输入的后果如下:

tensor([[-0.1423,  0.3766,  0.0443,  ..., -0.2513, -0.3099,  0.3183],
        [-0.5739,  0.1333,  0.2314,  ..., -0.1240, -0.1219,  0.2033],
        [-0.1579,  0.1335,  0.0291,  ...,  0.2340, -0.8801,  0.6216],
        ...,
        [-0.4042,  0.2284,  0.5241,  ..., -0.2046, -0.2419,  0.7031],
        [-0.3894,  0.4603,  0.4797,  ..., -0.3335, -0.6049,  0.4730],
        [-0.1433,  0.3785,  0.0450,  ..., -0.2527, -0.3121,  0.3207]],
       grad_fn=<SelectBackward>)

下面代码咱们也看到 Huggingface 也提供了 CodeBERT 相干的模型,咱们能够间接拿来应用:

import torch
from transformers import RobertaTokenizer,RobertaConfig,RobertaModel
device=torch.device("cuda"if torch.cuda.is_available() else"cpu")
tokenizer=RobertaTokenizer.from_pretrained("microsoft/codebert-base")
model=RobertaModel.from_pretrained("microsoft/codebert-base")
model.to(device)

codebert 地址:

https://github.com/microsoft/…

基于 CodeBERT 的其余模型介绍

GraphCodeBert:基于数据流的代码表征预训练模型

https://arxiv.org/abs/2009.08366

利用代码的语义构造来学习代码表征的预训练模型 GraphCodeBERT,基于 Bert 预训练模型实现,除了传统的 MLM 工作外,本文还提出了两个新的预训练任务(数据流边预测、源代码和数据流的变量对齐),基于数据流学习源代码的向量表征,在 4 个上游工作上获得了显著的晋升成果。

UniXcoder: 对立的跨模式预训练模型

https://arxiv.org/abs/2203.03850

Unixcoder 是一种用于编程语言的对立的跨模式预训练模型。该模型利用带有前缀适配器的掩码留神矩阵来管制模型的行为,并利用 AST 和代码正文等跨模式内容来加强代码示意。为了对并行示意为树的 AST 进行编码,论文提出了一种一对一的映射办法,能够保留 AST 中所有构造信息的序列构造。该模型还利用多模态内容通过比照学习来学习代码片段的示意,而后应用跨模态生成工作来对齐编程语言之间的示意。

CodeReviewer: 自动化代码审查

https://arxiv.org/abs/2203.09095

在下面钻研的根底上,又提出了 CodeReviewer,这是一个事后训练的模型,它利用了四个专门为代码审查场景量身定制的事后训练任务。模型的重点放在与代码评审流动相干的三个要害工作上,包含代码变更品质评估、评审正文生成和代码优化。模型的测试证实了通过预训练任务和多语言训练数据集能够让模型对代码更改和审查进行自动化的操作。

https://avoid.overfit.cn/post/29087fd920d847fb88671bc5e1cdad27

退出移动版