家用電器用戶行為分析與事件識別


 

目標

 

1、根據熱水器采集到的數據,划分一次完整用水數據。

 

2、在划分好的一次完整用水事件中,識別出洗浴事件。

 

數據預處理

 

1、原始數據集太大,進行數據抽取

 

2、由於熱水器采集的用水數據屬性較多,我們只選擇與分析目標相關的屬性。

 

3、如何划分一次完整的用水事件呢?

如果水流量為0的狀態記錄之間的時間間隔超過一個閾值T,則從該段水流量為0的狀態記錄向前找到最后一條水流量不為0的用水記錄作為上一次用水事件的結束;向后找到水流量不為0的狀態記錄作為下一個用水事件的開始。

 

實現方法:

只取水流量>0的值,然后對過濾后的數據進行相鄰時間差分運算,差分結果大於給定閾值的差分結果保留下來,統計所有值的個數,就是用水事件數。

data = data[data[u'水流量'] > 0] #只要流量大於0的記錄

d = data[u'發生時間'].diff() > threshold #相鄰時間作差分,比較是否大於閾值

data[u'事件編號'] = d.cumsum() + 1 #通過累積求和的方式為事件編號

 

4、閾值尋優模型:

對用戶某時間段不同用水時間間隔閾值事件划分個數和划分閾值作圖,

 

 

在某段閾值范圍內,下降趨勢明顯,說明在該段閾值范圍內,用戶的停頓習慣比較集中。在趨勢比較平穩部分,說明在對應段閾值范圍內,用戶的用水停頓習慣趨於穩定,所以取該段時間開始作為閾值,既不會將短的用水事件合並,也不會將長的用水事件拆開。

 

如何使用程序識別這個最優的閾值呢?

對每一個點求出一個斜率指標,這個指標不是改點和相鄰點形成的直線的斜率值,而是從改點往后選取n(3-6)個點,這n個點的相鄰點可以求出一個斜率值,將所有的斜率值求出平均值,作為起始點的斜率指標k。如果k<1,就將該點作為最優的閾值點。1是經過實際數據驗證的一個專家閾值。當不存在K<1時,則找所有閾值中斜率指標最小的閾值,如果該閾值的斜率指標小於5,則取該閾值作為用水事件划分的閾值,如果該閾值的斜率指標不小於5,則閾值取默認值的閾值為4分鍾。其中,斜率指標小於5是一個專家閾值。

 

代碼實現:

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'斜率指標'] = 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)

 

5、屬性構造

本案例研究的是用水行為,可構造4類指標:時長指標、頻率指標、用水的量化指標、用水的波動指標。

 

屬性構建說明:

 

 

模型構建

 

使用MLP進行建模

 

一般2層的神經網絡可以解決大部分分類問題。經反復驗證得到兩個隱層的 隱節點數分別為17,10時分類效果較好。

 

代碼實現:

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) #訓練模型


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM