8热水器用户行为分析与事件识别

来源:互联网 发布:服务业知乎 编辑:程序博客网 时间:2024/04/27 17:46

8热水器用户行为分析与事件识别

8.1背景与挖掘目标

国内某智能热水器,在状态发生改变或有水流状态时会采集数据,该厂商根据采集到的数据进行用户行为分析,热水器不仅可以用来细雨还可以洗手、洗脸、刷牙、洗菜等。本案例基于热水器采集的时间序列数据,将顺序排列的离散的用水时间节点根据水流量和停顿时间间隔划分不同大小的时间区间,每个时间区间可以理解成一次完整用水事件。

挖掘目标:第一,根据热水器采集到的数据,划分一次完整用水事件;第二,划分好的完整用水事件中识别出洗浴事件。

数据大体情况如下


8.2 分析方法与过程

第一:对热水器用户的历史用水数据进行选择性抽取,构建专家样本

第二:对步骤一形成的数据集进行数据探索分析与预处理,包括探索用水事件时间间隔的分布、规约冗余属性、识别用水数据的缺失值,并对缺失值进行处理,根据建模的需要进行属性构造,根据以上处理对用水数据建立用水事件时间间隔识别模型和划分一次完整用水事件模型,在再一次完整用水事件划分结果的基础上,剔除短暂用水事件缩小识别范围

第三:在第二得到的建模样本数据的基础上,建立洗浴事件识别模型,对洗浴事件识别模型进行模型分析评价

第四:在第三中形成的模型结果应用并对洗浴事件划分进行优化

第五:调用洗浴事件识别模型,对实时监控的热水器流水数据进行洗浴事件自动识别。

8.3 数据预处理

本案例的数据集的特点是数据量涉及上万个用户而且每个用户每天的用水数据多达数万条存在缺失值、与分析主题无关属性或未直接反应应用水事件的属性等,在数据预处理阶段,针对这些情况相应的应用了缺失值处理、数据规约和属性构造等来解决这些问题。

8.3.1数据规约

  案例采集到的数据属性非常的多,加之我们建模也需要不了这么多的数据,现在对建模数据进行数据规约

属性规约:要对热水器用户的洗浴行为的一般规律进行挖掘分析,所以热水器编号可以去除,在数据中的有无水流通过可以通过水流量反应,观察数据我们发现节能模式的数据都是关,对建模没有什么影响,现在我们可以把它去除。

数值规约:当热水器的开关状态为关时并且流水量为0时,说明热水器不处于工作状态,数据记录可以删除。

数据规约后的数据如下图:


8.3.2数据变换

案例的挖掘目标是对热水器用户的洗浴事件进行识别,这就需要从原始数据中识别出哪些状态记录是一个完整的用水事件,再识别出完整用水事件中的洗浴事件;而一次完整的用水事件是根据水流量和停顿时间间隔的阈值去划分的,SO,本案例还应建立阈值寻优模型,为了提高在一次完整用水事件中识别出洗浴事件,本案例建立了筛选规则以剔除那些肯定不是洗浴事件的数据,得到建模数据样本集。

(1) 一次完整用水事件划分模型

本案例首先需要在大量的记录中划分出哪些连续的数据是一次完整的用水事件。

在用水状态记录中,水流量不为0表面用户正在使用热水,而水流量为0时用户用热水发生提顿或者结束。如果水流量为0的状态记录之间的时间间隔超过阈值T,则从该段水流量为0的状态向前找到最后一条水流量不为0 的用水记录作为上一次用水事件结束;向后找到水流量不为0的状态记录作为下一个用水事件的开始。

代码如下:

# encoding=utf-8
#
划分一次用水事件代码
import pandasas pd
threshold=pd.Timedelta(
minutes=4)#阈值为4
inputfile=r'E:\PythonProject\python Data Analysis andMining\chapter10\demo\data\water_heater.xls'
outputfile=r'E:\PythonProject\python Data Analysis andMining\chapter10\demo\tmp\dividsequence.xls'

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#通过累计求和的方式为事件编号
data.to_excel(outputfile)

 

结果如下:


(2) 用水事件阈值寻优模型

