《Python数据分析与数据挖掘实战》第六章:电力窃漏电用户自动识别完整流程及pytorch代码实现
项目任务:通过数据分析与数据挖掘技术完成对窃漏电用户自动识别任务
子任务:
- 数据预处理:对数据中缺失值进行拉格朗日插补
- 建立模型:使用pytorch建立神经网络模型,使用sklearn建立CART决策树模型。
- 数据分析与模型评价:比较算法准确率,建立ROC曲线图
第一步:建立项目专属虚拟环境
由于不同项目之间依赖项版本需求不同,且在全局变量中加入太多包会造成一些问题,我们建议每个项目都有自己专属的虚拟环境,在虚拟环境中安装所需不同版本的库,并可选择你所希望适应的Python版本。
1.虚拟环境建立工具:virtualenv
该库需要安装,win用户在集成终端中输入:
pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple
(从清华源下载,速度较快)
2.建立虚拟环境
Virtualenv -p C:\Users\Administrator\AppData\Local\Programs\Python\Python39\python.exe ENV3.9
注:-p 指定使用python版本+版本exe文件位置+虚拟环境名称(这里叫ENV3.9)
3.虚拟环境建立完毕,安装项目所需依赖
pip install 库名
安装即可,本项目需要matplotlib、scikit-learn、torch、pandas等
第二步:完成子任务1:缺失值填充
数据:
这里我们采用scipy库中拉格朗日插值完成对缺失值的填充。
源码如下:
import pandas as pd
inputfile = 'D:/book/24064925aueh/01-数据和代码/chapter6/test/data/missing_data.xls'
outputfile = 'D:/book/24064925aueh/01-数据和代码/chapter6/test/data/data.xls'
data_pre = pd.read_excel(inputfile,header=None)
from scipy.interpolate import lagrange
# 要用到前五个与后五个的值进行插值,如果前面或者后面不足五个就要进行条件判断处理
def ployinterp_column(s,n,k=5):
if (n-k)<0:
y = s[list(range(0,n))+list(range(n+1,n+1+k))]
elif (n+1+k)>len(s):
y = s[list(range(n-k,n))+list(range(n+1,len(s)))]
else:
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_pre.columns:
for j in range(len(data_pre)):
if (data_pre[i].isnull())[j]:
data_pre[i][j] = ployinterp_column(data_pre[i],j)
data_pre.to_excel(outputfile,header=None,index=False)
结果如下:
第三步 完成神经网络搭建-基于pytorch
部分数据如下:
所以本质上是一个二分类问题,通过前三个指标完成对输出的预测。
因此可以搭建输入节点为3,输出节点为1,隐藏层节点为10的神经网络,进行训练完成预测。源码如下:
在这里插入代码片#神经网络完成二分类
import pandas as pd
import numpy as np
from torch import optim
import torch
import torch.nn as nn
from random import shuffle
from torch.utils.data import DataLoader,TensorDataset,Dataset
#1.数据打包分割
inputfile = 'D:/book/24064925aueh/01-数据和代码/chapter6/test/data/model.xls'
data = pd.read_excel(inputfile)
data = data.values
shuffle(data)
p = 0.8
train = data[:int(len(data)*p),:]
x_train = train[:,:3]
x_train = x_train.astype(np.float32)
x_train = torch.tensor(x_train)
y_train = train[:,3]
y_train = y_train.astype(np.float32)
y_train = torch.tensor(y_train)
test = data[int(len(data)*p):,:]
x_test = test[:,:3]
x_test = x_test.astype(np.float32)
x_test = torch.tensor(x_test)
y_test = test[:,3]
y_test = y_test.astype(np.float32)
y_test = torch.tensor(y_test)
trainloader = DataLoader(TensorDataset(x_train,y_train),batch_size=2,shuffle=True)
#2.模型
class model(nn.Module):
def __init__(self) -> None:
super(model,self).__init__()
self.net = nn.Sequential(
nn.Linear(3,20),
nn.ReLU(),
nn.Linear(20,5),
nn.ReLU(),
nn.Linear(5,1),
nn.Sigmoid()
)
def forward(self,x):
x = self.net(x)
return x
model1 = model()
optimzer = optim.Adam(model1.parameters())
criterion = nn.BCELoss()
for epoch in range(10):
for x,y in trainloader:
pred = model1(x)
pred =pred.squeeze(1)
loss = criterion(pred,y)
optimzer.zero_grad()
loss.backward()
optimzer.step()
with torch.no_grad():
y_pred1 = model1(x_train)
acc_train = (y_pred1.round()==y_train).float().mean().item()
y_pred = model1 (x_test)
acc_test = (y_pred.round()==y_test).float().mean().item()
print(epoch, acc_train, acc_test)
#print(model1.net[0].weight)
x = model1(x_train)
x= x.round()
#自己编写的混淆矩阵可视化函数
from cm_plot import *
cm_plot(y_train.detach(),x.detach()).show()
y_pred = model1(x_test)
y_pred = y_pred.round()
y_pred = y_pred.detach()
#对模型的评价,通过绘制ROC曲线图
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve
fpr,tpr,threshoulds = roc_curve(y_test,y_pred,pos_label=1)
plt.plot(fpr,tpr,linewidth=2,label='ROC OF NET')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.xlim(0,1.05)
plt.ylim(0,1.05)
plt.legend(loc=2)
plt.show()
结果如下:
第四步:CART决策树构建-基于sklearn
数据与第三步一致,故导入数据代码不再赘述,其余源码如下:
#CART决策树
from sklearn.tree import DecisionTreeClassifier
model2 = DecisionTreeClassifier()
model2.fit(x_train,y_train)
from cm_plot import *
#cm_plot(y_train,model2.predict(x_train)).show()
#cm_plot(y_test,model2.predict(x_test)).show()
# ROC曲线
from sklearn.metrics import roc_curve
import matplotlib.pyplot as plt
fpr,tpr,threshoulds = roc_curve(y_test,model2.predict(x_test),pos_label=1)
plt.plot(fpr,tpr,linewidth=2,label='ROC OF CART')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.xlim(0,1.05)
plt.ylim(0,1.05)
plt.legend(loc=2)
plt.show()
结果如下:
第五步:总结
这个简单的小项目主要是令我对项目流程有一个完整的认知,首先要明确项目任务,基于此分析原始数据,从原始数据中抽取出我们需要的数据,进行探索与分析,算法的运算只是其中一部分,数据的预处理部分同样存在很多问题,不可轻视。另外一下辅助工作也需要注意,比如专属环境的搭建、数据存放的规整度等等,做好这些细节都会给后期省不少事。
遇到的问题:
- 缺失值插补过程中,对于前后数目不足插补要求时的条件判断一开始没考虑到。
- 神经网络构建中,关于数据类型,什么时候tensor,什么时候ndarray也很繁琐,还有精度问题,不同函数精度要求不同,需要用float处理。
- 关于判断预测准确率,函数返回的不是0和1,而是0.几,需要用round()函数进行四舍五入。完成预测结果度量。