Page 189 - 《软件学报》2026年第2期
P. 189
668 软件学报 2026 年第 37 卷第 2 期
入子函数特征), 本文选择采用合并融合作为融合方式, 并将其应用于后续的实验与分析中.
值得注意的是, 子函数名称可能会被分词为多个连续的 token. 因此, 在融合过程中, 本文将每个 token 与学习
的子函数表示进行求和或替换. 与之前的方法不同, 在这些方法中, 子函数名仅作为一个字符串处理. DHCS 采用
了一种更合理的层次结构, 通过增强目标函数与调用的子函数之间的表示, 从而提升目标函数的表示能力.
4.2 主题感知复制解码器
本文同样采用 Transformer 作为解码器的骨架, 用于注释的生成. 解码器的输出是目标序列 Y = [Y 1 ,Y 2 ,...,Y n ].
t 中, 解码器首先计算基于前面生成的 token: H 的隐藏状态 , 然后通过
t
在解码步骤 [y 1 ,...,y t−1 ] 和上下文表示 h d
Softmax 操作计算每个注释 token 在词汇表上的生成概率 P v (t):
t
h = Decoder(H,y 1 ,...,y t−1 ) (10)
d
( )
t
P v (y t |y 1 ,...,y t−1 ) = Softmax h d (11)
直观上, 子函数的注释将有助于目标注释的生成. 受复制机制的启发 [21,55] , 本文设计了一个简单而有效的主题
感知复制机制, 允许解码器在生成词汇时既能从词汇表中生成单词, 也能从子函数的主题中复制信息. 具体来说,
ˆ H 生成子函数的注释 ′ ′
为了获得子函数的主题分布, 首先利用解码器根据子函数表示 token 分布 P (y 1 ),P (y 2 ),...,
v v
P (y n ), 然后计算注释 token 序列分布的均值. 公式如下:
′
v
( )
t
h ′ = Decoder ˆ H,y 1 ,...,y t−1 (12)
d
( )
t
P v ′ (y t |y 1 ,...,y t−1 ) = Softmax h ′ (13)
d
1 n ∑
P s = P v ′ (y t ) (14)
n
t=1
其中, P s 是一个子函数的主题分布. 最后, 本文通过计算每个子函数的主题分布 P s 均值, 获得目标函数中所有子函
数的最终主题分布 P topic . 实际上, P topic 可以视为词汇表中关键词的分布, 这些关键词可以部分反映子函数的逻辑
和功能. 值得注意的是, 本文在计算主题分布和最终生成注释时使用相同的解码器.
一旦获得了主题分布, 本文设计了一种软选择机制来决定是从词汇表中生成单词, 还是从子函数的主题中复
t
制信息. 具体来说, 在解码步骤 t 中, 根据解码器的状态 h 计算选择概率 P gate ∈ [0,1], 如下所示:
d
( ( ))
P gate = σ MLP h t d (15)
其中, MLP 表示一个多层感知机, 用于特征维度转换, σ 是 Sigmoid 函数. 最后, 通过联合概率计算在解码步骤 t 中
生成 token y t 的概率:
( )
= P gate ×P v + 1− P gate ×P topic (16)
P y t
通过选择门 P gate , 模型可以自适应地决定如何利用子函数的主题来辅助目标函数注释的生成.
4.3 掩码子函数预测
近年来, 预训练策略已经展示了它们显著提高下游任务性能的能力 [33,34,37] . 在本文的 DHCS 中, 编码器和解码
器可以使用基于代码的预训练语言模型 (如 CodeT5) 进行初始化, 从而继承编程语言中有价值的语义知识. 然而,
单靠这些语义知识可能不足以捕捉目标函数与其相关子函数之间深层的上下文层次关系. 为了解决这个问题, 本
文精心设计了一种名为“掩码子函数预测”的自监督训练目标. 这一目标旨在通过深入挖掘子函数的上下文细节,
丰富其语义表示.
在掩码子函数预测任务中, 本文采用了动态的子函数名称掩码技术, 并按照以下步骤进行掩码子函数预测.
4.3.1 动态子函数名称掩码
根据第 3 节的定义, 目标函数 X 包含一个或多个子函数 [ ˆ X 1 , ˆ X 2 ,..., ˆ X j ]. 在通过子函数编码器处理后, 获得了学
′ ′ ′ k 个子函数
习到的表示序列 H = [H ,H ,...,H ]. 在训练阶段, 对于当前批次中的每个目标函数, 本文随机选择
1 2 j
′ ′ H 替换这些子函数. 同时, 用特殊 token “<mask>”,
∗
[H ,...,H ], 其中 k < j, 并用一个随机初始化的掩码子函数向量
k
1
掩盖 X 中对应的子函数名称. 例如, 如果随机选择第 1 个和第 3 个子函数进行掩码, 那么掩码后的目标函数将变为

