數據挖掘實戰1:利用LM神經網路演算法進行電力竊漏電用戶自動識別

無小意丶

知乎主頁:無小意丶

公眾號: 數據路(shuju_lu)

剛剛開始寫博客,希望能保持關注,會繼續努力。以數據相關為主,互聯網為輔進行文章發布。

本文是《Python數據分析與挖掘實戰》一書的實戰部分,在整理分析後的復現。本篇文章是本書第六章的實戰:電力竊漏電用戶自動識別。相關附件代碼、數據和PDF,關注公眾號「數據路」,回復:挖掘實戰。

更好的觀看體驗,在線Jupyter notebook科賽平台,直接體驗,點擊這裡

一、背景與挖掘目標

1.1 背景

  1. 傳統的防竊漏電方法主要通過定期巡檢、定期校驗電錶、用戶舉報竊電等方法來發現竊電或計量裝置故障。
  2. 但這種方法對人的依賴性太強,抓竊查漏的目標不明確。
  3. 通過採集電量異常、負荷異常、終端報警、主站報警、線損異常等信息,建立數據分析模型,來實時監測竊漏電情況和發現計量裝置的故障。

1.2 目標

  1. 歸納出竊漏電用戶的關鍵特徵,構建竊漏電用戶的識別模型。
  2. 利用實時檢測數據,調用竊漏電用戶識別模型實現實時診斷。

二、分析方法與過程

2.1分析方法

  1. 竊漏電用戶在電力計量自動化系統的監控大用戶中只佔一小部分,同時某些大用戶也不可能存在竊漏電行為,如銀行、稅務、學校和工商等非居民類別,故在數據預處理時有必要將這些類別用戶剔除。
  2. 系統中的用電負荷不能直接體現出用戶的竊漏電行為,終端報警存在很多誤報和漏報的情況,故需要進行數據探索和預處理,總結竊漏電用戶的行為規律,再從數據中提煉出描述竊漏電用戶的特徵指標。
  3. 最後結合歷史竊漏電用戶信息,整理出識別模型的專家樣本數據集,再進一步構建分類模型,實現竊漏電用戶的自動識別。竊漏電用戶識別流程如圖6.1所示,主要包話以下步驟。

2.2過程整理

  1. 從電力計量自動化系統、營銷系統有選擇性地抽取部分大用戶用電負荷、終端報警及違約竊電處罰信息等原始數據。
  2. 對樣本數據探索分析,剔除不可能存在竊漏電行為行業的用戶,即白名單用戶,初步審視正常用戶和竊漏電用戶的用電特徵。
  3. 對樣本數據進行預處理,包括數據清洗、缺失值處理和數據變換。
  4. 構建專家樣本集。
  5. 構建竊漏電用戶識別模型。
  6. 在線監測用戶用電負荷及終端報警,調用模型實現實時診斷。

2.3數據探索分析

以下代碼可以使用Excel直接打開數據集,進行畫圖分析。

2.3.1 分布分析

2.3.2 周期性分析

2.3.3 竊漏電用電電量分析

2.4數據預處理

2.4.1數據清洗

  1. 非居民不存在透漏電,如學校,郵局等等
  2. 結合業務,節假日會比平時偏低,為了達到更好效果,去處掉節假日。

2.4.2缺失值處理

具體見數據集內容對於缺失值處理,採用拉格朗日插值法補值,具體方法如下。

  1. 首先,確定原始數據集中的自變數和因變數,
  2. 取出缺失值前後五個數據(空值和不存在,去掉)
  3. 取出十個數據為一組,採用拉格朗日多項式差值公式

