汽车蓄电池故障预测

关键字

蓄电池 特征工程 随机森林

项目背景

毫无疑问,蓄电池是一辆汽车不可缺少的一部分,它是一种将化学能转变成电能的装置,属于直流电源,其作用有:

  • 启动发动机时,给起动机提供强大的起动电流(10A左右)
  • 当发电机过载时,可以协助发电机向用电设备供电
  • 当发动机处于怠速时,向用电设备供电
  • 蓄电池还是一个大容量电容器,可以保护汽车的用电器
  • 当发电机端电压高于铅蓄电池的电动势时,将一部分电能转变为化学能储存起来,也就是进行充电
    该项目主要针对汽油车内的铅蓄电池故障,基于TBOX采集的原始数据建立机器学习模型以期挖掘故障特征或模式提前做出预警。
    实际场景中也很有意义,如果车子因蓄电池故障在半路抛锚估计只能叫拖车了,提前预警的话不仅一定程度上提升驾驶者的安全性,也利于车主安排维修计划,这对距离维修点较远的用户来说意义更大。

数据及问题描述

笔者当时就职于某汽车集团,所能拿到的数据是云平台积累的TBox秒级数据(TB级),总变量超过100多个,包括启停时间、发动机转速、车内外温度、车速、里程等,与蓄电池直接相关的变量只有蓄电池电压;另外还有对应车辆的蓄电池历史维修记录。业务给出的理想要求是能在蓄电池发生故障前一个月内给出预警,后来改为剩余可行驶里程为100公里时给出预警,这样更为合理。

解决方案

该项目初看起来并非典型的预测或分类问题。为了转化为我们熟悉的机器学习可解对象,首先需对数据进行标注,然后进行聚合操作,再进行特征工程,最后再选择合适的算法进行模型训练。

数据标注

上述原始数据是不带标签的,需要根据维修记录人为打标。具体问题需具体分析,这里经过和业务、设计、维保相关人员的交流,发现蓄电池故障绝大部分的情况具有渐进性,是非突发式的(除非是不可控的物理损坏)。这就为模式识别方式解决该问题提供了可能。也可据此推论,与正常数据相比在时间上接近蓄电池发生故障的数据是带有某种故障模式或表征的。
因此,将维修时间点往前15天且发动机转速非零的数据标记为1(故障负样本),将未发生蓄电池故障的同区域同时间区间的数据标记为0(正常样本)。

聚合与特征工程

该部分主要对秒级数据进行按天聚合(也可按更小的时间粒度),同时构造特征字段,包括各字段的统计量(均值、方差、峰度、偏度等)、驾驶行为归因表征、现象表征。其中驾驶行为归因表征是指可能导致蓄电池发生故障的驾驶行为变量,比如转速低于2000转的时长占比(转速2000转以下蓄电池不充电);现象表征是指即将发生蓄电池故障的车辆某些变量的异常情况,比如蓄电池电压低于标准电压时长等。
最终构造了42个变量。每天一条数据(未行驶的时间除外)。

算法建模

基于上述的特征工程,这里选择了随机森林作为初段建模算法。

关键过程

数据抽取

正常情况下应该是直接从数据库读取数据,但是出于“某种原因”,当时只能拿到离线数据,从csv文件进行处理,平均每个csv大小约5g,为按时间区间存储的若干辆汽车的秒级TBox数据,因此需要对这些数据重新按照车辆vin号进行抽取再计算特征进行聚合。由于数据量较大,为便于后期调试特征聚合及算法,这里对抽取后的中间数据进行缓存并采用多进程处理,核心代码如下:

  • 缓存装饰器
import hashlib
import pickle
import os
from tqdm import tqdm
import pandas as pd
from mix_class import Construction_data
import numpy as np
from multiprocessing import Pool

#缓存装饰器
cache_root_dir = 'cache_vin_copy'
if not os.path.exists(cache_root_dir):
   os.makedirs(cache_root_dir)
def md5(s):
   m = hashlib.md5()
   m.update(s.encode("utf8"))
   return m.hexdigest()
def cache_key(f, *args, **kwargs):
   s = '%s-%s-%s' % (f.__name__, str(args), str(kwargs))
   return os.path.join(cache_root_dir, '%s.dump' % md5(s))
