时间序列异常值检测方法

文章目录

  • 一、基于统计的方法
    • 1.1、标准差
    • 1.2、箱线图
    • 1.3、Z-Score法
  • 二、基于机器学习算法的方法
    • 2.1、K-NN
    • 2.2、孤立森林
  • 三、基于密度的方法
    • 3.1、LOF
    • 3.2、DBSCAN密度聚类

时间序列相关参考文章:
时间序列预测算法—ARIMA
时间序列预测算法—Prophet
时间序列分类任务—tsfresh
python时间序列处理
有季节效应的非平稳序列分析
时间序列异常值检测方法
时间序列异常值处理方法

一、基于统计的方法

1.1、标准差

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.rcParams['font.sans-serif'] = ['SimHei']  # 黑体
plt.rcParams['axes.unicode_minus'] = False    # 负号正常显示

data = pd.read_excel('data.xlsx')
mean = data['电量'].mean()
std_dev = data['电量'].std()
num_std_dev = 2
outliers = data[np.abs(data['电量'] - mean) > num_std_dev * std_dev]

plt.figure(figsize=(10, 6))
plt.plot(data.date,data['电量'], label='Forecast Data', color='blue', alpha=0.7)
plt.scatter(outliers.date, outliers['电量'], color='red', label='Outliers')
plt.axhline(mean, color='green', linestyle='--', label='Mean')
plt.axhline(mean + num_std_dev * std_dev, color='orange', linestyle='--', label='Upper Bound')
plt.axhline(mean - num_std_dev * std_dev, color='orange', linestyle='--', label='Lower Bound')
 
plt.title('用电量异常值检测', fontsize=15)
plt.xlabel('日期', fontsize=12)
plt.ylabel('电量', fontsize=12)
plt.legend()
plt.grid(True)
plt.show()

在这里插入图片描述

1.2、箱线图

计算步骤:
Q1(上四分位数):数据集中所有数值由小到大排列后,位于25%位置的数值。
Q3(下四分位数):数据集中所有数值由小到大排列后,位于75%位置的数值。
计算四分位距(IQR):IQR = Q3 - Q1
确定异常值范围:

  • 上界= Q3 + 1.5 * IQR
  • 下界= Q1 - 1.5 * IQR
    判断异常值:低于下界或高于上界的数值。
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    # 负号正常显示
 
data = pd.read_excel('data.xlsx')
 