#-*- coding: utf-8 -*-#拉格朗日插值代碼import pandas as pd #導入數據分析庫Pandasfrom scipy.interpolate import lagrange #導入拉格朗日插值函數inputfile = /home/kesci/input/date14037/missing_data.xls #輸入數據路徑,需要使用Excel格式;outputfile = /home/kesci/work/missing_data_processed.xls #輸出數據路徑,需要使用Excel格式,這裡在科賽上,所以本地運行需要修改路徑data = pd.read_excel(inputfile, header=None) #讀入數據print(data)#自定義列向量插值函數#s為列向量,n為被插值的位置,k為取前後的數據個數,默認為5def ployinterp_column(s, n, k=5): y = s[list(range(n-k, n)) + list(range(n+1, n+1+k))] #取數,注意這類()取最左,不取最右。 y = y[y.notnull()] #剔除空值 return lagrange(y.index, list(y))(n) #插值並返回插值結果#逐個元素判斷是否需要插值for i in data.columns: for j in range(len(data)): if (data[i].isnull())[j]: #如果為空即插值。 data[i][j] = ployinterp_column(data[i], j)print(data)data.to_excel(outputfile, header=None, index=False) #輸出結果 0 1 20 235.8333 324.0343 478.32311 236.2708 325.6379 515.45642 238.0521 328.0897 517.09093 235.9063 NaN 514.89004 236.7604 268.8324 NaN5 NaN 404.0480 486.09126 237.4167 391.2652 516.23307 238.6563 380.8241 NaN8 237.6042 388.0230 435.3508———————————數據處理前後———————————— 0 1 20 235.833300 324.034300 478.3231001 236.270800 325.637900 515.4564002 238.052100 328.089700 517.0909003 235.906300 203.462116 514.8900004 236.760400 268.832400 493.3525915 237.151181 404.048000 486.0912006 237.416700 391.265200 516.2330007 238.656300 380.824100 493.3423828 237.604200 388.023000 435.350800

2.4.3數據變換

通過電力計量系統採集的電量、負荷,雖然在一定程度上能反映用戶竊漏電行為的某些規律,但要作為構建模型的專家樣本,特徵不明顯,需要進行重新構造。基於數據變換,得到新的評價指標來表徵竊漏電行為所具有的規律,其評價指標體系如圖6巧所示。

1. 用電量趨勢下降指標

由之前的周期性分析,可以發現。竊漏電用戶的用電量,會不斷呈下降態勢。然後趨於平緩。正常用戶,整體上呈平穩態勢。所以,考慮用一段時間的用電量擬合成一條直線,判斷斜率進行指標計算。

2. 線損指標

綜上指標計算方法,得出數據,詳情看數據集中的model.xls你要問我怎麼數字計算。我也很懵呀,找個機會把數學公式計算辦法學習完後,再來補充相應的代碼但是,我覺得可以用excel比較簡單的較快處理這些數據。訓練用的專家樣本數據看附件中的model.xls

2.5模型構建

2.5.1構建竊漏電用戶識別模型

1. 數據劃分

對專家樣本,隨機選取20%作為測試樣本,80%作為訓練樣本,代碼如下

2. LM神經網路

使用Keras庫為我們建立神經網路模型,設定KM神經網路的輸入節點數為3,輸出節點為1,隱藏節點數為10,使用Adam方法求解,隱藏層使用Relu(x)=max(x,0)作為激活函數,實驗表面該函數能大幅提高模型的準確率。

以下代碼運行需要兩三分鐘時間,運行完畢後,得到混淆矩陣圖。可以算得,分類準確率為(161+58)/(161+58+6+7)=94.4%,正常的用戶被誤判為竊漏電用戶占正常的7/(161+7)=4.2%,竊漏電用戶被誤判為正常用戶占正常用戶的6/(6+58)=9.4%。

