6.4.2 源代码作者属性识别方法
本节构建基于连续和离散词段级N-gram模型的逻辑特征、以及基于操作数组方法等的多粒度上下文的源代码作者属性识别方法。源代码作者身份属性识别方法包括两个阶段:源代码作者画像构建和源代码作者识别,如图6.9所示。其中,源代码作者画像构建阶段包括四个步骤:源代码布局特征提取、源代码编程风格特征提取、源代码结构特征提取、源代码逻辑特征提取。另外,逻辑特征提取模型包括连续词段级N-gram模型、离散词段级N-gram模型、基于字符级N-gram模型。另外,采用序列最小优化方法来识别源代码或程序的作者身份。
图6.9 源代码作者身份属性识别过程
源代码作者画像特征提取的准则是,第一,源代码特征与程序的具体功能或目的无关;第二,能够展现程序员编写代码的个人偏好和使用习惯等,这些特征在程序员不同代码中呈现相对稳定的特点。具体地,主要包含四类源代码作者画像特征:源代码布局特征、源代码风格特征提取、源代码结构特征以及源代码逻辑特征。
表6.7给出相关研究工作中使用的源代码特性集合。表6.8给出了本节构建的源代码特征。表6.7和表6.8给出了源代码特征类别、特征ID、特征焦点(Feature focus)和特征描述。其中,特征焦点是指源代码主题或特征所关联的源代码对象。源代码行分为四种类型:代码行、注释行、空白行以及源代码和注释组成的混合行。一个源代码和注释的混合行是指该行既包括源代码,也包括注释。另外,源代码的非注释行包括代码行和空行。
表6.7 相关工作采用的源代码特征
续表
表6.8 本节构建的源代码特征
续表
(1)源代码布局特征。
定义(源代码布局特征):源代码布局特征是指能够反映程序布局或程序的源代码和注释的布局的特征。
在表6.7和表6.8中,源代码布局特征的特征焦点集合为:{import,if statement,format of operator,format of loop,leading whitespaces of lines,percentage of blank lines}。例如,表6.8中特征fl1的特点焦点是“import”,它表示导入包操作。另外,fl1表示在包含关键词“import”的最后一行与包含源代码的下一行之间,是否至少存在一个空白行。
进一步,对所引入的三个源代码布局特征解释如下。首先,引入特征fl1的目的是描述包含导入包的行与其他源代码行之间的布局特征。其次,fl2和fl3均用于表示在“for loop statements”循环语句中空格的布局安排特点。实际上,这三种特征是独立于具体程序的,展现了程序员对导入包代码行和循环语句for loops的布局设计的偏好。源代码作者身份识别实验中源代码布局特征集合包括表6.7和表6.8中的布局特征,即tl1,tl2,tl3,tl4,fl1,fl2,fl3。
(2)源代码布局特征。
定义(源代码风格特征):源代码风格特征是指能够反映程序员对编程风格特点的偏好,例如变量名称或变量长度。
本节采用表6.8中风格特征fs1,fs2,…,fs10的原因在于以下三个方面。第一,fs1,fs2,fs3,fs7主要反映程序员在注释、关键字、循环语句和add操作语句的使用方面的个人特点。特别地,特征fs4是指开发者在for循环语句中是否经常定义循环变量。第二,特征fs5和fs6则主要反映程序员如何定义数组下标、程序员在程序中是否使用二维数组。第三,特征fs8主要描述开发者在void方法的末尾是否写语句“return 0;”的习惯。第四,引入特征fs9和fs10的目的是为了捕获程序员使用import、interface和class的频率特征。在实验中,使用一组源代码风格特征,由表6.7和表6.8中的风格特征组成,即fs1,fs2,…,fs10,ts1,ts2,…,ts22。
(3)源代码结构特征提取。
定义(源代码结构特征):源代码结构特征是指能够反映程序结构的特征。例如,方法的平均长度,该特征通常与程序员的经验相关。
本节引入特征fr1,fr2和fr3的原因是,这三种特征体现了开发人员对方法和注释的使用偏好。在实验中,使用的源代码结构特征包括表6.7和表6.8的特征fr1,fr2,fr3,tr1。
(4)基于连续和离散的词语级N-gram模型的逻辑特征提取。
定义(连续词段级N-gram源代码模型):连续词段级N-gram源代码模型是指,程序中一个连续的长度为N的词项序列(或语段序列),也就是,包括N个连续语段的序列。其中,源代码的语段定义为:任意被空格分隔的字符串。语段可以为:关键词、运算符、用户定义的标识符、标点符号和语句等。
对于一个源代码的语段序列t1,t2,…,tp,根据连续的词段级N-gram模型,可以获得如图6.10所示的语段序列。图6.10给出了两个源代码逻辑特征示例,包括基于连续词段级N-gram模型的源代码逻辑特征,基于离散的词段级N-gram模型的源代码逻辑特征。
图6.10 连续词段级N-gram和离散词段级N-gram源代码模型
例如,对于下面程序“from util import print_time_info,set_random_seed,get_hits,getResult”,根据连续词语级3-gram模型,可以构建长度为3个语段的序列,如下所示。
定义(离散词段级N-gram源代码模型):对于程序的语段序列t1,t2,…,tp,含有m个间隔语段的离散词段级N-gram模型是指,一个包括n个语段的离散序列,即tk,tk+m+1,…,tp,其中,1≤k≤p-(n-1)(m+1)。
例如,对于上述程序,基于含有1个跳跃语段的离散词语级2-gram模型,可以构建带有1个跳跃语段的离散词语级2-gram模型,如下所示:
首先,从数据集的程序中提取一组前k个高频连续词段级N-gram序列、一组前k个高频的离散词段级N-gram序列,以及一组字符级N-gram序列。程序的特征fg1,fg2,tg1分别是这三个集合中序列的出现频率。
本节引入基于连续性和离散性词段级N-gram模型的源代码逻辑特征提取方法的原因在于以下四个方面。第一,基于连续和离散词段级N-gram模型所提取的特征反映了程序员对关键字、标识符、运算符和语句的使用偏好。第二,连续词段级N-gram模型能够捕获程序员隐含的编程模式,即关键字与用户自定义的标识符之间的搭配模式。其中,用户自定义的标识符包括变量名称、方法名称、类名称等。然后,对于字符级的N-gram模型难以挖掘隐含的关键字与用户自定义的标识符之间的搭配模式。第三,基于离散词段级Ngram模型能够发现程序员潜在的、关键字自身之间、用户自定义标识符自身之间、关键词和运算符之间的搭配模式。第四,基于连续和离散的词段级Ngram模型的特征,易于从源代码中提取,并且不需要任何预处理。因此,基于这两个模型提取的特征与程序的具体功能或目的无关,能够展现程序员无意识的、相对稳定的个人编程特点。
语料库中的源代码经过特征提取阶段,生成特征向量。进一步,将源代码作者识别问题转化为多类别的分类问题。利用序列最小优化方法进一步识别源代码的作者。