《Python資料分析與挖掘實戰》第六章案例代碼總結與修改分析
一、實驗目的
1.掌握拉格朗日插值算法進行缺失值處理的方法。
2.掌握LM神經網絡和CART決策樹建構分類模型的方法。
二、實驗要求
1.利用拉格朗日插值算法補全資料使用者的用電資料存在的缺失值。對拉格朗日插值法公式的了解,然後參考拉格朗日插值算法進行程式設計,将資料中的缺失值利用多項式函數對缺失值進行補充
2.建構分類模型對竊漏電使用者進行識别,兩模型為LM神經網絡和CART決策樹。通過建立模型研究竊漏電使用者的行為特征,總結出竊漏電使用者的特征名額,對比LM神經網絡和CART決策樹算法在竊漏電使用者的識别效果,從中選取最優模型進行竊漏電診斷,進而了解資料挖掘的整個過程,并對其相應的算法熟練運用。
三、實驗環境
Windows10系統
Pycharm軟體
Python3.5.4
第三方庫keras2.1.4、pandas0.25.3、Scikit-Learn0.22.2.post1
四、實驗分析及思路
1.首先做題目需求分析
①我們需要對樣本資料進行預處理,包括資料清洗、缺失值處理和資料變換。此處我們實驗隻說“缺失值處理”因為資料中存在缺失的想象,若将這些缺失值抛棄掉,會嚴重影響供出電量的計算結果,最終導緻日線損率資料誤差很大,為了達到較好的模組化效果,需要對缺失值處理。插值方法有:拉格朗日插值法、牛頓插值法。拉格朗日插值法的最大毛病就是每次引入一個新的插值節點,基函數都要發生變化,這在一些實際生産環境中是不合适的,有時候會不斷的有新的測量資料加入插值節點集,是以,通過尋找n個插值節點構造的的插值函數與n+1個插值節點構造的插值函數之間的關系,形成了牛頓插值法。由于能力有限,本次實驗采用拉格朗日插值法對缺失值進行插補。
②建構專家樣本完成後,需要劃分測試樣本和訓練樣本,随機選取20%作為測試樣本,剩下的作為訓練樣本。竊漏電使用者識别可通過建構分類預測模型來實作,比較常用的分類預測模型有LM神經網絡和CART決策樹,各個模型都有各自的優點,故采用這兩種方法建構竊漏電使用者識别,并從中選擇最優的分類模型。建構LM神經網絡和CART決策樹模型時輸人項包括電量趨勢下降名額、線損類名額和告警類名額,輸出項為竊漏電辨別。使用LM神經網絡和CART決策樹實作分類預測模型,利用混淆矩陣和ROC曲線對模型進行評價
2.涉及到的資料
使用者的用電資料存在缺失值的資料即為樣本資料
專家樣本即對所有竊漏電使用者及正常使用者的電量、告警及線損資料和該使用者在當天是否竊漏電的辨別,按竊漏電評價名額進行處理并選取其中291個樣本資料
3.主要設計思路
(1)缺失值處理(拉格朗日插值法補值思路)
首先從原始資料集中确定因變量和自變量,取出缺失值前後5個資料(前後資料中遇到資料不存在或者為空的,直接将資料舍去,将僅有的資料組成一組),根據取出來的10個資料組成一組。然後采用拉格朗日多項式插值公式:

