Python数据分析案例46——电力系统异常值监测(自编码器,孤立森林,SVMD)

案例背景

多变量的时间序列的异常值监测一直是方兴未艾的话题,我总能看到不少的同学要做什么时间序列预测,然后做异常值监测,但是很多同学都搞不清楚他们的区别。

这里要简单解释一下,时间序列预测是有监督的模型,而异常值监测在没有明确给出是不是异常值这个标签y的时候,通常都是无监督模型。通过数据的自身的规律来判断哪些是不是异常点。

本次用一组电力用电量的数据,某个用户的用电量的数据进行异常值监测的代码演示,数据量有点大,一个用户就有10w条,跑得太慢所以没有用很多模型,只用了(自编码器,孤立森林,SVMD)三个模型。

具体的数据文件csv,打开长这个样子:

第一列是时间,u是电压,i是电流,p是功率。言简意赅,简单明了。

我们要做的就是用模型算法去寻找哪些时刻是异常点。

需要该案例的全部代码和数据集可以参考:异常值监测


代码实现

读取数据

先导入包,由于要用深度学习,包有点多

import os
import pandas as pd
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 
import seaborn as sns

plt.rcParams ['font.sans-serif'] ='SimHei'               #显示中文
plt.rcParams ['axes.unicode_minus']=False               #显示负号


#from pandas.plotting import scatter_matrix
import pickle
import h5py
from scipy import stats
 
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import tensorflow as tf
from tensorflow.keras.models import Model, load_model
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
from tensorflow.keras import regularizers
from tensorflow.keras.utils import plot_model
%matplotlib inline
#sns.set(style='whitegrid', palette='muted', font_scale=1.5)

from sklearn.model_selection import train_test_split
from sklearn.svm import OneClassSVM
from sklearn.neural_network import MLPRegressor
from sklearn.ensemble import IsolationForest
from sklearn.metrics import accuracy_score
from sklearn.mixture import GaussianMixture

 从下面读取的文件名称就知道,这是编号60680306的用户在2022年1月到4月26日的用电量情况的数据。

data1=pd.read_csv('60680306_202201-20220426.csv',parse_dates=['time']).set_index('time')
data1.head()

把P功率单独拿出来画一下

data1['P'].plot(figsize=(20,3))

数据挺密集的,也具有明显的周期性。


异常值监测

下面开始用不同的模型进行异常值监测

先进行数据的标准化

#数据标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(data1)
X_s = scaler.transform(data1)
X_trainNorm=X_s

自编码器

自编码器就是神经网络进行重构后还原,我这里就用mlp层。

就是无监督模型,X是自己,y也是自己,重构后计算误差,误差大了就是异常值。

input_dim = X_trainNorm.shape[1]
layer1_dim = 64
encoder_dim = 32
 
input_layer = Input(shape=(input_dim, ))
encoder1 = Dense(layer1_dim, activation="relu")(input_layer)
encoder2 = Dense(encoder_dim, activation="relu")(encoder1)
decoder1 = Dense(layer1_dim, activation='relu')(encoder2)
decoder2 = Dense(input_dim, activation='linear')(decoder1)
print('input_layer: ',input_layer)
print('encoder1',encoder1)
print('encoder2',encoder2)
print('decoder1',decoder1)
print('decoder2',decoder2)

打印查看模型信息 

autoencoder = Model(inputs=input_layer, outputs=decoder2)
autoencoder.summary()

训练 

nb_epoch = 10
batch_size = 128
autoencoder.compile(optimizer='adam', loss='mean_squared_error')
#checkpointer = ModelCheckpoint(filepath="model.h5",verbose=0,save_best_only=True)
#earlystopping = EarlyStopping(monitor='val_loss', patience=5, verbose=0) # 'patience' number of not improving epochs
 
history = autoencoder.fit(X_trainNorm, X_trainNorm,epochs=nb_epoch, batch_size=batch_size,shuffle=True,
                    verbose=1).history

查看损失变化

plt.plot(history['loss'])
#plt.plot(history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper right');

基本2轮就收敛了。

用解码器进行预测

testPredictions = autoencoder.predict(X_trainNorm)
X_trainNorm.shape,testPredictions.shape

可以看到数据还原回来了

我们取出P这一列,然后计算误差

testMSE = mean_squared_error(X_trainNorm.transpose(), testPredictions.transpose(), multioutput='raw_values')
error_df = pd.DataFrame({'reconstruction_error': testMSE,'true_value': data1['P']})
print(error_df.shape)
error_df.head()