# 计算异常值
Q1 = data['电量'].quantile(0.25)
Q3 = data['电量'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR #下四分位数
upper_bound = Q3 + 1.5 * IQR #上四分位数
 
# 标识异常值
data['Outlier'] = ((data['电量'] < lower_bound) | (data['电量'] > upper_bound))
outliers = data[data['Outlier']]  # 标注异常值

#可视化
plt.figure(figsize=(12, 6))
sns.lineplot(data=data, x=data.date, y='电量', label='电量', color='blue')
plt.scatter(outliers.date, outliers['电量'], color='red', label='outlier')
 
plt.title('箱体图异常值检测', fontsize=15)
plt.xlabel('date', fontsize=12)
plt.ylabel('电量', fontsize=12)
plt.legend()
plt.show()

在这里插入图片描述

1.3、Z-Score法

  Z-Score(标准分数)是一种衡量数据点相对于其总体或样本平均值的偏离程度的统计方法。它表示数据点与均值之间的差异,并以标准差为单位来衡量。Z-Score的计算公式如下:
在这里插入图片描述

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats

data = pd.read_excel('data.xlsx')
# 如果Z-Score大于3或小于-3,通常被认为是异常值
data['Z_Score'] = stats.zscore(data['电量'])
 
# 定义离群点
data['Outlier_Z'] = data['Z_Score'].abs() > 3
plt.figure(figsize=(12, 6))

# 绘制forecast值的折线图
sns.lineplot(data=data, x=data.date, y='电量', label='电量', color='blue')
 
# 标注离群点
outliers = data[data['Outlier_Z']]
plt.scatter(outliers.date, outliers['电量'], color='red', label='Outliers (Z > 3)')
 
plt.title('Z-Score 异常值检测', fontsize=15)
plt.xlabel('date', fontsize=12)
plt.ylabel('电量', fontsize=12)
plt.legend()
plt.show()

在这里插入图片描述

二、基于机器学习算法的方法

2.1、K-NN

  k近邻算法的思想可参考之前的文章:K近邻算法

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.neighbors import NearestNeighbors
import seaborn as sns


data = pd.read_excel('data.xlsx')

# data['date'] = pd.to_datetime(data['date'])
data = data.sort_values(by='date')

n_neighbors = 5  # 设置 K 值
knn_smaller = NearestNeighbors(n_neighbors=n_neighbors)
knn_smaller.fit(data[['电量']])

distances_smaller, _ = knn_smaller.kneighbors(data[['电量']]) # 计算每个点到其邻居的距离
mean_distance_smaller = np.mean(distances_smaller, axis=1) # 计算每个点到其邻居的平均距离

# 计算距离的平均值和标准差
mean_distance_mean = np.mean(mean_distance_smaller)
mean_distance_std = np.std(mean_distance_smaller)

# 离群点检测:使用均值和标准差,判断大于某个阈值的数据为离群点
outlier_threshold = mean_distance_mean + 2 * mean_distance_std  # 使用2倍标准差作为阈值
outlier_indices_smaller = np.where(mean_distance_smaller > outlier_threshold)[0]

# 在数据框中标记离群点
data['Outlier_KNN'] = False
data.loc[outlier_indices_smaller, 'Outlier_KNN'] = True

# 绘制图表
plt.figure(figsize=(12, 6))
sns.lineplot(data=data, x='date', y='电量', label='电量', color='blue') # 绘制电量的折线图

# 标注离群点
outliers_knn_smaller = data[data['Outlier_KNN']]
plt.scatter(outliers_knn_smaller['date'], outliers_knn_smaller['电量'], color='red', label='Outliers (KNN, Smaller K)')

# 设置标题和标签
plt.title('K近邻异常检测', fontsize=15, fontweight='bold')
plt.xlabel('date', fontsize=12)
plt.ylabel('电量', fontsize=12)
plt.legend()
plt.show()

在这里插入图片描述

2.2、孤立森林

  孤立森林算法的核心思想是通过随机分割数据将异常值孤立开来
  具体来说,孤立森林通过以下几步来识别异常值:
1、构建树结构:我们将数据看作一个“树”,而树的每一层都是通过随机选择一个特征(比如电压、功率等)并随机选择一个分割点来将数据分成两部分。这样,我们可以从根节点开始,逐层对数据进行分割,直到最终每个数据点都被“孤立”在一片区域中。
2、树的“深度”:每个数据点在被孤立时,所经历的分割次数(树的深度)是非常关键的。如果一个数据点在很多分割后才被孤立,那么这个数据点通常是“正常”的;相反,如果数据点很容易被孤立,即分割层数很少,那么它很可能是一个“异常值”。
3、构建多个树:为了提高算法的鲁棒性(即处理不同类型数据的能力),孤立森林并不是只构建一棵树,而是会构建多棵树(森林)。每棵树都是随机选择不同的特征和分割点来训练的。
4、异常值的判定:对于每个数据点,算法会计算它在森林中每棵树的“孤立深度”,然后将这些孤立深度综合起来,得出一个最终的“异常评分”。分数越低,说明这个点越容易被孤立,越有可能是异常值。
  举个例子:假设我们有一组学生的身高数据,正常的身高大多在150-180厘米之间,但有一个学生的身高是220厘米。孤立森林算法通过随机选择身高的某些范围来分割数据,发现大部分学生的身高在某个区域内分布很密集,而这个220厘米的学生会在很早的分割阶段就被孤立出来。于是,它就会被认为是一个异常值。

  • 高效:孤立森林只需要少量的数据即可进行训练,不像一些其他算法需要复杂的计算。
  • 适用于大数据:由于它基于树结构,处理大规模数据时表现很优秀。
  • 无需标签:孤立森林是无监督算法,不需要事先标注哪些是正常值,哪些是异常值。
from sklearn.ensemble import IsolationForest
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
 
new_data = pd.read_excel('data.xlsx')
# 设置孤立森林参数
iso_forest = IsolationForest(n_estimators=100, contamination='auto', random_state=42)  # 可调整参数
#n_estimators=100 是 Isolation Forest 算法中的一个超参数,它表示 森林中树的数量
#如果对数据的异常值比例有所了解,可以调整 contamination 参数。如:知道数据中大约有5%的异常值,可以设置 contamination=0.05,而不是使用 'auto'。
iso_labels = iso_forest.fit_predict(new_data[['电量']])  # 使用孤立森林模型
new_data['Outlier_IsolationForest'] = (iso_labels == -1) # 标记离群点(在孤立森林中,-1标签表示离群点)
 
plt.figure(figsize=(12, 6))
sns.lineplot(data=new_data, x=new_data.date, y='电量', label='电量', color='blue') # 绘制forecast值的折线图
 
# 标注离群点
outliers_iso_forest = new_data[new_data['Outlier_IsolationForest']]
plt.scatter(outliers_iso_forest.date, outliers_iso_forest['电量'], color='red', label='Outliers (Isolation Forest)')
 
# 设置标题和标签
plt.title('孤立森林异常值检测', fontsize=15, fontweight='bold')
plt.xlabel('date', fontsize=12)
plt.ylabel('电量', fontsize=12)
plt.legend()
plt.show()

  总结:孤立森林算法通过随机分割数据,尽可能早地将异常点孤立出来,最后根据这些点被孤立的深度来判断它们是否异常。它是一种简单、高效且适用于大数据的异常值检测方法。

三、基于密度的方法

3.1、LOF

  LOF(局部离群因子,Local Outlier Factor)是一种用于异常检测的算法,它的主要作用是帮助我们找到那些在数据中表现得很“不同”或“离群”的数据点。简单来说,LOF可以帮助我们识别出哪些数据点可能是错误的、特殊的或不常见的。
  LOF算法的思路:LOF算法通过局部密度来判断数据点是否异常。它的基本想法是:一个数据点如果和周围点比较“远”,而且密度较低,那么它就有可能是一个异常点。
LOF算法的工作过程可以分为以下几个步骤:
1、定义“密度”
  首先,LOF需要计算每个数据点的“局部密度”。局部密度表示该点的邻近区域内的点的分布情况。如果某个数据点周围的点很密集(例如很多点都聚集在一起),我们就说这个点的局部密度较高;反之,如果周围点很稀疏,局部密度就较低。
2、计算“可达距离”
  为了衡量一个数据点与它的邻居之间的距离,LOF引入了一个叫做“可达距离”的概念。可达距离不仅仅看两个点之间的直线距离,还考虑到该点周围邻居的密度。如果一个数据点的邻居非常密集,那么这个点到邻居的可达距离就比较短。这样,LOF算法就能在更“稠密”的区域找到异常点。
3、计算“局部离群因子”
  LOF的核心是计算每个点的“局部离群因子”(Local Outlier Factor)。LOF的值通过比较数据点的局部密度与其邻居的局部密度来得到。如果一个数据点的局部密度显著低于它的邻居的局部密度,那么它的LOF值就较高,说明它是一个异常点。反之,如果一个数据点的局部密度与邻居差不多,它的LOF值就接近1,说明它是正常的。

from sklearn.neighbors import LocalOutlierFactor
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    # 负号正常显示


new_data = pd.read_excel('data.xlsx')
lof = LocalOutlierFactor(n_neighbors=10)  # 可以调整n_neighbors的值,来调整对数据的敏感度
 
lof_labels = lof.fit_predict(new_data[['电量']]) # 使用LoF模型
lof_scores = -lof.negative_outlier_factor_  # LoF分数(负数,越小越异常)
 
new_data['Outlier_LoF'] = (lof_labels == -1) # 标记离群点

plt.figure(figsize=(12, 6))
sns.lineplot(data=new_data, x=new_data.date, y='电量', label='电量', color='blue')
 
outliers_lof = new_data[new_data['Outlier_LoF']] # 标注离群点
plt.scatter(outliers_lof.date, outliers_lof['电量'], color='red', label='Outliers (LoF)')
 
# 设置标题和标签
plt.title('LoF异常值检测', fontsize=15, fontweight='bold')
plt.xlabel('date', fontsize=12)
plt.ylabel('电量', fontsize=12)
plt.legend()
plt.show()

在这里插入图片描述
  LOF算法的优缺点:
优点:

  • 不依赖全局密度:LOF算法考虑的是局部密度,因此它能发现一些在全局层面上看不出来的异常点。
  • 适用于复杂数据:它特别适用于那些数据分布复杂、密度不均匀的场景。

缺点:

  • 计算复杂度高:LOF需要计算每个点与其他点的距离,尤其是数据量较大时,计算开销较高。
  • 参数选择敏感:LOF算法需要设置邻居数量(通常是K),如果K选择不合适,可能影响异常点检测的准确性。

3.2、DBSCAN密度聚类

  DBSCAN算法的思想可参考之前的文章:聚类算法
  eps(邻域半径)值决定了每个点的邻域范围。eps值过小,很多点无法找到足够的邻居,导致它们被判定为离群点。
  方法:可以通过可视化k-distance图来选择一个合理的eps值。k-distance图会显示每个点到其k个邻居的距离,通常选择k为min_samples值。例如,你可以计算每个点与其最近min_samples个点的距离,并绘制出图像,寻找距离急剧上升的点,这个点的距离对应的eps值是较好的选择。
  观察k-distance图的“拐点”,通常拐点处的距离值是eps的一个合适选取。

from sklearn.neighbors import NearestNeighbors
import numpy as np

# 计算k个邻居的距离
neighbors = NearestNeighbors(n_neighbors=20).fit(data[['电量']])
distances, indices = neighbors.kneighbors(data[['电量']])

# 排序并绘制k-distance图
distances = np.sort(distances[:, -1], axis=0)
plt.plot(distances)
plt.title('k-distance plot')
plt.xlabel('Data Points')
plt.ylabel('Distance')
plt.show()

在这里插入图片描述

import pandas as pd
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt
import seaborn as sns

# 读取数据
data = pd.read_excel('data.xlsx')
data = data.sort_values(by='date')

# 设置 DBSCAN 参数,eps 和 min_samples 根据实际数据可能需要调整
dbscan = DBSCAN(eps=500, min_samples=5)
dbscan_labels = dbscan.fit_predict(data[['电量']]) # 使用 DBSCAN 模型进行拟合和预测

# 标记离群点(DBSCAN 中,-1 标签表示离群点)
data['Outlier_DBSCAN'] = (dbscan_labels == -1)

plt.figure(figsize=(12, 6))
sns.lineplot(data=data, x='date', y='电量', label='电量', color='blue')

outliers_dbscan = data[data['Outlier_DBSCAN']] # 标注离群点
plt.scatter(outliers_dbscan['date'], outliers_dbscan['电量'], color='red', label='Outliers (DBSCAN)', zorder=5)

# 设置标题和标签
plt.title('DBSCAN算法异常检测', fontsize=15, fontweight='bold')
plt.xlabel('时间', fontsize=12)
plt.ylabel('电量', fontsize=12)
plt.legend()
plt.show()

在这里插入图片描述

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

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

相关文章

8K+Red+Raw+ProRes422分享5个影视级视频素材网站

Hello&#xff0c;大家好&#xff0c;我是后期圈&#xff01; 在视频创作中&#xff0c;电影级的视频素材能够为作品增添专业质感&#xff0c;让画面更具冲击力。无论是广告、电影短片&#xff0c;还是品牌宣传&#xff0c;高质量的视频素材都是不可或缺的资源。然而&#xff…

顺序表的操作

注意位序和数组下标的关系 插入&#xff1a; 插入的时间复杂度&#xff1a; 最深层语句&#xff1a; 最好情况 最坏情况 平均情况 删除&#xff1a; 查找&#xff1a;

五、windows上vscode构建c/c++环境

1、安装vscode 官网下载界面&#xff1a;https://code.visualstudio.com/Download 请根据电脑系统安装所需版本点击下载链接&#xff08;一般情况下点击windows按钮即可&#xff09;鼠标左键双击&#xff0c;即可运行安装程序&#xff0c;点击【确认】&#xff1b;选择安装路径…

Spring实例化的基本流程和Bean处理器

目录 Spring实例化的基本流程 Bean的处理器 Bean工厂后处理器&#xff08;BeanFactoryPostProcessor&#xff09; 动态注册beanDefinition Bean后处理器&#xff08;BeanPostProcessor&#xff09; Spring实例化的基本流程 在了解处理器之前&#xff0c;要清除spring实例化…

【SH】Ubuntu Server 24搭建Web服务器访问Python程序研发笔记

文章目录 说个问题写个方案一、安装Ubuntu Server二、安装Web服务器采用Nginx服务器 三、安装Python及依赖创建项目虚拟环境 四、安装Python Web框架采用Flask框架创建和运行Flask应用&#xff08;以后的重点&#xff09; 五、安装WSGI服务器采用Gunicorn 六、配置Nginx七、验证…

109.【C语言】数据结构之求二叉树的高度

目录 1.知识回顾&#xff1a;高度&#xff08;也称深度&#xff09; 2.分析 设计代码框架 返回左右子树高度较大的那个的写法一:if语句 返回左右子树高度较大的那个的写法二:三目操作符 3.代码 4.反思 问题 出问题的代码 改进后的代码 执行结果 1.知识回顾&#xf…

瑞吉外卖项目学习笔记(二)Swagger、logback、表单校验和参数打印功能的实现

瑞吉外卖项目学习笔记(一)准备工作、员工登录功能实现 文章目录 3 项目组件优化3.1 实现Swagger文档输出3.2 实现logback日志打印3.3 实现表单校验功能3.4 实现请求参数和响应参数的打印 3 项目组件优化 3.1 实现Swagger文档输出 1&#xff09;在application.yml中增加knife4…

OpenEuler 22.03 安装 flink-1.17.2 集群

零&#xff1a;规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器&#xff0c;用于搭建 flink 集群。这里使用flink1.17.2 的原因&#xff0c;是便于后续与springboot的整合 服务器名IP地址作用其他应用flink01192.168.159.133主jdk11、flink-1.17.2flink02192.168.…

[数据结构] 链表

目录 1.链表的基本概念 2.链表的实现 -- 节点的构造和链接 节点如何构造? 如何将链表关联起来? 3.链表的方法(功能) 1).display() -- 链表的遍历 2).size() -- 求链表的长度 3).addFirst(int val) -- 头插法 4).addLast(int val) -- 尾插法 5).addIndex -- 在任意位置…