考虑到不同地区人们的用水习惯不同,以及不同季节使用热水器时停顿的时长也可能不同,固定的停顿时长阈值对于某些特殊的情况的处理是不理想的,存在把一个事件划分为两个事件或者把两个事件合为一个事件的情况。所以考虑要在不同的时间段内更新阈值,本案例建立阈值寻优模型来更新寻找最优的阈值这样可以解决因时间变化和地域不同导致阈值存在差异的问题  

     我选取了某热水电器用户的数据进行了不同阈值的划分,得到了相应的时间个数,阈值变化与划分得到的事件个数如下图


在上图中我们发现有的地方下降趋势明显有的较为平缓,下降趋势明显的说明用户的停顿习惯比较集中,平缓的说明用户的停顿习惯趋于稳定,所以取该段时间作为阈值,这样的话不会将短时间的用水事件合并,又不会将长的用水时间拆开。

#阈值寻优
import numpyas np
n=
4#使用以后4个点的平均斜率
threshold=pd.Timedelta(minutes=5)#专家阈值
def event_num(ts):
    d=data[
u'发生时间'].diff()>ts#相邻时间做差分,比较是否大于阈值
   
return d.sum()+1#这样直接返回事件数
dt=[pd.Timedelta(minutes=i)for iin 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'斜率指标']=pd.rolling_mean(h[u'斜率'].abs(),n)#采用后n个斜率绝对值平均作为斜率指标
ts=h[u'阈值'][h[u'斜率指标'].idxmin()-n]
#idxmin返回最小值的Index,由于rolling——mean()自动计算的是前n个斜率的绝对值平均,所以结果要进行平移(-n
if ts>threshold:
    ts=pd.Timedelta(
minutes=4)
print ts

得到的结果是最优阈值为4分钟


(3) 属性构造

本案例研究的是用水行为,可构造4类指标:时长指标、频率指标、用水的量化指标以及用水波动指标。

(4) 筛选得“候选洗浴事件”

洗浴事件的识别是建立在一次用水事件识别的基础上,也就是从已经划分好的一次用水事件中识别出哪些一次用水事件是洗浴事件

8.4 模型构建

本案例使用神经网络模型,在训练神经网络的时候选取了“候选洗浴事件”的11个属性作为网络的输入。分别为,洗浴时间点、总用水时长、总停顿时长、用水时长、总用水量、平均水流量、水流量波动和停顿时长波动。在训练神经网络的时候发现含二层隐层的神经网络训练效果较好,其中2个隐层的节点数分别为17,10,训练效果较好。

训练多层神经网络的代码如下:

#建立、训练多层神经网络,并完成模型的检验
inputfile1=r'E:\PythonProject\python Data Analysis andMining\chapter10\demo\data\train_neural_network_data.xls'
inputfile2=r'E:\PythonProject\python Data Analysis andMining\chapter10\demo\data\test_neural_network_data.xls'
testoutputfile=r'E:\PythonProject\python Data Analysisand Mining\chapter10\demo\tmp\test_output_data.xls'
data_train=pd.read_excel(inputfile1)
data_test=pd.read_excel(inputfile2)
y_train=data_train.iloc[:
,4].as_matrix()
x_train=data_train.iloc[:
,5:17].as_matrix()
y_test=data_test.iloc[:
,4].as_matrix()
x_test=data_test.iloc[:
,5:17].as_matrix()
from keras.modelsimport Sequential
from keras.layers.coreimport Dense,Activation

model=Sequential()
#建立模型
model.add(Dense(input_dim=11,output_dim=17))#输入层隐藏层的连接
model.add(Activation('relu'))
model.add(Dense(
input_dim=17,output_dim=10))#隐藏层到隐藏层的连接
model.add(Activation('relu'))#激活函数
model.add(Dense(input_dim=10,output_dim=1))#隐藏层到输出层的连接
model.add(Activation('sigmoid'))
model.compile(
loss='binary_crossentropy',optimizer='adam')
model.fit(x_train
,y_train,nb_epoch=100,batch_size=20)
model.save_weights(
r'E:\PythonProject\python Data Analysisand Mining\chapter10\demo\tmp\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)

#模型可视化
from keras.utils.vis_utilsimport plot_model
plot_model(model
, to_file='model.png',show_shapes=True)


我们做的只是一个案例,训练数据比较小,不太准确,当数据量增大时,模型会越来越准确。

原创粉丝点击