画个直方图看看:

error_df['reconstruction_error'].plot.hist()

可以看到误差基本都是0附近,但是存一些极大值,

我们用97.5%作为分位点,以此作为是不是异常值的阈值判断

threshold = error_df.reconstruction_error.quantile(q=0.975)
threshold

大于这个阈值就是异常值,小于就是正常值。查看计算出来的异常值和正常值的数量

mlp_label=np.where( error_df.reconstruction_error.to_numpy()>threshold,1,0)
error_df['pred_class']=mlp_label
error_df['pred_class'].value_counts()

异常值2.6k,正常值1w,差不多是这个比例。

画个图直观看看

groups = error_df.groupby('pred_class')
fig, ax = plt.subplots(figsize=(10,3),dpi=128)
for name, group in groups:
    if name == 1:
        MarkerSize = 3 ; Color = 'orangered' ; Label = 'Fraud' ; Marker = 'd'
    else:
        MarkerSize = 3 ; Color = 'b' ; Label = 'Normal' ; Marker = 'o'
        
    ax.plot(group.index, group.reconstruction_error, linestyle='',color=Color,label=Label,ms=MarkerSize,marker=Marker)
    
ax.hlines(threshold, ax.get_xlim()[0], ax.get_xlim()[1], colors="r", zorder=100, label='Threshold')
ax.legend(loc='upper left', bbox_to_anchor=(0.95, 1))
plt.title("Probabilities of fraud for different classes")
plt.ylabel("Reconstruction error")  ;   plt.xlabel("Data point index")
plt.show()

上面红色的,误差大的,就是异常值。

然后把这些异常点画在功率曲线上面

def plot_Abnormal(error_df,mode='Autoencoder'):
    plt.figure(figsize=(14, 4),dpi=128)
    plt.plot(error_df.index, error_df["true_value"], label='Power')
    # Plotting the pred_class scatter plot for points where pred_class is 1
    pred_class_1 = error_df[error_df["pred_class"] == 1]
    plt.scatter(pred_class_1.index, pred_class_1["true_value"], color='orange', label='Abnormal value')

    # Adding labels and legend
    plt.xlabel('Time')
    plt.ylabel('Power')
    plt.title(mode)
    plt.legend()
    plt.grid(True)
    plt.show()
plot_Abnormal(error_df,mode='Autoencoder')

 可以看到很多极大的点,或者是下面一些极小的点,都被判断为异常值。

计算一下误差指标MSE,MAE,方便等下模型对比。

def calculate_mse_mae(df):
    true_mean = df[df["pred_class"] == 0]["true_value"].mean()
    pred_class_1 = df[df["pred_class"] == 1]["true_value"]
    
    if pred_class_1.empty:
        mse = np.nan
        mae = np.nan
    else:
        mse = np.mean((pred_class_1 - true_mean) ** 2)
        mae = np.mean(np.abs(pred_class_1 - true_mean))
    
    return mse, mae

# Calculate MSE and MAE for the given DataFrame
df_eval_all=pd.DataFrame(columns=['MSE','MAE'])
df_eval_all.loc['Autoencoder',:]=calculate_mse_mae(error_df)


支持数据描述

支持数据描述,Support Vector Data Description,SVMD,就是支持向量机的无监督版:

直接用sklearn就行

svmd = OneClassSVM(nu=0.025, kernel="rbf", gamma=0.1)
# Fit the SVM model only on normal data (X_normal)
svmd.fit(X_trainNorm)  # Ensure to use scaled normal data
y_pred = svmd.predict(X_trainNorm)
print(y_pred.shape)
pd.Series(y_pred).value_counts()

差不多也是这个比例

画图查看

error_df = pd.DataFrame({'true_value': data1['P']})
error_df['pred_class']=pd.Series(y_pred).map({1:0,-1:1}).to_numpy()
plot_Abnormal(error_df,mode='SVMD')

 可以看到 和自编码器一样,很多极大的点,或者是下面一些极小的点,都被判断为异常值。

计算误差指标

df_eval_all.loc['SVMD',:]=calculate_mse_mae(error_df)


孤立深林

孤立深林 Isolation Forest,也是机器学习模型的无监督版

进行异常值监测

iso_forest = IsolationForest(contamination=0.025)
iso_forest.fit(X_trainNorm)  #X_normal_scaled
y_pred_iso = iso_forest.predict(X_trainNorm)
pd.Series(y_pred_iso).value_counts()

