《数据分析与挖掘 第十章 家用电器用户行为分析与事件识别》

家用电器用户行为分析与事件识别

数据抽取 首先对原始数据采用无放回的随机抽取 数据预处理 热水器编号对实验无实际性的意义,这个属性特征是可以删除的 有无水流可以用水流量来表示,因此这个属性是没有必要的 节能模式是一种模式,所有数据都是一样的,因此也是可以删去的属性 删去三种属性之后,留下九种属性

又,热水器“开关状态”为关的时候,“水流量”为0时,说明热水器不工作,此条数据是可以删除的

数据变化 除了筛选出这九个属性之外 在这里插入图片描述 我们还要知道每次使用水的行为,要区分几次流水的情况,是属于同一次用水行为,还是好几次用水行为,这就需要计算两次流水间隔时间,设定一个阈值T,如果间隔时间大于这个T值,就说明是两次用水事件,如果小于T,就说明是一次用水事件

下面对用水事件进行划分:

    #-*- coding: utf-8 -*-
    #用水事件划分
    import pandas as pd
    
    threshold = pd.Timedelta('4 min') #阈值为分钟
    inputfile = 'water_heater.xls' #输入数据路径,需要使用Excel格式
    outputfile = 'dividsequence.xls' #输出数据路径,需要使用Excel格式
    
    data = pd.read_excel(inputfile)
    #将时间字符串,变成时间的标准格式
    data[u'发生时间'] = pd.to_datetime(data[u'发生时间'], format = '%Y%m%d%H%M%S')

将时间从20141019063917变成了2014-10-19 06:39:17

    data = data[data[u'水流量'] > 0] #只要流量大于0的记录

从18840条记录中选出了7696条数据,这些事全部检测到在使用水的数据,相邻数据做差,既是时间间隔 data[u’发生时间’].diff() 求时间间隔

    d = data[u'发生时间'].diff() > threshold #相邻时间作差分,比较是否大于阈值

d这是是一些列的bool类型值

    #-*- coding: utf-8 -*-
    #用水事件划分
    import pandas as pd
    
    threshold = pd.Timedelta('4 min') #阈值为分钟
    inputfile = 'water_heater.xls' #输入数据路径,需要使用Excel格式
    outputfile = 'dividsequence.xls' #输出数据路径,需要使用Excel格式
    
    data = pd.read_excel(inputfile)
    #将时间字符串,变成时间的标准格式
    data[u'发生时间'] = pd.to_datetime(data[u'发生时间'], format = '%Y%m%d%H%M%S')
    data = data[data[u'水流量'] > 0] #只要流量大于0的记录
    
    d = data[u'发生时间'].diff() > threshold #相邻时间作差分,比较是否大于阈值
    data[u'事件编号'] = d.cumsum() + 1
    #cumsum()
    #d.cumsum()求出来的是从0开始的,但是为了让第一件事件记为1,所以+1
    #通过累积求和的方式为事件编号
    
    data.to_excel(outputfile)

在这里插入图片描述阈值的选取 我们事件的划分是根据两次流水之间的间隔时间阈值来看的,不同的阈值会导致划分事件的结果不同,那么该如何选取阈值呢,绘制阈值与事件个数的曲线,趋势平缓的部分,说明用户的停顿习惯趋于稳定,应该以该段时间开始作为阈值,选取曲线较为平缓的五个点,放大观看

阈值的优化 五个点出现四个斜率,算四段斜率绝对值的平均值K,作为最左端点的斜率指标 若K<1则,选这一段的坐左边的点A作为阈值 若K>=1且<5则用最小斜率指标的最左边的点作为阈值 若K>5,则直接以4作为阈值

    #阈值寻优
    import numpy as np
    import pandas as pd
    
    inputfile = 'water_heater.xls' #输入数据路径,需要使用Excel格式
    n = 4 #使用以后四个点的平均斜率
    
    threshold = pd.Timedelta(minutes = 5) #专家阈值
    data = pd.read_excel(inputfile)
    data[u'发生时间'] = pd.to_datetime(data[u'发生时间'], format = '%Y%m%d%H%M%S')
    data = data[data[u'水流量'] > 0] #只要流量大于0的记录
    
    def event_num(ts):
      d = data[u'发生时间'].diff() > ts #相邻时间作差分,比较是否大于阈值
      return d.sum() + 1 #这样直接返回事件数
    
    dt = [pd.Timedelta(minutes = i) for i in np.arange(1, 9, 0.25)]
    h = pd.DataFrame(dt, columns = [u'阈值']) #定义阈值列
    h[u'事件数'] = h[u'阈值'].apply(event_num) #计算每个阈值对应的事件数
    h[u'斜率'] = h[u'事件数'].diff()/0.25 #计算每两个相邻点对应的斜率
    h[u'斜率指标'] = h[u'斜率'].abs().rolling(n).mean() #采用后n个的斜率绝对值平均作为斜率指标
    ts = h[u'阈值'][h[u'斜率指标'].idxmin() - n]
    #注:用idxmin返回最小值的Index,由于rolling(n).mean()自动计算的是前n个斜率的绝对值平均
    #所以结果要进行平移(-n)
    
    if ts > threshold:
      ts = pd.Timedelta(minutes = 4)
    
    print(ts)