20241220在荣品开发板PRO-RK3566的buildroot下适配gc2093

20241220在荣品开发板PRO-RK3566的buildroot下适配gc2093 2024/12/20 16:00 余顺?PRO-RK3566开发板 挂 gc2093模块。刷 buildroot的预编译固件。 update-pro-rk3566-buildroot-hdmi-20231130-034633.img 1、现在发现 qcamera的 拍照Capture、Record录像模式都是640x480分辨率…

实习冲刺数据库练习-01 基础查询

原题链接&#xff1a;牛客网在线编程_SQL篇_非技术快速入门 数据表示例&#xff1a; 根据数据表示例要求我们完成以下查询&#xff1a; &#xff08;1&#xff09;获取用户信息表中所有的数据&#xff0c;请你取出相应结果 &#xff08;2&#xff09;获取用户的设备id对应的…

【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换

相关链接&#xff1a; http://mars3d.cn/editor-vue.html?keyex_1_2_1&idmap/other/backgroundImg 实现代码&#xff1a; export function show1() {map.setOptions({scene: {backgroundType: "image",backgroundImage: "url(//data.mars3d.cn/img/busin…

telnet命令检查端口

1、简介 telnet是一种用于远程登录的协议&#xff0c;可以通过telnet客户端连接到远程主机&#xff0c;并在远程主机上执行命令。 2、使用telnet命令检查端口 2.1 进入linux终端 2.2 输入telnet命令 如果没有安装telnet命令&#xff0c;请执行以下命令安装 sudo yum install…

