比赛页面:https://competition.huaweicloud.com/information/1000029328/introduction?track=111
作者:slaine
本人代号slaine,有幸在此次华为网络人工智能黑客松大赛的硬盘异常检测赛题中收获第一名的成绩,在这里简单跟大家分享下比赛方案。
一、赛题背景
硬盘生命周期通常为3-5年,在2-3年后故障率明显升高,导致换盘量陡增。在华为数据中心服务器硬件故障中,硬盘故障占比达到48%+。因此通过机器学习构建硬盘故障预测模型,对数据中心典型硬件进行预测,可以提前感知硬件故障,降低运维成本,显著提升业务体验。
此次比赛,非常荣幸能够免费接触和体验到的华为先进的NAIE训练平台。我花了大概一到两天的时间,就能够熟练使用该平台开发模型。
二、任务理解
本次比赛为典型的二分类问题,根据硬盘当天运行数据及之前的历史记录,判断硬盘未来是否会损坏。此前有不少人误解这个标签指的是硬盘当天损坏与否,但实际上所有的标签都是官方根据硬盘最终是否损坏与否来标注的,标注为0的就是硬盘最终没有坏,标注为1的是该盘最终坏掉了。
评分标准官方定义如下:
在业务上评价硬盘故障预测算法有两个指标:
误报率FAR(False Alarm Rate)和检出率FDR(Fault Detect Rate)。
业务目标是在误报率FAR<=0.1%的情况下尽量提高FDR。因此本任务的评价指标为:
Score = max(FDR) s.t. FAR≤0.1%,
其中,
FDR = TP/(TP+FN),
FAR = FP/(TN+FP).
实质上从数据分析的角度来看,就是在保证准确率的情况下,尽量提高召回率。
三、数据理解
由于时间有限,本次比赛我没有在可视化分析上花太多时间,所以这里就不作详细地数据分析,重点给大家介绍一下数据里的破题点。
此次比赛提供的训练集一共有55w+行数据,特征维度为52,标签值为0或者1,0代表好盘,1代表坏盘,每一条记录对应着一个硬盘某一天的状态信息,原始数据如下:


1. 数据组织
因为赛题目的是为了根据硬盘当天和历史数据来预测硬盘未来发生损坏的概率,那么数据组织就有至少两种方式:一是对每一个硬盘每一天的数据进行建模,模型输出每个硬盘每天的预测概率,最后对每个硬盘每天的预测概率取平均或者取最大值,作为当前硬盘在未来一段时间内损坏概率的最终预测值;二是对硬盘ID进行聚合分组,对每一个特征按硬盘ID分组计算统计特征,由此建模得到的预测概率就是在未来一段时间内该硬盘的损坏概率。我在这里优先选择了第二种数据组织方式,该方式可以有效回避个别数据异常值的影响,也更便于发现数据里的潜在规律。
2. 数据筛选
官方将测试集每条硬盘的数据记录数统一截取为20条。如果在构造训练集时不针对性地做出调整,很容易训练出过拟合的模型。所以我在构造训练集时首先删除了数据记录小于20条的硬盘,随后对于记录数大于20条的硬盘,按日期从小到大进行排列,并取最后20条记录来做聚合,从而保证和测试集的一致性,具体操作如下:

四、特征工程
这里重点讲一下特征处理的一些操作。
原始特征
训练集中原始的52个特征都是对硬盘当前性能的描述,在度娘上可以很容易找到对应特征的解释,比如所有raw特征均代表着从硬盘上采集到的数据的原始值,而normalized特征是对相应raw特征进行归一化操作的结果,另外各个特征数字代表的含义如下:

上图中特征9,241,242等都与硬盘启用时间有强相关,一般而言硬盘工作时间越长,出故障的概率越高,这些与工作时间相关的特征应该具有很强的建模价值,所以我的baseline思路就是对所有的原始特征进行简单的均值、最值统计,具体如下:
这样的操作在验证的时候(验证数据日期与训练集数据日期在同一个区间时)很有效,能轻松达到0.97+,但是当在测试集(2019年的数据)上提交时,线上得分却只有0.1不到,这意味着2019年的数据与2018年的数据有严重的不同。
2. 特征构造
此次比赛还有一个难点就是测试集的特征我们拿不到,这样导致我们不能像往常一样逐特征分析对比训练集和特征集的差异,包括kaggle上一些专门针对特征筛选的trick(比如对抗性验证等等)都无法使用,这时只有通过反复实验来求证(充分体现了数据科学中科学的一面)。
尝试一:为了解决过拟合问题,首先想到的是剔除在训练集中表现强劲的特征,也就是我在上面讲到的与硬盘工作时间强相关的特征(9,241,242等等),但是删除这些特征后线上成绩依然没有得到明显提升。
尝试二:期间我也尝试过解决训练集和测试集的一致性问题,因为测试集是统一在2019年1月头20天的数据,我便考虑构造训练集在2018年头20天或者最后20天的数据,但是训练集2018年头20天的数据标签全为1,最后20天的标签全为0,显然无法构造二分类。
尝试三:前面提到过所有raw特征均代表着从硬盘上采集到的数据的原始值,而normalized特征是对相应raw特征进行归一化操作的结果。如果测试集和训练集硬盘是同一个批次且同一个时期开启使用的,那么由于测试集的时间在训练集之后,测试集硬盘的raw特征取值应该普遍大于训练集,所以我删除了所有raw特征,仅使用normalized特征建模。本来信心满满,结果依然GG。
尝试四!!本来已经感觉快山穷水尽时,我做了最后一个灵光一闪的关键尝试,考虑到normalized特征是对raw特征的某种归一化操作的结果,那么两者之间应该有潜在关系可以挖掘,我条件反射地将两者拿来做除法,结果bingo!!此题的magic就这样发现了。通过将原始所有数字特征的normalized特征和raw特征分别做除法操作,线上成绩终于突破了0.1,而随后的上分操作就是一马平川。通过去除时间强相关特征,并加入一些有意义的统计特征,线上单模可以轻松突破0.4,具体操作如下:

3. 特征筛选
通过上述方法构造出来的特征共100多维,为进一步增强泛化能力,我采用了wrapper(封装式)特征筛选法,以lgb模型作为筛选模型,通过递归特征消除的方式最终筛选得到了最优的特征子集,这样可以有效减小特征维度并增强模型泛化能力。
具体来说就是原始特征数为N,每次删除K个特征并检验当前N-K个特征下的模型得分,如果当前得分有所提高,则取当前N-K个特征为最优特征子集,继续下一次循环,再删除k个特征,以此类推,可以求得最优特征子集。
五、模型
模型方面我采用了简单的lgb和xgb的bagging融合,粗暴的bagging融合就是对lgb和xgb预测值之和取平均,而我稍微做了一些调整,通过遍历两个模型权重来选择最优的融合比例,操作如下:

另外lgb和xgb均用了3个不同种子的5折融合,相当于最后一共融合了30个模型的预测结果,这样的操作使最终线上得分突破了0.5。本来我还打算尝试stacking融合,加入NN和逻辑回归增强泛化能力,还好各位大佬手下留情,没有逼我放大招哈哈,开玩笑。
六、总结
华为的服务还是很到位的,前期熟悉平台遇到的问题都能及时解答或者协助解决,甚至远程视频,诚意满满。NAIE平台本身也不错,JupyterLab特征工程有交互式编码体验,SDK调用代码一键生成,也支持在Jupyter里敲自定义代码,同时还有有强大的图表分析能力,WebIDE提供了强大的云端编码和debug能力。
方案写得不怎么样,主要是跟大家分享一下心路历程和踩过的坑,因为是一边加班一边偷偷打比赛,所以过程相当艰辛,还有很多地方可以优化都没有尝试。今年据说华为还有不少比赛,如果工作时间允许还会继续支持参加,要是奖金再高一点就更好了哈哈。
原文链接:https://zhuanlan.zhihu.com/p/131272835
来源:网络人工智能园地