dt是1-9分钟每隔0.25分钟取的阈值点: [Timedelta(‘0 days 00:01:00’), Timedelta(‘0 days 00:01:15’), Timedelta(‘0 days 00:01:30’), Timedelta(‘0 days 00:01:45’), Timedelta(‘0 days 00:02:00’), Timedelta(‘0 days 00:02:15’), Timedelta(‘0 days 00:02:30’), Timedelta(‘0 days 00:02:45’), Timedelta(‘0 days 00:03:00’), Timedelta(‘0 days 00:03:15’), Timedelta(‘0 days 00:03:30’), Timedelta(‘0 days 00:03:45’), Timedelta(‘0 days 00:04:00’), Timedelta(‘0 days 00:04:15’), Timedelta(‘0 days 00:04:30’), Timedelta(‘0 days 00:04:45’), Timedelta(‘0 days 00:05:00’), Timedelta(‘0 days 00:05:15’), Timedelta(‘0 days 00:05:30’), Timedelta(‘0 days 00:05:45’), Timedelta(‘0 days 00:06:00’), Timedelta(‘0 days 00:06:15’), Timedelta(‘0 days 00:06:30’), Timedelta(‘0 days 00:06:45’), Timedelta(‘0 days 00:07:00’), Timedelta(‘0 days 00:07:15’), Timedelta(‘0 days 00:07:30’), Timedelta(‘0 days 00:07:45’), Timedelta(‘0 days 00:08:00’), Timedelta(‘0 days 00:08:15’), Timedelta(‘0 days 00:08:30’), Timedelta(‘0 days 00:08:45’)]

h: 在这里插入图片描述 因为每四个斜率作为五个点中最左边点的斜率指标,所以前四个点是没有斜率指标的

最后得出结果是4分钟作为阈值: 在这里插入图片描述 所以这里实际的实践过程应该是:先判断阈值,然后根据这个阈值,去对事件进行划分,然后得出哪些是用水事件

属性构造 由于我们现在要知道的是哪些事件是洗浴时间,所以我们不但要分辨出那些事用水事件,还要分离出这些事件里面的洗浴时间,这就需要再构造一些属性: 用水时长,用水量,水温

洗浴事件的特征:温度设定越高,水就越烫,兑的冷水多,热书使用就少,所以X与Y成反比的

根据热量守恒守恒,得到: Y = (50 - C)*V/(X - C)

模型构建 这里假设已经将加上的一些属性计算好,并且已经添加到表格中了,现在对表格中数据进行训练:

    from __future__ import print_function
    import pandas as pd
    
    inputfile1='train_neural_network_data.xls' #训练数据
    inputfile2='test_neural_network_data.xls' #测试数据
    testoutputfile = 'test_output_data5.xls' #测试数据模型输出文件
    data_train = pd.read_excel(inputfile1) #读入训练数据(由日志标记事件是否为洗浴)
    data_test = pd.read_excel(inputfile2) #读入测试数据(由日志标记事件是否为洗浴)

在这里插入图片描述 我们发现训练数据有28条,测试数据有21条,每条数据有16个属性,但是只有其中十一个属性是有意义的(是否为洗浴事件后面的11条),故选取十一个特征属性,将数据整理成x_train,y_train,x_test,y_test:

    y_train = data_train.iloc[:,4].values #训练样本标签列
    x_train = data_train.iloc[:,5:17].values #训练样本特征
    y_test = data_test.iloc[:,4].values #测试样本标签列
    x_test = data_test.iloc[:,5:17].values #测试样本特征

在这里插入图片描述 建立神经网络模型,这里对神经网络进行参数寻优,找到两层隐层神经网络比较好,并且两层隐层分别为17,10个节点,效果明显,好,就这么办:

建立模型

    from keras.models import Sequential
    from keras.layers.core import Dense, Dropout, Activation
    
    model = Sequential() #建立模型
    model.add(Dense(input_dim=11, output_dim=17)) #添加输入层、隐藏层的连接
    model.add(Activation('relu')) #以Relu函数为激活函数
    model.add(Dense(input_dim=17, output_dim=10)) #添加隐藏层、隐藏层的连接
    model.add(Activation('relu')) #以Relu函数为激活函数
    model.add(Dense(input_dim=10, output_dim=1)) #添加隐藏层、输出层的连接
    model.add(Activation('sigmoid')) #以sigmoid函数为激活函数
    #编译模型,损失函数为binary_crossentropy,用adam法求解
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) 

训练模型

    model.fit(x_train, y_train, nb_epoch = 100, batch_size = 1) #训练模型
    model.save_weights('net.model') #保存模型参数

预测模型:

    r = pd.DataFrame(model.predict_classes(x_test), columns = [u'预测结果'])
    pd.concat([data_test.iloc[:,:5], r], axis = 1).to_excel(testoutputfile)
    model.predict(x_test)

在这里插入图片描述 训练了100次: 在这里插入图片描述 保存了训练效果较好的一次结果模型 其实中间有的时候训练精度可能只有0.2几,这是因为训练数据太少的缘故,训练数据多一些,应该可以提升一下训练模型的精度

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值