Unity 根据文本宽度自动移动图像位置

游戏中有时候需要变动的显示一个物品的数量&#xff0c;变化的文本宽度不停的变化&#xff0c;这时候需要将物品的icon随着文本的长度而改变位置。 实现思路&#xff1a;使用Content Size Fitter来动态改变内容的大小。 首先建立一个文本组件&#xff0c;添加Content Size Fi…

基于Springboot人口老龄化社区服务与管理平台【附源码】

基于Springboot人口老龄化社区服务与管理平台 效果如下&#xff1a; 系统登陆页面 系统主页面 社区信息页面 社区文件页面 活动报名页面 走访任务管理页面 社区资讯页面 老人信息管理页面 研究背景 随着社会老龄化的加剧&#xff0c;老年人口比例逐渐增加&#xff0c;对老年…

加密数据库在现代企业中的应用实践

以下是对加密数据库在现代企业中的应用实践的详细阐述&#xff1a; 一、加密数据库的应用背景 随着信息技术的飞速发展&#xff0c;现代企业对于数据的安全性和隐私保护要求越来越高。数据库作为存储大量敏感信息的关键设施&#xff0c;其安全性直接关系到企业的商业利益和声誉…

安卓环境配置及打开新项目教程,2024年12月20日最新版

1.去官网下载最新的Android Studio&#xff0c;网址&#xff1a;https://developer.android.com/studio?hlzh-cn 2.下载加速器&#xff0c;注册账号&#xff0c;开启加速器。网址&#xff1a;放在文末。 3.下载安卓代码&#xff0c;项目的路径上不能有中文&#xff0c;特别是…

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕 2024/12/17 17:21 缘起&#xff0c;最近需要识别法国电影《地下铁》的法语字幕&#xff0c;使用 字幕小工具V1.2【whisper套壳/GUI封装了】 无效。 那就是直接使用最原始的whisper来干了。 当你重装WIN10的时候&#…

sqlite3 支持位运算 和view和 triger

数据设置条件以后可以.根据门限自动调整其他的值 由数据库记录修改时间,及记录-> 网元设备的告警产生时间,设置超时清除时间,记录系统的原始时间戳 CPp 有 sqlite 支持 json 导出字符串,json 库将字符串,映射为结构体 triger update table 更新到一个 可设置参数列表 ,view …

11-C语言结构体(下篇)

一、结构体指针变量 结构体指针变量&#xff1a;本质上是一个指针变量&#xff0c;保存的是结构体变量的地址。 1.结构体变量的地址 结构体变量的地址&#xff1a;对结构体变量名取地址。 代码演示 typedef struct stu {char name[32];int age;float score; }STU;int main…