宣布 PyCaret 1.0.0
Python 中一个开源的低代码机器学习库。
我们很兴奋地宣布 PyCaret ,这是一个用 Python 编写的开源机器学习库,用于在低代码环境中训练和部署有监督和无监督的机器学习模型。PyCaret 允许您从选择笔记本电脑环境开始,在几秒钟内从准备数据到部署模型。
与其他开源机器学习库相比,PyCaret 是一个替代的低代码库,可以用来替换数百行代码,只需要几个单词。这使得实验快速有效。PyCaret 本质上是几个机器学习库和框架的 Python 包装器,比如 scikit-learn 、 XGBoost 、 Microsoft LightGBM 、 spaCy 等等。
py caret简单 好用。PyCaret 中执行的所有操作都顺序存储在一个完全为部署编排的管道**中。**无论是输入缺失值、转换分类数据、特征工程还是超参数调整,PyCaret 都能实现自动化。要了解 PyCaret 的更多信息,请观看这段 1 分钟的视频。
PyCaret 1.0.0 发布 Python 中的开源低代码机器学习库
PyCaret 入门
PyCaret 版本 1.0.0 的第一个稳定版本可以使用 pip 安装。使用命令行界面或笔记本环境,运行下面的代码单元来安装 PyCaret。
pip install pycaret
如果你使用的是 Azure 笔记本或 Google Colab ,运行下面的代码单元来安装 PyCaret。
!pip install pycaret
安装 PyCaret 时,所有依赖项都会自动安装。点击此处查看完整的依赖关系列表。
没有比这更容易的了👇
📘循序渐进的教程
1.获取数据
在本分步指南中,我们将使用**“糖尿病”**数据集,目标是根据血压、胰岛素水平、年龄等几个因素预测患者结果(二进制 1 或 0)。数据集可以在 PyCaret 的 github 库上获得。直接从存储库中导入数据集的最简单方法是使用 pycaret.datasets 模块中的 get_data 函数。
from **pycaret.datasets** import **get_data**
diabetes = **get_data**('diabetes')
get_data 的输出
💡PyCaret 可以直接处理 pandas dataframe。
2.设置环境
PyCaret 中任何机器学习实验的第一步都是通过导入所需的模块并初始化 setup ()来设置环境。本例中使用的模块是py caret . class ification。
模块导入后, setup() 通过定义数据帧(【糖尿病】)和目标变量(【类变量】)进行初始化。
from **pycaret.classification** import ***** exp1 = **setup**(diabetes, target = 'Class variable')
所有预处理步骤都在设置()中应用。py caret 有超过 20 个特征为机器学习准备数据,它根据设置功能中定义的参数创建一个转换管道。它会自动编排一个管道中的所有依赖项,这样您就不必手动管理测试或不可见数据集上转换的顺序执行。PyCaret 的管道可以轻松地跨环境传输,以便大规模运行或轻松部署到生产中。下面是 PyCaret 第一次发布时提供的预处理特性。
PyCaret 的预处理功能
💡初始化 setup()时,会自动执行机器学习必需的数据预处理步骤,例如缺失值插补、分类变量编码、标签编码(将是或否转换为 1 或 0)以及训练-测试-分割。点击这里了解更多关于 PyCaret 的预处理能力。
3.比较模型
这是监督机器学习实验中推荐的第一步(分类或回归)。此函数训练模型库中的所有模型,并使用 k 倍交叉验证(默认为 10 倍)比较常用评估指标。使用的评估指标包括:
- **用于分类:**准确度、AUC、召回率、精确度、F1、Kappa
- 用于回归: MAE,MSE,RMSE,R2,RMSLE,MAPE
**compare_models**()
compare_models()函数的输出
💡默认情况下,使用 10 重交叉验证来评估指标。可以通过改变 折叠 参数的值来改变。
💡默认情况下,表格按“精确度”(从高到低)值排序。可以通过改变 排序 参数的值来改变。
4.创建模型
在 PyCaret 的任何模块中创建一个模型就像编写 **create_model 一样简单。**它只有一个参数,即作为字符串输入传递的型号名称。该函数返回一个表,其中包含 k 倍交叉验证的分数和一个训练好的模型对象。
adaboost = **create_model**('ada')
变量“adaboost”存储由 create_model 函数返回的训练模型对象,它是一个 scikit-learn 估计器。被训练对象的原始属性可以通过使用*句点( .)*复变。参见下面的例子。
训练模型对象的属性
💡PyCaret 拥有超过 60 种开源的现成算法。点击这里查看 PyCaret 中可用的评估者/模型的完整列表。
5.调整模型
tune_model 函数用于自动调整机器学习模型的超参数。 PyCaret 在预定义的搜索空间内使用随机网格搜索。该函数返回一个表,其中包含 k 倍交叉验证的分数和一个训练好的模型对象。
tuned_adaboost = tune_model('ada')
💡无监督模块 pycaret.nlp 、 pycaret.clustering 和 pycaret.anomaly 中的 tune_model 函数可以与有监督模块配合使用。例如,PyCaret 的 NLP 模块可用于调整主题数量参数,方法是评估监督 ML 模型的目标/成本函数,如“准确度”或“R2”。
6.集合模型
ensemble_model 函数用于集合训练好的模型**。**它只需要一个参数,即一个训练好的模型对象。这个函数返回一个表,其中包含 k 倍交叉验证的分数和一个训练好的模型对象。
# creating a decision tree model
dt = **create_model**('dt')# ensembling a trained dt model
dt_bagged = **ensemble_model**(dt)
💡默认情况下,集合使用“Bagging”方法,可以通过使用 ensemble_model 函数中的 方法 参数将其更改为“Boosting”。
💡PyCaret 还提供了 blend_models 和 stack_models 功能来集成多个训练模型。
7.绘图模型
可以使用 plot_model 函数对经过训练的机器学习模型进行性能评估和诊断。它在 plot_model 函数中将一个训练好的模型对象和绘图类型作为字符串输入。
# create a model
adaboost = **create_model**('ada')# AUC plot
**plot_model**(adaboost, plot = 'auc')# Decision Boundary
**plot_model**(adaboost, plot = 'boundary')# Precision Recall Curve
**plot_model**(adaboost, plot = 'pr')# Validation Curve
**plot_model**(adaboost, plot = 'vc')
单击此处了解 PyCaret 中不同可视化的更多信息。
或者,您可以使用 evaluate_model 函数,通过笔记本内的用户界面查看图*。*
**evaluate_model**(adaboost)
💡py caret . NLP模块中的 plot_model 函数可以用来可视化文本语料库和语义主题模型。点击这里了解更多信息。
8.解释模型
当数据中的关系是非线性的时,这在现实生活中是常见的情况,我们总是看到基于树的模型比简单的高斯模型做得更好。然而,这是以失去可解释性为代价的,因为基于树的模型不像线性模型那样提供简单的系数。PyCaret 使用 interpret_model 函数实现SHAP(SHapley Additive exPlanations)。
# create a model
xgboost = **create_model**('xgboost')# summary plot
**interpret_model**(xgboost)# correlation plot
**interpret_model**(xgboost, plot = 'correlation')
测试数据集中特定数据点(也称为原因参数)的解释可使用“原因”图进行评估。在下面的例子中,我们检查测试数据集中的第一个实例。
**interpret_model**(xgboost, plot = 'reason', observation = 0)
9.预测模型
到目前为止,我们看到的结果仅基于训练数据集的 k-fold 交叉验证(默认为 70%)。为了在测试/保留数据集上查看模型的预测和性能,使用了 predict_model 函数。
# create a model
rf = **create_model**('rf')# predict test / hold-out dataset
rf_holdout_pred **= predict_model**(rf)
predict_model 函数也用于预测未知数据集。现在,我们将使用我们用于训练的相同数据集作为新的看不见的数据集的代理。在实践中, predict_model 函数将被迭代使用,每次使用一个新的看不见的数据集。
predictions = **predict_model**(rf, data = diabetes)
💡predict_model 函数还可以预测使用 stack_models 和 create_stacknet 函数创建的一系列模型。
💡predict_model 函数也可以使用 deploy_model 函数直接从 AWS S3 上托管的模型进行预测。
10.部署模型
利用已定型模型对未知数据集生成预测的一种方法是,在模型已定型的笔记本/ IDE 中使用 predict_model 函数。然而,对未知数据集进行预测是一个迭代过程;根据使用情况,进行预测的频率可以从实时预测到批量预测。PyCaret 的 deploy_model 函数允许从笔记本环境部署整个管道,包括云上的训练模型。
**deploy_model**(model = rf, model_name = 'rf_aws', platform = 'aws',
authentication = {'bucket' : 'pycaret-test'})
11.保存模型/保存实验
一旦训练完成,包含所有预处理转换和训练的模型对象的整个管道可以保存为二进制 pickle 文件。
# creating model
adaboost = **create_model**('ada')# saving model **save_model**(adaboost, model_name = 'ada_for_deployment')
您还可以将包含所有中间输出的整个实验保存为一个二进制文件。
**save_experiment**(experiment_name = 'my_first_experiment')
💡您可以使用 PyCaret 所有模块中可用的 load_model 和 load_experiment 函数加载已保存的模型和已保存的实验。
12.下一个教程
在下一个教程中,我们将展示如何在 Power BI 中使用经过训练的机器学习模型,以在真实的生产环境中生成批量预测。
请参见我们的初级笔记本,了解这些模块:
开发管道中有什么?
我们正在积极改进 PyCaret。我们未来的开发管道包括一个新的时间序列预测模块,与 TensorFlow 的集成,以及对 PyCaret 可扩展性的重大改进。如果您想分享您的反馈并帮助我们进一步改进,您可以在网站上填写此表格,或者在我们的 GitHub 或 LinkedIn 页面上发表评论。
想了解某个特定模块?
从第一个版本 1.0.0 开始,PyCaret 有以下模块可供使用。单击下面的链接查看文档和工作示例。
重要链接
用户指南/文档
Github 资源库
安装 PyCaret
笔记本教程
贡献于 PyCaret
如果你喜欢 PyCaret,给我们 github 回购⭐️。
想了解更多关于 PyCaret 的信息,请在 LinkedIn 和 Youtube 上关注我们。
生物传感器数据中的异常检测和校正
机器学习|信号处理|可穿戴技术
Owen r . Bidder-Insight 健康数据科学研究员
目前监测血压的方法是有缺陷的
三分之一的美国成年人患有高血压,即高血压。高血压会增加心脏病发作和中风的风险,而心脏病和中风本身就是美国的主要死亡原因。仅在 2017 年,美国就有超过 50 万例死亡病例将高血压列为加重因素,美国疾病预防控制中心估计,高血压每年在医疗保健成本、处方药和因误工和病假导致的生产力损失方面给美国经济造成超过 559 亿美元的损失。不幸的是,高达 10%的患者还表现出“隐性”高血压,即在诊所通过袖带方法测量的血压明显低于患者日常生活时的血压。这种低估的后果可能是可怕的;不正确的预测或者更糟的是,完全漏诊。
显然,允许人们在诊所外监测血压的方法对于抗击这种“无声杀手”至关重要。然而,大多数当前的方法在某些方面是有缺陷的。在手术过程中,使用导管通过静脉监测血压,但这增加了感染的风险,因此几乎只在重症监护中使用。由于这个原因,它也不适合日常测量。基于袖带的血压测量是非侵入性的,因此感染的风险很小。然而,它们通常由训练有素的医疗保健专业人员在门诊期间进行管理,因此它们也不允许我们在患者的日常生活中监测他们的血压——这是我们之前确定的对捕捉隐性高血压病例至关重要的。
血压在一天中会有波动,所以看医生时的一次测量只能提供一个快照(鸣谢:omronhealthcare.com)
PyrAmes 通过其新颖的传感器设计解决了这一问题
在我担任 Insight 数据科学项目的健康数据科学研究员期间,我有机会为一家公司提供咨询,该公司试图解决现有血压监测方法的缺陷。PyrAmes 开发了一种放置在风险上的传感器,使其成为静脉监测的非侵入性替代方法。与基于袖带的方法不同,它还可以连续监测血压,使其成为手术和长期监测患者的理想解决方案。
PyrAmes 传感器的早期原型(左)和 4 个信号通道记录的数据示例(右)。
PyrAmes 面临的一个挑战是运动可能在信号数据中产生运动伪影。该传感器依靠身体压力的微小变化来监控动脉波形,由此可以将各种指标(峰值高度、宽度、曲线下面积)校准为平均动脉压(MAP),这是我们感兴趣的血压指标。受运动伪影影响的数据必须被识别并从分析中排除,但这意味着用户无法在体育活动中监测他们的血压。考虑到这一点,皮拉梅斯要求我考虑以下几点:
- 开发一个简单的异常检测模型,该模型可以准确地标记低延迟的信号质量,以便可以即时执行运动伪影检测。
- PyrAmes 不是排除所有受运动伪影影响的数据,而是希望开发一种信号处理方法,通过这种方法可以恢复有用的信息,提供用户健康的更完整图像,并增加设备的价值。
开发低延迟模型
目前,PyrAmes 使用深度学习方法在后处理中执行异常检测。该模型提供了范围从-5 到+5 的分数,在任何极端的值表示良好的信号质量,接近 0 的分数表示差的信号质量。虽然深度学习模型可以提供高精度,但它们往往是计算密集型的。这使得它们不适合可穿戴设备,因为可穿戴设备可能需要将有限的硬件用于异常检测以外的任务。我开始尝试开发一个模型,可以重现这些信号质量分数,但使用一种计算量较小的方法,以便可以在运行中进行异常检测。
PyrAmes 提供的数据包括来自传感器的 4 个通道,用于检测动脉波形和一个记录三维动态运动的加速度计。加速度计应该对设备的运动非常敏感,但是不包含关于动脉波形的信息。任何重复的运动,比如运动节奏产生的运动,都会在加速度计中形成明显的信号。所提供的数据是在 660 小时的总持续时间内在 2 个不同的参与者身上的 5 次设备部署中获得的。参与者进行各种典型的活动,如走路、坐着、在电脑前工作等。传感器以 125 赫兹的频率记录(也就是每小时 450,000 条记录!),产生超过 4 Gb 的总数据集。
特征工程
在异常检测中,简化建模过程的一个策略是将我们的高分辨率数据转换为定义长度的仓,称为“时期”。每个时期代表一个 8 秒的数据窗口,这个窗口在时间序列上每次下移 2 秒,这样我们的时期就重叠了。对于每个时期,我计算了分为三类的汇总统计数据;
—关于信号和加速度计通道的广泛统计数据(如最小值、最大值、方差等)。)
—每对通道的相关系数,包括信号通道对和信号与加速度计的相关性。
—两个频率范围内的功率谱密度,0 至 3 Hz 用于捕捉典型的心率节奏(通常在每分钟 60 至 180 次之间),10 至 50 Hz 用于捕捉更高频率的噪声。
总的来说,这产生了 44 个特征,我可以用它们来为每个时期的平均质量分数(从-5 到+5)建模。
建模程序
对于这个任务,我选择尝试随机森林(RF)回归模型。我的基本原理是,RF 模型往往计算成本低,对过拟合具有鲁棒性,并且能够很好地处理大量的特征。最后一点是随机森林中每棵树的制作方式的产物,每棵树都使用了可用特征的随机子集。RF 还提供了相对变量重要性的便捷测量方法,让我们有更多机会进行特性选择,并进一步优化可穿戴设备的使用。
每个 8 秒的时期总共设计了 44 个特征。这些特征大致分为三类。
对于模型拟合程序,我选择排除每个部署数据 20%的分层样本进行验证。剩余的 80%进行了分层的 10 倍交叉验证。我使用这种方法是因为我想确保我们的最终模型可以推广到未来后续部署中收集的新数据。从模型拟合中排除每个部署的 20%的数据模拟了遇到新数据的过程。
随机森林准确检测运动伪影
我使用两个指标评估了异常检测模型,均方根误差(RMSE)和决定系数®。该模型在 10 倍和验证集中产生的误差很小,RMSE 分别为 0.24 和 0.52。为了验证该结果,如果我们的目标质量分数可以从-5 到+5(范围为 10),深度学习模型(以验证集为例)给出的分数平均低 0.5 分是可以接受的。在验证集中,我们的 R 值是 0.89,表示由工程特征解释的质量分数的变化量,对于计算开销如此低的模型来说,这是一个非常积极的结果。
从噪声中恢复信号
因为随机森林在检测运动伪影方面表现非常好,而不是迭代模型以获得边际性能收益,所以我开始通过处理 PyrAmes 设定的下一个任务来增加项目的价值,从受运动伪影影响的数据中恢复可用的指标。为了做到这一点,我借鉴了我在学术界的经验,并从文献中寻找灵感。PyrAmes 用来计算血压的最重要的指标之一是心率。幸运的是,我能够找到 Islam 等人的一篇论文(你可以在这里阅读),其中详细介绍了一种从类似的生物传感器(PPG 的光电容积描记器)恢复心率的方法。该方法被称为具有复合运动伪影参考生成的修改的谱减法方案,或简称为 SPECMAR,对于每个历元具有以下步骤:
—使用低带通滤波器去除每个通道原始数据中的高频噪声
—对滤波后的数据进行快速傅立叶变换,然后在频域中表示每个历元
—加速度计频谱中每个频率的幅度可以通过频谱减法从信号频谱的相应频率中去除。这是根据 Islam 等人指定的重量来完成的。
—心率数据中的自相关用于执行运动伪影参考生成。这里,我们使用来自前一时段的频域中的峰值来改进所考虑的时段中的峰值场。然后,我们可以忽略任何会导致心率突变的频率。
SPECMAR 方法的简单直观总结
在 SPECMAR 的验证试验中,该方法产生的心率估计值与使用 ECG 获得的地面实况高度相关(r=0.99),并且在 29 次不同记录中的平均绝对误差仅为 2.09 BPM。PyrAmes 提供的数据不包括来自 ECG 等来源的经过验证的基本事实,因此我无法完全验证将 SPECMAR 应用于 PyrAmes 传感器时产生的估计值。然而,该方法在 89%的测试时期产生了合理的心率估计(在 50 和 200 BPM 之间)。与以前排除任何不符合必要质量分数的数据的做法相比,这使得每个记录中可使用的数据量增加了 66%。增加可用数据量对用户有切实的影响,让他们更全面地了解自己的健康状况,增加 PyrAmes 传感器的价值。
未来方向
心率只是 PyrAmes 用来得出血压的指标之一。理论上,我们应该能够使用傅里叶逆变换将频域中的干净频谱转换回时域中的可用波形。不幸的是,在我分配给这个咨询项目的时间里,我无法调整这最后一步。然而,这确实为 PyrAmes 的工程师们继续研究提供了一个有用的起点。一旦这一阶段完善,他们应该能够消除信号中的所有运动伪影。一段时间以来,运动伪影一直是生物传感器行业的一个重要问题,这项技术代表了该领域技术水平的重大飞跃。
最后
在我与 PyrAmes 进行咨询的短暂时间里,我能够以两种重要的方式推进他们的产品开发;
首先,我能够优化他们用于可穿戴设备的异常检测算法。这允许实时的低延迟运动伪影检测,并且降低了该过程的硬件要求。降低 PyrAmes 传感器的硬件要求使他们的产品更加通用,并与目前市场上更多的可穿戴设备兼容。
其次,我能够利用最近开发的信号处理方法,从受运动伪影影响的数据中恢复心率估计值。这一过程将可用数据量增加了 66%。鉴于 PyrAmes 开发其传感器的部分动机是为其用户提供比目前不频繁的门诊更好的血压记录,开发对用户日常活动稳定的系统与他们的商业模式和他们与市场上其他生物传感器竞争的能力相关。
动态图中的异常检测
MIDAS:基于微簇的边缘流异常检测器
动机:
拒绝服务攻击(DoS 攻击)是一种网络攻击,旨在关闭网络,使其目标用户无法访问。2018 年 2 月 Github 上最近的一个重大(来源)。
简单的可视化展示一个 DoS 攻击- 来源
在这里,我们可以看到一个异常行为,在很短的时间内在动态图中创建了突然的可疑边。
什么是动态图?
节点是实体的视觉表示,而边是节点之间关系的视觉表示,表示为连接它们的线。图是由节点和边组成的非线性数据结构。经过一系列更新的图称为动态图。大多数现实世界的问题都属于这一类,包括交易网络,所有的即时通讯网络,包括 twitter,脸书等等。
问题:
在所有这些情况下都可以发现异常行为,在本文中,我们专注于检测微集群异常,如在 DoS 攻击的情况下突然到达可疑相似边缘的组,甚至是重大事件期间的推文等。
迈达斯:
基于微聚类的边缘流异常检测器是一种方法
(I)检测微团簇异常,同时提供关于其假阳性概率的理论保证。
(ii)由于它是在线的,因此在恒定时间和恒定存储器中处理每个边沿,并且处理数据的速度比最先进的方法快 162-644 倍。
(iii)它提供了比最先进的方法高 42%-48%的准确性(就 AUC 而言)。
方法:
我们将输入一个时间演化图,证明异常分数输出到边缘。
假设:
假设与时间戳小于 10 相比,时间戳为 10 时有大量的边(~1000)。如下图所示。t=10 时的平均水平等于 t 的平均水平<10.
考虑到这一假设,我们使用 Count-Min-Sketch 数据结构,该数据结构使用哈希函数将事件映射到频率,与哈希表不同,它使用可能发生冲突的子线性空间,这被认为是由于使用子线性空间而产生的成本,更多详细信息可在本文中找到。
- sᵤᵥ : u-v 边沿直到时间 t
- aᵤᵥ :当前时间 t 时 u-v 边沿
- ŝᵤᵥ :大致总计数
- âᵤᵥ :近似电流计数
异常分数由下式给出
快速准确:
与最近在动态图(如 SEDANSPOT)中发现边缘流异常的方法相比,由于需要几个子过程(随机游走、采样等),需要花费大量计算时间。对于 DARPA 数据集,SEDANSPOT 的运行时间为~1.2 min,其中作为 MIDAS <的计算时间为 0.4 sec。
与 DARPA 数据集上的 SEDANSPOT 相比,MIDAS 具有更好的准确度和精密度。
DARPA 数据集的 ROC-来源
实施:
C++编译器:
按照链接使用 MinGW 发行版安装最新的 C++17 编译器。将默认路径 C:\MinGW\bin 添加到系统环境变量%path%中。
Git Bash:
添加系统环境变量路径后检查 g++版本,确保其≥ 9.2.0
使用以下命令克隆 MIDAS 存储库。
运行使编译并创建可执行文件。
让我们在 DARPA 数据集上运行 midas,您可以下载原始格式和使用原始格式转换的 MIDAS 格式(‘源’、‘目的地’和‘时间戳’),这些格式可以通过链接从数据集下载。
scores.txt 文件提供了每条边的异常得分,对于约 450 万个 IP 到 IP 通信,该文件在不到 1.3 秒的时间内生成。使用原始数据集中的“攻击”变量,我们可以在存储库中 auc.py 文件的帮助下找到 AUC 得分。
AUC 为~0.95!
结论:
Dos 攻击、检测银行交易中的异常、推特寻找一些特定事件等。现实世界中有许多问题都是时间演变图。应用这些技术来更好地了解和发现可疑活动,实时可能是一个很好的解决方案。
参考文献:
- SEDANSPOT
- 西达尔特·巴蒂亚,布莱恩·胡伊,姬敏·尹,吉荣·申和克里斯特斯·法鲁索斯。" MIDAS:基于微团簇的边缘流异常检测器."2020 年 AAAI 人工智能大会(AAAI)。https://arxiv.org/abs/1911.04464
- CMS
基于 MIDAS 的动态图异常检测
一种有趣的网络安全建模方法
随着网络攻击范围的不断扩大,网络安全研究近年来变得至关重要。从遗传算法到深度学习的各种想法已经被用来识别可能的攻击场景,并通知网络管理员。
在这些方法的花哨细节下,大多数都有一个相似的核心思想:注意到怪异 模式。作为一个密切观察网络的人,凭直觉您会对来自某些地理位置的请求的突然增加或网络流量的突然捕获/重新路由感到忧虑。
从技术上讲,这些怪异图案被称为**异常、**不寻常的东西。在识别可能的攻击时,这些是最明显的要点。
异常检测对于研究人员和工业家来说都是一个重要的问题。在本文中,我将重点介绍如何使用图表来识别这种模式。我们需要做的就是使用这些数学结构对整个网络流量(是的,您当前连接的局域网或 WiFi)进行建模。
一些帮助您入门的链接:
- 一篇关于 MIDAS 应用和实现细节的有趣的 TDS 文章:https://towards data science . com/controlling-fake-news-using-graphs-and-statistics-31ed 116 a 986 f
- 源代码:https://github.com/bhatiasiddharth/MIDAS
- 西达尔特·巴蒂亚,布莱恩·胡伊,姬敏·尹,申基贞和克里斯特斯·法鲁索斯。" MIDAS:基于微团簇的边缘流异常检测器."2020 年 AAAI 人工智能大会(AAAI)。https://arxiv.org/abs/1911.04464
那么我们如何用图来建模网络呢?
图是一种简单的数学结构:它有几个点,称为节点或顶点,以及一些连接它们的线,称为边。逻辑上,边代表顶点之间的某种关系。
我们可以利用这个抽象的定义。
要将问题建模为图形,您可以将某些实体标识为顶点,然后在它们之间绘制边来表示某些关系。
在我们的例子中,我们将计算机节点(如笔记本电脑、台式机等计算机设备)建模为图的顶点,并将它们之间的连接建模为边。
因此,上图可以理解为:
- 网络中的 5 台计算机设备:P、Q、R、S、T
- 上图是一个有向图。这意味着对于每条边,我们定义一个源顶点和一个目的顶点;例如,考虑有向边 P → Q,这意味着从顶点(或者在我们的情况下,计算机设备 P)到另一个顶点(也称为计算机设备 Q)的有向边。
我们现在得到了模拟我们网络的完美材料。假设我们创建一个由特定网络中的所有节点组成的有向图,每当一个节点试图与另一个节点建立连接时,我们就连接一条有向边。基于这些连接/边缘中已建立的模式,可能会注意到一些奇怪的模式和异常。
但是网络不是很动态吗?他们不经常改变吗?
是的,他们是。这是任何网络模型都面临的一个大问题。
您一定见过任何设备都有可能在几秒钟内上线。到目前为止一切顺利。现在,想象一下在一个巨大的人口统计区域中同样的事情——几个设备正在进入,其他几个正在进行。我说的进出,并不是指你简单地走进一个网络。有很多事情正在进行,其中最重要的也是理解子网的一个很好的起点是网络上每个节点的动态 IP 配置。而且,人们总是在发送文件、图像、视频、文本、HTTP 请求等等;服务器通常发现很难处理过多的流量。
除此之外,了解以下这一点是很有用的:您的节点/计算机和另一个(比如说服务器)之间的一个连接使用一个非常常见的协议——TCP——可能来回需要多达 3-4 个事务才能成功地传递一个信息单元(称为数据包)。你通常在几分钟内发送和接收数千个数据包。成千上万的人在和你完全相同的时刻做着完全相同的事情。
如果你深入思考,所有这些意味着一件事:
互联网是一个非常繁忙的地方。一个遍布全球的虚拟网络。而且很容易藏在那里。
那么这对异常检测意味着什么呢?
意味着变得强硬。在如此密集的网络动态中,你可以想象在数百个顶点上会有多少条边(最初是数千条)。那么,我们实际上如何开始触及问题的表面呢?
这就是迈达斯的用武之地。它建立在它的前辈(其细节超出了本文的范围)的基础上,在某种意义上,它通过考虑网络的时间性质和通过考虑微簇而不是单个边缘来执行检测。
MIDAS-R(MIDAS 的近似变体)考虑了网络的时间特性
到现在为止,你一定已经对计算机网络强烈的动态特性有了一个概念——它们变化的速度和规模。
使用使用*静态图的异常检测技术,*我们立即看到一个问题:没有时间关系(时间=时间,或者网络如何随时间演变)。让我们更详细地探讨一下这个问题。
仅用于演示目的。来源:https://towards data science . com/large-graph-visualization-tools-and-approach-2b 8758 a1 CD 59
仔细看上面的图表。考虑一个你正在观察的网络。现在看起来像图(b)中的。一小时后,看起来像(a)。有哪些异常?如何判断是否有人攻击?
使用**静态图,**您可以在特定的时间间隔拍摄网络配置的快照。你看到的图形就像独立的现存实体。
很直观的,这个方法没有意义。为什么?因为网络配置不是独立存在的。(a)中发生的每件事都与过去某个时候发生的事情有某种联系,就像(b)中一样。这就是时间特征的全部概念。这就是使用动态图的 MIDAS(和其他类似算法)所做的。他们会问以下问题:
当前的情景与过去有什么联系?什么变了,什么没变?
从你开始问这些问题的那一刻起,你就意识到了与网络过去配置的重要联系——你可以利用这一点更好地发现一些奇怪的模式并得到提醒。
MIDAS 考虑微团簇(这是它的一个新颖特征)
考虑一种非常流行的网络攻击:DoS(或另一种变种 DDoS)。虽然细节不在讨论范围之内,但是这些攻击非常粗略地向服务器加载了如此多的请求,以至于服务器不可用于来自真正客户端的真正请求,实际上使整个系统崩溃。
如果我们试图用我们的*动态有向图、*来对此建模,我们会期望什么呢?
左 iamge 来源:https://www . research gate . net/publication/301453477 _ Dynamic _ Graph _ Visualization _ with _ Multiple _ Visual _ anatomies/figures?lo = 1;右图来源:https://www . research gate . net/publication/277649495 _ A _ class ification _ of _ pentagent _ arc-transitive _ bicirculants/figures?lo=1
观察到了什么?
让我们首先考虑第二幅图像,所有点(被认为是节点)正在接收来自不同节点的几条边。然而,在第一幅图像中,由 1 标记的节点正在从单个节点 0 接收几条边。
早期的算法没有区分这些。但是迈达斯问了一个有趣的问题:
为什么两个相似的节点之间有这么多平行的边?
我们的网络模型中的并行节点意味着一台计算机正在向另一台计算机发送几个独立的请求。说 1 是服务器, 0 是运行浏览器的家用电脑。这个浏览器可能会同时请求几个东西:一个 YouTube 视频、一篇维基百科文章、一篇媒体文章、一篇关于数据科学的文章,以及其他几个东西。这仍然是对实际发生的事情过于简单化。事实上,你在浏览器中输入的每个 URL 都会被映射到分布在世界各地的不同服务器上。不要把来自一个浏览器的所有请求都发送到一个服务器。但是为了理解,我们假设他们真的做了。
到目前为止一切顺利。现在,如果并行请求的数量开始攀升,该怎么办呢?如下图所示:
资料来源:迈达斯文件原件
作者的上图说明了这一点。在一段时间的正常活动之后,两个节点之间会突然爆发活动。回想一下我们关于图的时间特性的讨论:*现在发生的事情也取决于过去。*在这里,过去有大约 100–200 个连接,突然计数上升到大约 1000。
迈达斯说,在这种情况下,可能会出问题。仔细检查这个。
这是 微簇检测的整个核心: 在用于监控异常的几个参数中,包括监控突然出现的活动突发,这些突发共享在图形表示(空间局部性) 意义上邻近的几个节点或边 。这是迈达斯非常强大的原因。
MIDAS 与现有解决方案相比如何?
MIDAS(或 MIDAS-R)的性能优于现有的解决方案/算法。作者报道的一些有趣的亮点包括:
假阳性概率的理论保证
我将把详细的讨论留在本文范围之外。粗略地说,作者表明 MIDAS (MIDAS-R)可以给出二元决策(异常是否存在),最高可达用户定义的 阈值 ε *。*因此,根据你是否希望将 10%或 1%作为误报的最大概率, MIDAS 可以处理它。
*注意:假阳性意味着算法将某个事件检测为假阳性,即事件是阴性,但算法却说是阳性。在目前的情况下,这将意味着没有异常,但迈达斯说有。这只是通过设置一个高概率而应用的额外一层谨慎。*你可能更愿意检查一个正常的事件,而不是让一个异常事件溜走(由于概率太低)。
然而,这并不总是令人满意的,这在很大程度上取决于用例。考虑一种检测癌症肿瘤的算法。你希望门槛高吗?这意味着几个没有患癌症的人被报道患有癌症。另一方面,过低的阈值意味着一些癌症患者可能会逃避检测。这两种情况都是危险的;因此,选择阈值是基于问题用例的经验决策。
恒定存储和更新时间
考虑一个典型网络的可能场景:
真正的网络要比这密集得多。问题出现了:
你把这么大的一个网络模型存储在哪里?
为了理解更多困扰我们的内存和时间复杂性问题,举一个例子:
找出所有小于给定数 n 的质数?
一个非常简单的算法:
- 取任何小于 n 的数。
- 检查 q 是否为质数。(这本身是在步骤 3 之后详述的算法)
- 重复直到 q 到达 n-1
(步骤 2 展开)检查 q 是否质数:
- 考虑所有比 q. 小的数字 p
- p 除以 q 吗? 是:增加某个计数器。否:重复。
- 在最末端(当 p 到达 q-1 时),查看计数器是否为 2(意味着有 2 个因子:1 和数字本身)。是:数字是质数。否:不是质数。
一个糟糕的算法,但它做到了。你现在对问题有感觉了:先把 n: 增加到几十,再增加到几千,再增加到几万;你将开始看到时差。
粗略地说,我们认为时间和空间复杂性是这样的,当输入大小增加时,时间和空间需求都增加很多,以至于在某个限制之后解决问题是不可行的。
将此移植到我们的网络图问题中,MIDAS 面临着将几千台计算机表示为节点/顶点和几万条边的挑战。你可以查找图的标准表示法(邻接表、矩阵等)。),你马上就会看到问题。与素数算法一样,在这种表示中,随着节点和它们之间的连接的数量增加,用于存储的空间需求和用于执行算法的时间需求急剧增加。
作者使用一种不常见的数据结构解决了这个问题:计数最小草图(CMS)。细节不在讨论范围内,但这消除了上述问题。
迈达斯(MIDAS-R)简直更好
引用作者所做实验的一些结果:
MIDAS 和 MIDAS-R 得分高于基准。资料来源:迈达斯文件原件。
实验证明,MIDAS 和 MIDAS-R 比基准测试更准确、更精确。资料来源:迈达斯文件原件
随着图形越来越密集,线性时间和空间关系。资料来源:迈达斯文件原件
结论
我认为基于微聚类,包括时间和空间局部性,动态图上的异常检测将会有很长的路要走,并在不久的将来找到有趣的应用。作为一个整体,作者对重要的安全事件检测进行了基准测试,并发现了以下内容:
MIDAS 捕捉重要事件,就像之前建立的基准一样。资料来源:迈达斯文件原件
在未来的几年里,我们将会看到越来越多的研究致力于开发越来越干净和新颖的异常检测方法,并继续在其他领域实现对怪异模式的搜索。
监控系统中的异常检测(上)
了解高斯分布及其属性如何帮助我们对监控数据执行异常检测。
监控系统中的异常检测(图片来自维基媒体
自上世纪中叶第一台计算机问世以来,监控解决方案就一直存在,并且一直试图回答一个简单的问题:“我的计算机内部发生了什么?”。就像老师可能要求学生解释他的思维过程一样,我们也想了解我们程序的内部运作。如果我们找出了它运行时的问题所在,我们就可以获得更好的见解,帮助我们纠正它的行为。
回答这个问题最简单的方法可能是将数据写入任何标准输出,比如计算机屏幕或日志文件。在预定义的时间间隔或在程序执行到某个点时进行定期日志记录,可以让我们将它的状态与我们预期的结果进行比较。如果输出与我们预期的不匹配,我们可以修改代码来纠正这种情况。
这些年来,计算机沿着许多不同的道路发展。你可能在一部老电影里看到的笨重的电脑,已经被笔记本电脑、手机、物联网设备、网络系统、工业电脑,你能想到的都有了;这些系统,从现在开始我将称之为“设备”,通常有许多我们不能监控给定设备内部的应用。由于我们仍然希望监控它们的行为,以验证它们是否按预期运行,因此我们需要找到一种新的方法,仅基于输出就能给出可靠的结果。
最初的方法是为特定设备编写定制的监控解决方案。例如,如果我们有一个组件向我们发送一栋办公楼的功耗,我们可以用给定的指令集编写一个程序来监控该设备的输出值。虽然这种解决方案首次出现时被认为是一种好的方法,但它们有两个主要缺点。第一个是我们必须在编写程序时知道程序允许的操作参数,而在很多情况下我们并不知道。第二个缺点是,即使我们知道这些参数,我们也需要编写一个定制的算法,其中包含一组固定的指令,用于检查设备的输出是否在允许的工作参数范围内。
除非您是专业的电工或工程师,否则您必须长时间监控您的设备,经历许多电源故障、电涌和短缺,然后才能区分正常功耗和异常功耗。即使这样,你的知识也只对一个用电范围的办公楼有用。
我们能克服这两个缺点吗?答案是肯定的,这就是事情变得有趣的地方:一种称为“多元分布的测量方法可以帮助我们推广我们的监控解决方案,只需要很少的数据来进行初始预测,并且可以在我们编写算法时无需指定任何阈值的情况下检测异常。
那么多元分布是什么呢?让我们从本文中的“分布”部分开始,然后在第二篇文章中学习如何使用它,并在最后一篇文章中解释“多元”部分。如果你在阅读方程时感到自信,并且了解基本统计学,你可以安全地跳到下一篇文章。
在统计学中,分布向我们展示了我们的数据可以取的所有可能的值,以及落入给定范围内的任何额外样本的概率。为了使事情变得简单,并且因为我不想太深入问题背后的数学,我将假设我们的数据是“正态分布”。如果你学习统计学,你应该知道它的意思,但是对于那些不知道它的人来说,知道正态分布给我们一些关于我们监控的输出的有用属性就足够了。
如果我们将被监控设备的输出视为数字(从现在开始我将称之为“数据”),并假设它是正态分布的,我们就可以开始对它们进行预测。如果你从高中就不记得什么函数了,知道函数会根据我们给它的数字返回给我们数字就够了。正态分布的数据可以用一个叫做高斯函数的函数来描述。它有一个比你的标准高中函数稍微复杂一点的公式,但是如果你曾经看过为智商测试展示的著名的“钟形曲线”,它们是完全相同的函数。
带有高斯函数公式的钟形曲线(i 作者图片)
这个函数具体描述了什么?原来它描述了很多东西。其中第一个叫做“概率”。概率告诉我们数据中的随机数有给定值的机会。结果是任何给定值的概率都是零,但是高斯函数可以告诉我们一个数在两个值之间的概率。
钟形曲线下方的较大区域表示获得该范围内的值的可能性较高(Iimage by author)
它通过计算曲线下的面积来实现,由这两个值来界定。在上面的例子中,由数字 3 和 4 限定的区域大于由数字 5 和 6 限定的区域。这意味着,如果我们从数据中测量一个随机数,并将其称为 x,那么 x 在 3 和 4 之间的概率比在 5 和 6 之间的概率更高。我们将这个概率表示为 p(x) 。
出现的第二个问题是关于高斯函数公式中的许多符号:它们是什么意思?除了数学运算,公式中我们还有四个字母: e 、 π 、 μ 、 σ 。前两个是众所周知的常数值,在数学中有许多应用。e 大约等于 2.71828,而π大约是 3.14159。可能需要解释的是后两种情况。
数学家们有一个奇怪的习惯,他们从英语术语中抽取第一个字母,并用发音相同的希腊字母来表示它们。这使得希腊字母μ (Mu)成为表示英语单词“意思是”的标准符号。如果我们用一个字母和一个数字的组合来标记数据中的每个输出,我们可以得到如下所示的一系列值:x1,x2,x3 …等等。我们对这个系列的一个衡量标准是平均值,它给出了我们收到的所有值的平均值:
平均值方程
其中 n 是我们已经测量平均值的值的数量。写这个公式的一种更简洁的方式是使用“适马符号”。希腊字母σ(大写适马)标记多个元素的总和。如果我们想对 x 的所有值求和,我们可以写
适马记谱法对斯佩德记谱法
这意味着我们迭代 1 到 n 之间的所有值;用 I 标记当前迭代的值,我们取 x 的第 I 个值,并把它加到所有先前求和的值上。我们现在可以用适马符号来定义我们均值:
平均值方程,使用西格玛符号
第二个值称为“标准偏差”,描述 x 的不同值偏离平均值的程度。标准差用希腊字母σ(小写适马)标记,其公式如下:
标准偏差方程,无贝塞尔校正
现在,我们可以将这四个值结合起来,得出高斯函数的等式:
高斯函数 g(x),表示具有均值μ和标准差σ的正态分布
高斯函数还有另外两个简单的特性:它取的最大值等于我们数据的平均值,曲线的高度和宽度与标准偏差成比例。这在下图中可以清楚地看到:紫色曲线的标准差是红色曲线的两倍,但它们的均值相同。
这两个高斯函数具有相同的平均值,但是不同的标准偏差(i 作者的图片)
这让我们对 x 可以取的值有了几何上的了解:给定范围的值越接近我们数据的平均值,x 包含在该范围内的概率就越高。如果该值离我们数据的平均值太远,我们可以将其归类为异常。
看看你是否能找出这个图中的问题。提示:单值的概率是多少?(作者本人法师)
简单回顾一下,我们已经了解到:
我们希望检测受监控系统中的异常,但这并不总是那么简单
通过将输出视为数据并查看其分布,可以检测出输出中的异常
我们数据中的均值、标准差和概率代表什么
高斯函数有很多有趣的特性,可以用来检测异常。
这都是在此期间。在下一篇文章中,我们将讨论如何在实践中使用高斯函数来检测异常,并实现一个简单的程序来做到这一点。
该系列的第二部分现已准备就绪:
https://medium . com/@ yonatanalon/anomaly-detection-in-monitored-systems-part-2-c 2108 c143 a6
监控系统中的异常检测(下)
了解高斯分布及其属性如何帮助我们对监控数据执行异常检测。
使用高斯分布进行异常检测(图片由作者提供)
在本系列的第一篇文章中,我们讨论了高斯函数的属性以及如何使用它们来检测监控数据中的异常。在这一部分中,我们将把这些知识付诸实践,并构建我们自己的异常检测程序。
概括地说,我们用上图中的高斯函数完成了上一篇文章,其中两点标记了给定数据样本 x 可能取的不同值。然后我们说明 x 离平均值越远,它代表异常的概率就越高。
绘制在高斯函数 g(x)上的两点 p(x1)和 p(x2)(图片由作者提供)
该语句中唯一的问题是,获得任何单个值的概率恰好为零。这是为什么呢?原来高斯函数是一组函数中的一员,这组函数被称为“概率密度函数,简称 PDF。无需深究 pdf 背后的数学,理解它们给我们一个“连续随机变量在给定的“**范围”**内产生一个值的概率就足够了。
现在让我们来解释一下:范围就是两个数字之间的长度,用两个数字相减来表示。两点 a 和 b 之间的距离的常用符号是(a,b)。在下列情况下,数字 x 被认为是“在”一个范围内
随机变量是我们输出数据的正式术语。虽然我们将每个值视为单个数据点,但是当我们查看我们的输出随着时间推移所取的所有值时,我们可以将我们的输出视为一个整体,就像一个随机变量一样。我们要做一个小的捷径——我们要假设,对于给定的输出取值范围,没有一个值是不可能出现的。这种能够取任何可能值的性质,我们称之为“连续的”。因此,表现出这种性质的随机变量称为连续随机变量。标准符号是大写的 x。
回到 PDF 和高斯函数,它们表达概率的方式是计算给定范围内曲线下的面积。这种面积的计算是用积分来完成的。如果你有微积分背景,那么你就知道积分和面积的联系。对于那些不熟悉微积分的人来说,把它们当作工具就足够了,它允许我们计算给定范围内函数所限定的面积。
使用经典几何计算图形下的面积(图片由作者提供)
通过检查一个常数直线函数,例如 f(x) = 1(上面用红色标出),您仍然可以深入了解曲线下的区域。我们可以用两种不同的方法计算函数下面的面积:使用积分和使用矩形面积公式。首先,我们计算矩形的高度和宽度:我们可以看到底边是范围(2,3),我们通过减去左边的右点来获得它的长度。这样我们得到 3–2 = 1,这使得矩形的宽度正好为 1。
接下来,我们将计算矩形左边缘的长度。如果你不知道如何去做,看看这个关于测量距离的维基百科页面。因为我希望你知道如何做到这一点,如果你一直在阅读我到这一点,你可以很容易地验证左边缘的长度(代表高度)也等于 1。
通过使用矩形的面积公式,我们可以计算出它的表面积:
矩形区域,按宽度和高度
这给了我们一个关于测量由函数限定的面积的几何观点。即,在对应于矩形宽度的范围和它的表面积之间存在关系。事实证明,这种关系对每个函数都成立,这就给我们带来了以下问题:如果我们将值域的定义扩展到单点 x,我们可以说任何点都是形状(x,x)的值域。这个范围的长度是用同样的方法得到的——从左边减去右边的点。这使得长度 x - x = 0。
但是由于矩形的宽度是该范围的长度,我们将得到 W = 0。将新值代入面积公式,我们现在得到:
矩形区域,按宽度和高度
这就是为什么 p(x)对于任何给定值都是零。如果是这种情况,我们如何使用随机变量 X 的属性来执行异常检测呢?事实证明这比听起来简单,我们将再次使用我们的几何直觉。
给定值 X 在点 T1 和 T2 之间的概率(图片由作者提供)
对于任何给定值 x,我们计算范围(μ,x)的长度,并用常数 t 标记该长度。然后,我们使用以下公式选择两个值 T1 和 T2:
其中 g 表示高斯函数。事实证明高斯函数有一个很好的性质,它是一个关于均值的对称函数。即对于 x 的每一个值,g(μ - x) = g(μ + x)。因为每两个点只有一条剖切它们的线,所以 g(x)对称的事实意味着通过 T1 和 T2 的线垂直于 x 轴。
高斯函数的另一个特性是,当不受 x 轴限制时,曲线下的面积等于 1。这可以用积分表示为:
表示高斯函数下方面积的无界积分
这意味着,如果我们计算由范围(T1,T2)界定的面积,我们可以通过从 1:
概率 p(x) w.r.t. μ和σ的表示
使用高斯函数下方的区域可视化我们的概率(图片由作者提供)
这些结果在几何上意味着什么?请记住,这里的关键参数是我们用 t 表示的长度:x 离平均值越远,范围 t 就变得越长。t 的尺寸每增加一点,T1 和 T2 之间的面积 A 就相应增加一点。A 的增加自然意味着 1-A 值的减少,这被视为钟形曲线边缘下面的蓝色“尾部”。
在这个图中,x 比前面的图离μ更远;代表该概率的区域确实更小(图片由作者提供)
现在我们已经有了结果,我们需要决定的是一个给定的值 x 需要异常到什么程度,我们才能把它归类为异常。这个值完全取决于您和您试图监控的设备的域。常见的值可能是 0.1%,1%,5%,但当然,你可以选择最适合你的值。
简单回顾一下,我们已经了解到:
随机变量是一种统计上表示我们输出数据的方式。
概率密度函数和高斯函数一样,给出了我们的随机变量在一个范围内产生值的概率。
高斯传递这种概率的方式是通过其曲线下的表面积,以目标范围为界。
这个系列的第三部分已经准备好了:
https://medium . com/@ yonatanalon/anomaly-detection-in-monitored-systems-part-3-52c 172 CFA 589
python 中的代码示例(版本 3.8.3):
使用高斯分布的单变量异常检测—源代码
监控系统中的异常检测(第三部分)
了解高斯分布及其属性如何帮助我们对监控数据执行异常检测。
检测高维数据中的异常(图片由作者提供)
在本系列的第二篇文章中,我们学习了更多关于高斯函数的知识,然后我们使用它的属性构建了一个工作异常检测系统。在这最后一部分中,我们将处理多变量的情况,正如在本系列的第 1 部分中所承诺的。与第 1 和第 2 部分不同,第 1 和第 2 部分不需要任何先前的知识,本文将需要至少线性代数的基础知识(特别是使用向量和矩阵)。
那么到底什么是多元分布呢?“多元”部分将一个维度中的分布推广到任意有限个维度。这使得多元分布在建模与给定设备的许多监控参数相关的数据时非常有用。我们将我们的定义扩展到更高维度的方法是通过一个叫做“随机向量”的东西。如果 Xk 是每个 1≤k≤n 的随机变量,则向量 X = (X1,X2,…,Xn)称为随机向量。除了上述性质外,如果随机变量的任何线性组合也是正态分布的随机变量,则认为随机向量是正态分布的。
我们如何解读这些读数,从而对受监控设备的异常行为进行分类?最简单的方法也许是将随机变量相乘。因为随机变量随着时间监控输出,所以我们可以将随机变量视为向量,其值只是给定字段中的普通数字。然后,我们可以将它们按元素相乘,得到所谓的乘积分布:
z 是随机向量 X 中所有随机变量的乘积分布
我们可以建立产品分布的平均值和标准偏差,并使用它们来计算样本相对于产品分布 Z 异常的概率:每当我们从被监控设备读取一组新值时,我们就构造一个向量 z = (z1,z2,…,zn),其中 zi 表示第 I 个被监控参数的最新值。然后,我们通过将独立值相乘来计算 z 成为异常的概率:
读取样本向量 z 的概率是读取其各个分量的概率的乘积
使用乘积分布的主要好处是,计算数字之间的乘积是执行成本最低的计算之一。但是使用产品分销也有几个缺点。想到的两个这样的缺点是,不能保证 Z 将是正态分布的,并且 Z 可能无法捕捉某些类型的异常。
来自监控计算机网络中的防火墙的示例数据。注意异常的红色 X(图片由作者提供)
假设我们正在监控一个计算机网络,并且正在从我们的一个防火墙收集数据。我们对这个防火墙的两个操作参数感兴趣:并发连接数和每秒传输的千字节数。我们开始监控防火墙,并将 X1 指定为连接的用户数量,将 X2 指定为传输的 kb/s 数量。
经过一段时间后,我们得到一个读数 z = (z1,z2 ),并在上图中将其标为红色的“X”标记。当我们查看图表时,我们可以清楚地看到 z 是一个异常值——它被绘制在远离主要读数“簇”的地方。但是如果我们沿着红色的虚线,我们发现 z 是一个正常的读数:z1 非常接近连接用户的平均读数,z2 也接近传输的 kb/s 的平均值。因此,如果我们将 p(z1)*p(z2)相乘来检查异常,结果将显示 z 不是异常。
但事实证明,我们可以使用另一种统计方法,它也可以捕捉我们数据中的这些异常。这种方法使用所谓的多元高斯分布,它是一维高斯函数的多维抽象。
在解释其含义之前,让我们先来看看这个公式:
多元高斯分布方程
因为我假设你在第一段接受了我的建议,我希望你知道这个公式中的大多数符号。如果你有足够的勇气在没有这些知识的情况下继续下去,你至少应该知道向量就像一行或一列数字,矩阵是数字的网格(或一行向量)。向量和矩阵都有自己特殊的加法和乘法规则,而行列式、求逆和转置则是我们对矩阵进行的更专门的运算。
然而,该公式中真正的精华是协方差矩阵:这个非常特殊的矩阵在统计学中有一些有用的属性,包括作为多元高斯的基础。协方差矩阵的公式如下所示:
随机向量与其自身的协方差矩阵
我们在此描述的协方差矩阵测量随机向量与其自身之间的关系,由矩阵的每个单元中的标量值表示。表达这种关系的一种有用的方式是通过协方差矩阵的近亲,称为相关矩阵。相关矩阵将协方差矩阵中的每个值除以随机变量 Xi 和 Xj 的标准偏差的乘积
从协方差矩阵导出相关矩阵
这种划分的实际结果是协方差矩阵的值现在被限制在-1 和+1 之间。Rij = 1 表示 Xi 和 Xj 之间的正线性关系——测量 Xi 的大值表明 Xj 的相同测量值增加。相反,Rij = 1 表示 Xi 和 Xj 之间的负线性关系——测量大值的 Xi 表示减小相同的 Xj 测量值。
随机向量元素之间的关系(图片来自维基媒体
介于-1 和 1 之间的值表示非线性关系,0 表示 Xi 和 Xj 线性无关。由于这种关系的性质,它立即意味着σ(和 R)是对称矩阵。即—σij =σJi 对于每 1≤i≤j≤n。
这些统计的非线性关系正是协方差矩阵如此强大的原因。因为它可以捕捉组成随机向量 X 的随机变量之间的所有这些关系,所以多元高斯可以检测我们在产品分布中未检测到的异常。它们可能接近于每个随机变量的平均值,但是因为它们位于多元分布之外,所以它们可以被归类为异常。
同一个分布被绘制了三次,不同的协方差矩阵塑造了每一次绘制(图片来自 Coursera
我们将使用的技术类似于我们在单变量情况下使用的技术:我们将使用一个平面(或更高维的类似物)来“分割”分布,然后计算多变量高斯和坐标平面之间的体积。
请注意绿色平面是如何“切割”高斯曲线的,就像我们用直线切割单变量分布一样(图片由作者提供)
因为我们在一个 n 维空间中工作,所以我们需要进行 n 次积分。这让我们计算:
样本向量落入由任意范围界定的多元高斯下方体积内的概率
但是解析地计算 n 个积分,特别是当 n 可能非常大(例如超过 10,000)时,计算量非常大。这就是为什么我要走捷径:高斯的“钟形曲线”意味着返回值越低(您可能已经注意到 G(X,μ,σ)返回一个标量值,而不管 n 的大小),高斯“尾部”下面的区域越小。
叠加两个具有不同ε值的高斯图显示了不同的值如何设置不同的异常阈值(图片由作者提供)
由于 G 返回的值与距离分布平均值给定距离的观察值的概率之间的关系,我可以将 p(x)与任意阈值进行比较,并将任何小于给定阈值的值归类为异常。这可能不是直接计算在我们的数据中观察到给定值的概率,但也许您可以证明这种分类的一种方法是注意到,因为高斯是一个连续函数,每个阈值ε ∈ (0,max(G))都有一个匹配值 t,因此 p(t) = ε。不是将异常分类为 p(x) < ε, we can think of our classification as marking any x for which p(x) < p(t) as an anomaly.
Plotting a density function for a multivariate distribution as a height map. Darker colours indicate a larger volume underneath a given slice (image by author)
概括的任何值,我们已经知道:
乘积分布是一种简单的多元异常分类方法,计算量也很小。
他们的主要缺点是无法对某些异常进行分类。
协方差矩阵(及其近亲,相关矩阵)可以用来度量随机向量 x 的随机变量之间的关系
这些关系允许多元高斯函数对产品分布遗漏的所有异常进行分类。
我们可以通过将异常与任意值ε ∈ (0,max(G))进行比较来对异常进行分类,因为执行高维积分在计算上是昂贵的。
python 中的代码示例(版本 3.8.3):
基于 VAR 的多元时间序列异常检测
存在序列相关性时的系统监控
异常检测是机器学习中的一个热门话题。正如我们所猜测的,“异常”的定义是可变的,并且与领域相关。在时间序列应用中,当我们面对这类问题时,我们还必须考虑时间维度。一个系列的历史包含了关于其行为的大量信息,并且可以暗示其未来的变化。这对于不是由随机游走过程产生的序列和表现出循环/周期性模式的序列来说尤其如此。
处理时间序列并从过去学习信息的简单已知模型是 ARIMA。ARIMA 模型是开发时间序列预测工具的重要工具。他们学习序列如何演变的能力在异常检测任务中也是有用的。从这个意义上说,经典方法包括将超出容许阈值的观察标记为异常。这种方法仅限于奇异级数;如果我们想考虑一个更复杂的系统,我们需要另一种方法。
在这篇文章中,我们将介绍一种方法来检测由多个相关序列组成的复杂系统中的异常。我们使用 VAR 模型,ARIMA 的多变量扩展,从我们处理的序列中提取相关模式。VAR 学习到的信息随后用于构建阈值机制,以便在我们的指标超过临界值时发出警报。
数据
我们从 Kaggle 那里获取实验数据。西雅图伯克吉尔曼步道是西雅图市托管的数据集,是其开放数据项目的一部分。数据集存储传感器检测到的每小时计数序列。这些传感器可以计算骑自行车的人和行人。为每种出行模式记录单独的交通量。混凝土中菱形排列的电线探测自行车,安装在木柱上的红外传感器探测行人。
可供我们使用的每日汇总时间序列示例
总共提供 5 个计数系列。2 个与行人计数相关,2 个与自行车计数相关,总计是前面系列的总和。行人和自行车有两个柜台,因为登记了两个行驶方向。
根据这些数据,我们的异常检测之旅分为两部分。首先,我们提供了一个经典的单变量异常检测方法使用 ARIMA。最后,我们通过一个多变量的方法考虑所有的系列和他们在系统中的相互作用。根据这篇文章的范围,我们决定聚合我们可以处理的数据,从每小时的数据到每天的数据。
单变量异常检测
在单变量异常方法中,我们计划使用 ARIMA 来检测奇怪模式的存在。我们决定把重点放在总计数系列上。开发 ARIMA 时,首先要处理的是平稳性、爆炸性趋势或季节性。从上面的图和下面的自相关可以很容易地看出,总计数序列呈现出双重季节性:每周和每年。
原始自相关
长期的季节性会很烦人。为了消除它,我们每天减去根据训练数据计算的相对月平均值。这样,我们只剩下每周的模式,我们的模型可以毫无问题地学习它。
去除长期季节性后的自相关
我们拟合了最佳 ARIMA,将搜索限制在 7 自回归阶附近,同时最小化 AIC。最终的模型似乎产生没有任何自相关程度的正常残差。
ARIMA 拟合数据
安装好 ARIMA 后,我们就可以开始寻找异常点了。我们有两种可能性:我们可以将置信区间之外的每个观察值识别为异常,或者我们可以查看残差。每个程序都需要生成迭代预测,并每次用实际值评估我们的预测。
测试预测
标准化测试残差
可以通过 alpha 置信度参数来指定预测间隔深度。残差分析需要标准化操作(必须计算训练残差的平均值和标准偏差)。这样,我们可以使用正态分布的残差和来自正态分布的固定置信阈值进行操作。
多元异常检测
前一种方法的多元推广涉及到 VAR 模型的采用。VAR 模型通过捕捉多个变量之间的线性关系,扩展了单变量自回归(AR)模型。对于每个输入序列,进行回归。原始变量根据它们自己的滞后值和其他变量的滞后值进行回归。对于我们的多元任务,我们同时考虑自行车和行人系列。
在存在序列相关性的多变量过程系统中,我们使用 VAR 模型来逼近系统,并将残差作为一个序列独立的序列进行监控。由于过程动力学的物理原理,使用 VAR 来近似线性系统是合适的。
VAR 训练与选择最小化 AIC 的最佳阶数之前一样计算。数据以同样的方式标准化,以消除长期的季节性。毫不奇怪,最好的模型是 VAR(7)。测试残差数据的独立性和正态性后,可以计算霍特林 T 平方统计量来检测异常的早期存在:
霍特林·T2 的公式。e 是估计的残差;适马是 e 的协方差矩阵
T 平方控制图的应用分两个阶段进行:控制界限建立阶段和监控阶段。第一阶段的重点是获得模型残差,以便计算出的控制极限可用于第二阶段,用于监控未来异常的残差过程。T 平方控制图的控制限由下式给出:
上限控制统计
其中 F 代表具有 p 和 n-p 个自由度和α显著性水平的 F 分布。如果 T2 > UCL,那么停下来调查一下。在阶段 1 结束时获得的估计适马(以及残差均值和标准差)用于计算每个新观测值的 T 平方统计量。
列车数据上的 T2 加 UCL
测试数据上的 T2 加 UCL
摘要
在这篇文章中,我们介绍了执行异常检测任务的良好工作流。我们开始研究单变量的情况。我们使用一个拟合的 ARIMA 作为判断来检测未来的观察是否异常。我们也意识到现实可能更复杂,可能需要考虑不同变量之间的相互作用。出于这个原因,我们将我们的分析扩展到 VAR 模型的多变量情况。我们收集了 VAR 残差,并使用它们来建立一个阈值警报系统,在出现异常行为时发出警报。
保持联系: Linkedin
参考文献
利用向量自回归残差在序列相关下监测多元过程
基于机器学习的过程控制数据异常检测
实践教程
引入异常检测,使用您自己的温控实验室设备桌面上生成的数据
迪米特里·阿尼金在 Unsplash 上拍摄的照片
异常检测是机器学习在现实世界中的一个强大应用。从检测欺诈交易到预测组件故障,我们可以训练一个机器学习模型来确定什么时候发生了不寻常的事情。
说到机器学习,我非常支持通过实验来学习。机器学习模型背后的实际数学可能有点像黑箱,但这并不妨碍它的有用性;事实上,我觉得这是机器学习的优势之一。你可以用同样的算法来解决所有的问题。有时候,最好的学习方法是处理一些真实的数据,看看会发生什么。
在本例中,我们将能够使用温度控制实验室设备生成一些真实数据,并训练一个监督分类器来检测异常。TCLab 是一个很棒的小设备,可以通过简单的即插即用 Arduino 设备生成真实数据。如果你想为此创建自己的数据,这里有很棒的介绍性资源;否则,我会将我在自己的 TCLab 设备上生成的数据包含在 Github 存储库中。如果你想自己运行这些例子,你可以在这里下载并遵循代码。
问题框架
TCLab 是一个简单的 Arduino 设备,带有两个加热器和两个温度传感器。这是一个简单的即插即用设备,一个插头为加热器供电,一个 USB 端口与计算机通信。可以在 Python 脚本中调整加热器的级别(确保pip install tclab
),温度传感器用于读取每个加热器周围的温度。对于这个例子,我们将保持它的基本,只使用一个加热器和传感器,但同样的原则也可以适用于 2 加热器系统,甚至更复杂的系统,如你可能会发现在化学精炼厂。
图像来自 APMonitor 。经允许重新发布。
我们可以这样想象这个问题:我们的车库车间有一个加热器,有一个简单的开/关设置。我们可以设定加热器每天开启或关闭一定时间,以保持温度在一个舒适的水平。当然,我们可以使用更复杂的控制系统;然而,这是作为机器学习异常检测的介绍而设计的,所以我们现在将保持原始数据简单。
在正常情况下,这是一个足够简单的练习来验证加热器是否开启并工作——只要看看温度,看看它是否在上升。但是如果有外部因素使评估复杂化了呢?也许车库门开着,让一股气流进来,或者你的一些设备开始过热。或者更糟糕的是,如果温度控制受到网络攻击,并且被攻击者掩盖了,怎么办?有没有办法查看我们正在收集的数据,并确定什么时候出现了问题?这是异常检测的核心。
使用监督分类器,我们可以查看传感器数据,并训练它在加热器打开或关闭时进行分类。因为我们也知道何时加热器应该打开或关闭,我们可以将分类器应用于任何新的数据,并确定行为是否与我们看到的数据相符。如果两者不匹配,我们知道存在某种类型的异常,并可以进一步调查。
生成数据
为了模拟这个场景,我们将从 TCLab 生成一个数据文件,以不同的时间间隔打开和关闭加热器。如果你的 TCLab 设置有问题,这里有一些很好的故障诊断资源。
首先,我们将设置几个数组来存储数据,我们将以 1 秒的间隔收集这些数据。加热器开/关循环现在非常简单,只需将它一直打开或关闭,并让它保持几分钟。我们将运行一个小时,以确保我们有大量的数据进行训练和验证。
TCLab 输入很简单,根据我们生成的内容将lab.Q1
设置为开或关。我们只将加热器开至 70%以避免过热,然后记录从lab.T1
开始的每个时间点的温度。最后,让循环延迟 1 秒。
异常数据是以基本相同的方式创建的,但只用了 20 分钟。最大的不同是,我在指定的时间让风扇吹过加热器,模拟车库里的通风。风扇的对流会自然冷却系统,抵消加热器的作用。由于这是意料之外的,我们应该看到分类器拾取它——也许在我们知道加热器是开着的时候指示它是关着的。让我们继续下去,看看它是否有效!
数据预处理
机器学习的关键之一是研究如何以对模型有用的方式构建数据。当我做机器学习的任何项目时,这往往是最耗时的一步。如果我没弄错的话,这个模型非常有效;否则,我可能会花几个小时甚至几天的时间感到沮丧,想知道为什么我的模型行不通。
你应该总是为机器学习应用缩放你的数据,这可以很容易地用 scikit-learn 的MinMaxScaler
来完成。此外,检查数据的格式对于模型是否正确(例如,numpy 数组的形状是否与分类器所期望的相匹配?否则,您可能会收到警告)。让我们看看目前为止这个是什么样子的。请注意,我们没有缩放 y 数据,因为它已经只是 0 和 1。
您会注意到,我们的输入只是温度,我们试图预测的输出是加热器状态(开或关)。这样有效吗?分类器能否仅根据温度判断加热器是开还是关?幸好有了 scikit-learn,使用监督分类器进行训练和预测只需要几行代码。我们还将使用逻辑回归分类器,但是还有许多其他监督分类器可以使用。
绘制结果会产生以下结果:
作者的情节
对于我们是否可以只使用原始温度作为输入,答案是断然否定的。这具有直观意义,例如,在 35°C 时,加热器要么打开,要么关闭。然而,温度的变化会告诉我们很多关于加热器在做什么。
特征工程
这介绍了特征工程的领域,这是为机器学习设置问题的另一个重要部分。我们可以在现有的基础上创造新的功能。从原始温度中我们还能收集到什么其他数据?我们可以得到一阶和二阶导数,过去几个读数的标准差,甚至可以看到长期的差异趋势。另一个可以尝试的技巧是对数据进行日志缩放,尤其是在数据是日志分布式的情况下。这些都是新特性,其中一些可能是分类器获得良好性能的灵丹妙药!
同样,一些特定问题的领域知识和直觉对于特征工程来说是非常有用的。让我们先来看看温度的变化。有一点传感器噪声,因此采用温度的滚动平均值会给出更好的曲线,这可能会导致更好的性能。
基于原始温度(dT)和滚动平均温度(dT_ave)的温度数据变化。作者的情节
让我们看看效果如何。唯一的区别是我们在 dataframe 中创建了dT
列,并将其用作输入特性。我们还必须丢弃任何带有NaN
值的数据。
结果…相当不错!有一些失误,但那些总是在加热器刚刚打开或关闭的边缘。我们可以研究更多的特性,例如二阶导数,这可能会有所帮助,但目前来看,这看起来就像它会做到这一点。
作者的情节
根据新数据验证分类器
在开始使用经过训练的分类器之前,最佳实践是验证从未见过的数据的性能。我个人喜欢在最初的原始训练数据上进行尝试,只是作为一种直觉检查;如果它在那里不起作用,它就不会对新数据起作用。然而,我们看到它在上述数据上运行良好,所以现在让我们在一组新的数据上进行检查。您可以从 TCLab 生成一个新的无异常数据文件,或者使用来自 scikit-learn 的train_test_split
。请注意,我们仅在数据缩放上使用transform
功能,因为我们已经安装了缩放器,并使用该缩放来训练分类器。
这是结果的图表:
作者的情节
已经核实了。同样,当加热器打开或关闭时,会出现边缘情况。我们可以研究额外的特性来输入到分类器中,或者甚至改变分类器的超参数,但是对于一个简单的演示来说,这已经足够了。
利用训练好的分类器进行异常检测
这里是橡胶接触路面的地方。我们知道分类器可以很好地告诉我们加热器是开着还是关着。当意想不到的事情发生时,它能告诉我们吗?
流程真的一样。唯一的区别是现在我们有一个数据异常。我们将创建新特征(温度变化,使用平滑滚动平均值),缩放数据,并将其输入分类器进行预测。
结果如下:
作者的情节
这看起来很有效!我们看到的预测是,当风扇运行时加热器关闭,而实际上加热器是打开的,这只是一个异常事件。即使在风扇关闭后,系统也在重新平衡,因此加热器的实际情况和分类器预测的情况之间存在一些额外的不匹配。如果一个操作者正在看进来的数据,他们可以比较他们期望加热器正在做什么和分类器正在预测什么;任何差异都表明异常,可以进行调查。
其他想法
这是一个很好的实验,只有一种异常,使用的是我们在桌面上生成的数据!当然这很简单,但是这类问题会很快变得复杂。然而,指导原则是相同的。
还有哪些异常事件可能发生?我们可以通过打开加热器 2 来模拟异常的外部热量。我们可以通过在更冷的房间中运行 TCLab 来模拟更冷的环境温度。这些设备还有一个巧妙的技巧:如果你在传感器附近打手机,电波会干扰信号,你会得到一种全新的异常。什么样的特征对检测这些其他类型的异常有用?我们可以调整超参数来提高性能吗?
最后,在分类器方面,也许我最喜欢的策略是训练几个不同的分类器,然后取一个总分数。继续尝试来自 scikit-learn 的一些其他类型的分类器。哪些好用?哪个不是?如果您发现 4 或 5 个工作得很好,您可以训练所有的分类器,然后只在大多数分类器显示不匹配的情况下将某些东西标记为异常。
这有帮助吗?你喜欢能够生成自己的数据吗?你还发现了哪些对异常检测有用的想法?感谢您的阅读,我希望这篇介绍为您自己的项目打开了一些新的思路。
时间序列传感器数据中的异常检测
威尔·梅尔斯在 Unsplash 上拍照
异常检测包括识别数据集中与标准的差异、偏差和异常。它有时被称为离群点检测。
异常检测不是一个新概念或新技术,它已经存在很多年了,是机器学习的一个常见应用。其使用案例的真实示例包括(但不限于)检测欺诈交易、欺诈性保险索赔、检测异常设备行为的网络攻击。
在本文中,我将重点介绍异常检测在制造业中的应用,我认为与其他行业相比,制造业在有效利用机器学习技术方面远远落后。
问题描述
制造业被认为是重工业,其中他们倾向于使用各种类型的重型机械,如巨型电机、泵、管道、熔炉、传送带、拖运卡车、推土机、平地机和电铲等。这些通常被认为是他们运营中最重要的资产。因此,这些设备的完整性和可靠性通常是其资产管理计划的核心焦点。
他们如此关注这些资产的主要原因是,这些设备的故障通常会导致生产损失,从而导致数十万美元(如果不是数百万美元的话)的损失,这取决于运营的大小和规模。因此,对于制造工厂的维护经理来说,这是一件非常重要的事情,他们需要与高技能的可靠性工程师一起运行一个强大的资产管理框架,以确保这些关键资产的可靠性和可用性。
因此,提前检测异常情况并降低风险的能力是一项非常有价值的能力,可进一步防止计划外停机、不必要的维护(基于条件的维护与强制维护),还能更有效地管理这些资产的关键部件。计划外停机造成的生产损失、不必要的维护成本以及关键部件的过剩或短缺都会转化为严重的经济损失。
在这篇文章中,我将使用 Scikit-learn(又名 sklearn)在 Python 中实现不同的异常检测技术,我们的目标是使用无监督学习算法在泵的时间序列传感器读数中搜索异常。我们开始吧!
数据
很难从制造业中找到这种特定用例的公开数据,但我能够找到一个不完美的数据。数据集包含来自安装在泵上的 53 个传感器的传感器读数,以测量泵的各种行为。这个数据集可以在这里找到。
首先,我将使用以下代码和 Kaggle API 下载数据
!kaggle datasets download -d nphantawee/pump-sensor-data
下载完成后,用下面的代码将 CSV 文件读入 pandas 数据帧,并检查数据的细节。
df = pd.read_csv('sensor.csv')
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 220320 entries, 0 to 220319
Data columns (total 55 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Unnamed: 0 220320 non-null int64
1 timestamp 220320 non-null object
2 sensor_00 210112 non-null float64
3 sensor_01 219951 non-null float64
4 sensor_02 220301 non-null float64
5 sensor_03 220301 non-null float64
6 sensor_04 220301 non-null float64
7 sensor_05 220301 non-null float64
8 sensor_06 215522 non-null float64
9 sensor_07 214869 non-null float64
10 sensor_08 215213 non-null float64
11 sensor_09 215725 non-null float64
12 sensor_10 220301 non-null float64
13 sensor_11 220301 non-null float64
14 sensor_12 220301 non-null float64
15 sensor_13 220301 non-null float64
16 sensor_14 220299 non-null float64
17 sensor_15 0 non-null float64
18 sensor_16 220289 non-null float64
19 sensor_17 220274 non-null float64
20 sensor_18 220274 non-null float64
21 sensor_19 220304 non-null float64
22 sensor_20 220304 non-null float64
23 sensor_21 220304 non-null float64
24 sensor_22 220279 non-null float64
25 sensor_23 220304 non-null float64
26 sensor_24 220304 non-null float64
27 sensor_25 220284 non-null float64
28 sensor_26 220300 non-null float64
29 sensor_27 220304 non-null float64
30 sensor_28 220304 non-null float64
31 sensor_29 220248 non-null float64
32 sensor_30 220059 non-null float64
33 sensor_31 220304 non-null float64
34 sensor_32 220252 non-null float64
35 sensor_33 220304 non-null float64
36 sensor_34 220304 non-null float64
37 sensor_35 220304 non-null float64
38 sensor_36 220304 non-null float64
39 sensor_37 220304 non-null float64
40 sensor_38 220293 non-null float64
41 sensor_39 220293 non-null float64
42 sensor_40 220293 non-null float64
43 sensor_41 220293 non-null float64
44 sensor_42 220293 non-null float64
45 sensor_43 220293 non-null float64
46 sensor_44 220293 non-null float64
47 sensor_45 220293 non-null float64
48 sensor_46 220293 non-null float64
49 sensor_47 220293 non-null float64
50 sensor_48 220293 non-null float64
51 sensor_49 220293 non-null float64
52 sensor_50 143303 non-null float64
53 sensor_51 204937 non-null float64
54 machine_status 220320 non-null object
dtypes: float64(52), int64(1), object(2)
memory usage: 92.5+ MB
我们已经可以看到,数据需要一些清理,有丢失的值,一个空列和一个数据类型不正确的时间戳。因此,我将应用以下步骤来整理数据集。
- 移除多余的列
- 删除重复项
- 处理缺失值
- 将数据类型转换为正确的数据类型
# Drop duplicates
df = df.drop_duplicates()
# Entire "sensor_15" column is NaN therefore remove it from data
del df['sensor_15']
# Let's convert the data type of timestamp column to datatime format
import warnings
warnings.filterwarnings("ignore")
df_tidy['date'] = pd.to_datetime(df_tidy['timestamp'])
del df_tidy['timestamp']
接下来,让我们处理缺失值,为此,我们首先查看缺失值的列,并查看缺失数据的百分比。为此,我将编写一个计算缺失值百分比的函数,这样我就可以在整个笔记本中多次使用同一个函数。
# Function that calculates the percentage of missing values
def calc_percent_NAs(df):
nans = pd.DataFrame(df.isnull().sum().sort_values(ascending=False)/len(df), columns=['percent'])
idx = nans['percent'] > 0
return nans[idx]# Let's use above function to look at top ten columns with NaNs
calc_percent_NAs(df).head(10)
每列缺失值的百分比
经过一些分析后,我决定用它们的平均值来估算一些缺失的值,并去掉其余的。在数据争论过程之后,我最终整理的数据如下所示,并为下一步探索性数据分析做好了准备。tidy 数据集有 52 个传感器,机器状态列包含三个类别(正常、损坏、恢复),分别代表泵的正常运行、损坏和恢复状态,然后是日期时间列,代表时间戳。
整齐数据的前 10 行
探索性数据分析
既然我们已经清理了数据,我们可以开始探索以熟悉数据集。
在一些定量 EDA 之上,我执行了额外的图形 EDA 来寻找趋势和任何奇怪的行为。特别是,有趣的是看到传感器读数随着时间的变化而变化,机器状态“损坏”用红色标记在同一图表上。这样,我们可以清楚地看到泵何时出现故障,以及这如何反映在传感器读数中。下面的代码为每个传感器绘制了上面提到的图表,但是让我们看看 sensor_00 的图表。
# Extract the readings from the BROKEN state of the pump
broken = df[df['machine_status']=='BROKEN']
# Extract the names of the numerical columns
df2 = df.drop(['machine_status'], axis=1)
names=df2.columns
# Plot time series for each sensor with BROKEN state marked with X in red color
for name in names:
_ = plt.figure(figsize=(18,3))
_ = plt.plot(broken[name], linestyle='none', marker='X', color='red', markersize=12)
_ = plt.plot(df[name], color='blue')
_ = plt.title(name)
plt.show()
从上面的图中可以清楚地看到,代表泵损坏状态的红色标记与传感器读数的观察到的干扰完全重叠。现在我们有了一个很好的直觉,当泵坏了和正常运行时,每个传感器读数是如何表现的。
平稳性和自相关性
在时间序列分析中,重要的是数据是平稳的,没有自相关。平稳性是指数据的平均值和标准偏差随时间变化的行为,具有这种行为的数据被认为是不平稳的。另一方面,自相关是指数据在不同时间段内与其自身相关的数据行为。下一步,我将直观地检查数据集中每个特征的稳定性,下面的代码将完成这一任务。稍后,我们还将执行 Dickey Fuller 测试来定量验证观察到的平稳性。此外,在将特征输入聚类算法以检测异常之前,我们将检查特征的自相关性。
# Resample the entire dataset by daily average
rollmean = df.resample(rule='D').mean()
rollstd = df.resample(rule='D').std()
# Plot time series for each sensor with its mean and standard deviation
for name in names:
_ = plt.figure(figsize=(18,3))
_ = plt.plot(df[name], color='blue', label='Original')
_ = plt.plot(rollmean[name], color='red', label='Rolling Mean')
_ = plt.plot(rollstd[name], color='black', label='Rolling Std' )
_ = plt.legend(loc='best')
_ = plt.title(name)
plt.show()
时间序列看起来相当稳定
查看其中一个传感器(在本例中为 sensor_17)的读数,注意数据实际上看起来非常稳定,滚动平均值和标准偏差似乎不随时间变化,除非在预期的泵停机期间。该数据集中的大多数传感器都是这种情况,但在训练数据之前必须应用各种变换方法来使数据稳定的情况下,情况可能并不总是如此。
预处理和降维
用所有 52 个传感器/特征来训练模型在计算上非常昂贵,并且效率不高。因此,我将采用主成分分析(PCA)技术来提取用于建模的新特征。为了正确应用 PCA,必须对数据进行缩放和标准化。这是因为 PCA 和大多数学习算法都是基于距离的算法。如果从整洁数据的前 10 行注意到,每个特征的值的大小是不一致的。有些值非常小,而有些值非常大。我将使用管道库执行以下步骤。
- 缩放数据
- 执行主成分分析,并根据惯性查看最重要的主成分
# Standardize/scale the dataset and apply PCA
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
# Extract the names of the numerical columns
df2 = df.drop(['machine_status'], axis=1)
names=df2.columns
x = df[names]
scaler = StandardScaler()
pca = PCA()
pipeline = make_pipeline(scaler, pca)
pipeline.fit(x)# Plot the principal components against their inertiafeatures = range(pca.n_components_)
_ = plt.figure(figsize=(15, 5))
_ = plt.bar(features, pca.explained_variance_)
_ = plt.xlabel('PCA feature')
_ = plt.ylabel('Variance')
_ = plt.xticks(features)
_ = plt.title("Importance of the Principal Components based on inertia")
plt.show()
根据图表,前两个组件是最重要的
根据上述重要性图中 PCA 提取的特征,似乎前两个主成分是最重要的。因此,作为下一步,我将使用 2 个组件执行 PCA,这将是我在模型训练中使用的特征。
# Calculate PCA with 2 components
pca = PCA(n_components=2)
principalComponents = pca.fit_transform(x)
principalDf = pd.DataFrame(data = principalComponents, columns = ['pc1', 'pc2'])
现在,我将再次检查这两个主成分的平稳性和自相关性,以确保它们是平稳的,不是自相关的。
from statsmodels.tsa.stattools import adfuller
# Run Augmented Dickey Fuller Test
result = adfuller(principalDf['pc1'])
# Print p-value
print(result[1])
对第一个主成分运行 Dickey Fuller 测试,我得到的 p 值为 5.4536849418486247e-05,这是一个非常小的数字(远小于 0.05)。因此,我会拒绝零假设,说数据是平稳的。我对第二个组件执行了同样的操作,得到了类似的结果。所以两个主成分都是静止的,这就是我想要的。
现在,让我们检查这两个主成分的自相关性。有两种方法可以做到:使用 pandas autocorr()方法或 ACF 绘图。在这种情况下,我将使用后者来快速直观地验证没有自相关。下面的代码就是这样做的。
# Plot ACF
from statsmodels.graphics.tsaplots import plot_acf
plot_acf(pca1.dropna(), lags=20, alpha=0.05)
假设我的 PCA 的新特征是稳定的,并且不是自相关的,我已经准备好建模了。
建模
在这一步中,我将执行以下学习算法来检测异常。
- 基准模型:四分位距(IQR)
- k 均值聚类
- 隔离森林
让我们开始用这些算法进行训练。
四分位间距
策略:
- 计算 IQR,即第 75(Q3)和第 25th)百分位数之间的差值。
- 计算异常值的上限和下限。
- 过滤超出上限和下限的数据点,并将其标记为异常值。
- 最后,在时间序列数据(本例中是 sensor_11 的读数)的顶部绘制异常值
# Calculate IQR for the 1st principal component (pc1)q1_pc1, q3_pc1 = df['pc1'].quantile([0.25, 0.75])
iqr_pc1 = q3_pc1 - q1_pc1# Calculate upper and lower bounds for outlier for pc1lower_pc1 = q1_pc1 - (1.5*iqr_pc1)
upper_pc1 = q3_pc1 + (1.5*iqr_pc1)# Filter out the outliers from the pc1df['anomaly_pc1'] = ((df['pc1']>upper_pc1) | (df['pc1']<lower_pc1)).astype('int')# Calculate IQR for the 2nd principal component (pc2)
q1_pc2, q3_pc2 = df['pc2'].quantile([0.25, 0.75])
iqr_pc2 = q3_pc2 - q1_pc2# Calculate upper and lower bounds for outlier for pc2lower_pc2 = q1_pc2 - (1.5*iqr_pc2)
upper_pc2 = q3_pc2 + (1.5*iqr_pc2)# Filter out the outliers from the pc2df['anomaly_pc2'] = ((df['pc2']>upper_pc2) | (df['pc2']<lower_pc2)).astype('int')# Let's plot the outliers from pc1 on top of the sensor_11 and see where they occured in the time seriesa = df[df['anomaly_pc1'] == 1] #anomaly
_ = plt.figure(figsize=(18,6))
_ = plt.plot(df['sensor_11'], color='blue', label='Normal')
_ = plt.plot(a['sensor_11'], linestyle='none', marker='X', color='red', markersize=12, label='Anomaly')
_ = plt.xlabel('Date and Time')
_ = plt.ylabel('Sensor Reading')
_ = plt.title('Sensor_11 Anomalies')
_ = plt.legend(loc='best')
plt.show();
用红色标记的异常
如上所述,异常是在泵发生故障之前检测到的。对于操作员来说,这可能是一个非常有价值的信息,可以在泵实际停止工作之前正确地关闭泵。让我们看看是否能从接下来的两个算法中检测到相似的异常模式。
k 均值聚类
策略:
- 计算每个点与其最近质心之间的距离。最大的距离被认为是异常。
- 我们使用 outliers_fraction 为算法提供关于数据集中离群值比例的信息。不同数据集的情况可能有所不同。然而,作为一个开始的数字,我估计 outliers_fraction=0.13 (13%的 df 是 outliers,如图所示)。
- 使用离群值分数计算离群值的数量。
- 将阈值设置为这些异常值的最小距离。
- anomaly1 的异常结果包含上述方法簇(0:正常,1:异常)。
- 用时序视图可视化异常。
# Import necessary libraries
from sklearn.cluster import KMeans
# I will start k-means clustering with k=2 as I already know that there are 3 classes of "NORMAL" vs
# "NOT NORMAL" which are combination of BROKEN" and"RECOVERING"kmeans = KMeans(n_clusters=2, random_state=42)
kmeans.fit(principalDf.values)
labels = kmeans.predict(principalDf.values)
unique_elements, counts_elements = np.unique(labels, return_counts=True)
clusters = np.asarray((unique_elements, counts_elements))# Write a function that calculates distance between each point and the centroid of the closest clusterdef getDistanceByPoint(data, model):
""" Function that calculates the distance between a point and centroid of a cluster,
returns the distances in pandas series"""
distance = []
for i in range(0,len(data)):
Xa = np.array(data.loc[i])
Xb = model.cluster_centers_[model.labels_[i]-1]
distance.append(np.linalg.norm(Xa-Xb))
return pd.Series(distance, index=data.index)# Assume that 13% of the entire data set are anomalies outliers_fraction = 0.13# get the distance between each point and its nearest centroid. The biggest distances are considered as anomalydistance = getDistanceByPoint(principalDf, kmeans)# number of observations that equate to the 13% of the entire data setnumber_of_outliers = int(outliers_fraction*len(distance))# Take the minimum of the largest 13% of the distances as the thresholdthreshold = distance.nlargest(number_of_outliers).min()# anomaly1 contain the anomaly result of the above method Cluster (0:normal, 1:anomaly) principalDf['anomaly1'] = (distance >= threshold).astype(int)
异常用红色标记
隔离森林
# Import IsolationForestfrom sklearn.ensemble import IsolationForest# Assume that 13% of the entire data set are anomalies
outliers_fraction = 0.13model = IsolationForest(contamination=outliers_fraction)
model.fit(principalDf.values)
principalDf['anomaly2'] = pd.Series(model.predict(principalDf.values))# visualization
df['anomaly2'] = pd.Series(principalDf['anomaly2'].values, index=df.index)
a = df.loc[df['anomaly2'] == -1] #anomaly
_ = plt.figure(figsize=(18,6))
_ = plt.plot(df['sensor_11'], color='blue', label='Normal')
_ = plt.plot(a['sensor_11'], linestyle='none', marker='X', color='red', markersize=12, label='Anomaly')
_ = plt.xlabel('Date and Time')
_ = plt.ylabel('Sensor Reading')
_ = plt.title('Sensor_11 Anomalies')
_ = plt.legend(loc='best')
plt.show();
用红色标记的异常
模型评估
有趣的是,这三个模型都发现了许多相似的异常现象。仅仅从视觉上看上面的图表,人们可以很容易地得出结论,隔离林可能比其他两个检测到更多的异常。然而,下面的表格显示,相反,IQR 检测到的异常比 K-Means 和隔离森林要多得多。
每个模型检测到的异常数量
你认为这是为什么?当其他两个模型检测分布在不同时间段的异常时,IQR 是否主要检测相距较近的异常?IQR 比其他两位更科学吗?我们如何定义准确性?现在,让我把这些问题留给你去思考。我将在以后的帖子中更详细地写关于模型评估的更多内容。
结论
到目前为止,我们已经用三种不同的方法进行了异常检测。在此过程中,我们经历了常用数据科学流程的大部分步骤,包括以下步骤:
- 问题识别
- 数据角力
- 探索性数据分析
- 预处理和训练数据开发
- 建模
- 证明文件
在这个项目中,我面临的一个挑战是,使用无监督学习算法训练异常检测模型具有如此大的数据集,在计算上可能非常昂贵。例如,我不能用这些数据正确地训练 SVM,因为它花了很长时间来训练模型,却没有成功。
我建议接下来采取以下步骤,其中前 3 步侧重于改进模型,后两步则是让事情变得真实:
- 利用高级特征工程技术进行特征选择
- 高级超参数调谐
- 实现其他学习算法,如 SVM,DBSCAN 等。
- 使用给定测试集的最佳模型预测机器状态—砰!
- 将最佳模型部署到生产中——DOUBLE BAM!
除了实施上述步骤,我将继续改进模型,并计划在未来的另一篇文章中分享结果。
Jupyter 笔记本可以在 Github 上找到详情。享受检测异常,让我们在 LinkedIn 上联系。
在线参考和有用的资料
旁观者眼中的异常检测
一副扑克牌揭示了如何检测异常值
作者图片
在网络安全中,异常检测的重点是发现可能被认为是网络攻击的异常事件。异常检测的承诺是,该算法将检测到以前从未见过的攻击。网络数据的一些问题是数据量太大,攻击数量很少,而且攻击每天都在演变。
机器学习的许多入侵检测应用依赖于监督学习。监督机器学习擅长检测已知的攻击。通过适当的拟合,有监督的机器学习算法甚至能够发现一些新的攻击。但是,异常检测会在没有预定义攻击特征的情况下重新审视数据。
异常是正常的
在处理网络流量数据时,异常检测算法可能会发现真正异常的事件,但它们可能不是您想要的事件。大型计算机网络是有节奏的。他们有定期运行的流程。他们通常有相同的用户,每天做相同的事情。但网络数据远非规律。网络上发生的一些事件会中断正常的程序。存在由系统错误、缺陷或错误配置导致的操作事件。服务器上部署了一些系统更改,以添加软件功能和修补安全漏洞。有些新用户开始工作,有些人的工作发生了变化,他们发现自己肩负着新的责任。随着所有这些变化的发生,哪些事件是真正的异常呢?
用异常检测算法在不断变化的网络生态系统中检测网络攻击是非常具有挑战性的,因为异常可能与利用企图无关。虽然看似矛盾,但异常是正常的。
重要的是要认识到,你发现的异常可能不是你实际寻找的异常。这适用于入侵检测以及许多其他领域的无监督学习。一个数据不一样,不代表它不好。在欺诈检测中,您可能会观察客户的购买模式,并在客户从未做生意的商店中发现不寻常的购买行为。这可能是欺诈行为,也可能只是客户决定做一些随机的、不同的或不正常的事情。这也是异常检测器误报率如此之高的原因之一。
你发现的异常可能不是你实际寻找的异常。
不要气馁,回到监督学习。有一些方法可以改进对您真正想要找到的事件的检测。你如何用你的算法得到更好的结果?
没有单一正确的集群方式
异常检测类似于聚类问题。聚类也是无监督学习的一个例子。在聚类中,目标是将彼此最相似而与其他组中的项目最不相似的项目分组在一起。聚类的一个已知问题是没有一种算法可以成功地对所有数据进行聚类。聚类的挑战在于,这些组可能由于非常不同的原因而相似或不相似。聚类可以用密度函数或距离函数来衡量,但即使这样,数据中的一些分组也不容易找到。例如,如果没有专门的聚类算法,数据中的某些连续形状可能不会很好地聚类。
这就是为什么埃斯蒂维尔-卡斯特罗宣称,“集群是在旁观者的眼中。”[1]他认为聚类是不同研究者如何描述一个聚类的数学定义。对于每一个归纳原则,有不同的聚类算法来满足研究者的意图。
一副牌揭示了什么
为了用您可能熟悉的数据集进行说明,请考虑一副扑克牌。一副标准的扑克牌有 52 张。每张卡都将是我们数据集中的一条记录。每张卡都有一组特征,例如花色、卡的面值和颜色。您知道每张卡都有一个 Unicode 值吗?我们也可以把它作为一个特性包括进来。大多数卡牌还会增加两张百搭牌。小丑牌有点反常,因为它没有花色或特定的颜色,但它有面值和 Unicode 值。
给定这副牌,如果让你把它们分成合理的组,你会如何组织它们?请记住,在聚类中,您的目标是选择分组,使每张卡片与其自己的聚类中的卡片最相似,而与其他聚类中的卡片最不相似。
你可以按花色分组。你可以把所有的方块放在一起,所有的红心放在一起,所有的梅花放在一起,所有的黑桃放在一起。结果是每种花色有 13 张牌。那些小丑呢?他们有点反常,所以也许他们应该进入他们自己的群体。
作者图片
你可以按颜色将卡片分组,所有的红色卡片在一组,所有的黑色卡片在另一组。因此每组有 26 张牌,但是小丑显然是个例外,因为他们不属于任何一个颜色组。
作者图片
最后,你可以按面值将卡片分组。您可以将所有的 a 放在一个组中,将所有的 2 放在另一个组中,依此类推。由于玩笑者在外表上彼此相似,你可以再次将他们归入他们自己的群中。在这种情况下,玩笑者可能看起来不是异常,因为他们有面值。
作者图片
哪个集群解决方案是正确的?每一个都是正确的。这取决于你的目标和你解决问题的方式。如果你的目标是将卡片分成尽可能少的组,那么颜色似乎是最好的特征。如果你想分成尽可能多的组,那么按面值分组是最有意义的。
您获得的解决方案取决于您用来对数据进行分组的功能。
如果无监督的机器学习算法是神奇的,那就太好了。如果是,你可以给算法一组数据,不需要任何初始分析,就能得到正确的解。但是从扑克牌的例子中可以看出,您得到的解决方案取决于您用来对数据进行分组的特性。
对于这个讨论,同样重要的是考虑到一些分组清楚地揭示了玩笑者是异常的,而其他解决方案没有。从这个简单的例子可以清楚地看出,异常检测也是因人而异的。
特征选择
将异常检测应用于入侵检测或任何其他应用程序时,最重要的步骤是选择最合适的功能。如果你想得到神奇的结果,你可以使用像 bagging 这样的方法来测试随机特性,但是不集中的特性选择可能不会给你真正想要的解决方案。相反,想想异常在您的网络和数据集的上下文中意味着什么。
选择特征时,您可能会发现数据集中存在非常自然的特征。在扑克牌的例子中,颜色、花色和面值都很简单。但是如果基本特征无助于指出异常呢?
也许您想看看一周中的某些天或一天中的某些小时有什么异常。从网络数据的日期特征中提取星期几和一天中的小时将允许算法发现一些异常活动。
也许你想看到一段时间内的模式。例如,在网络数据中,您可能希望找到用户以正常或异常模式登录到特定系统的模式。常规特征不提供这种上下文,因此您可能需要创建一个时间序列或从原始数据创建 N 元模型。
用用例定义异常
但是如果你在寻找几种不同类型的异常呢?例如,如果您既想区分用户正常登录到不同的系统,又想检测用户在一天中不同时间登录的事件,该怎么办?也许您还对网络上系统之间的网络行为模式感兴趣。
一种解决方案是为您想要检测的每种异常创建用例。在网络安全中,这些通常被称为滥用案例,因为它们不是关于计算机系统应该如何工作,而是它们可能如何受到攻击。以下是您可能用于入侵检测的一些示例用例:
- 用户在一天中不寻常的时间登录
- 两台计算机系统之间异常的网络流量
- 异常状态消息
- 系统帐户登录到不寻常的计算机
- 不规则的登录模式
在您的用例被定义之后,您可以选择最有助于识别每个用例的异常的特性。然后,为每个用例分别运行异常检测算法,您可以关注您最感兴趣的异常。
使用不同异常检测器的结果,每一个都基于不同的特性集,有一些方法或公式来组合用例的结果是有帮助的。例如,如果四个用例中的三个表明一个事件是异常的,那么它可能比一个只触发一个用例的事件得到更高的分数。
虽然合并结果有助于区分异常的优先级,但是展示每个用例的得分也是很好的。向最终用户呈现这些信息提供了一些可解释性。根据触发警报的用例,用户将理解为什么警报被视为异常。
通过实验,您可能还会发现,您开始使用的一些用例是不值得的,只会制造噪音。在这些情况下,消除这些用例是有好处的,因为它们不会帮助找到您试图检测的异常。这将有助于降低你的假阳性率。
结论
使用机器学习的异常检测不是魔术。需要规划和分析来找到正确的方法并充分利用您的算法。
由于异常检测是因人而异,因此定义您想要检测的异常类型非常重要。您可以通过缩小与目标异常最相关的特征来做到这一点。
用例有助于确保您能够检测到数据集中可能出现的各种类型的异常。使用为每个用例选择的不同特性集分别运行您的异常检测算法,可以产生非常有趣且可解释的结果。
对于检测网络入侵,异常检测可以通过发现非网络攻击的异常事件来产生大量噪声。尝试使用这些方法来微调您的算法,并向响应结果的安全分析师提供更有意义的数据。
参考
[1] V. Estivill-Castro,为什么有这么多聚类算法:立场文件 (2002),ACM SIGKDD 探索时事通讯,4(1)
异常检测变得简单
利用 pycaret 包的信用卡诈骗案
在这个银行业的新时代,Stripe、Square 等金融支付服务巨头使信用卡支付无缝化,信用卡交易每年都以倍数增长(来源)。因此也导致信用卡诈骗报告每年翻一番(来源)。
按年份分类的信用卡欺诈报告(来源)
什么是异常?
异常是偏离正常或预期的东西。在信用卡交易中,大多数欺诈案件偏离了正常交易的行为。说什么是正常的交易行为是主观的,但是有不同类型的异常检测技术来发现这种行为。这里我们将讨论三种类型的技术。
信用卡诈骗侦破案例:
我正在考虑卡格尔信用卡欺诈检测进行异常 detection⁴.
从 API 调用下载数据集:
首先,进入您的 Kaggle 我的帐户(https://www.kaggle.com/Your-Username/account)),进入“API”部分,点击“创建新的 API 令牌”,下载您的 API 令牌。您现在将下载一个名为“kaggle.json”的文件。你必须把这个文件上传到你的笔记本上。
from google.colab import files
uploaded = files.upload()
现在,您可以使用下面给出的代码来下载和解压缩数据集。
!pip uninstall -y kaggle
!pip install --upgrade pip
!pip install kaggle==1.5.6
!kaggle -v
!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle/
!chmod 600 ~/.kaggle/kaggle.json
!kaggle datasets download -d mlg-ulb/creditcardfraud
!unzip creditcardfraud.zip
预处理:
在给定的数据集中,284,807 笔交易中有 492 笔欺诈,我正在考虑一个 0.1 的样本用于我们的分析,而不会丢失离群分数用于进一步的无监督学习。异常分数是 0.001723。
设置初始化 pycaret⁵的环境,并创建转换管道,为建模和部署准备数据。
1。隔离林:
T 隔离森林算法通过随机选择一个特征,然后随机选择所选特征的最大值和最小值之间的分割值来分离观察值,类似地,通过创建随机决策 trees⁶.来构建分离因此,异常分数被计算为分离给定观察所需的条件的数量。
建立模型:
我们可以使用 pycaret 包中的 create_model 函数建立模型,可以使用下面的代码相应地修改参数。
使用 assign_model⁷函数寻找孤立森林异常分数和标签。
评价:
隔离林的 ROC_AUC 为 0.935。
2。基于角度的异常检测:
在中,基于角度的异常值检测通过比较距离向量对之间的角度来解决高维度问题,而不是使用距离 directly⁸.
建立模型:
我们可以使用 pycaret 包中的 create_model 函数建立模型,可以使用下面的代码相应地修改参数。
使用 assign_model 函数查找 ABOD 分数和标签。
评估:
基于角度的异常值检测的 ROC_AUC 是 0.777。
3。子空间离群点检测:
t子空间离群值通过寻找低维空间中具有异常低 density⁹.的数据的局部区域来识别
建立模型:
我们可以使用 pycaret 包中的 create_model 函数建立模型,可以使用下面的代码相应地修改参数。
使用 assign_model 函数查找 SOD 分数和标签。
评价:
子空间离群点检测的 ROC_AUC 为 0.942。
4。最小协方差行列式:
这是发现异常值的最稳健的方法之一,它考虑使用称为 MCD 估计量的稳健估计量。这说明了掩蔽效应:经典估计值会受到污染的强烈影响,以至于诊断工具(如马氏距离)无法检测异常值⁰.由于稳健距离对掩蔽效应不敏感,因此它们可用于标记异常值。
建立模型:
我们可以使用 pycaret 包中的 create_model 函数建立模型,可以使用下面的代码相应地修改参数。
使用 assign_model 函数查找 MCD 异常分数和标签。
评价:
最小协方差行列式异常值检测的 ROC_AUC 为 0.906。
比较结果:
从这个 kaggle 信用欺诈检测数据集的所有四种异常检测技术中,我们看到,根据 ROC_AUC,子空间异常检测相对给出更好的结果。
子空间异常值检测的异常值的 3d TSNE 图(黄色欺诈,蓝色正常)
请从这个 colab 查看这些异常检测技术的详细代码。
结论:
大多数银行和支付服务使用不同的异常评分方法,要么使用一个异常评分,要么对某些异常评分技术的分级异常评分进行平均,以确保不丢失任何欺诈交易。
参考资料:
- 按年份统计的信用卡统计。
- 信用卡报表统计。
- 人工智能的进展和趋势。
- kaggle 信用卡欺诈检测。
- pycaret
- 隔离林研究论文。
- pycaret assign_model 。
- 基于角度的离群点检测研究论文。
- 子空间离群点检测研究论文。
- 稳健统计异常检测。
- 最小协方差行列式估计量的快速算法。
使用本福德定律的异常检测
掷骰子得到 5 的几率有多大?当然是 1/6。从 1 到 100 之间随机选择的数字是 32 的几率有多大?1/100.
假设你下载了 2020 年的银行交易。随机交易的金额以 3 开头的可能性有多大?考虑到有 9 个可能的数字(省略 0 作为第一个数字),逻辑上你会猜测 1/9。令人惊讶的是,这是错误的。真实概率其实在 12%左右。第一个数字是 1 的概率惊人地超过了 30%。
那么这个规律是从哪里来的,我们又该如何运用呢?
历史
虽然通常被称为本福德定律,但和许多著名定律一样,它并不是以第一个发现它的人命名的。实际上,是一位名叫西蒙·纽康的天文学家在 19 世纪晚期注意到,在对数表中,一些页面比其他页面磨损得更多——尤其是前几页。他的发现后来被弗兰克·本福特重新发现,他继续做更多的实验来验证这一理论。
简而言之,该定律表明“真实”数据集中数字的首位数字不会以一致的概率出现。我们所说的“真实”是什么意思?这里,我们指的是自然出现的数字集合——银行账户交易、街道地址、数学常数。数字以 d (1,2,3…9)开头的概率由以下公式给出:
作者图片
如果我们画出第一位数字的预期频率,我们会得到以下图形:
作者图片
同样,我们可以对第二个数字做同样的事情。
作者图片
那么,我们如何利用新发现的知识呢?它最合乎逻辑的应用是在会计(尤其是审计)领域,但也可以在其他领域找到用途。这部法律被广泛记载,以至于在联邦、州和地方法院案件中经常被用作证据。
更多示例:
- 如果你看过本·阿弗莱克主演的电影《会计师 T2》,你会看到他利用本福德定律揭露欺诈。
- Ciaponia 和 Mandanici 在一篇研究论文中使用该定律来调查意大利大学是否故意使用虚假数据来支持他们的书籍。
- 本福德定律曾被用于检测 2009 年伊朗选举中的选民欺诈。
利用法律
既然你理解了本福特定律的理论,让我们把它付诸实践。在我们的例子中,我们将检查大约 2,100 笔金融交易,看它们是否符合。如果我们检测到超出预期频率的数据,我们会将这些交易标记为可疑,并让其他人进一步调查。(代码和例子可以在我的 github 中找到。)
首先,我们需要创建一个预期频率的列表。出于我们的目的,我们将关注前两位数字,并利用 numpy 创建一个 10×2 矩阵。行将代表数字(0–9)。列将表示数字位置(第一或第二)。
现在,我们需要从我们的数据(2,100 笔交易)中计算每个位置上不同数字的频率。我们将首先把我们的数据加载到 pandas 数据框架中。然后,我们将清理数字(删除否定标识、逗号等)。)并提取第一个和第二个数字。
作者图片
为了便于与我们预先计算的预期概率进行比较,我们还将在另一个 numpy 数组中计算观察数据的概率。
根据 Nigrini 和 Mittermaier 在分析程序中使用本福特定律作为辅助手段,我们可以根据给定的α水平计算期望值的置信区间。
作者图片
我们可以在两个 numpy 数组中保存我们的上限和下限,然后比较我们的观察结果,看看我们是否落在计算置信区间之外。如果是这样,我们知道我们有可疑的数据。
为了形象化我们的发现,我们可以绘制第一个和第二个数字的分布,以及置信区间。
作者图片
作者图片
正如我们所看到的,在第一个数字中,我们看到 8 出现的频率比本福特定律预测的要高得多。在第二个数字中,我们发现 5 也出现得更频繁——实际上是第二个数字中出现频率最高的。
我希望你学到了一些东西,并能够找到本福特定律的另一个有用的应用。同样,代码在我的 github 上。
感谢您的阅读。
关注我的博客
将新内容直接发送到您的收件箱。
原载于 2020 年 10 月 1 日 http://lowhangingfruitanalytics.com。
TensorFlow 2.0 中的自动编码器异常检测
如何在 TensorFlow 2.0 中实现神经网络以检测异常的指南。
在这篇详细的指南中,我将解释深度学习如何用于异常检测领域。此外,我将解释如何在 TensorFlow 2.0 中实现用于异常检测的深度神经网络模型。当然,所有的源代码和相应的数据集都可以下载——很好;)
目录
- 简介
- 异常检测
- 异常检测系统的用例
- 异常案例研究:金融欺诈
- 自动编码器如何工作?
- 使用自动编码器的异常检测
- tensor flow 2.0 中的欺诈检测
1.介绍
异常是指与数据集中的其他实例明显不同的数据实例。通常它们是无害的。这些只能是数据中的统计异常值或错误。但有时数据中的异常可能表明以前已经发生了一些潜在的有害事件。
此类事件可能是金融欺诈。
在本文中,我将向您展示如何使用深度神经网络的力量来识别欺诈性的金融信用卡交易,这些交易可以被识别为数据集中的异常。
2.异常检测
不幸的是,常规前馈神经网络不太适合检测异常。正因为如此,我将介绍一种新的神经网络架构,称为 Autoencoder。
但首先,我想更详细地解释术语异常,并说明为什么异常检测系统在预测分析领域发挥如此重要的作用。
在分析真实世界的数据时,一个常见的观察结果是,数据集中的一些实例或观察结果可能会让人产生怀疑,因为它们与数据集中的大多数数据有很大的不同。这些特定的数据实例是不同的,因为它们不匹配数据集中的其他预期模式或行为。这种情况通常被称为异常。
请考虑以下由 4 个要素组成的数据集。
仔细观察会发现这个数据集中的一些不规则之处。第二个和第五个数据实例中的值与其他实例中的值非常不同。这两个实例的特征值与其他实例的相应特征值有很大不同。
显然,我们在这里观察到两个异常现象。数据中的异常可能有几个原因。有时,异常是在数据收集或预处理过程中出现的数据错误。
当然,也有很大的可能性,异常可能属于实际数据。在这种情况下,它们只不过是一些统计异常值。另一方面,异常有时可以指示一个新的、先前未知的潜在事件,该事件首先导致这些异常。
在这种情况下,数据中的异常可能表明欺诈、滥用或服务中断等事件,所有这些都对企业或组织构成威胁。你现在可能会问自己的问题是,为什么我们可以将这些事件视为数据中的异常。
简单的答案是,欺诈、滥用或服务中断当然是不符合企业或组织中通常的、预期的行为或流程的事件。事实上,这些都是相当罕见的事件。
3.异常检测系统的用例
让我们来看看某个特定的业务领域,数据中的异常可能意味着潜在的威胁或问题。
银行:在银行领域,异常可能与异常高的购买/存款或网络入侵有关
医疗保健:在医疗保健领域,索赔和支付方面的欺诈可能是异常现象。但更重要的是,患者健康数据的异常可以暗示疾病或健康状况的恶化
制造:在制造过程中,异常的机器行为可以被记录为机器产生的数据中的异常
金融:正如前面的例子中已经提到的,在金融领域(也可以属于银行业,反之亦然),欺诈性金融交易可以被注册为异常数据实例
智能家居:在智能家居的情况下,能量泄漏会导致数据中出现一些意想不到的观察结果
电信:在电信漫游滥用、收入欺诈、服务中断可能被识别为数据中的异常实例。
从这些例子中可以看出,异常检测是各种业务领域的重要组成部分。异常检测模型可以保护公司和机构免受财务和个人损失。甚至成为医疗保健领域的潜在救星。
4.异常用例:金融欺诈
以诈骗为例。想象一下,你正在从你的银行账户里取钱。你每周做一次,每次都是在你上班时间从自动取款机上取。每当金额在 100-250 美元之间时,你就在取款。当然,每次您取款时,您的银行都会收集与取款相关的数据,如时间、地点、金额等。
只要您坚持您通常的模式,收集的数据实例看起来几乎是一样的。现在想象一下,你的卡被偷了,小偷发现了你的 ATM 个人识别码。小偷利用这个机会,从一台不在你家乡的自动取款机上提取了一大笔远远超过你平时数额的钱。
正如您可以想象的那样,包含特定现金提取相关信息的数据实例在金额和提取地点方面与前面的实例有很大不同。
在这种情况下,数据实例将作为异常引起注意。
当然,异常和它可能暗示的威胁类型取决于行业和相关的数据类型。在任何情况下,异常检测模型的目标是检测异常数据,以便采取措施进一步调查检测到的异常,并避免公司或其客户可能面临的威胁或问题。
5.自动编码器是如何工作的?
在本文的其余部分,我将只把金融欺诈作为异常检测的案例研究。
这是我们可以利用深度神经网络的时候了。神经网络是通用的模式识别系统,可以识别模式,并将其与我们人类永远不会考虑的欺诈行为相关联。
例如,在准备交易时,停留在特定按钮或屏幕区域上的时间等模式。
一个人可能永远不会发现这种模式是否与某种欺诈行为有关。然而对于神经网络来说,这根本不是问题。非常适合于识别这种模式的神经网络架构被称为自动编码器。
向您详细解释这种神经网络架构肯定超出了本文的范围。相反,我想给这个网络一个简短的概述。关于 Autoencoder 更详细的解释,请随意阅读文章“tensor flow 2.0 中的 Deep auto encoder”。
自动编码器最简单的形式是你已经熟悉的前馈神经网络。与前馈神经网络一样,自动编码器有一个输入层、一个输出层和一个或多个隐藏层。下图显示了自动编码器的体系结构。正如我们所见,自动编码器的输入层和输出层具有相同数量的神经元。
自动编码器可以分为两部分:
- 编码器
- 解码器
编码器
编码器指的是自动编码器的前半部分,其中隐藏神经元的数量随着网络的深入而减少。
神经元数量的减少迫使输入特征 x 被“编码”或压缩成可以在中间隐藏层中找到的更短的表示。我们姑且把这种 x 的表示称为隐向量*。*
解码器
解码器代表自动编码器的一部分,其中隐藏层中的神经元数量再次增加。
解码器使用编码到中间隐藏层中的输入特征的更短的潜在表示来重构原始输入特征 x 。让我们称重构的输入为 x_hat 。
如果解码器能够从比这短得多的向量中重构输入特征 x ,这意味着 x 包含大量不相关的信息,并且可以被丢弃。**
描述x100 的编码和解码的整个过程的等式如下:
这里 W1 、 W2 、 W3 和 W4 表示连接自动编码器各层的权重矩阵。西格玛代表任意的非线性激活函数。
这种潜在表示 z 非常重要,因为它可以用于许多不同的目的,比如检测金融交易中的欺诈,我们几分钟后就会看到。首先,我们将讨论如何训练自动编码器,以便获得输入的准确潜在表示。
自动编码器的训练
自动编码器的训练方式与前馈神经网络相同。我们必须最小化输入特征和它们的重建对应物 x_hat 之间的距离。
x 和 x_hat 之间的距离可以用均方误差损失函数来恰当地度量。为了最小化距离或损失函数的值,我们必须使用常规梯度下降法:
通过最小化 MSE 损失函数,我们减小了 x 和 x_hat 之间的差异。这些自动导致一个更好的潜在表象 z 的输入特征 x 。
6.使用自动编码器的异常检测
现在,我们已经了解了什么是自动编码器以及如何训练它,让我们讨论如何使用这种神经网络架构来检测数据中的异常。
我们必须清楚一个事实,即数据集中的异常是非常罕见的事件。
这意味着应该检查任何类型异常的数据集是非常不平衡的。数据集中的绝大多数实例将是绝对正常的——与极少数异常数据实例形成对比。
客观地说,在接下来的异常检测示例中,我们将使用的数据集将包含超过 280,000 个信用卡交易数据实例,其中只有 492 个是欺诈性的。这只是可被视为异常的数据实例的 0.17%。这种不平衡是一个严重的问题。
提到的数据集就是著名的“信用卡诈骗数据集”。它包含欧洲持卡人在 2013 年 9 月通过信用卡进行的交易。该数据集显示了两天内发生的交易,其中 284,807 笔交易中有 492 笔欺诈。
数据集如下所示:
- 特征 V1 ,…, V28 是用 PCA(主成分分析)得到的主成分
- “时间”:每笔交易与第一笔交易之间经过的秒数
- 【金额】:交易金额
- “类”:是我们的标签。1 表示欺诈交易,否则为 0
用于异常检测的训练自动编码器
我们将很难像以前一样执行基于特征标签的神经网络监督训练。因为这一次我们没有足够的数据实例来描述我们想要检测的异常情况——在我们的案例中是欺诈交易。
因此,我们的模型可能很难了解异常或欺诈交易的一般概念,因为模型几乎从未见过这种情况。此外,我们需要将数据集划分为训练集、测试集和验证集,这将进一步减少相应数据集中的异常数量。
数量非常有限的异常数据实例的一般结果是,我们的模型在对这些事件进行分类时效率非常低,因为在绝大多数情况下,模型仅从正常数据实例中学习。幸运的是,现在我们可以使用自动编码器来帮助我们。我们可以使用这种神经网络的独特性质来解决数据集非常不平衡的问题。
这意味着,我们将自动编码器的预测与初始输入特征进行比较,而不是提供将输入特征分类为欺诈性或非欺诈性的标签。
此外,在欺诈检测的情况下,我们必须只在非欺诈数据实例上训练自动编码器。在训练期间,自动编码器将看到数百万次非欺诈性的信用卡交易。
通过这种方式,我们使用自动编码器将输入要素的基础信息或最相关的信息编码成更短的潜在表示。直觉上,我们可以说,这样自动编码器只学习绝对正常的信用卡交易的概念。
并且这种学习到的正常信用卡交易的概念可以作为中间层中的潜在表示被发现,其用于重新创建用作自动编码器的输入数据的原始特征。
使用经过训练的自动编码器检测异常情况
在用正常数据实例训练之后,我们可以最终使用神经网络来检测异常。
这一次,我们可以显示两种类型的网络数据——异常数据和正常数据。如前所述,输入特征由自动编码器编码成用于重构输入的潜在表示。
如前所述,自动编码器使用均方误差函数作为损失函数来测量重构输入和原始输入之间的差异或误差。
****请注意以下几点:如果自动编码器经过适当训练,我们预计正常数据的输出和输入之间的误差会非常小。
然而,对于异常情况或我们这里的欺诈性数据交易来说,情况并非如此。
请记住,在培训过程中,autoencoder 仅学习普通数据实例的概念和特征。这意味着 autoencoder 的权重和偏差仅被调整为编码和重建正常数据——在我们的案例中为非欺诈性交易。
如果我们现在试图对欺诈性交易进行编码,该交易的潜在表示将与正常交易的潜在表示显著不同。
直接结果是,重建的输入将与原始输入相差更大,导致比正常交易情况下更大的误差。
欺诈性输入数据会导致均方误差损失函数的损失值更高,这一事实可以为我们所用。我们所需要做的就是找到一个损失阈值来区分正常数据和欺诈数据。
在实践中,这意味着我们获得的损失值高于该阈值的数据实例将该实例归类为异常或欺诈交易。
另一方面,丢失值低于此阈值的数据实例可被视为正常数据或非欺诈性交易。
- 情况 1: 输入特征的 MSE 损失值为高于损失阈值 →输入特征为异常(此处:欺诈交易)
- 情况 2: 输入特征的 MSE 损失值低于阈值 →输入特征正常(此处:非欺诈交易)
概述:使用自动编码器进行异常检测
让我们总结一下关于如何检测数据集中的异常的知识。
- 首先,如果应该检查异常的数据集是不平衡的(几乎总是这样),您必须使用自动编码器
- 仅在正常数据上使用均方误差损失函数来训练自动编码器,在训练期间不使用任何异常数据实例
- 在训练之后,异常的损失值应该比正常数据实例的损失值高得多
- 现在,您必须找出一个损失值阈值,该阈值能够最好地区分异常数据和正常数据。
找到一个合适的损失值阈值
为了找到最佳区分异常数据和正常数据的阈值,您只需尝试许多不同的阈值。
对于这个过程,我建议取几千个数据实例,其中大约 5–10%的实例是异常的。然后,您只需计算每个实例的损失值,将其与阈值进行比较,并将其归类为异常或不异常。
最后,您必须使用实际的标签来检查这些分类有多好。为了量化分类结果,我建议使用我们在上一篇文章“数据科学和机器学习中的评估指标”中介绍的评估指标。
有了评估指标的结果,您就可以决定这个阈值是否良好,并在必要时调整阈值。
7.TensorFlow 2.0 中的欺诈检测
正如您可能已经猜到的,异常检测模型将是一个自动编码器,它将识别前面介绍的数据集中的欺诈性金融交易。
所有的源代码和使用的数据集都可以在这个项目的我的 GitHub 库中访问。请随意下载代码并亲自试用。
不幸的是,我不能详细介绍所有使用的函数和类,因为这超出了课程的范围。相反,我想只关注神经网络模型的实现。所有其他使用的类和方法(特别是数据预处理可以在 GitHub 库中查看)。所有的源代码都有很好的文档记录,因此您在理解代码时不会有任何困难。
在这一点上,让我们开始…
首先,我喜欢定义一个 BaseModel 类,它包含初始化权重和偏差以及计算正向传递的方法。
这些方法稍后将被继承到定义实际异常检测模型的类中。通过这种方式,我们可以稍后定义几个自动编码器模型(例如,使用不同的超参数),它们将从 BaseModel 类继承方法。通过这样做,我们可以节省相当多的代码,因为模型的不同版本共享相同的功能。
在init _ variables(self)中我们定义了权重和偏差。正如你所看到的,自动编码器总共有三个隐藏层。这些层中神经元的数量是[20,8,20]。
forward_propagation(self,x) 只计算自动编码器的输出,即重构的输入特征
在下面,我们可以定义自动编码器将被训练的实际类:
该类包含计算均方误差损失值和梯度下降步骤的方法。
培训过程应该一目了然:
首先,我们预测几个超参数,如批量大小、学习速率等。
一个非常重要的超参数是引入的损失值阈值,我在这里称之为 THRESHOLD=10 。MSE 损失函数值将在测试阶段从正常数据实例中区分异常。
然后我们定义类 AnomalyDetector()、的实例,这是实际的 Autoencoder 模型和性能(阈值),其中将计算一些评估指标(精度、召回、F1 分数)。如果您不熟悉这些指标,请随时查看文章“深度学习中的评估指标”
训练和评估数据集先前被转换成 TensorFlow 记录数据格式。在方法 get_training_data() 和get _ test _ data()中,我使用了 tf.data API 来提取、加载、生成小批量和混洗数据集。
在下一步中,我们迭代训练数据集,为每个小批量计算均方误差损失函数,并应用梯度下降。
在处理了 1000 个小批量之后,我使用了 Performance() 类和 loss-value-threshold 来评估异常检测器模型。测试数据集中有 34000 个实例。测试数据集包含所有 480 个欺诈性数据实例(异常),其余为正常数据实例。
就在 5 个时期之后,我们得到以下结果:
- 异常检测器具有非常好的精度值 93。这意味着模型在 93%的情况下正确地对异常进行分类。
- 召回值 43.3 告诉我们,自动编码器已经识别了数据集中 43.3%的异常。不幸的是,超过一半的异常对模型来说仍然是不可见的。
有趣的是,对于非欺诈性数据实例,平均绝对误差损失值仅为 0.385。另一方面,欺诈性数据实例的 MSE 损失值是高得多的值 19.518。正如我们所期待的那样。
最初发布于https://www . deep learning-academy . com/p/ai-wiki-anomaly-detection
基于局部异常因子的异常检测(LOF)
小型数据科学
今天的文章是我写的关于用于异常检测的不同技术的一系列“小文章”中的第 5 篇。如果有兴趣,以下是之前的四篇文章:
今天,我将超越统计技术,进入用于异常检测的机器学习算法。
什么是本地异常因素(LOF)?
LOF 是一种无监督(半监督)的机器学习算法,它使用分布中数据点的密度作为检测异常值的关键因素。
LOF 将任何给定数据点的密度与其相邻数据点的密度进行比较。由于异常值来自低密度区域,因此异常数据点的比率会更高。根据经验,正常数据点的 LOF 在 1 到 1.5 之间,而异常观测值的 LOF 要高得多。LOF 越高,越有可能是异常值。如果点 X 的 LOF 是 5,这意味着 X 的邻居的平均密度比其局部密度高 5 倍。
用数学术语来说,
LOF(X)=[(LRD(1st neighbor) + LRD(2nd neighbor ) + .................+ LRD(kth neighbor))/LRD(X)]/k
其中,LRD 是本地可达性距离,计算方法如下。
LRD(X) = 1/(sum of Reachability Distance (X, n))/k)where n is neighbors upto k
该算法有四个不同的部分:
- 超参数 k :决定邻居的数量
- 可达性距离:使用 3 种方法测量的距离——欧几里德、闵可夫斯基、曼哈顿
- 局部可达性: (LRD) (X) = 1/(可达性距离之和(X,n))/k),其中 n 是 k 以内的邻居
- 本地异常值因子(LOF)
理论和数学讲够了。如果你不太明白,不要难过。正如我过去常说,要驾驶一辆汽车,我们不需要了解它的机械结构,但我们需要知道如何驾驶!因此,请直接进入下一节,讨论用 Python 实现 LOF。
Python 实现
我们将使用 Scikit-Learn 库实现 Python 环境中异常检测的 LOF。让我们首先导入所需的库:
# data preparation
import pandas as pd
import numpy as np# data visualzation
import matplotlib.pyplot as plt
import seaborn as sns# outlier/anomaly detection
from sklearn.neighbors import LocalOutlierFactor
现在让我们创建一个包含 5 个数据点的假设数据集。
# data
df = pd.DataFrame(np.array([[0,1], [1,1], [1,2], [2,2], [5,6]]), columns = ["x", "y"], index = [0,1,2,3,4])
如果你绘制数据点,用目视检查找出异常值并不困难。
# plot data points
plt.scatter(df["x"], df["y"], color = "b", s = 65)
plt.grid()
编造数据点
所以的确,我们不需要机器学习算法来发现第 5 个数据点是异常值。但是让我们看看算法是否能检测出来。
# model specification
model1 = LocalOutlierFactor(n_neighbors = 2, metric = "manhattan", contamination = 0.02)# model fitting
y_pred = model1.fit_predict(df)# filter outlier index
outlier_index = where(y_pred == -1) # negative values are outliers and positives inliers# filter outlier values
outlier_values = df.iloc[outlier_index]# plot data
plt.scatter(df["x"], df["y"], color = "b", s = 65)# plot outlier values
plt.scatter(outlier_values["x"], outlier_values["y"], color = "r")
使用 LOF 检测异常数据点
这就对了。该算法正确地检测出异常值。
总结和结论
本文的目的是介绍一种基于密度的异常检测技术——局部异常因子。LOF 将给定数据点的密度与其相邻数据点的密度进行比较,并确定该数据是正常的还是异常的。由于有了sklearn
库,这个算法的实现并不太困难。对结果的解释也相当直接。
为了只关注一件事,我忽略了LocalOutlierFactor()
算法的另一个重要用例——新奇感检测。这是另一篇文章的主题,但简单来说,LOF 是一种半监督 ML 算法,其中该算法仅在正常数据上训练*。在训练算法之后,显示新的数据来识别它是否新颖。*
异常检测与实例
异常检测服务
假设你在一家金融科技公司做系统管理员。前端可能会出现问题,阻止您的客户在您的平台上购物。你如何知道当你的服务仍然正常运行时,你的客户支出是否突然下降?这时异常检测就派上了用场。
马库斯·温克勒在 Unsplash 上的照片
异常检测是一种在给定集合中发现异常点或异常模式的技术。术语异常也被称为异常值。离群值是在数据集中的其他对象中脱颖而出并且不符合数据集中的正常行为的数据对象。异常检测是一种数据科学应用程序,它结合了多种数据科学任务,如分类、回归和聚类。
异常可以大致分为:
- **点异常:**如果数据的单个实例离其他实例太远,那么它就是异常的。*业务用例:*根据“消费金额”检测信用卡欺诈
- **上下文异常:**异常是上下文特定的。这种异常在时间序列数据中很常见。*业务用例:*节日期间每天在食物上花费 100 美元是正常的,但在其他情况下可能是奇怪的。
- **集体异常:**一组数据实例集体帮助检测异常。*业务用例:*有人试图将数据从远程机器意外地复制到本地主机,这种异常会被标记为潜在的网络攻击。
异常检测类似于噪声消除和新奇检测,但并不完全相同。新奇感检测关注的是在新的观察中发现一种未被观察到的模式,这种模式不包括在训练数据中——比如圣诞节期间突然对 YouTube 上的一个新频道感兴趣。噪声去除 ( NR )是使分析免于出现不需要的观察结果的过程;换句话说,从有意义的信号中去除噪声。
异常检测中的数据类型
- 离群值
离群值是与数据的其余部分有很大不同的值或点。
异常值可能是这样的:
来自 Datanee
或者这个
来自塔努卡的博客
- 四分位间距
四分位距 (IQR)是一种可变性的度量,基于将数据集分成四分位。
四分位数将按等级排序的数据集分成四个相等的部分。划分每个部分的值称为第一、第二和第三四分位数;并且它们分别由 Q1、Q2 和 Q3 表示。
- Q1 是排序数据集的第一个一半的中的“中间”值。
- Q2 是集合中的中值。
- Q3 是排序数据集的第第二半部分的“中间”值。
四分位间距等于 Q3 减去 Q1。
来自维基百科
- 电平移动
时间序列中的电平移动是指在特定的时间步长上,过程的标称值从一个电平移动到另一个电平。在两个连续的电平变化之间,该过程可以表现得像标准的自回归移动平均(ARMA)过程。
电平转换的两个例子:
- 当日交易股票,从某一天的收盘到第二天的开盘价不等
- 车间内的温度或湿度传感器,用于记录从一个加工操作结束到下一个加工操作开始之间的液位变化
这实际上意味着一些值会周期性地(或非周期性地)偏离过程平均值,从而导致异常值。电平移动分析通常是使用 ARIMA 等模型的时间序列分析的一部分。
来自交叉验证
- 道钉
棘波分类是一类用于电生理数据分析的技术。棘波分类算法使用通过大脑中的一个或多个电极收集的波形的形状来从背景电噪声中区分一个或多个神经元的活动。
从研究门
- 季节性(日时、周时、月、假日)
在时间序列数据中,季节性是指以少于一年的特定固定间隔出现的变化,如每周、每月或每季度。季节性可能是由各种因素引起的,如天气、假期和假日,它由周期性的、重复的、通常有规律的和可预测的时间序列模式组成。
时间序列中的季节性波动可以与周期性模式相对照。后者发生在数据呈现非固定周期的上升和下降时。这种非季节性波动通常是由于经济状况,往往与“商业周期”有关;它们的周期通常超过一年,波动通常至少两年。
面临季节变化的组织,如冰淇淋供应商,通常有兴趣了解他们相对于正常季节变化的表现。劳动力市场的季节性变化可以归因于离校生进入就业市场,因为他们的目标是在完成学业后为劳动力做出贡献。对于那些研究就业数据的人来说,这些有规律的变化不如由于经济的基本状态而发生的变化有趣;他们关注的是劳动力中的失业率是如何变化的,尽管有规律的季节性变化的影响。
组织有必要识别和衡量市场中的季节性变化,以帮助他们规划未来。这可以让他们为劳动力需求和库存的暂时增加或减少做好准备,因为对他们产品或服务的需求在一定时期内会有波动。这可能需要提前组织培训、定期维护等等。除了这些考虑之外,组织需要知道他们所经历的变化是多于还是少于预期的量,超出了通常的季节性变化的范围。
来自 simplexCT
使用 Grafana 和 Hastic 插件进行异常检测
我们将通过一个例子来说明异常检测是如何在 Grafana 和 Hastic 插件的帮助下工作的。为了与示例保持一致,我们需要安装和设置以下内容:
- 格拉夫纳
- InfluxDB
- 石墨
- Grafana 的 Hastic 插件
- 要测试的服务
- 运行负载测试的 Gatling 环境
这个想法是这样的:
- 我们将在一个特定的服务上用 Gatling 运行负载测试
- loadtest 的测试结果将被加载到 InfluxDB 中的 Graphite 中
- 我们设置了 Grafana 和 Hastic 插件来跟踪视觉效果
为了了解如何运行与 Grafana 集成的加特林,您可以参考可视化实时加特林报告。
因为这篇文章的目的是向展示异常检测是如何工作的,我们将进入在 Grafana 设置 Hastic 的细节。
从 Grafana 中,选择配置->数据源
Hastic 数据源
在 Hastic 数据源信息中,我们设置从浏览器获取信息,然后点击“保存和测试”。
现在,我们将使用数据源 InfluxDB 和 Hastic visual 创建仪表板。
从 Grafana 中选择创建新仪表板。这里你选择可视化。
然后将哈斯蒂克图形设置为可视化
哈斯蒂克图形可视化
在查询选项卡中,选择 InfluxDB。如果您的时间序列数据库中存在数据,Grafana 将自动建议可用的查询。
涌入数据库查询
然后,当我们保存您的仪表板并运行测试时,我们可以看到异常数据被突出显示。
Hastic 异常仪表板实时
感谢您阅读我的帖子。
平安一如既往~~~。
参考
异常检测是在给定的数据集中发现异常值的过程。离群值是突出的数据对象…
www.sciencedirect.com](https://www.sciencedirect.com/topics/computer-science/anomaly-detection) [## 异常检测
11.1.1 研究问题异常检测是一种在给定集合中寻找异常点或模式的技术。的…
www.sciencedirect.com](https://www.sciencedirect.com/topics/engineering/anomaly-detection) [## 异常检测
在各种领域,例如,但不限于,统计,信号处理,金融,计量经济学,制造业…
en.wikipedia.org](https://en.wikipedia.org/wiki/Anomaly_detection) [## 异常检测简介
特定主题的经验:新手专业经验:无行业经验本概述旨在…
blogs.oracle.com](https://blogs.oracle.com/datascience/introduction-to-anomaly-detection) [## 四分位范围:定义
四分位数范围的定义,来自 Stat Trek 统计术语和概念词典。这个统计数据…
stattrek.com](https://stattrek.com/statistics/dictionary.aspx?definition=interquartile%20range) [## 四分位间距
在描述性统计中,四分位距(IQR)也称为中间分布、中间 50%或 H 分布,是一个…
en.wikipedia.org](https://en.wikipedia.org/wiki/Interquartile_range) [## 时间序列中的移位级别是什么意思?
答:时间序列中的水平移动是指在特定的时间步长上,名义…
www.quora.com](https://www.quora.com/What-is-meant-by-a-shift-level-in-a-time-series)