#-*- coding: utf-8 -*-import matplotlib.pyplot as pltimport pandas as pdfrom random import shuffledef cm_plot(y, yp): from sklearn.metrics import confusion_matrix #導入混淆矩陣函數 cm = confusion_matrix(y, yp) #混淆矩陣 import matplotlib.pyplot as plt #導入作圖庫 plt.matshow(cm, cmap=plt.cm.Greens) #畫混淆矩陣圖,配色風格使用cm.Greens,更多風格請參考官網。 plt.colorbar() #顏色標籤 for x in range(len(cm)): #數據標籤 for y in range(len(cm)): plt.annotate(cm[x,y], xy=(x, y), horizontalalignment=center, verticalalignment=center) plt.ylabel(True label) #坐標軸標籤 plt.xlabel(Predicted label) #坐標軸標籤 return pltdatafile = /home/kesci/input/date14037/model.xlsdata = pd.read_excel(datafile)data = data.as_matrix()shuffle(data)p = 0.8 #設置訓練數據比例train = data[:int(len(data)*p),:]#多維數據的切片方法test = data[int(len(data)*p):,:]#逗號左邊,代表行,右邊代表列#構建LM神經網路模型from keras.models import Sequential #導入神經網路初始化函數from keras.layers.core import Dense, Activation #導入神經網路層函數、激活函數netfile = /home/kesci/input/date14037/net.model #構建的神經網路模型存儲路徑net = Sequential() #建立神經網路net.add(Dense(input_dim = 3, output_dim = 10)) #添加輸入層(3節點)到隱藏層(10節點)的連接net.add(Activation(relu)) #隱藏層使用relu激活函數net.add(Dense(input_dim = 10, output_dim = 1)) #添加隱藏層(10節點)到輸出層(1節點)的連接net.add(Activation(sigmoid)) #輸出層使用sigmoid激活函數net.compile(loss = binary_crossentropy, optimizer = adam) #編譯模型,使用adam方法求解net.fit(train[:,:3], train[:,3], nb_epoch=100, batch_size=1) #訓練模型,循環1000次,不用於書籍源代碼,這裡需要刪除class這個值才能正常運行net.save_weights(netfile) #保存模型predict_result = net.predict_classes(train[:,:3]).reshape(len(train)) #預測結果變形這裡要提醒的是,keras用predict給出預測概率,predict_classes才是給出預測類別,而且兩者的預測結果都是n x 1維數組,而不是通常的 1 x n#導入自行編寫的混淆矩陣可視化函數,具體見最上代碼 cm_plot(y, yp)def cm_plot(y, yp): from sklearn.metrics import confusion_matrix #導入混淆矩陣函數 cm = confusion_matrix(y, yp) #混淆矩陣 import matplotlib.pyplot as plt #導入作圖庫 plt.matshow(cm, cmap=plt.cm.Greens) #畫混淆矩陣圖,配色風格使用cm.Greens,更多風格請參考官網。 plt.colorbar() #顏色標籤 for x in range(len(cm)): #數據標籤 for y in range(len(cm)): plt.annotate(cm[x,y], xy=(x, y), horizontalalignment=center, verticalalignment=center) plt.ylabel(True label) #坐標軸標籤 plt.xlabel(Predicted label) #坐標軸標籤 return pltcm_plot(train[:,3], predict_result).show() #顯示混淆矩陣可視化結果from sklearn.metrics import roc_curve #導入ROC曲線函數predict_result = net.predict(test[:,:3]).reshape(len(test))fpr, tpr, thresholds = roc_curve(test[:,3], predict_result, pos_label=1)plt.plot(fpr, tpr, linewidth_=2, label = ROC of LM) #作出ROC曲線plt.xlabel(False Positive Rate) #坐標軸標籤plt.ylabel(True Positive Rate) #坐標軸標籤plt.ylim(0,1.05) #邊界範圍plt.xlim(0,1.05) #邊界範圍plt.legend(loc=4) #圖例plt.show() #顯示作圖結果

以下是運行結果,可以在科賽上看訓練過程。

模型評價與分析:LM神經網路使用Keras庫為我們建立神經網路模型,設定KM神經網路的輸入節點數為3,輸出節點為1,隱藏節點數為10,使用Adam方法求解,隱藏層使用Relu(x)=max(x,0)作為激活函數,實驗表面該函數能大幅提高模型的準確率。

以上代碼運行需要兩三分鐘時間,運行完畢後,得到混淆矩陣圖。可以算得,分類準確率為(161+58)/(161+58+6+7)=94.4%,正常的用戶被誤判為竊漏電用戶占正常的7/(161+7)=4.2%,竊漏電用戶被誤判為正常用戶占正常用戶的6/(6+58)=9.4%。

3. CART決策樹演算法