def cache(f):
   def wrap(*args, **kwargs):
       fn = cache_key(f, *args, **kwargs)
       if os.path.exists(fn):
           print('loading cache')
           with open(fn, 'rb') as fr:
               return pickle.load(fr)

       obj = f(*args, **kwargs)
       with open(fn, 'wb') as fw:
           pickle.dump(obj, fw,protocol=4)
       return obj
   return wrap 
  • 多进程+缓存中间结果
def vin_combin(k,pathss):
    s1 = time.time()
    with open(pathss, 'rb') as fr:
        temp_vin = pickle.load(fr)
    temp_vin = temp_vin.drop_duplicates()
    temp_vin.loc[:,'starttime'] = pd.to_datetime(temp_vin.loc[:,'starttime'])
    temp_vin.index = temp_vin.starttime
    temp_vin = temp_vin.sort_index()
    mix = Construction_data(temp_vin,time='D')
    mixx = mix.concat_data();mixx['vin'] = k
    mix['label']=0
    efors = time.time()
    print("for one vin cost time :", int(efors - s1)/3600)
    return [mixx]


@cache    
def mix_pool(path,times):
    print(times);path = dict(path)
    nor_list = [] 
    pool = Pool(15);pool_list = []
    for k,v in tqdm(path.items()):
        results = pool.apply_async(vin_combin,(k,v))
        pool_list.append(results)
    print(len(pool_list))
    pool.close()#关闭进程池,不再接受新的进程
    pool.join()#主进程阻塞等待子进程的退出
    for result in pool_list:
        try:
            nor_df = result.get()
            nor_list.append(nor_df[0])
        except:
            pass
    return nor_list

特征工程

根据上述特征构造思路,基于pandas强大的数据处理能力实现了一个数据聚合与特征生成的类,输入df输出聚合后的特征。核心代码如下:

class Construction_data():
    '''
    the class of converge of data, default time is day!
    two args need give : df and time
    for df need have common vin at serial time.
    time can give : 'M'/'D'/'H'
    return 42 columns data in every VIN
    
    '''
    
    def __init__(self,df,time='D'):
        self.n_power_time = 'n_power_time'
        self.run_time_2k = 'run_time_2k'
        self.num_non_p = 'num_non_p'
        self.battery_start = 'battery_start'
        self.battery_avg = 'battery_avg'
        self.battery_var = 'battery_var'
        self.battery_max = 'battery_max'
        self.battery_mix4 = 'battery_mix4'
        self.battery_mix1 = 'battery_mix1'
        self.battery_min = 'battery_min'
        self.kurt_v_battery = 'kurt_v_battery'
        self.skew_v_battery = 'skew_v_battery'
        self.avg_temperature_in = 'avg_temperature_in'
        self.avg_temperature_out = 'avg_temperature_out'
        self.starting_num_day = 'starting_num_day'
        self.minutes15_st = '15_minutes_st'
        self.remote_boot_times = 'remote_boot_times'
        self.x_acc = 'x_acc'
        self.y_acc = 'y_acc'
        self.z_acc = 'z_acc'
#        self.accepos_var = 'accepos_var'
        self.brakepos_var = 'brakepos_var'
        self.dr_avg_v = 'dr_avg_v'
        self.dr_avg_mile = 'dr_avg_mile'