异常值和正常值差不多也是这个比例

画图

error_df = pd.DataFrame({'true_value': data1['P']})
error_df['pred_class']=pd.Series(y_pred_iso).map({1:0,-1:1}).to_numpy()
plot_Abnormal(error_df,mode='IF')

  可以看到 和前面方法一样,很多极大的点,都被判断为异常值。

但是孤立森林明显下面极小的点没有太多异常值。

计算误差指标

df_eval_all.loc['IF',:]=calculate_mse_mae(error_df)


评价指标对比

df_eval_all

可视化

bar_width = 0.4
colors=['tomato','springgreen','skyblue','gold']
fig, ax = plt.subplots(1,2,figsize=(6,3))
for i,col in enumerate(df_eval_all.columns):
    n=int(str('12')+str(i+1))
    plt.subplot(n)
    df_col=df_eval_all[col]
    m =np.arange(len(df_col))
    
    #hatch=['-','/','+','x'],
    plt.bar(x=m,height=df_col.to_numpy(),width=bar_width,color=colors)
    
    #plt.xlabel('Methods',fontsize=12)
    names=df_col.index
    plt.xticks(range(0, 3),names,fontsize=11)
    plt.ylabel(col,fontsize=11)
plt.tight_layout()
#plt.savefig('柱状图.jpg',dpi=512)
plt.show()

可以看到,自编码器效果好于SVMD好于孤立森林。

因为数据量大,深度学习的方法还是好一些。

本次就演示了3中异常值监测的方法,时间序列都可以套用,更多的异常值监测的模型可以参考我之前的文章。
 


创作不易,看官觉得写得还不错的话点个关注和赞吧,本人会持续更新python数据分析领域的代码文章~(需要定制类似的代码可私信)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/678887.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用API有效率地管理Dynadot域名,使用API创建文件夹管理域名