#-*- coding: utf-8 -*-#構建並測試CART決策樹模型import pandas as pd #導入數據分析庫from random import shuffle #導入隨機函數shuffle,用來打算數據datafile = /home/kesci/input/date14037/model.xls #數據名data = pd.read_excel(datafile) #讀取數據,數據的前三列是特徵,第四列是標籤data = data.as_matrix() #將表格轉換為矩陣shuffle(data) #隨機打亂數據p = 0.8 #設置訓練數據比例train = data[:int(len(data)*p),:] #前80%為訓練集test = data[int(len(data)*p):,:] #後20%為測試集#構建CART決策樹模型from sklearn.tree import DecisionTreeClassifier #導入決策樹模型treefile = /home/kesci/work/tree.pkl #模型輸出名字tree = DecisionTreeClassifier() #建立決策樹模型tree.fit(train[:,:3], train[:,3]) #訓練#保存模型from sklearn.externals import joblibjoblib.dump(tree, treefile)#導入自行編寫的混淆矩陣可視化函數def cm_plot(y, yp): from sklearn.metrics import confusion_matrix #導入混淆矩陣函數 cm = confusion_matrix(y, yp) #混淆矩陣 import matplotlib.pyplot as plt #導入作圖庫 plt.matshow(cm, cmap=plt.cm.Greens) #畫混淆矩陣圖,配色風格使用cm.Greens,更多風格請參考官網。 plt.colorbar() #顏色標籤 for x in range(len(cm)): #數據標籤 for y in range(len(cm)): plt.annotate(cm[x,y], xy=(x, y), horizontalalignment=center, verticalalignment=center) plt.ylabel(True label) #坐標軸標籤 plt.xlabel(Predicted label) #坐標軸標籤 return pltcm_plot(train[:,3], tree.predict(train[:,:3])).show() #顯示混淆矩陣可視化結果#注意到Scikit-Learn使用predict方法直接給出預測結果。from sklearn.metrics import roc_curve #導入ROC曲線函數fpr, tpr, thresholds = roc_curve(test[:,3], tree.predict_proba(test[:,:3])[:,1], pos_label=1)plt.plot(fpr, tpr, linewidth_=2, label = ROC of CART, color = green) #作出ROC曲線plt.xlabel(False Positive Rate) #坐標軸標籤plt.ylabel(True Positive Rate) #坐標軸標籤plt.ylim(0,1.05) #邊界範圍plt.xlim(0,1.05) #邊界範圍plt.legend(loc=4) #圖例plt.show() #顯示作圖結果

運行結果如下:

模型評價與分析:分類的準確率為(160+56)/(160+56+3+13)=93.1%,得到的混淆矩陣如上。因為每次隨機的樣本不同,隨意準確率是在一定區間內浮動。

模型對比評價

採用OCR曲線評價方法進行評估,一個優秀的分類器所對應的ROC曲線應該是盡量靠近左上角的。

通過對比,可以比較容易得出,LM神經網路的ROC曲線更加符合優秀的定義。說明LM神經網路模型的分類性能較好,能應用於竊漏電用戶識別。

3.進行竊漏電診斷

在線監測用戶用電負荷及終端報警數據,並利用經過2.3節的處理所得到模型,輸入在線實時數據,再利用前面代碼構建好的竊漏電用戶識別模型計算用戶的竊漏電診斷結果,實現了竊漏電用戶實時診斷。

三、小結

  1. 了解了數據挖掘演算法中LM神經網路和CART決策樹演算法的實際應用場景
  2. 但是還未深刻理解,這個兩個演算法背後原理,往後在學習《數據挖掘導論》時要理解。
  3. 了解了識別模型優劣中的ROC比較方法,但是應該還會有更好的方式。
  4. 這個案例,可以類推到汽車相關的偷漏稅項目上。但是,自己實戰時發現,目標原始數據很難去發現有效指標與建立評價指標,業務的理解轉換能力不足
  5. 目前,還在同步學習秦路的《七周數據分析師》希望能獲得一些業務能力,幫助項目進行。

推薦閱讀:

用Python玩GTA 5—使用OpenCV讀取遊戲面面
Python數據分析之鎖具裝箱問題
Python built-in functions F&G
黃哥教Python初學者如何調試錯誤。
nginx日誌如何正確顯示整個http請求的服務端處理時間?

TAG:數據分析 | 數據挖掘 | Python |