目录
一、背景和挖掘目标
1、问题背景
2、原始数据
3、挖掘目标
二、分析方法与过程
1、初步分析
2、总体流程
第一步:数据抽取
第二步:探索分析
第三步:数据的预处理
第四步:构建专家样本
第五步: 构建用水事件行为识别模型
三、总结和思考
用户用水数据表:包括了洗浴、洗手、洗脸、洗菜、做饭等用水行为
属性名称 |
属性说明 |
热水器编码 |
热水器出厂编号 |
发生时间 |
记录热水器处于某状态的时刻 |
开关机状态 |
热水器是否开机 |
即热 |
即时加热 |
加热中 |
热水器处于对水进行加热的状态 |
保温中 |
热水器处于对水进行保温的状态 |
有无水流 |
热水水流量大于等于10L/min为有水,否则为无 |
实际温度 |
热水器中热水的实际温度 |
热水量 |
热水器热水的含量 |
水流量 |
热水器热水的水流速度 单位:L/min |
节能模式 |
热水器的一种节能工作模式 |
预约洗 |
预约一个时间使用热水 |
即时洗 |
不预约直接使用热水器 |
加热剩余时间 |
加热到设定温度还需多长时间 |
当前设置温度 |
热水器加热时热水能够到达的最大温度 |
为了探究用户真实用水停顿时间间隔的分布情况,统计用水停顿的时间间隔并作频率分布直方图。
停顿时间间隔为0~0.3分钟的频率很高,根据日常用水经验可以判断其为一次用水时间中的停顿;停顿时间间隔为6~13分钟的频率较低,分析其为两次用水事件之间的停顿间隔。两次用水事件的停顿时间间隔分布在3~7分钟与现场实验统计用水停顿的时间间隔近似。
2、数据变换
一次完整用水事件的划分:用水状态记录中,水流量不为0表明用户正在使用热水;而水流量为0时用户用热水发生停顿或者用热水结束。水流量为0的状态记录之间的时间间隔如果超过一个阈值T,则从该段水流量为0的状态记录向前找到最后一条水流量不为0的用水记录作为上一次用水事件的结束;向后找到水流量不为0的状态记录作为下一个用水事件的开始。
#-*- coding: utf-8 -*-
#用水事件划分
import pandas as pd
threshold = pd.Timedelta('4 min') #阈值为分钟
inputfile = 'data/water_heater.xls' #输入数据路径,需要使用Excel格式
outputfile = 'tmp/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 #通过累积求和的方式为事件编号
data.to_excel(outputfile)
用水事件阈值寻优:根据水流量和停顿时间间隔的阈值划分一次完整的用水事件。
# -*- coding: utf-8 -*-
# 阈值寻优
import numpy as np
import pandas as pd
inputfile = 'data/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 # 计算每两个相邻点对应的斜率
# df_test['col_name'].rolling(ma).mean()新版本 ---->pd.rolling_mean(df_test['col_name'], ma) 旧版本
# pd.rolling_mean(h[u'斜率'].abs(), n)
h[u'斜率指标'] = h[u'斜率'].rolling(n).mean() # 采用后n个的斜率绝对值平均作为斜率指标
ts = h[u'阈值'][h[u'斜率指标'].idxmin() - n]
# 注:用idxmin返回最小值的Index,由于rolling_mean()自动计算的是前n个斜率的绝对值平均
# 所以结果要进行平移(-n)
if ts > threshold:
ts = pd.Timedelta(minutes=4)
print(ts)
属性构造:根据用水行为,需构造四类指标:时长指标、频率指标、用水的量化指标以及用水的波动指标。
属性解释:
候选洗浴事件:从大量的一次完整用水事件中筛选规则剔除可以明显判定不是洗浴的事件
筛选掉非常短暂的用水事件:一次完整的用水事件满足其中任意一个条件,就被判定为短暂用水事件,其筛选条件为:1、一次用水事件中总用水量(纯热水)小于y升;2、用水时长小于100秒;3、总用水时长小于120秒。
3、缺失值的处理
根据建模样本数据和用户记录的包含用水的用途、用水开始时间、用水结束时间等属性的用水日志,建立BP神经网络模型识别洗浴事件。
# -*- coding: utf-8 -*-
# 建立、训练多层神经网络,并完成模型的检验
from __future__ import print_function
import pandas as pd
inputfile1 = '../data/train_neural_network_data.xls' # 训练数据
inputfile2 = '../data/test_neural_network_data.xls' # 测试数据
testoutputfile = '../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.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
model = Sequential() # 建立模型
model.add(Dense(11, 17)) # 添加输入层、隐藏层的连接
model.add(Activation('relu')) # 以Relu函数为激活函数
model.add(Dense(17, 10)) # 添加隐藏层、隐藏层的连接
model.add(Activation('relu')) # 以Relu函数为激活函数
model.add(Dense(10, 1)) # 添加隐藏层、输出层的连接
model.add(Activation('sigmoid')) # 以sigmoid函数为激活函数
# 编译模型,损失函数为binary_crossentropy,用adam法求解
model.compile(loss='binary_crossentropy', optimizer='adam', class_mode="binary")
model.fit(x_train, y_train, nb_epoch=100, batch_size=1) # 训练模型
model.save_weights('../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)
通过某热水器用户记录了两周的热水器用水日志,将前一周的数据作为训练数据,后一周的数据作为测试数据。根据该热水器用户提供的用水日志与多层神经网络模型识别结果的比较,总共21条检测数据,准确识别了18条数据,模型对洗浴事件的识别准确率为85.5%。