家用电器用户行为分析与事件识别.docx
《家用电器用户行为分析与事件识别.docx》由会员分享,可在线阅读,更多相关《家用电器用户行为分析与事件识别.docx(14页珍藏版)》请在冰豆网上搜索。
家用电器用户行为分析与事件识别
挖掘目标
1根据热水器采集到的数据,划分一次完整的用水事件。
2在划分好的一次完整的用水事件中,识别出洗浴事件。
分析方法、过程
1对热水用户的历史用水数据进行选择性抽取,构建专家样本。
2对步骤1形成的数据集进行数据探索与预处理。
包括探索用水时间时间间隔的分布,规约冗余属性、识别用水数据的缺失值,并对缺失值进行处理,根据建模的需要进行属性构造等。
3在步骤2的建模样数据基础上,建立洗浴事件识别模型,对洗浴事件识别模型进行分析评价。
4对步骤3形成的模型结果应用并对洗浴事件划分进行优化。
5调用洗浴时间识别模型,对实时监控的热水器流水数据进行洗浴时间自动识别。
数据抽取
1数据量比较大,对原始数据采用无放回随机抽样200家用户2014.1.1——2014.12.31的用水记录建模
212个属性:
热水器编码、发生时间、开关状态、加热中、保温中、有无水流、实际温度、热水量、水流量、节能模式、加热剩余时间、当前设置温度
数据探索分析
用水停顿时间间隔为两条水流量不为0的流水记录之间的时间间隔,为了探究用户真实的用水停顿时间间隔分布情况,统计用水停顿的时间间隔并做频率分布直方图。
可以知道,正常的两次用水间隔在3~7分钟。
通过频率分布直方图分析用户用水停顿时间间隔的规律性
数据预处理
属性规约
9个属性:
发生时间、开关状态、加热中、保温中、实际温度、热水量、水流量、加热剩余时间、当前设置温度
对用户的洗浴行为的一般性分析,所以“热水器编号”属性多余,可以去除;而且,“有无水流”属性可以通过“水流量”反映,可以去除,减少特征复杂;“节能模式”都为“关”,没有意义。
当“开关机状态”为“关”且“水流量”为0,说明热水器不在工作,记录可以规约掉
数据变换
由于目标是对洗浴事件进行识别,这就需要识别出哪些状态是完整的用水事件,继而识别出其中的洗浴事件。
由于一次完整的用水事件是根据水流量和停顿时间间隔的阈值去划分的,所以本案例还建立了阈值寻优模型。
同时,为了提高在大量用水事件中寻找洗浴事件的效率,本案例建立了筛选规则剔除明显不是洗浴事件的记录,得到建模数据样本。
一次完整用水事件的划分模型
哪些连续的数据是一次完整的用水事件
水流量不为0表示正在使用热水,水流量为0则表示用热水停顿或者结束。
如果水流量为0的状态记录之间的时间间隔超过一个阈值T(也就是前后是两个不同事件),那么从该段水流量为0的记录向前找到最后一条水流量不为0的记录作为上一次用水事件的结束,向后找到水流量不为0的记录作为下一个用水事件的开始。
操作流程
Step1:
读取数据记录,识别到第一条水流量不为0的数据记录,记为R1按照顺序,下一条水流量不为0的记录记为R2。
Step2:
计算Ri与Ri+1之间的差值记为gapi,若gapi大于阈值T则Ri和Ri+1之间的数据记录不能认为是同一个用水事件。
同时将Ri+1记录作为新的读取数据记录的开始,返回Step1;若gapi小于阈值T,则将Ri+1与Ri之间的数据记录划分到一个用水事件,并记录下一个水流量不为0的数据记录为Ri+2。
Step3:
循环Step2,直到数据记录读取完毕,结束事件划分。
data<-read.csv("./data/water_heater.csv",header=TRUE)
data$"发生时间"<-strptime(data$"发生时间","%Y%m%d%H%M%S")
data$eventnum<-as.numeric(row.names(data))
whdata<-data[data$"水流量"!
=0,]
t1<-whdata$"发生时间"
m<-length(t1)#得到读取的表格的数据维数
Tm<-240#阀值设置为4分钟(240秒)
t2<-c(t1[1],t1[1:
(m-1)])
t3<-c(t1[2:
m],t1[m])
td1<-difftime(t1,t2,units="secs")#生成向前时差列
td2<-difftime(t1,t3,units="secs")#生成向后时差列
headornot<-rep(0,m)
endornot<-rep(0,m)
if(whdata$"水流量"[1]!
=0)headornot[1]=1
if(whdata$"水流量"[m]!
=0)endornot[m]=1
for(iin2:
length(headornot)){#寻找连续用水起点
if(abs(td1[i])>=Tm){
headornot[i]<-1
}else{
headornot[i]<-0
}
}
for(iin1:
(length(endornot)-1)){#寻找连续用水终点
if(abs(td2[i])>=Tm){
endornot[i]<-1
}else{
endornot[i]<-0
}
}
dividsequence<-data.frame(matrix(NA,sum(headornot==1),3))
colnames(dividsequence)<-c("事件序号","事件起始编号","事件终止编号")
dividsequence[,1]<-c(1:
sum(headornot==1))
dividsequence[,2]<-whdata$eventnum[which(headornot==1)]
dividsequence[,3]<-whdata$eventnum[which(endornot==1)]
write.csv(file="./tmp/dividsequence.csv",dividsequence,row.names=F)
用水事件阈值寻优模型
原因
不同地区,不同季节,使用热水器停顿时长是不同的,固定一个阈值做上述处理是不合适的,所以考虑到在不同的时间段内要更新阈值,故建立阈值寻优模型来寻找最优阈值。
实现方法
指定连续的阈值尝试划分,得到的事件个数必定不太相同,绘制折线图不难发现曲线平稳处符合大多数人的要求,利用斜率来刻画寻找这个最优点。
data<-read.csv("./data/water_heater.csv",header=TRUE)
Tm<-seq(2,8,by=0.25)*60#阀值设置为2到8分钟,每0.25分钟取次值,存在Tm向量中
divide_event_for_optimization<-function(x,data){
#x:
划分事件的阈值;data:
输入数据
data$"发生时间"<-strptime(data$"发生时间","%Y%m%d%H%M%S")
data$eventnum<-as.numeric(row.names(data))
whdata<-data[data$"水流量"!
=0,]
t1<-whdata$"发生时间"
m<-length(t1)#得到读取的表格的数据维数
t2<-c(t1[1],t1[1:
(m-1)])
t3<-c(t1[2:
m],t1[m])
td1<-difftime(t1,t2,units="secs")#生成向前时差列
td2<-difftime(t1,t3,units="secs")#生成向后时差列
headornot<-rep(0,m)
endornot<-rep(0,m)
if(whdata$"水流量"[1]!
=0)headornot[1]=1
if(whdata$"水流量"[m]!
=0)endornot[m]=1
for(iin2:
length(headornot)){#寻找连续用水起点
if(abs(td1[i])>=x){
headornot[i]<-1
}else{
headornot[i]<-0
}
}
return(sum(headornot))
}
div<-data.frame(matrix(0,length(Tm),2))
div[,1]<-Tm
for(iin1:
length(Tm)){#分别求各阀值对应的事件数,并存于div中
div[i,2]<-divide_event_for_optimization(Tm[i],data)
}
#求最优阀值
k<-rep(0,length(Tm))
for(iin1:
(length(Tm)-4)){
k[i]<-(abs((div[i+1,2]-div[i,2])/0.25)+
abs((div[i+2,2]-div[i,2])/0.5)+
abs((div[i+3,2]-div[i,2])/0.75)+
abs((div[i+4,2]-div[i,2])/1))/4
}#k[i]记录每个阈值对应的平均斜率
kl<-length(k)
if(any(k[-c((kl-3):
kl)]<=1)==TRUE){
Tm_best<-k[-c((kl-3):
kl)][k[-c((kl-3):
kl)]<=1][1]
}else{
Tm_best<-Tm[which(k==min(k[-c((kl-3):
kl)]))][1]/60
if(Tm_best>=5)Tm_best=4
}
Tm_best
∙属性构造
∙本案例研究的是用水行为,可以构造四类指标:
时长指标、频率指标、用水的量化指标以及用水的波动指标。
都是为了模型服务建立特征项。
∙筛选“洗浴事件”
∙剔除短暂用水事件,剩余的为候选洗浴事件。
从已经划分好的用水事件中识别出洗浴事件
满足任一条件就不是用水事件:
1)一次用水事件的总用水量(纯热水)小于y升
2)用水时长小于100秒(用水时间,不包括停顿)
3)总用水时长小于120秒(事件开始到结束)
数据清洗
∙对异常值和缺失值处理,
在用水状态记录缺失的的情况下,填充一条状态记录使水流量为0,发生时间加2秒,其余属性状态不变
模型构建
由于洗浴事件和普通用水事件在特征上不同,根据用水日志,将洗浴事件作为训练样本训练神经网络,然后根据训练好的网络检验新的数据。
选取11个特征作为神经网络的输入:
洗浴时间点、总用水时长、总停顿时长、平均停顿时长、停顿次数、用水时长、用水时长/总用水时长、总用水量、平均用水量水流量波动和停顿时长波动。
训练BP神经网络给定的输出为0或1,其中1表示为洗浴事件,0表示不是洗浴事件。
使用keras库训练神经网络。
#训练BP神经网络
#install.packages("AMORE")
library(AMORE)
#读入训练数据
data<-read.csv("./data/train_neural_network_data.csv",head=TRUE)
for(iin5:
16){
data[,i]<-as.numeric(as.vector(data)[,i])
}#将数据处理为可用的numeric类型
inputdata<-data[,6:
16]#记录被选择用来作为输入的属性
outputdata<-data[,5]#记录教师信号所在列
n.neurons<-c(11,17,10,1)#11个输入,2个隐层,分别为17、10个节点,1个输出
net<-newff(n.neurons,learning.rate.global=0.05,momentum.global=0.5,
error.criterium="LMS",Stao=NA,hidden.layer="tansig",
output.layer="purelin",method="ADAPTgdwm")#创建神经网络,其中:
#学习率为0.05,采用最小均方LMS作为测量误差函数,隐层间传递函数设置为tansig,
#输出层传递函数为purelin,优先考虑ADAPTgdwm训练方法
result<-train(net,inputdata,outputdata,error.criterium="LMS",
report=TRUE,show.step=100,n.shows=5)
#保存训练好的BP神经网络
save(result,file="./tmp/result.RData")
library(AMORE)
#BP神经网络模型测试
#参数初始化
netfile<-"./tmp/result.RData"#神经网络模型存储路径
testdatafile<-"./data/test_neural_network_data.csv"#待验证数据存储路径
testoutputfile<-"./tmp/test_output_data.csv"#测试数据模型输出文件
data<-read.csv(testdatafile,header=TRUE)#读入验证数据
for(iin5:
16){
data[,i]<-as.numeric(as.vector(data)[,i])
}#将数据处理为可用的numeric类型
targetoutput<-data[,5]#记录教师信号所在列
#神经网络仿真
testdata<-data[,6:
16]#神经网络输入形式
load(netfile)#载入训练好的神经网络模型
output<-sim(result$net,testdata)#仿真得到输出结果
output[which(output<=0)]<--1
output[which(output>0)]<-1
#计算正确率
sum<-0
for(iin1:
nrow(data)){
if(output[i]==targetoutput[i]){
sum<-sum+1
}
}
cat("正确率",sum/nrow(data))
#导出数据
temp<-data.frame(matrix(NA,nrow(data),6))
temp[,1:
5]<-data[1:
5]
temp[,6]<-output
colnames(temp)<-c("热水事件","起始数据编号","终止数据编号","开始时间",
"根据日志判断是否为洗浴(1表示是,-1表示否)",
"神经网络判断是否为洗浴")
write.csv(temp,file=testoutputfile,quote=F,row.names=F)