1. 背景与挖掘目标:
项目为《Python 数据分析与挖掘实战》第 6 章:电力窃漏电用户自动识别。 挖掘目标为根据用电记录原始数据,归纳出窃漏电用户的关键特征,构建窃漏电用户的识别模型。从而可以利用实时检测数据,调用窃漏电用户识别模型实现实时诊断
2. 分析方法与过程:
2.1 缺失值处理
原始数据中有很多缺失现象,如下采用拉格朗日差值法对缺失值进行插补:
'''拉格朗日插值'''
import pandas as pd
from scipy. interpolate import lagrange
inputfile = 'chapter6/test/data/missing_data.xls'
outputfile = 'chapter6/test/tmp/missing_data_processed.xls'
data = pd. read_excel( inputfile, header= None )
def ployinterp_column ( series, n, k= 5 ) :
y = series[ list ( range ( n- k, n) ) + list ( range ( n+ 1 , n+ k+ 1 ) ) ]
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 )
2.2 提取特征指标
由于书中并未提供完整的原始数据,因此直接使用书中给出的数据变换后的专家样本数据进行模型构建。 数据转换的核心思想如下:
电量趋势下降指标 :使用前后几天作为窗口期,统计窗口期间的下降趋势,利用用电量做直线拟合,如果斜率随时间不断下降,那用户的窃漏电嫌疑很大。因此电量趋势下降指标为 11 天窗口期内当天比前一天用电量趋势为递减的天数。线损指标 :窃漏电用户的线损率一般会明显上升,因此线损指标为后 5 天线损率平均值与前 5 天线损率平均值比较,增长率大于 1% 则为 1,小于 1% 则为 0。告警类指标 :与窃漏电相关的终端报警次数总和。
2.3 模型构建
构建窃漏电用户识别模型:分别构建 LM 神经网络和 CART 决策树
数据划分:抽取 20% 为测试样本,80% 为训练样本
'''原始数据分为训练数据和测试数据'''
from random import shuffle
datafile = 'chapter6/test/data/model.xls'
data = pd. read_excel( datafile)
data = data. values
shuffle( data)
p = 0.8
train = data[ : int ( len ( data) * p) , : ]
test = data[ int ( len ( data) * p) : , : ]
LM 神经网络:输入节点数为 3,输出节点数为 1,隐层节点数为 10,使用 Adam 方法求解。分类准确率为 (162 + 56) / (162 + 56 + 7 + 7) = 94.0%
'''LM 神经网络'''
from keras. models import Sequential
from keras. layers. core import Dense, Activation
netfile = 'chapter6/test/tmp/net.model'
net = Sequential( )
net. add( Dense( input_dim= 3 , units= 10 ) )
net. add( Activation( 'relu' ) )
net. add( Dense( input_dim= 10 , units= 1 ) )
net. add( Activation( 'sigmoid' ) )
net. compile ( loss = 'binary_crossentropy' , optimizer= 'adam' )
net. fit( train[ : , : 3 ] , train[ : , 3 ] , epochs= 1000 , batch_size= 1 )
net. save_weights( netfile)
predict_result = net. predict_classes( train[ : , : 3 ] ) . reshape( len ( train) )
from cm_plot import *
% matplotlib notebook
cm_plot( train[ : , 3 ] , predict_result) . show( )
CART 决策树:分类准确率为 (156 + 64) / (156 + 64 + 7 + 5) = 94.8%
'''CART决策树'''
from sklearn. tree import DecisionTreeClassifier
treefile = 'chapter6/test/tmp/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( )
模型评价:ROC 曲线,CART 决策树较 LM 神经网络好(书中为 LM 神经网络较好,推测为数据抽取时随机打乱了的原因)
'''ROC曲线'''
from sklearn. metrics import roc_curve
import matplotlib. pyplot as plt
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' )
fpr2, tpr2, thresholds2 = roc_curve( test[ : , 3 ] , tree. predict_proba( test[ : , : 3 ] ) [ : , 1 ] , pos_label= 1 )
plt. plot( fpr2, tpr2, linewidth= 2 , label= 'ROC of CART' , c= 'r' )
plt. xlabel( 'False Positive Rate' )
plt. ylabel( 'True Positive Rate' )
plt. xlim( 0 , 1.05 )
plt. ylim( 0 , 1.05 )
plt. legend( loc= 4 )
plt. show( )
3. 拓展思考
读取数据
inputfile = 'chapter6/拓展思考/拓展思考样本数据.xls'
data = pd. read_excel( inputfile)
data. head( )
纳税人编号 销售类型 销售模式 汽车销售平均毛利 维修毛利 企业维修收入占销售收入比重 增值税税负 存货周转率 成本费用利润率 整体理论税负 整体税负控制数 办牌率 单台办牌手续费收入 代办保险率 保费返还率 输出 0 1 国产轿车 4S店 0.0635 0.3241 0.0879 0.0084 8.5241 0.0018 0.0166 0.0147 0.4000 0.02 0.7155 0.1500 正常 1 2 国产轿车 4S店 0.0520 0.2577 0.1394 0.0298 5.2782 -0.0013 0.0032 0.0137 0.3307 0.02 0.2697 0.1367 正常 2 3 国产轿车 4S店 0.0173 0.1965 0.1025 0.0067 19.8356 0.0014 0.0080 0.0061 0.2256 0.02 0.2445 0.1301 正常 3 4 国产轿车 一级代理商 0.0501 0.0000 0.0000 0.0000 1.0673 -0.3596 -0.1673 0.0000 0.0000 0.00 0.0000 0.0000 异常 4 5 进口轿车 4S店 0.0564 0.0034 0.0066 0.0017 12.8470 -0.0014 0.0123 0.0095 0.0039 0.08 0.0117 0.1872 正常
数据探索
'''定义分类计算正常率函数'''
def get_rate ( data, col) :
table = data. pivot_table( '纳税人编号' , index= col, columns= [ '输出' ] , aggfunc= 'count' )
table[ 'rate' ] = table[ '正常' ] / table. sum ( 1 )
table = table. sort_values( by= 'rate' , ascending= False )
return table
销售类型分类:可见商用型(客车、货车等)正常率较低
get_rate( data, '销售类型' )
输出 异常 正常 rate 销售类型 进口轿车 5 12 0.705882 国产轿车 22 42 0.656250 其它 4 6 0.600000 工程车 1 1 0.500000 微型面包车 3 3 0.500000 卡车及轻卡 4 3 0.428571 商用货车 3 2 0.400000 大客车 11 2 0.153846
get_rate( data, '销售模式' )
输出 异常 正常 rate 销售模式 4S店 20 56 0.736842 多品牌经营店 3 4 0.571429 其它 3 2 0.400000 一级代理商 14 6 0.300000 二级及二级以下代理商 13 3 0.187500
计算各指标正常与异常平均差值比例,并降序排列,取前三大指标进行建模
def get_mean ( data, col) :
return data. groupby( '输出' ) . mean( ) [ col]
mean = get_mean( data, data. columns[ 3 : - 1 ] )
( mean. diff( ) . abs ( ) / mean. loc[ '正常' , : ] ) . dropna( ) . T. sort_values( by= '正常' , ascending= False )
输出 正常 维修毛利 1.149654 整体税负控制数 0.908304 汽车销售平均毛利 0.904309 代办保险率 0.687667 保费返还率 0.651494 企业维修收入占销售收入比重 0.505450 整体理论税负 0.269718 存货周转率 0.147804 办牌率 0.113657 增值税税负 0.046442 成本费用利润率 0.031140 单台办牌手续费收入 0.024349
建立模型
'''选择维修毛利、整体税负控制数、汽车销售平均毛利三个指标进行建模'''
chosen = data[ [ '维修毛利' , '整体税负控制数' , '汽车销售平均毛利' , '输出' ] ]
chosen. loc[ : , '输出' ] = pd. get_dummies( chosen. loc[ : , '输出' ] ) [ '异常' ]
chosen_data = chosen. values
shuffle( chosen_data)
p = 0.8
train = chosen_data[ : int ( len ( chosen_data * p) ) , : ]
test = chosen_data[ int ( len ( chosen_data) * p) : , : ]
LM 神经网络:训练集正确率为 91.1%,测试集正确率为 84%
'''LM 神经网络'''
from keras. models import Sequential
from keras. layers. core import Dense, Activation
net = Sequential( )
net. add( Dense( input_dim= 3 , units= 10 ) )
net. add( Activation( 'relu' ) )
net. add( Dense( input_dim= 10 , units= 1 ) )
net. add( Activation( 'sigmoid' ) )
net. compile ( loss= 'binary_crossentropy' , optimizer= 'adam' )
net. fit( train[ : , : 3 ] , train[ : , 3 ] , epochs= 1000 , batch_size= 10 )
predict_result = net. predict_classes( train[ : , : 3 ] ) . reshape( len ( train) )
cm_plot( train[ : , 3 ] , predict_result) . show( )
predict_result = net. predict_classes( test[ : , : 3 ] ) . reshape( len ( test) )
cm_plot( test[ : , 3 ] , predict_result) . show( )
CART 决策树:训练集正确率为 100%,测试集正确率也为 100%
'''CART决策树'''
from sklearn. tree import DecisionTreeClassifier
tree = DecisionTreeClassifier( )
tree. fit( train[ : , : 3 ] , train[ : , 3 ] )
cm_plot( train[ : , 3 ] , tree. predict( train[ : , : 3 ] ) ) . show( )
cm_plot( test[ : , 3 ] , tree. predict( test[ : , : 3 ] ) ) . show( )
由混淆矩阵图可以看出 CART 决策树更胜一筹,如下 ROC 曲线也能得出同样的结论
'''ROC曲线'''
from sklearn. metrics import roc_curve
import matplotlib. pyplot as plt
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' )
fpr2, tpr2, thresholds2 = roc_curve( test[ : , 3 ] , tree. predict_proba( test[ : , : 3 ] ) [ : , 1 ] , pos_label= 1 )
plt. plot( fpr2, tpr2, linewidth= 2 , label= 'ROC of CART' , c= 'r' )
plt. xlabel( 'False Positive Rate' )
plt. ylabel( 'True Positive Rate' )
plt. xlim( 0 , 1.05 )
plt. ylim( 0 , 1.05 )
plt. legend( loc= 4 )
plt. show( )
4. 总结
本项目完成了拉格朗日插值法、LM 神经网络的模型构建、CART 决策树的模型构建、两种模型的性能评价。最后对拓展项目进行了探索建模,使用 CART 决策树得出了 100% 的正确率,不过由于数据量较少,正确率仅供参考。
项目代码及数据文件地址:https://github.com/Raymone23/Data-Mining