机器学习[笔记]
记录下之前做用户反馈的 NLP 处理时,机器学习的笔记
概念定义
TensorFlow
一个科学计算库
张量 (Tensor)作为数据的基本单位。TensorFlow 的张量在概念上等同于多维数组,我们可以使用它来描述数学中的标量(0 维数组)、向量(1 维数组)、矩阵(2 维数组)等各种量
监督式机器学习定义
机器学习系统通过学习如何组合输入信息来对从未见过的数据做出有用的预测。
线性回归
线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。
其表达形式为y = w'x+e,e为误差服从均值为0的正态分布。
标签
标签是我们要预测的事物,即简单线性回归中的 y 变量。
标签可以是小麦未来的价格、图片中显示的动物品种、音频剪辑的含义或任何事物。
标签可以是测试用例的规模/覆盖率。
标签可以是BUG的数量
标签可以是产生BUG风险较大的功能模块
特征
特征是输入变量,即简单线性回归中的 x 变量。简单的机器学习项目可能会使用单个特征,而比较复杂的机器学习项目可能会使用数百万个特征,按如下方式指定:
x1,x2,…xn
在垃圾邮件检测器示例中,特征可能包括:
电子邮件文本中的字词
发件人的地址
发送电子邮件的时段
电子邮件中包含“一种奇怪的把戏”这样的短语
测试用例的功能模块
测试用例的优先级
测试用例发现BUG较多的功能模块
样本
样本是指数据的特定实例:x。
(我们采用粗体 x 表示它是一个矢量。)我们将样本分为以下两类:
有标签样本
无标签样本
有标签样本同时包含特征和标签。即:
labeled examples: {features, label}: (x, y)
我们使用有标签样本来训练模型。 无标签样本包含特征,但不包含标签。即:
unlabeled examples: {features, ?}: (x, ?)
模型
模型定义了特征与标签之间的关系。例如,垃圾邮件检测模型可能会将某些特征与“垃圾邮件”紧密联系起来。
重点介绍一下模型生命周期的两个阶段:
【训练】是指创建或学习模型。也就是说,向模型展示有标签样本,让模型逐渐学习特征与标签之间的关系。
【推断】是指将训练后的模型应用于无标签样本。也就是说,使用经过训练的模型做出有用的预测 (y’)。
回归与分类模型
回归模型可预测连续值。例如,回归模型做出的预测可回答如下问题:
加利福尼亚州一栋房产的价值是多少? 用户点击此广告的概率是多少?
分类模型可预测离散值。例如,分类模型做出的预测可回答如下问题:
某个指定电子邮件是垃圾邮件还是非垃圾邮件? 这是一张狗、猫还是仓鼠图片?
Gompertz 增长模型:y=a*bcT
把特征与标签结合,举例:某些系统信息特征(如历史版本出现问题频率、与其他功能的耦合关系、用户场景触发相关功能的频次)与风险指数较大的模块、BUG的数量
通过训练集,不断识别特征,不断建模,最后形成有效的模型,这个过程就叫“机器学习”
机器学习步骤:数据收集、数据清洗、数据准备
示例 1:支付宝信用评分
步骤一:构建问题,选择模型
5 个影响因素
付款记录 账户总金额 信用记录跨度(自开户以来的信用记录、特定类型账户开户以来的信用记录…) 新账户(近期开户数目、特定类型账户的开户比例…) 信用类别(各种账户的数目)
Y=f(ABCDE)
Y=结果
f 是公式关联 5 个因素
步骤二;收集已知数据
收集 5 种因素的信息以及对应的信用评分 数据分成 3 种类型: 训练集(60%)、测试集(20%)、验证集(20%)
示例 2:通过酒精度和颜色来区分红酒和啤酒
步骤一.收集数据
颜色
酒精度数
种类
步骤二.数据分类
训练集
测试集
验证集
步骤三.选择模型
小型线性模型
步骤四.训练
步骤五.评估
步骤六.参数调整
步骤七.预测
线性回归示例:蝉鸣叫声与温度之间的关系
Y 指的是温度(以摄氏度表示),即我们试图预测的值
m 指的是直线的斜率
x 指的是每分钟的鸣叫声次数,即输入特征的值
b 指的是 y 轴截距
模型方程式:$$Y = mx + b$$
其中:
y'指的是预测标签(理想输出值)
b 指的是偏差(y 轴截距)
w 指的是权重
w1 指的是特征 1 的权重(权重与上文中用 m 表示的“斜率”的概念相同)
x1 指的是特征(已知输入项)
要根据新的每分钟的鸣叫声值 x1 推断(预测)温度 y',只需将 x1 值代入此模型即可
下标(例如 w1 和 x1)预示着可以用多个特征来表示更复杂的模型。例如,具有三个特征的模型可以采用以下方程式:$$y'= b + w1x1 + w2x2 + w3x3$$
迭代
[梯度下降法]http://www.doc88.com/p-2445313427576.html
\(Y=a \* b^{c^T}\)
方法总结
基于代码指标的预测
预测对象:代码源文件(代码长度,运算复杂度,圈复杂度等)
主要方法:主要分析代码特征与 bug 的关联关系
备注:需要一个相对复杂的预测模型
不足:特征不准确,模型难落地
基于 bug 历史数据的预测
预测对象:代码源文件
主要方法:以 bug 历史数量作为主要计算依据
备注:从版本控制系统日志获取修复每个 bug 时被改动的源文件记录,统计出每个源文件历史上产生的 bug 数量,从而识别出一批在过去产生 bug 最多的源文件,同时为了避免历史记录产生的误报(有的模块即使存在大量历史 bug 记录,重构优化后 bug 实际是减少的),给每个 bug 增加权重,值随时间增加而减少(离当前时间最近的值权重为 1,离当前时间最远的值权重为 0)
不足:仅看 bug 历史数据不足以支撑预测准确率
基于代码活动特征的预测(即时 bug 预测)
预测对象:代码改动活动(代码特征+源文件)
主要方法:通过分析一次代码变更时,牵涉的所有代码变更活动(代码特征+源文件),映射模型,预测出 bug 发生概率,输出风险值(设置阈值,形成代码合入门槛)
备注:活动特征————
改动大小(添加、修改、删除行数)
改动范围(发生变动的源文件、目录数量)
改动历史(发生改动的源文件历史上的修改情况)
作者信息(提交代码、产生 bug 的记录)
代码评审信息(comments 数量、reviewer 记录)
不足:深层特征提取难度大,模型相对复杂
基于深度学习的即时 bug 预测
预测对象:代码改动活动(CommitMassage)
主要方法:通过对描述代码改动的 commit message 与实现代码改动的代码片段。将 commit message 和代码改动作为文本型输入,算法可以自动从中学习各种各样的低阶和高阶特征(包括代码语法和语义特征),并利用这些特征来构建预测模型。这个过程中用到的典型技术有 word embedding、卷积神经网络 CNN 等。
即时缺陷预测技术的一般过程,主要包括三个阶段,数据标注、特征提取和模型构建。其中 数据标注阶段主要依赖于版本控制系统(例如 Git)和缺陷追踪系统(例如 Bugzlla 或 Jira),将代码变更标注为缺 陷变更(Buggy)或非缺陷变更(Clean);特征提取阶段主要通过提取不同维度的特征来表示代码变更;模型构建 阶段主要依赖于机器学习技术构建预测模型,当新的代码变更提交时,模型将预测其缺陷可能性。
数据标注是指将代码变更标注为缺陷引入变更和非缺陷引入变更。准确的数据标注是完成模型训练和模型评估的前提。
SZZ 算法
1.查找 commit massage 数据中 fix bug 的记录,定位到具体的源文件
2.对上一步找到的源文件,通过 diff 算法,查找修复 bug 进行的代码变更,定位到产生 bug 的代码行(标记为‘-’号的代码行)
3.对上一步找到的产生 bug 的代码行,通过 annotate 命令,查找该 bug 的代码变更(提交)历史,定位到最早引入该 bug 的代码变更(标记为‘+’号的代码行)
4.以上一步找到的 bug 引入变更为基准,清除所有提交 bug 之后产生的代码变更(噪音消除)
B-SZZ
AG-SZZ(annotation grahp)
MA-SZZ
RA-SZZ
基于变更元数据的特征。
定义:描述变更属性(例如开发者、提交时间、变更日志、修改文件、每个文件增加和减少的代码行数等)的数据。
获取方式:
1.直接通过软件项目的版本控制系统中的变更提交记录获取。
基于变更代码内容的特征。
定义:基于变更代码内容的特征。
获取方式:
1.使用代码复杂度特征来表征变更。同时使用代码变更代码、日志和文件名的词频率特征来量化代码变更内容
2.将这些基于变更代码内容的特征与基于变更元数据的特 征结合,构建预测模型。
基于软件演进过程的特征。
定义:基于项目代码修改历史量化变更。
获取方式: 1.基于文件修改历史的特征可以直接通过变更提交历史记录计算。从文件修改历史角度提取变更特征,例如变更相关文件被修改的次数、修改变更相关文件的开发者人数等。
基于多源软件制品的特征。
定义:结合多源软件制品提取多维代码变更特征。
获取方式:
1.从项目的代码审查系统、测试管理系统、项目管理系统等提取特征来表征代码变更。
9 个维度:
变更元数据
规模 (Size):(要注意这里采用的是相对比值:相对增加行数、相对减少行数分别指变更实际增加、减少行数与变更提交前其相关文件代码行数的比值)
commit 活动中增加、减少的代码行数|与产生 bug 的概率成正比
commit 活动中增加、减少的代码片段|与产生 bug 的概率成正比
修改前的代码源文件大小|与产生 bug 的概率成正比
代码分布(Diffusion):
commit 活动中修改的子系统数|与产生 bug 的概率成正比
commit 活动中修改的代码目录数|与产生 bug 的概率成正比
commit 活动中修改的文件数|与产生 bug 的概率成正比
commit 活动中整体源文件的修改点分布(信息熵)|与产生 bug 的概率成正比
目标(Purpose)
commit 活动中的目的是否为修复 bug |与产生 bug 的概率成正比
commit 活动中与该变更相关的 bug 记录|与产生 bug 的概率成正比
开发者经验(Developer Experience)
提交记录越多的开发者|与产生 bug 的概率成反比(这里是指相对所有开发者的提交记录中的占比)
变更代码内容
复杂度(Complexity):
commit前后,复杂度指标的差值,复杂度指标如代码总行数(LOC)、注释代 码行数、圈复杂度等|与产生bug的概率成正比
文本(Text)
commit前后,变更日志、文件内容、目录、文件名的词频率特征|未知
代码结构(Structure)
commit前后,抽象语法树的差异|未知
软件演进过程
文件修改历史(File History)
该变更文件修改的开发者数量|与产生bug的概率成正比
该变更文件修改的次数|与产生bug的概率成正比
该变更文件修复的bug数量|与产生bug的概率成正比
变更文件的最近变更时间的时间差平均值|最近引入的变更产生bug的概率较大
多源软件系统
代码审查(Code Review)
变更被重复修正的次数、审查人数、审查意见数量以及审查时间|与产生bug的概率成正比
标签:
模块的 bug 发生概率
特征:
模块的 bug 历史总数、模块上一版本的 bug 总数、模块的严重级别为高的 bug、模块的优先级为高的 bug、模块的遗留(挂起)bug、模块的遗留(挂起)严重级别高的 bug
样本:
一组数据,由标签+特征组成【有标签样本】;由特征组成【无标签样本】
模型:
定义特征与标签之间的关系,生命周期;训练+推断
回归模型:
预测连续值,如用户点击此广告的概率是多少?
分类模型:
预测离散值,如某个指定电子邮件是垃圾邮件还是非垃圾邮件?
代码示例
import tensorflow as tf
#Set up a linear classifier.
classifier = tf.estimator.LinearClassifier()
#Train the model on some example data.
classifier.train(input_fn=train_input_fn, steps=2000)
#Use it to predict.
predictions = classifier.predict(input_fn=predict_input_fn)
步骤
第 1 步:定义特征并配置特征列
第 2 步:定义目标
第 3 步:配置 LinearRegressor
第 4 步:定义输入函数
特征提取
hot portions of the code base 代码库热门部分
git log --pretty=format:"%h - %an - %ad - %ar - %cd - %cr - %s" --shortstat >> /Users/jo/Development/Makeblock/mBlock/mblockWEB_commit.txt
初步导出了一份数据,一条记录里有两行(因为 git log 不支持一行显示)
第一行 提交记录 ID - 作者 - 修订时间 - 修订时间(按距今多久显示) - 提交时间 - 提交时间(按距今多久显示) - 提交注释信息
第二行 文件改动数量, 新增代码行数量, 删除代码行数量
在 TensorFlow 中,使用估计器开发机器学习程序的一般过程如下:
1.创建一个或者多个输入函数(Input Function)。
2.定义模型的特征列(Feature Column)。
3.用特征列和超参数(Hyper-parameter)等作为入参,实例化估计器,得到估计器对象(object)。
4.用输入函数作为入参,调用估计器对象的若干方法(训练、评价、预测等),完成机器学习工作。
代码示例
es.normalize_entity(base_entity_id ='bigmart', new_entity_id ='outlet', index ='Outlet_Identifier',
additional_variables = ['Outlet_Establishment_Year', 'Outlet_Size', 'Outlet_Location_Type', 'Outlet_Type'])
feature_matrix, feature_names = ft.dfs(entityset = es,
target_entity ='bigmart',
max_depth = 2,
verbose = 1,
n_jobs = 3)
特征基元
聚合基元:多个表之间的父子关系,例如:通过 client_id 将 loan 表进行分组,为每个客户找到最大贷款值
转换基元:单个表内的多列之间关系,例如:取 2 列之间的差值,取 1 列的绝对值
#bug、项目、字段之间的关系
r_issue_project = ft.Relationship(es['issues']['project_id'],
es['projects']['project_id'],
es['customfield']['project_id'])
#将关系添加到实体集
es = es.add_relationship(r_issue_project)
#以前的贷款和以前的付款之间的关系
r_payments = ft.Relationship(es['projects']['p_id'],
es['payments']['loan_id'])
思路
多表字段合并单表,再进行特征自动化
单表特征合成后特征数量 364 个,初步筛选出 185 个,特征工程的工作流程已经确定;
选择【即时缺陷预测】方案
数据标注:通过 git&jira 将代码变更的记录标注是否产生缺陷(buggy/clean)
具体方法:szz 算法
1.识别缺陷修复变更
扫描存储在版本控制系统的所有历史数据,即所有代码变更,识别日志中包含缺陷 ID 的代码变更。这些代码变更被识别为缺陷修复变更。
区分迭代周期,在单个迭代周期内,扫描整个代码库,根据代码 commit 修改文件,找出关联的模块 (git commit id -> 软件模块)找出 jira 中所有 bugID,再将 bugID 与 git 的 massage 做关联,查出包含 bugID 的提交记录(bug id -> git commit id) => (git commit id -> 软件模块 s -> (bug ids))
2.识别被修复的缺陷代码。利用版本控制系统实现的 diff 算法来识别上述修复缺陷的代码变更修改的代码行。这些被修改的代码行被识别为缺陷代码。
c.找出包含bugID的代码提交记录对应的,为了修复缺陷的代码变更。(定位错误代码位置)
3.识别可能的缺陷引入变更。使用代码版本控制系统中的annotate命令回溯代码变更提交历史,第一次引入缺陷代码的变更被识别为可能的缺陷引入变更。
d.找出该错误代码引入的提交记录(定位错误代码的引入信息)
4.噪音数据消除。缺陷引入变更应当在该缺陷被报告之前被提交。因此,提交时间晚于缺陷报告时间的代码变更会被当作噪音去除。
e.找出提交时间晚于缺陷产生的时间的错误代码引入的提交记录,并删除该类数据
git commit id1(代码改动) -|
|- Module1-—-
| |- bug 1 (严重性、reopen、...)
| |— bug 2
| |...
| |- bug n
|
|
|- Module2
|
|...
|- Moudule n
git commit id2(代码改动) -|
|- Module1-——
| |- bug 1
| |— bug 2
| |...
| |- bug n
|
|
|- Module2
|
|...
|- Moudule n
F(git commit id ) = [Pm1, Pm2, Pm3, ..., Pmn] Pm表示模块产生bug的概率或影响程度
Pm = F1(bug1,bug2,bug3 ... bug n) = sum(1 * c0 + bug.priority * c1 + bug.reopen * c2 + ... + bug.xxx * cn) //根据测试经验指定cn
st. sum (c0,c1 ... cn) = 1
样本:
[git commit id 1] [Pm1, Pm2, Pm3, ..., Pmn]
[git commit id 2] = [Pm1, Pm2, Pm3, ..., Pmn]
... ...
[git commit id n] [Pm1, Pm2, Pm3, ..., Pmn]
git commit idn = [filepath1, 改动行数1, ]
git commit idn = { //从gitlog提取特征
author: {P4, 参与项目时间, 责任心}
time: "",
modulechanges :[{name: "Module1", changeRatio:0.1, coverage: 0.6} , {name: "Module2", line:0}]
}
最终模型:
{ //从gitlog提取特征
author: {P4, 参与项目时间, 责任心}
time: "",
modulechanges :[{name: "Module1", line:5} , {name: "Module2", line:0}]
} => [Pm1, Pm2, Pm3, ..., Pmn]
{
"author": {
"author_level": "p4",
"author_bugs": 110,
"author_commits": 130
},
"commit_info": {
"commit_id": "c2as13b",
"commit_time": "2020-03-05",
"commit_purpose": "fix | feat | refactor | doc | style | test"
},
"modules_change": [{
"modules_id": "",
"module_name": "modules1",
"files_change": 2,
"insertions": 4,
"deletions": 4,
"testCoverage": 0.9,
"testPass": 0.8,
"testFail": 0.2,
"TotalBugs": 14,
"lastIterationBugs": 3,
"suspendedRatio": 0.1,
"reopenRatio": 0.1,
"missRatio": 0.01,
"highPriorityBugs": 5,
"highSeverityBugs": 3,
"affectingModulesBugs": 12,
"affectingVersionBugs": 3,
"affectingClientBugs": 7,
"bugs_info": [{
"bug_id": "[MBLOCK-00001]",
"modules": ["modules1", "modules2", "...", "modulesN"],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
},
{
"bug_id": "[MBLOCK-00002]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
},
{
"...": "..."
},
{
"bug_id": "[MBLOCK-N]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
}
]
},
{
"modules_id": "",
"module_name": "modules2",
"files_change": 2,
"insertions": 4,
"deletions": 4,
"testCoverage": 0.9,
"testPass": 0.8,
"testFail": 0.2,
"TotalBugs": 14,
"lastIterationBugs": 3,
"suspendedRatio": 0.1,
"reopenRatio": 0.1,
"missRatio": 0.01,
"highPriorityBugs": 5,
"highSeverityBugs": 3,
"affectingModulesBugs": 12,
"affectingVersionBugs": 3,
"affectingClientBugs": 7,
"bugs_info": [{
"bug_id": "[MBLOCK-00001]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
},
{
"bug_id": "[MBLOCK-00002]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
},
{
"...": "..."
},
{
"bug_id": "[MBLOCK-N]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
}
]
},
{
"...": "..."
},
{
"modules_id": "",
"module_name": "modulesN",
"files_change": 2,
"insertions": 4,
"deletions": 4,
"testCoverage": 0.9,
"testPass": 0.8,
"testFail": 0.2,
"TotalBugs": 14,
"lastIterationBugs": 3,
"suspendedRatio": 0.1,
"reopenRatio": 0.1,
"missRatio": 0.01,
"highPriorityBugs": 5,
"highSeverityBugs": 3,
"affectingModulesBugs": 12,
"affectingVersionBugs": 3,
"affectingClientBugs": 7,
"bugs_info": [{
"bug_id": "[MBLOCK-00001]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
},
{
"bug_id": "[MBLOCK-00002]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
},
{
"...": "..."
},
{
"bug_id": "[MBLOCK-N]",
"modules": ["modules1", "modules2", "...",
"modulesN"
],
"versions": ["v1", "v2", "...", "vN"],
"priority": "3 | 2 | 1",
"severity": "5 | 4 | 3 | 2 | 1",
"reopen": 3,
"missable": 1,
"suspendable": 1
}
]
}
]
}
{
"author": {
{
"author_level": "p4",
"author_bugs": 110,
"author_commits": 130
}
},
"commit_info": [{
"id": "",
"time": "",
"purpose": "fix | feat | refactor | doc | style | test"
}],
"modules_change": [{
modules_id: "",
module_name: "modules1",
files_change: 2,
insertions: 4,
deletions: 4,
testCoverage: 0.9,
testPass: 0.8,
testFail: 0.2,
TotalBugs: 14,
lastIterationBugs: 3,
suspendedRatio: 0.1,
reopenRatio: 0.1,
missRatio: 0.01,
highPriorityBugs: 5,
highSeverityBugs: 3,
affectingModulesBugs: 12,
affectingVersionBugs: 3,
affectingClientBugs: 7,
bugs_info: [{
bug_id: "[MBLOCK-00001]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
},
{
bug_id: "[MBLOCK-00002]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
},
{ ...
},
{
bug_id: "[MBLOCK-N]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
}
]
},
{
modules_id: "",
module_name: "modules1",
files_change: 2,
insertions: 4,
deletions: 4,
testCoverage: 0.9,
testPass: 0.8,
testFail: 0.2,
TotalBugs: 14,
lastIterationBugs: 3,
suspendedRatio: 0.1,
reopenRatio: 0.1,
missRatio: 0.01,
highPriorityBugs: 5,
highSeverityBugs: 3,
affectingModulesBugs: 12,
affectingVersionBugs: 3,
affectingClientBugs: 7,
bugs_info: [{
bug_id: "[MBLOCK-00001]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
},
{
bug_id: "[MBLOCK-00002]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
},
{ ...
},
{
bug_id: "[MBLOCK-N]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
}
]
},
{
...
},
{
modules_id: "",
module_name: "modules1",
files_change: 2,
insertions: 4,
deletions: 4,
testCoverage: 0.9,
testPass: 0.8,
testFail: 0.2,
TotalBugs: 14,
lastIterationBugs: 3,
suspendedRatio: 0.1,
reopenRatio: 0.1,
missRatio: 0.01,
highPriorityBugs: 5,
highSeverityBugs: 3,
affectingModulesBugs: 12,
affectingVersionBugs: 3,
affectingClientBugs: 7,
bugs_info: [{
bug_id: "[MBLOCK-00001]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
},
{
bug_id: "[MBLOCK-00002]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
},
{ ...
},
{
bug_id: "[MBLOCK-N]",
modules: ["modules1", "modules2", ..."modulesN"],
versions: ["v1", "v2", ..., "vN"],
priority: "3 | 2 | 1",
severity: "5 | 4 | 3 | 2 | 1",
reopen: 3,
missable: 1,
suspendable: 1
}
]
}
]
}
ps:其他优化 szz 算法
AG-szz,避免空行、注释、代码风格的对引入缺陷的误标记
MA-szz,避免分支创建、合并、修改文件属性等的(元变更)对引入缺陷的误标记
RA-szz,(不实用)避免代码重构的对引入缺陷的误标记
补充步骤:
1.查找 commit massage 数据中 fix bug 的记录,定位到具体的源文件
2.对上一步找到的源文件,通过 diff 算法,查找修复 bug 进行的代码变更,定位到产生 bug 的代码行(标记为‘-’号的代码行)
3.对上一步找到的产生 bug 的代码行,通过 annotate 命令,查找该 bug 的代码变更(提交)历史,定位到最早引入该 bug 的代码变更(标记为‘+’号的代码行)
4.以上一步找到的 bug 引入变更为基准,清除所有提交 bug 之后产生的代码变更(噪音消除)
特征提取:
通过提取不同维度特征来表示代码变更
模型构建:
依赖机器学习构建预测模型,当产生新的代码变更记录时,预测出现 bug 的可能性
具体方法:
gitlog 筛出所有代码关联的模块,1-N 关系,1 次提交对应多个模块
1个完整的提测周期内:代码提交->对应模块的相关度->是否产生 bug
输入:
存在Bug的模块的特征
输出:
迭代提测周期内,代码提交时,涉及的模块产生 bug 的概率
迭代提测周期内,代码提交时,产生 bug 的概率
step
移动量,取决于当前的微分值,和常数项
源代码、缺陷报告、测试报告、代码审查报告、代码静态扫描
影响模块产生 bug 概率的特征(代码改动特征):
改动大小(添加、修改、删除行数)
改动范围(发生变动的源文件、目录数量)
改动历史(发生改动的源文件历史上的修改情况)
开发信息(提交代码、产生bug的记录)
代码评审信息(comments数量、reviewer记录)
变更增加减少行数
修改文件数量
变更类型
开发者
开发者经验
提交时间
变更日志
修改文件
模块的历史bug数量
模块的历史严重级别bug数量
迭代需求故事数量
技术挑战数量
迭代天数
人力数量
源文件变更时
源文件方法数量
源文件总行数
源文件圈复杂度
源文件包(方法)引用数量
改动的源文件数量
改动的(增加、减少)行数
改动前源文件大小
源文件历史改动次数
修复 bug 为目的的提交次数
实现新需求为目的的提交次数
重构为目的的提交次数
增加注释为目的的提交次数
Jira 历史数据
模块历史 bug 数量
模块历史严重级别较高的(致命/严重/一般)bug 数量
模块历史优先级较高的(最高/高/一般)bug 数量
模块上一迭代 bug 数量
模块上一迭代严重级别较高的(致命/严重/一般)bug 数量
模块上一迭代优先级较高的(最高/高/一般)bug 数量
模块发现阶段为用户反馈的 bug 数量
模块影响版本较多(>=1/2/3...)的 bug 数量
模块影响客户端较多(>=1/2/3...)的 bug 数量
模块影响其他模块较多(>=1/2/3...)的 bug 数量
模块遗留(挂起)bug 的数量
模块创建时间较近的(上一迭代)、挂起的 bug 数量
模块遗留严重级别较高的(致命/严重/一般)bug 数量
模块遗留严重级别较低的(提示/建议)bug 数量
模块遗留优先级较高的(最高/高/一般)bug 数量
模块遗留优先级较低的(低/最低)bug 数量
模块必现 bug 的数量
模块偶现 bug 的数量
模块测试步骤较多的(>=1/2/3...)bug 数量
模块挂起时间较长的(>1 个迭代周期)bug 数量
模块挂起时间较短的(<=1 个迭代周期)bug 数量
模块挂起时间较长的、严重级别较高的、优先级较高的 bug 数量
模块挂起时间较短的、严重级别较低的、优先级较低的 bug 数量
模块存在评论内容的 bug 数量
模块 reopen 次数较多的 bug 数量
产品需求信息
模块需求的历史修改次数
模块需求上一迭代是否修改
模块需求因为修复 bug 而修改的次数
模块需求修改内容为“文案”的次数
模块需求修改内容为“逻辑”的次数
模块需求修改影响其他需求(较多)的次数
代码审查信息
代码审查不通过的次数
代码审查通过的次数
代码审查的单次时长
代码审查的总时长
代码审查反复修正的次数
人为因素信息(同类比)
提交记录次数较多的开发者
职级较高的开发者
名下 bug 较多的开发者
名下挂起的 bug 较多的开发者
名下挂起的、严重级别较高 bug 较多的开发者
名下 bug 平均解决耗时较高的开发者
Commit Log 规范
type 用于说明 commit 的类别,只允许使用下面 8 个标识
br: 此项特别针对 bug 号,用于向测试反馈 bug 列表的 bug 修改情况
feat:新功能(feature)
fix:修补 bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改 bug 的代码变动)
test:增加测试
chore:构建过程或辅助工具的变动