Page 29 - 《软件学报》2024年第4期
P. 29
杨宏宇 等: 基于多模态对比学习的代码表征增强预训练方法 1607
5. _SemanticsStructureFusion(Code,the root of the AST parsed by Code)
6. Return TokensAST
7. Function _SemanticsStructureFusion(Code,root)
8. TokensAST←∅
9. If root.Children=∅ then Return
10. For child in root.children
11. If child.type=“identifier” and child.children≠∅ then
12. tokens←AlignNodeToTokens(child is one leaf node N leaf of the AST,Code)
13. add the tokens to the TokensAST
14. Else
15. ast←child.type and add the ast to the TokensAST
16. _SemanticsStructureFusion(Code,child)
17. Return TokensAST
18. Function AlignNodeToTokens(N leaf ,Code)
19. start←N leaf .start_node,end←N leaf .end_node
20. tokens←∅ and tokens⊂Code
21. If start[0]=end[0] then tokens←Code[start[0]][start[1]:end[1]]
22. Else
23. tokens←Code[start[0]][start[1]:]
24. For i in [start[0]+1,…,end[0]]
25. concatenate Code[i] to tokens
26. concatenate Code[end[0]][:end[1]] to tokens
27. Return tokens
注意: AlignNodeToTokens 函数(第 18−27 行)中, 根据 N leaf 的 start_node 和 end_node 属性值,在源代码中有
唯一确定的 tokens⊂S 与 N leaf 对齐. 并且 start_node 是一个元组, 表示为(行号,序号). 例如图 3 所示: 源代码中
的字符“sum”位于第 1 行, 包含第 5 个字符到第 7 个字符, 因此它的 start_node 值为(0,4); 同理,它的 end_point
的值为(0,6).
Code S 的函数名和自然语言注释形式化为 f 和 n, 其中, J 和 L 是 f 和 n 应用 RoBERTa [25] 分词器划分的
长度:
i
j
ca = ( , ,..., ,...,t t 2 c 1 t |N nonleaf | ,...,c |N leaf | ), t = ( t N nonleaf ), c = (N leaf ) (1)
i
j
1
f=(f 1 ,f 2 ,…,f j ,…,f J ), 1≤j≤J, n=(n 1 ,n 2 ,…,n l …,n L ), 1≤l≤L (2)
将公式(1)的 ca 和公式(2)的 f 进行拼接, 且使用特殊符号[CLS]表示是一个位于段序列最前端的特殊开始
字符, [SEP]是分隔不同模态数据的特殊字符, 源代码的输入 code 表示如下:
code=([CLS]⊕f⊕[SEP]⊕ca⊕[SEP]) (3)
2.2 编码器
[3]
REcomp 分别以 CodeBERT, GraphCodeBERT 和 UniXcoder 为初始化模型 , 其编码向量函数表示为
Embedding(⋅), 结合多模态输入 code, 如公式(3)所示, 其中间表示 e code 表示在公式(4):
e code =Embedding(code) (4)
如图 2(b)编码器模块所示: REcomp 由 N(N=12)层 Transformer [23] 组成, 由中间形式 e 作为模型输入生成每
N
一层的隐藏状态 H , 每一层 Transformer 都含有一个架构相同的转换器, 该转换器使用多头注意力机制(multi-
0
headedself-attention), 通过一个前馈神经网络(FeedForwardLayer)覆盖上一层的输出, 初始化时 H =e code , 对于