代码开源
代码地址:https://github.com/SeafyLiang/machine_learning_study/tree/master/practical_project/05异常电池检测比赛
由于便于可读性,代码是*.ipynb。可读性极强,运行结果也有,希望大家可以star and fork ,非常感谢。
比赛介绍
汽车产业正在经历巨大变革,新能源汽车市场规模持续扩大,电池安全问题日益引发重视。 电池异常检测面临着汽车数据质量差,检出率低,误报率高,大量无效报警无法直接自动化运维等问题。
为了更好的检验电池安全问题,比赛通过募集优秀异常检测方案,使用特征提取、参数优化、异常对比等手段对实车数据进行处理,优化异常检测结果,以便更好的应用于车辆预警、故障模式识别等多种场景。
赛题简介
1、赛题链接
https://aistudio.baidu.com/aistudio/competition/detail/495/0/introduction
2、赛题背景
新能源车辆电池的故障检测对于及时发现车辆问题、排除隐患、保护人的生命财产安全有着重要意义。新能源电池的故障是多种多样的,包括热失控、析锂、漏液等,本次比赛数据中包含了多种故障类型,但在数据中统一标注为故障标签“1”,不做进一步的区分。
一般故障检测都会面临故障标签少的问题,在本次比赛中,我们对数据进行了筛选,正常数据和故障数据的比例不是非常悬殊,即便如此,常规的异常检测算法依然会是一个非常好的选择。
电池的数据是一种时序数据,在数据中的‘timestamp’列是该数据的时间戳,理解时序数据的处理方式可能会对异常检测有更好的效果。除此之外,发生异常的数据可能看起来很“正常”,需要提取更多的特征来进行分析。
3、比赛任务
具体任务:
本次赛题任务为“挑选出异常的电池数据”,选手在训练集对数据进行分析,选取特征,训练并优化模型等,最终需要检出测试集中的异常充电数据,保证较高的检出和较低的误报,评分会使用综合指标AUC。
4、评估指标
AUC(area under curve)
5、数据集
训练集:
文件类型为.pkl文件,每个pkl文件内容为元组形式(data,metadata);
data:形状为(256,8),每列数据对应特征[‘volt’,‘current’,‘soc’,‘max_single_volt’,‘min_single_volt’,‘max_temp’,‘min_temp’,‘timestamp’]
metadata:包含label和mileage信息,label标签中‘00’表示正常片段,‘10’表示异常片段。
测试集:
文件类型为.pkl文件,每个pkl文件内容为元组形式(data,metadata);
data:形状为(256,8),每列数据对应特征[‘volt’,‘current’,‘soc’,‘max_single_volt’,‘min_single_volt’,‘max_temp’,‘min_temp’,‘timestamp’]
metadata:仅包含mileage信息。
我就不啰里八嗦了
下面是我们的思路总结,代码部分在github,是一个*.ipynb文件,跑动的过程我们已经展示了,部分解释也写了。应该很容易懂,所以下面是想法的来源和分析。
赛题分析
首先,很明显是一个二分类问题,但是赛题给出的数据集数据极其不平衡比例大约是(neg)4:1(pos)。对于这种电池异常背景很显然异常状态有一些特征会很特别,所以入手思路基本就两个要么搞数据要么搞特征。下面从两个方面分析我们的做法。
特征方面
我们组也不是很懂这个电池这个玩意,特征没有做特别深入的分析和构建。特征构建方面很简单:由于是一条序列数据所以会对每一列的特征做最大值、最小值、均值、方差、众数或者中位数、求和。另外还有一些相对的信息,比如电压上一时刻减去下一时刻的相对电压信息,相对最大温度,相对最大单体电压、相对最小单体电压、温度缩放、以及最后一个时刻减去第一个时刻的变化。总体没什么特别的特征。
def helper(x):
'''
x: 特征
比如 volt,会有序列的信息 比如第一时刻到256时刻的volt数据
对这序列数据取到 最大值、最小值、均值、求和、median、方差
这些特征用来反映这条时序数据的信息
后续会对每一个特征都会进行这样的操作,另外还会引入新的特征序列,比如相对volt时序信息等等
'''
if isinstance(x, type(np.array([1,2,]))):
x = pd.DataFrame(x)
max_num = x.max()
min_num = x.min()
mean_num = x.mean()
sum_num = x.sum()
median_num = float(x.median())
std_num = float(x.std())
res = []
for i in [max_num, min_num, mean_num, sum_num, median_num, std_num]:
res.append(float(i))
return res