喜欢就点关注吧!
作者:大风君
Github:
https://github.com/woxima/2019iFLYTEK_MachineryLife_Baseline/blob/master/README.md
赛题来源科大讯飞数据挖掘竞赛机械部件寿命预测,目前离初赛结束还有11天,本文分享目前排名第一的团队开源的baseline,帮助大家更好地进入比赛。
1.赛题分析
预测性维护是工业互联网应用“皇冠上的明珠”,实现预测性维护的关键是对设备系统或核心部件的寿命进行有效预测。对工程机械设备的核心耗损性部件的剩余寿命进行预测,可以据此对于相关部件的进行提前维护或者更换,从而减少整个设备非计划停机时间,避免因计划外停机而带来的经济损失,比如导致整个生产现场其他配套设备等待故障设备部件的修复。本赛题由中科云谷科技有限公司提供某类工程机械设备的核心耗损性部件的工作数据,包括部件工作时长、转速、温度、电压、电流等多类工况数据。希望参赛者利用大数据分析、机器学习、深度学习等方法,提取合适的特征、建立合适的寿命预测模型,预测核心耗损性部件的剩余寿命。
2.赛题难点
主办方并没有给出确定的训练集,因自变量并非一一对应结构化,如何构建合理有效的训练集是关键。
针对该问题采用以下方案解决:
训练集与测试集的构造:
a.一个训练样本按照寿命的0.45、0.55、0.63、0.75,0.85的比例进行构造五个小样本; b.测试集不变。
比如说一个样本的寿命为1000,我们截取450前的数据作为一个训练样本,其剩余寿命为550;然后截取550前的数据,标签为450,以此类推。
3.数据预处理
数据中有大量的负值和突变数据存在,我尝试一些方法,发现效果并不好,如何处理这一部分数据暂时没有找到比较好方案。如果大家有比较好处理方法,也可以一起交流讨论。
4.特征工程
该比赛的数据个人感觉是类时序数据,但不是那么严格,本文给出的baseline提取了一些基本的统计特征,比如最大最小值、均值、方差等。对设备进行独热编码。
#处理统计数据
def stat(data,c,name):
c[name + '_max'] = data.max()
c[name + '_min'] = data.min()
c[name + '_count'] = data.count()
c[name + '_mean'] = data.mean()
c[name + '_ptp'] = data.ptp()
c[name + '_std'] = data.std()
return c
在进行特征提取时还用一些小技巧,利用模块化处理单个数据样本,然后用多进程加快提取速度,处理单个样本的代码如下:
#处理单个训练样本
def process_sample_single(e,train_p):
data = pd.read_csv(e)
lifemax=data['部件工作时长'].max()
data=data[data['部件工作时长']<=lifemax*train_p]
c = {'train_file_name': os.path.basename(e)+str(train_p),
'开关1_sum':data['开关1信号'].sum(),
'开关2_sum':data['开关2信号'].sum(),
'告警1_sum':data['告警信号1'].sum(),
'设备':data['设备类型'][],
'life':lifemax-data['部件工作时长'].max()
}
for i in ['部件工作时长', '累积量参数1', '累积量参数2',
'转速信号1','转速信号2','压力信号1','压力信号2',
'温度信号','流量信号','电流信号']:
c=stat(data[i],c,i)
this_tv_features = pd.DataFrame(c, index=[])
return this_tv_features
多进程提取:
# 多进程调用单文件处理函数,并整合到一起
def get_together(cpu, listp,istest,func):
if istest :
train_p_list=[]
rst = []
pool = Pool(cpu)
for e in listp:
for train_p in train_p_list:
rst.append(pool.apply_async(func, args=(e,train_p,)))
pool.close()
pool.join()
rst = [i.get() for i in rst]
tv_features=rst[]
for i in rst[:]:
tv_features = pd.concat([tv_features, i], axis=)
cols=tv_features.columns.tolist()
for col in [idx,ycol]:
cols.remove(col)
cols=[idx]+cols+[ycol]
tv_features[idx]=tv_features[idx].apply(lambda x:x[:-1])
tv_features=tv_features.reindex(columns=cols)
else:
train_p_list=[0.45,0.55,0.63,0.75,0.85]
rst = []
pool = Pool(cpu)
for e in listp:
for train_p in train_p_list:
rst.append(pool.apply_async(func, args=(e,train_p, )))
pool.close()
pool.join()
rst = [i.get() for i in rst]
tv_features=rst[]
for i in rst[:]:
tv_features = pd.concat([tv_features, i], axis=)
cols=tv_features.columns.tolist()
for col in [idx,ycol]:
cols.remove(col)
cols=[idx]+cols+[ycol]
tv_features=tv_features.reindex(columns=cols)
return tv_features
5.模型构建
baseline是单模lgb五折交叉验证,无调参
#lgb
def lgb_cv(train, params, fit_params,feature_names, nfold, seed,test):
train_pred = pd.DataFrame({
'true': train[ycol],
'pred': np.zeros(len(train))})
test_pred = pd.DataFrame({idx: test[idx], ycol: np.zeros(len(test))},columns=[idx,ycol])
kfolder = KFold(n_splits=nfold, shuffle=True, random_state=seed)
for fold_id, (trn_idx, val_idx) in enumerate(kfolder.split(train)):
print(f'\nFold_{fold_id} Training ================================\n')
lgb_trn = lgb.Dataset(
data=train.iloc[trn_idx][feature_names],
label=train.iloc[trn_idx][ycol],
feature_name=feature_names)
lgb_val = lgb.Dataset(
data=train.iloc[val_idx][feature_names],
label=train.iloc[val_idx][ycol],
feature_name=feature_names)
lgb_reg = lgb.train(params=params, train_set=lgb_trn, **fit_params,
valid_sets=[lgb_trn, lgb_val])
val_pred = lgb_reg.predict(
train.iloc[val_idx][feature_names],
num_iteration=lgb_reg.best_iteration)
train_pred.loc[val_idx, 'pred'] = val_pred
test_pred[ycol] += lgb_reg.predict(test[feature_names]) / nfold
score = compute_loss(train_pred['true'], train_pred['pred'])
print('\nCV LOSS:', score)
return test_pred
# ====== lgb ======
params_lgb = {'num_leaves': ,
'max_depth':,
'learning_rate': 0.02,
'objective': 'regression',
'boosting': 'gbdt',
'verbosity': -1}
fit_params_lgb = {'num_boost_round': ,
'verbose_eval':,
'early_stopping_rounds': }
6.其他
a.这套baseline线上分数可能并不是很高(其实稍微改动就能上0.9),主要还是分享分析的思路和过程。另外构建一个可扩展的基础框架在比赛中是非常重要的,这也本次分享的核心之一。
b.开源代码参考Github
深度学习与Python,专注于深度学习、机器学习前沿知识与资讯