关于Dynadot Dynadot是通过ICANN认证的域名注册商,自2002年成立以来,服务于全球108个国家和地区的客户,为数以万计的客户提供简洁,优惠,安全的域名注册以及管理服务。 Dynadot平台操作教程索引(包括域名邮…

contenteditable实现插入标签的输入框功能(Vue3版)

需求:实现一个简易的函数编辑器 点击参数能够往输入框插入标签点击函数能够往输入框插入文本删除能够把标签整体删除输入的参数能够获取到其携带的信息 插入文本 /*** description 点击函数展示到输入框*/ const getValue ({ item, type }: any) > {// 创建…

计算机网络之crc循环冗余校验、子网划分、rip协议路由转发表、时延计算、香浓定理 奈氏准则、TCP超时重传 RTO

crc循环冗余校验 异或运算 : 相同得0,相异得1 从多项式获取除数 在原数据的末端补0 , 0的个数等于最高次项的阶数 如果最后结果的有效位数较少时,前面应该补0,补到个数与阶位相同 子网划分 子网掩码:用于识别IP地址中的网络号和主机号的…

MySQL数据库整体知识点简述

目录 第一章:数据库系统概述 第二章:信息与数据模型 第3章 关系模型与关系规范化理论 第四章——数据库设计方法 第六-七章——MySQL存储引擎与数据库操作管理 第九章——索引 第10章——视图 第11章——MySQL存储过程与函数 第12章——MySQL 触…

深度解析:ISP代理与住宅代理区别

代理充当用户和互联网之间的中介,提供各种功能以增强安全性、隐私性和可访问性。在众多代理类型中,ISP 和住宅代理脱颖而出,每种代理都具有独特的功能和应用。 了解 ISP 代理 代理ISP,通常称为互联网服务提供商代理,通…

打造高效问答系统:合合信息文档解析工具的应用与实践

官.网地址:合合TextIn - 合合信息旗下OCR云服务产品 LLM(大型语言模型)的应用落地正快速推动着各行各业工作模式的革新。根据埃森哲在2023年发布的研究报告,预计全行业中有40%的工作时间将得到大语言模型的支持与协助。通过引入A…

23种模式之一— — — —适配器模式的详细介绍与讲解

适配器介绍与讲解 一、概念二、适配器模式结构适配器分类核心思想核心角色模式的UML类图应用场景模式优点模式缺点 实例演示图示代码演示运行结果 一、概念 适配器模式(别名:包装器) 是一种结构型设计模式 将一个类的接口转换成客户希望的另…

存内计算与扩散模型:下一代视觉AIGC能力提升的关键

目录 前言 视觉AIGC的ChatGPT4.0时代 扩散模型的算力“饥渴症” 存内计算解救算力“饥渴症” 结语 前言 ​ 在这个AI技术日新月异的时代,我们正见证着前所未有的创新与变革。尤其是在视觉内容生成领域(AIGC,Artificial Intelligence Generate…

家政预约小程序12用户登录

目录 1 创建全局变量2 创建页面3 搭建页面4 实现登录逻辑总结 在小程序中,登录是一个常见的场景。比如我们在小程序预约或者购买时,通常要求用户先登录后购买。如果使用传统方案,登录这个动作其实最终的目的是为了获取用户的openid。而使用低…

如何理解与学习数学分析——第一部分——数学分析概观

第1 部分:数学分析概观(Studying Analysis) 1. 数学分析之面目(What is Analysis like?) 本章说明了分析中的定义、定理和证明。 它介绍了一些符号,并解释了如何使用数学分析中的这些数学符号和数学词汇、以及应该把它们读成什么。它指出了这种类型的…

【通俗易懂搞算法】一篇文章弄懂Manacher算法

Manacher算法 manacher算法解决的问题回文 最长回文子串最长回文子串解法解法1.0解法2.0Manacher算法回文半径、回文直径回文半径数组之前扩的所有位置中所到达的最右回文右边界(R)取得更远边界的中心点的位置(C)Manacher算法优化情形Manacher算法优化情形总结 manacher算法代码…

PySpark特征工程(I)--数据预处理

有这么一句话在业界广泛流传:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功的关键。 特征工程是数据分析…

工业网关有效解决企业在数据采集、传输和整合方面的痛点问题-天拓四方

一、企业背景概述 随着信息技术的飞速发展,工业互联网已成为推动制造业转型升级的关键力量。在众多工业企业中,某公司凭借其深厚的技术积淀和广阔的市场布局,成为行业内的佼佼者。然而,在数字化转型的道路上,该公司也…

Java中getBytes()方法

我以为旅人将我 热情都燃尽 —— 24.6.4 String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示 而与getBytes相对的,可以通过new String(byte[], decode)的方式来还原这个“深”字时,这个new String(byte[],…

【UML用户指南】-07-对基本结构建模-公共机制

目录 1、术语和概念 1.1、注解(note) 1.2、修饰 1.3、衍型 1.4、标记值 1.5、约束 1.6、标准元素 1.7、外廓(profile) 2、对新特性建模 3、对新语义建模 注解 (note)是附加在元素或元素集上用来表…

EcoVadis审核方法是什么符合EcoVadis规范的文件清单

EcoVadis审核方法是参照全球契约社会责任国际标准进行,包括环境、劳工及人权、商业道德、可持续采购等四大主题又分:能源消耗及温室气体排放、水环境管理、生态环境与物种多样性保护、局部环境污染、原材料及化学品使用(含废弃物)、产品使用、产品生命末期、消费者健…

控制应优先

先从大体上的去找规律,然后才是数字归纳(更为详细的),同时控制关系应该优先(这里是天数和位置)。是否涉及所有对象不是广泛,如果是具体的数值就不是广泛。

天润融通携手好丽友,打造食品零售行业智能客服新标杆

AI大模型,如何给食品零售行业的客服服务带来质变? 在很多人印象中,食品零售行业是不需要客户服务的。 因为绝大多数食品都是通过经销商、零售商、商场这样的渠道进行销售。所以在食品零售行业,一直都有一句话,叫“渠…

贝加莱工控机维修5PC810.SX01-00 APC810系列

工控机维修常见故障:工控机无显示、自检不过、死机、触摸不灵、按键无法操作、与PLC通讯不上驱动器报过流过载、电压高、编码器错误 等。 PLC有输入无输出、报错等工控机维修常见故障现象 。 贝加莱工控机维修常见故障排查: 电源灯亮但工控机没有反应: …

ChatTTS:对话式文本转语音模型,开源啦!突破开源语音天花板...

最近,一个名为 ChatTTS 文本转语音项目爆火出圈,短短三天时间,在 GitHub 上已经斩获了 9.2 k 的 Star 量。 ChatTTS:对话式文本转语音模型 项目地址:https://github.com/2noise/ChatTTS/tree/main 体验地址&#xff1a…