其中,x為缺失值對應的下标序号,Ln(x)為缺失值的插值結果,x為非缺失值y的下标序号。對全部缺失資料依次進行插補,直到不存在缺失值為止實驗過程
(2)模型的建構及評價
①建構竊漏電使用者識别模型,先對原始資料進行劃分,分為訓練資料和測試資料;再建立LM神經網絡使用 Keras庫為我們建立神經網絡模型。設定LM神經網絡的輸入節點數為3,輸出節點數為1,隐層節點數為10,使用Adam方法求解。對于激活函數,在隐藏層使用Relu(x)=max(x,0)作為激活函數,實驗表明該激活函數能夠大幅提高模型的準确率。根據訓練樣本模組化的混淆矩陣可以算得分類準确率、正常使用者被誤判為竊漏電使用者占正常使用者的機率、竊漏電使用者被誤判為正常使用者占正常竊漏電使用者的機率;之後建立CART決策樹通過Scikit- Lean利用訓練樣本建構CART決策樹模型,得到混淆矩陣可以算出分類準确率、正常使用者被誤判為竊漏電使用者占正常使用者的機率、竊漏電使用者被誤判為正常使用者占正常竊漏電使用者的機率。
②對建構的模型進行對比和評價。對于訓練樣本比較LM神經網絡和CART決策樹的分類準确率。評估模型分類的性能則利用測試樣本對兩個模型進行評價,采用ROC曲線評價方法進行評估,一個優秀分類器所對應的ROC曲線應該是盡量靠近左上角的。分别畫出LM神經網絡和CART決策樹在測試樣本下的ROC曲線,然後兩圖比較
五、實驗結果及分析
1.拉格朗日插值法
代碼:
#-*- coding: utf-8 -*-
#拉格朗日插值代碼
import pandas as pd #導入資料分析庫Pandas
from scipy.interpolate import lagrange #導入拉格朗日插值函數
inputfile = 'F:/大二下合集/Python資料分析與挖掘/missing_data.xls' #輸入資料路徑,需要使用Excel格式;
outputfile = 'F:/大二下合集/Python資料分析與挖掘/missing_data_processed.xls' #輸出資料路徑,需要使用Excel格式
data = pd.read_excel(inputfile, header=None) #讀入資料
#自定義列向量插值函數
#s為列向量,n為被插值的位置,k為取前後的資料個數,預設為5
def ployinterp_column(s, n, k=5):
y = s.reindex(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)
data.to_excel(outputfile, header=None, index=False) #輸出結果
運作圖:
運作結果:(補全資料vs原資料)
2. 利用訓練樣本建構LM神經網絡的混淆矩陣及繪制模型的ROC曲線
代碼:
#-*- coding: utf-8 -*-
#建構并測試CART決策樹模型
import matplotlib.pyplot as plt
import pandas as pd #導入資料分析庫
from random import shuffle #導入随機函數shuffle,用來打算資料
datafile = 'F:/大二下合集/Python資料分析與挖掘/model.xls' #資料名
data = pd.read_excel(datafile) #讀取資料,資料的前三列是特征,第四列是标簽
data = data.values #将表格轉換為矩陣
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 = 'F:/大二下合集/Python資料分析與挖掘/tree.pkl' #模型輸出名字
tree = DecisionTreeClassifier() #建立決策樹模型
tree.fit(train[:,:3], train[:,3]) #訓練
#儲存模型
from sklearn.externals import joblib
joblib.dump(tree, treefile)
from cm_plot import * #導入自行編寫的混淆矩陣可視化函數
cm_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() #顯示作圖結果
運作圖及結果:
分類準确率為:(163+57)/(163+57+4+8)≈94.8%
正常使用者被誤判為竊漏電使用者占正常使用者的:8/(163+8)≈4.6%
竊漏電使用者被誤判為正常使用者占正常使用者的:4/(4+57)≈6.5%
3.利用訓練樣本建構CART決策樹的混淆矩陣及繪制模型的ROC曲線
代碼:
#-*- coding: utf-8 -*-
import pandas as pd
import matplotlib.pyplot as plt
from random import shuffle
datafile = 'F:/大二下合集/Python資料分析與挖掘/model.xls'
data = 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 = 'F:/大二下合集/Python資料分析與挖掘/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=1000, batch_size=1) #訓練模型,循環1000次
net.save_weights(netfile) #儲存模型
predict_result = net.predict_classes(train[:,:3]).reshape(len(train)) #預測結果變形
'''這裡要提醒的是,keras用predict給出預測機率,predict_classes才是給出預測類别,而且兩者的預測結果都是n x 1維數組,而不是通常的 1 x n'''
from cm_plot import * #導入自行編寫的混淆矩陣可視化函數
cm_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() #顯示作圖結果
運作圖及結果:
分類準确率為:(163+56)/(163+56+8+5)≈94.3%
正常使用者被誤判為竊漏電使用者占正常使用者的:5/(163+5)≈2.9%
竊漏電使用者被誤判為正常使用者占正常使用者的:8/(8+56)≈12.5%
4.模型評價
對于訓練樣本,LM神經網絡和CART決策樹的分類準确率相差不大,分别為94.8%和94.3%。為進一步評估模型分類的性能,故利用測試樣本對兩個模型進行評價,采用ROC曲線評價方法進行評估,一個優秀分類器所對應的ROC曲線應該是盡量靠近左上角的。
LM神經網絡和CART決策樹在測試樣本下的ROC曲線,如下所示:
經過對比發現CART神經網絡的ROC曲線比LM決策樹的ROC曲線更加靠近機關方形的左上角,CART神經網絡ROC曲線下的面積更大,說明CART神經網絡模型的分類性能較好,能應用于竊漏電使用者識别。