Deep Learning for Source Code Modeling and Generation: Models, Applications and Challenges
一篇对源代码建模的综述。
传统的源代码建模方法.
-
Domain-specific language guided models
基于特定的编程语言来进行建模,不同的编程语言其语法结构还是不同的。 这种建模方法能够捕捉程序的结构信息,但是需要详细的规则来对程序进行解析表示。
-
Probabilistic grammars(概率语法?)
有两种语法规则,一种是Context-Free Grammars(CFGs) 上下文无关的语法。通过这种方法可以生成语法树。但是通过这种方法生成的语法树会有二义性,即同一个句子会有不同的意思。为了减少这种歧义,提出了一种Probabilistic Context-Free Grammar(PCFG),即在所有能生成的语法树中选择一个概率最大的一种。
-
Tree Substitution Grammar(TSG)
这个不太理解,应该是自然语言处理中的相关处理方法
-
n-gram
对于长序列的依赖问题不能很好的解决。向量空间的稀疏表示,造成语料库很大。
-
simple neural program models
用神经网络来进行词嵌入。
用深度学习模型来建模的优势,a.自动学习特征;b.捕捉长序列依赖;c.端到端的;d.泛化性强。现有的深度学习都是为了在这四者之间进行权衡。
通过encoder-decoder 框架进行建模
-
循环神经网络
RNN
LSTM
GRU
BLSTM
-
非循环神经网络
CNN+RNN
CNN
BERT
Transformer
-
注意力机制
-
记忆增强神经网络(Memory-augmented neural networks)
-
集束搜索(beam search)
输入的建模方式
- one-hot
- real-valued(Word2vec)
- 用预训练的NLP的模型来对下游任务进行再次训练
深度学习建模方式
-
序列建模方式,直接将代码按照序列来处理
但是有这些不足,
①代码中的句法结构不能很好的表示。代码结构可以看做是一个多维特征,而序列可以看做是一维特征,因此不能有效地表达其结构信息。
②语料库很大,而且很可能会出现有不在语料库的情况,这些都会影响模型的泛化性能。
③用循环网络时,其隐藏状态所包含的信息十分有限,即长序列的前后依赖问题。
-
结构化建模方式。
2.1 抽象语法树。
对于解析抽象语法树的方式有很多种。
①可以直接通过深度遍历的方式来解析;
②通过深度学习模型比如RNN,Tree-LSTM、CNN来处理;
③分解一个个代码语句组成的子树;
④用AST的路径来表示;(code2vec 、code2seq)
2.2 图结构
①GGNN
-
可变的语料库模型
对于源码中有很多用户自定义的标识符,这些不可能完全被语料库所包括。因此,往往存在有新的token不在语料库中的情形,即OoV(Out-of-Vocabulary 集外词)。
Karampatsis提出了一种open-vocabulary neural language model(Maybe Deep Neural Networks are the Best Choice for Modeling Source Code. arXiv preprint arXiv:1903.05734 (2019))这是对那些罕见词进行sub-Word的建模,将罕见词进行切分成子串进行建模。
还可以基于字符级别进行建模( Character-Aware Neural Language Models,AAAI16 )
还可以基于图的结构(Open vocabulary learning on source code with a graph-structured cache)
-
注意力机制
注意力机制也可以解决OoV问题。
Learning Python Code Suggestion with a Sparse Pointer Network(arxiv 2016)用的pointer network