#        self.day_fuel = 'day_fuel'
        self.dr_mile50 = 'dr_mile50'
        self.dr_v0_rate = 'dr_v0_rate'
        self.avg_run_mile = 'avg_run_mile'
        self.avg_run_times = 'avg_run_times'
        self.ac_on_count = 'ac_on_count'
        self.ac_auto_on_count = 'ac_auto_on_count'
        self.fanspeed_avg = 'fanspeed_avg'
        self.fanspeed_var = 'fanspeed_var'
        self.d_temp_avg = 'd_temp_avg'
        self.c_temp_avg = 'c_temp_avg'
        self.side_light_count = 'side_light_count'
        self.dip_light_count = 'dip_light_count'
        self.main_light_count = 'main_light_count'
        self.wiperswitch_avg = 'wiperswitch_avg'
        self.oli_box_avg = 'oli_box_avg'
        self.cool_avg = 'cool_avg'
        self.batt_1 = 'batt_1'
        self.batt_0 = 'batt_0'
        self.mils = 'mils'

        
        self.df = df
        self.time = time
        
        self.df.starttime = pd.to_datetime(self.df.starttime)
        self.df.index = self.df.starttime
        self.df = self.df.sort_index()
        
        self.day_index = self.df.to_period(self.time)
        self.day_group = self.day_index.groupby(self.day_index.index)
        
        
    def n_p_time(self,g_df):
        vehsyspwrmod_list = list(g_df.loc[:,'vehsyspwrmod'])
        values_counts = Counter(vehsyspwrmod_list)
        return (values_counts[0]+values_counts[1])/len(vehsyspwrmod_list)
    
    def run_t_2k(self,g_df):
        vehrpm_2k = len(list(g_df[g_df.vehrpm < 2000].loc[:,'vehrpm']))
        return vehrpm_2k/len(list(g_df.loc[:,'vehrpm']))
        
    def num_n_p(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        start_t = g_df[g_df.temp > 10].starttime.tolist()
        i=0
        if len(start_t) == 0:
            return 0
        for t in start_t:
            diff = float(g_df[g_df.starttime==t].iloc[-1].vehbatt)- float(g_df[g_df.starttime<t].iloc[-1].vehbatt)
            i+=diff
            pass
        return i/len(start_t)
    
    def batt_start(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        start_t = g_df[g_df.temp > 10].starttime.tolist()
        i=0
        if len(start_t) == 0:
            return 0
        for t in start_t:
            diff = float(g_df[g_df.starttime==t].iloc[-1].vehbatt)
            i+=diff
            pass
        return i/len(start_t)
    
    def batt_avg(self,g_df):
        return g_df.vehbatt.mean()
        
    
    def batt_var(self,g_df):
        return g_df.vehbatt.std()
    
    def batt_max(self,g_df):
        return g_df.vehbatt.max()
    
    def batt_mix4(self,g_df):
        return g_df.vehbatt.quantile(0.4)   
    
    def batt_mix1(self,g_df):
        return g_df.vehbatt.quantile(0.1) 
    
    def batt_min(self,g_df):
        return g_df.vehbatt.min() 
    
    def kurt_v_batterys(self,g_df):
        return g_df.vehbatt.kurt()
    
    def skew_v_batterys(self,g_df):
        return g_df.vehbatt.skew()
    
    def avg_temp_in(self,g_df):
        return g_df.vehinsidetemp.mean()
    
    def avg_temp_out(self,g_df):
        return g_df.vehoutsidetemp.mean()
        
    def start_num_day(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        return len(g_df[g_df.temp > 10].starttime.tolist())
    
    def min15_st(self,g_df):
        ttx = np.array(g_df.starttime)
        c = list(np.diff(ttx)/np.timedelta64(1, 's'))
        c.insert(0,1);g_df.loc[:,'temp'] = c
        start_t = g_df[g_df.temp > 10].starttime.tolist()
        i=0
        ax = pd.DataFrame(start_t,columns=['t'])
        tc = [x.total_seconds()/60 for x in ax.diff().dropna().t]
        for t in tc:
            if t < 10:
                i+=1
        return i
        
    def remote_times(self,g_df):
        return g_df.vehbatt.median()
    
    def x_ac(self,g_df):
        return g_df.tboxaccelx.std()
    
    def y_ac(self,g_df):
        return g_df.tboxaccely.std()
    
    def z_ac(self,g_df):
        return g_df.tboxaccelz.std()
        
#    def acc_var(self,g_df):
#        pass########################################
#    
    def brak_var(self,g_df):
        return g_df.vehbrakepos.std()
        
    def d_avg_v(self,g_df):
        g_1 = g_df[g_df.vehspeed>0]
        return g_1.vehspeed.mean()
    
    def d_avg_mile(self,g_df):
        return g_df.vehodo.iloc[-1]-g_df.vehodo.iloc[0]
    
#    def days_fuel(self,g_df):
#        pass########################################
    
    def dr_miles50(self,g_df):
        g_1 = g_df[g_df.vehspeed>0]
        return g_1[g_1.vehspeed<50].shape[0]/3600
    
    def dr_v0_rates(self,g_df):
        g_1 = g_df[g_df.vehspeed>0]
        if g_1.shape[0]==0:
            return 0
        return g_1[g_1.vehspeed<50].shape[0]/g_1.shape[0]
    
#    def avg_run_mile(self,g_df):
#        pass########################################
    
    def avg_run_time(self,g_df):
        return g_df[g_df.vehsyspwrmod > 0].shape[0]/3600
        
    def ac_on_counts(self,g_df):
        return g_df[g_df.vehac > 0].shape[0]/g_df.shape[0]
    
    def ac_auto_on_counts(self,g_df):
        return g_df[g_df.vehacauto > 0].shape[0]/g_df.shape[0]
    
    def fanspeed_avgs(self,g_df):
        return g_df.vehacfanspeed.mean()
    
    def fanspeed_vars(self,g_df):
        return g_df.vehacfanspeed.std()
        
    def d_temp_avgs(self,g_df):
        g_p = g_df[g_df.vehacdrvtargettemp>0]
        return g_p.vehacdrvtargettemp.mean()
    
    def c_temp_avgs(self,g_df):
        g_p = g_df[g_df.vehacpasstargettemp>0]
        return g_p.vehacpasstargettemp.mean()
    
    def side_light_counts(self,g_df):
        gs = g_df[g_df.vehsidelight>0]
        return gs.shape[0]/g_df.shape[0]
    
    def dip_light_counts(self,g_df):
        return g_df[g_df.vehdiplight > 0].shape[0]/g_df.shape[0]
    
    def main_light_counts(self,g_df):
        return g_df[g_df.vehmainlight > 0].shape[0]/g_df.shape[0]
    
    def wiperswitch_avgs(self,g_df):
        gs = g_df[g_df.vehwiperswitchfront>0]
        return gs.shape[0]/g_df.shape[0]
    
    def oli_box_avgs(self,g_df):
        return g_df.vehfuellev.mean()
        
    
    def cool_avgs(self,g_df):
        return g_df.vehcoolanttemp.mean()
    
    def milss(self,g_df):
        return g_df.vehodo[-1]
    
    def batt_1s(self,g_df):
        return g_df.vehbatt[-1]
    
    def batt_0s(self,g_df):
        return g_df.vehbatt[0]

    def concat_data(self):
        n_power_time = self.day_group.apply(self.n_p_time).to_frame(name=self.n_power_time)
        run_time_2k =  self.day_group.apply(self.run_t_2k).to_frame(name=self.run_time_2k)
        num_non_p =  self.day_group.apply(self.num_n_p).to_frame(name=self.num_non_p)
        battery_start =  self.day_group.apply(self.batt_start).to_frame(name=self.battery_start)
        battery_avg =  self.day_group.apply(self.batt_avg).to_frame(name=self.battery_avg)
        battery_var =  self.day_group.apply(self.batt_var).to_frame(name=self.battery_var)
        battery_max =  self.day_group.apply(self.batt_max).to_frame(name=self.battery_max)
        battery_mix4 =  self.day_group.apply(self.batt_mix4).to_frame(name=self.battery_mix4)
        battery_mix1 =  self.day_group.apply(self.batt_mix1).to_frame(name=self.battery_mix1)
        battery_min =  self.day_group.apply(self.batt_min).to_frame(name=self.battery_min)
        kurt_v_battery =  self.day_group.apply(self.kurt_v_batterys).to_frame(name=self.kurt_v_battery)
        skew_v_battery =  self.day_group.apply(self.skew_v_batterys).to_frame(name=self.skew_v_battery)
        avg_temperature_in =  self.day_group.apply(self.avg_temp_in).to_frame(name=self.avg_temperature_in)
        avg_temperature_out =  self.day_group.apply(self.avg_temp_out).to_frame(name=self.avg_temperature_out)
        starting_num_day =  self.day_group.apply(self.start_num_day).to_frame(name=self.starting_num_day)
        minutes15_st =  self.day_group.apply(self.min15_st).to_frame(name=self.minutes15_st)
        remote_boot_times =  self.day_group.apply(self.remote_times).to_frame(name=self.remote_boot_times)
        x_acc =  self.day_group.apply(self.x_ac).to_frame(name=self.x_acc)
        y_acc =  self.day_group.apply(self.y_ac).to_frame(name=self.y_acc)
        z_acc =  self.day_group.apply(self.z_ac).to_frame(name=self.z_acc)
#        accepos_var =  self.day_group.apply(self.acc_var).to_frame(name=self.accepos_var)
        brakepos_var =  self.day_group.apply(self.brak_var).to_frame(name=self.brakepos_var)
        dr_avg_v =  self.day_group.apply(self.d_avg_v).to_frame(name=self.dr_avg_v)
        dr_avg_mile =  self.day_group.apply(self.d_avg_mile).to_frame(name=self.dr_avg_mile)
#        day_fuel =  self.day_group.apply(self.days_fuel).to_frame(name=self.day_fuel)
        dr_mile50 =  self.day_group.apply(self.dr_miles50).to_frame(name=self.dr_mile50)
        dr_v0_rate =  self.day_group.apply(self.dr_v0_rates).to_frame(name=self.dr_v0_rate)
#        avg_run_mile =  self.day_group.apply(self.avg_run_miles).to_frame(name=self.avg_run_mile)
        avg_run_times =  self.day_group.apply(self.avg_run_time).to_frame(name=self.avg_run_times)
        ac_on_count =  self.day_group.apply(self.ac_on_counts).to_frame(name=self.ac_on_count)
        ac_auto_on_count =  self.day_group.apply(self.ac_auto_on_counts).to_frame(name=self.ac_auto_on_count)
        fanspeed_avg =  self.day_group.apply(self.fanspeed_avgs).to_frame(name=self.fanspeed_avg)
        fanspeed_var =  self.day_group.apply(self.fanspeed_vars).to_frame(name=self.fanspeed_var)
        d_temp_avg =  self.day_group.apply(self.d_temp_avgs).to_frame(name=self.d_temp_avg)
        c_temp_avg =  self.day_group.apply(self.c_temp_avgs).to_frame(name=self.c_temp_avg)
        side_light_count =  self.day_group.apply(self.side_light_counts).to_frame(name=self.side_light_count)
        dip_light_count =  self.day_group.apply(self.dip_light_counts).to_frame(name=self.dip_light_count)
        main_light_count =  self.day_group.apply(self.main_light_counts).to_frame(name=self.main_light_count)
        wiperswitch_avg =  self.day_group.apply(self.wiperswitch_avgs).to_frame(name=self.wiperswitch_avg)
        oli_box_avg =  self.day_group.apply(self.oli_box_avgs).to_frame(name=self.oli_box_avg)
        cool_avg =  self.day_group.apply(self.cool_avgs).to_frame(name=self.cool_avg)
        mils =  self.day_group.apply(self.milss).to_frame(name=self.mils)
        batt_1 = self.day_group.apply(self.batt_1s).to_frame(name=self.batt_1)
        batt_0 = self.day_group.apply(self.batt_0s).to_frame(name=self.batt_0)
        
        
        vin_data = pd.concat([n_power_time,run_time_2k,num_non_p,battery_start,battery_avg,
                                   battery_var,battery_max,battery_mix4,battery_mix1,battery_min,
                                   kurt_v_battery,skew_v_battery,avg_temperature_in,avg_temperature_out,
                                   starting_num_day,minutes15_st,remote_boot_times,x_acc,y_acc,z_acc,
                                   brakepos_var,dr_avg_v,dr_avg_mile,dr_mile50,dr_v0_rate,
                                   avg_run_times,ac_on_count,ac_auto_on_count,fanspeed_avg,fanspeed_var,
                                   d_temp_avg,c_temp_avg,side_light_count,dip_light_count,main_light_count,wiperswitch_avg,
                                   oli_box_avg,cool_avg,mils,batt_1,batt_0],axis=1)
        vin_data = vin_data.fillna(method='pad');vin_data = vin_data.fillna(method='bfill');vin_data = vin_data.sort_index()
        return vin_data

算法建模

这里该出初段采用随机森林的建模代码,这个结果F1值达到了0.85,代码如下:

import copy
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDAs
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
from collections import Counter  
from sklearn.feature_selection import SelectFromModel
from sklearn import preprocessing
import numpy as np
from sklearn.utils import shuffle  
from sklearn.preprocessing import Imputer
from sklearn.externals import joblib
import random
from sklearn.metrics import roc_curve, auc

use_cols = ['15_minutes_st', 'ac_auto_on_count', 'ac_on_count', 'avg_run_times',
       'avg_temperature_in', 'avg_temperature_out', 'batt_0', 'batt_1',
       'battery_avg', 'battery_max', 'battery_min', 'battery_mix1',
       'battery_mix4', 'battery_start', 'battery_var', 'brakepos_var',
       'c_temp_avg', 'cool_avg', 'd_temp_avg', 'dip_light_count',
       'dr_avg_mile', 'dr_avg_v', 'dr_mile50', 'dr_v0_rate', 'fanspeed_avg',
       'fanspeed_var', 'kurt_v_battery', 'main_light_count', 'mils',
       'n_power_time', 'num_non_p', 'oli_box_avg',
       'remote_boot_times', 'run_time_2k', 'side_light_count',
       'skew_v_battery', 'starting_num_day', 'wiperswitch_avg', 'x_acc',
       'y_acc', 'z_acc','label']

use_colsl = ['15_minutes_st', 'ac_auto_on_count', 'ac_on_count', 'avg_run_times',
       'avg_temperature_in', 'avg_temperature_out', 'batt_0', 'batt_1',
       'battery_avg', 'battery_max', 'battery_min', 'battery_mix1',
       'battery_mix4', 'battery_start', 'battery_var', 'brakepos_var',
       'c_temp_avg', 'cool_avg', 'd_temp_avg', 'dip_light_count',
       'dr_avg_mile', 'dr_avg_v', 'dr_mile50', 'dr_v0_rate', 'fanspeed_avg',
       'fanspeed_var', 'kurt_v_battery', 'main_light_count', 'mils',
       'n_power_time', 'num_non_p', 'oli_box_avg',
       'remote_boot_times', 'run_time_2k', 'side_light_count',
       'skew_v_battery', 'starting_num_day', 'wiperswitch_avg', 'x_acc',
       'y_acc', 'z_acc']


def confusion_matrix_plot_matplotlib(y_truth, y_predict,cmap=plt.cm.Blues):
    cm = confusion_matrix(y_truth, y_predict)
    plt.matshow(cm, cmap=cmap)  # 混淆矩阵图
    plt.colorbar()  # 颜色标签
    for x in range(len(cm)): 
        for y in range(len(cm)):
            plt.annotate(cm[x, y], xy=(x, y), horizontalalignment='center', verticalalignment='center')
    plt.ylabel('True label') 
    plt.xlabel('Predicted label') 
    plt.show()  # 显示作图结果


def classification_report(y_true, y_pred):  
    from sklearn.metrics import classification_report  
    print ("classification_report(left: labels):")  
    print (classification_report(y_true, y_pred))  


def get_xy(df):
    x = df[use_colsl]
    y = df['label']
    return x,y

def merged(wdata):
    return pd.concat(wdata)

def clean_list(ll):
    ls=[]
    for item in ll:
        if item.shape[0]>0:
            ls.append(item)
            pass
    return ls


    
def count_01(df):
    pre_list = list(df.loc[:,'pre_label'])
    values_counts = Counter(pre_list)
    if df.loc[:,'label'].iloc[0] == 0:
        return values_counts[0]/len(pre_list),0
    elif df.loc[:,'label'].iloc[0] == 1:
        return values_counts[1]/len(pre_list),1    

def split_data(err1,nor1,norn,num=0.75):
#    err1 = [x[use_cols] for x in err1];nor1 = [x[use_cols] for x in nor1];norn = [x[use_cols] for x in norn]
    random.shuffle(err1);random.shuffle(nor1);random.shuffle(norn)
    train_list = err1[:round(len(err1)*num)];test_list=err1[round(len(err1)*num):]
    train_list.extend(nor1[:round(len(nor1)*num)])
    test_list.extend(nor1[round(len(nor1)*num):])
    train_list.extend(norn[:round(len(norn)*num)])
    test_list.extend(norn[round(len(norn)*num):])
    return train_list,test_list    


def data_scaler(X_train, X_test):
    '''
    根据scaler对训练集和测试集的特征变量实现标准化(0均值,方差为1)
    :return: 
    '''
    scaler = sklearn.preprocessing.StandardScaler().fit(X_train)
    X_train_std = scaler.transform(X_train)
    X_test_std = scaler.transform(X_test)
    return X_train_std,X_test_std,scaler

def data_split(e_list,err_e_list,err_n_list,nor_list):
    all_list = [];emptylist=[]
    for i in range(1717):
        if err_e_list[i].shape[0] ==0 or err_n_list[i].shape[0]==0:
            emptylist.append(i)
        else:
            all_list.append([e_list[i],err_e_list[i],err_n_list[i]])
    print('ok,num == %d'%(len(all_list)))
    train_l,test_l = train_test_split(all_list,train_size=0.8,test_size=0.2)
    train_nor,test_nor = train_test_split(nor_list,train_size=0.8,test_size=0.2)
    train_list = [];test_ll = []
    for item in train_l:
        train_list.append(item[1])
        train_list.append(item[2])
    for item2 in test_l:
        test_ll.append(item2[1])
        test_ll.append(item2[2])
    test_ll.extend(test_nor)
    train_list.extend(train_nor)
    nor_no_label = copy.deepcopy(test_nor)
    nor_no = [x.drop(['label'],axis=1) for x in nor_no_label]
    test_list = [x[0] for x in test_l]
    test_list.extend(nor_no)
    return train_list,test_list,test_ll,emptylist
    
        


    
    
if __name__ == '__main__':
#    trainx,testlist,testx,emptylist = data_split(e_list,err_e_list,err_n_list,temp_vin)
#    df_train = merged(trainx)
#    df_test = merged(testx)
#    df_train = shuffle(df_train)
#    df_test = shuffle(df_test)
#
#    xr,yr = get_xy(df_train)
#    test_xr,test_yr = get_xy(df_test)
    
    
    
    
#    xr = Imputer().fit_transform(xr)
#    test_xr = Imputer().fit_transform(test_xr)
#    pca = PCA(n_components=15,whiten=True)

#    pca.fit(xr)

#    xp = pca.transform(xr)

#    test_xp = pca.transform(test_xr)
#    joblib.dump(pca, 'pca.pkl') 
#    feature_train, feature_test, target_train, target_test = train_test_split(xr,yr,train_size=0.8,test_size=0.2)
    #随机森林分类树

#    rfc = RandomForestClassifier(n_jobs=-1,oob_score=True,criterion='gini',max_features=None,min_samples_split = 10,verbose = 1,max_depth =8,
#                                 min_samples_leaf=1,n_estimators =200,
#                                 class_weight='balanced')
#    rfc = RandomForestClassifier(
#            n_estimators=122, n_jobs=-1,oob_score=1, random_state=None,
#            verbose=1)
    rfc = RandomForestClassifier(n_jobs=-1,oob_score=True,criterion='gini',max_features='auto',
                                 verbose = 1,n_estimators =100,class_weight={0: 1, 1: 7})

    Y = rfc.predict(feature_test)
    #评估模型准确率

    r_rate = rfc.score(feature_test , target_test)
    print('准确率:',r_rate) 
    classification_report(target_test,Y)

    confusion_matrix_plot_matplotlib(Y,target_test, cmap=plt.cm.tab10_r)
    joblib.dump(rfc, 'rc01.pkl') 
#    rcf = joblib.load('rcf.pkl')
    print('...............>> now give real test ! <<.....................')
    y_test = rfc.predict(test_xr)

    classification_report(test_yr,y_test)
    confusion_matrix_plot_matplotlib(y_test,test_yr,cmap=plt.cm.tab10_r)
    print('...............>>  real test over ! <<.....................')
##    rfc = joblib.load('.//model//7_rcf73-92.pkl')
##    pca = joblib.load('.//model//7_pca73-92.pkl')
#
#
#
imports = dict(zip(use_colsl,list(rfc.feature_importances_)))
imports = sorted(imports.items(), key = lambda x: x[1],reverse=True)

小结

  • 后期经过模型融合准确率和召回率都在93%以上。值得指出的是,预测结果是统计指定时间段内label为1的占比,超过指定值即认为会发生故障。如将预测目标改为剩余公里数,需对打标方式进行调整,即以维修时间前转速非零的里程值开始前推100公里标记为1,更好的方式是使label为递增值,最后对label做回归。
  • 其实不仅是汽车蓄电池故障,很多类似的场景如能做到提前预知,将大大提升效率降低相关风险。如对工业生产设备的故障预测,可提前计划排产最终降低维护、运营成本。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 选择题部分 1.(),只有在发生短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。...
    skystarwuwei阅读 12,732评论 0 7
  • A. 问答题 1. 简述运维工作中专业巡视的内容及周期。 答:运维工作中专业巡视的内容及周期如下: 1) 专业巡视...
    tomding阅读 3,102评论 0 2
  • 1、排气管冒黑烟 故障判定:真故障。 原因分析:表明混合气过浓,燃烧不完全。主要原因是汽车发动机超负荷,气缸压力不...
    老柳说车阅读 1,637评论 0 1
  • 很多车主有用车的时候,总是分不清楚各种故障,真真假假的分不清。今天小编就统一普及一下汽车基本故障的判断以及分析其原...
    石哦哦阅读 518评论 0 1
  • 叁品姐姐每天分享一段爱情感悟,幸福可以很简单,点击右上角关注哦。 在喜欢你这件事上,我做过无数蠢事,听过很多劝告,...
    三品姐姐阅读 524评论 0 0