任务
1、基于 anomaly_data.csv 数据,可视化数据分布情况、及其对应高斯分布的概率密度函数
2、建立模型,实现异常数据点预测
3、可视化异常检测处理结果
4、修改概率分布阈值 EllipticEnvelope (contamination=0.1) 中的 contamination,查看阈值改变对结果的影响
代码工具:jupyter notebook
算法工具
Elliptic Envelope算法的思路是,假设正常数据符合正态分布。基于这个假设,可以确定数据的形状(边界),将远离边界的样本点定义为异常点。SKlearn提供了一个covariance.EllipticEnvelope类,它可以根据数据做一个鲁棒的协方差估计,然后学习到一个包围中心样本点并忽视离群点的椭圆。
资料
视频资料: 22.25 异常检测_哔哩哔哩_bilibili
博客资料: https://www.cnblogs.com/zwh0910/p/18711234
数据准备
数据集名称:anomaly_data.csv
点我转到百度网盘获取数据集 提取码: 8497
#load the data
import pandas as pd
import numpy as np
data = pd.read_csv('anomaly_data.csv')
data.head()
原数据可视化
# Visualize the data
%matplotlib inline
from matplotlib import pyplot as plt
fig1 = plt.figure(figsize = (10,5))
plt.title('data')
plt.scatter(data.loc[:,'x1'], data.loc[:,'x2'])
plt.xlabel('x1')
plt.ylabel('x2')
plt.show()
#建立模型,进行异常数据点的检测
#define x1 and x2
x1 = data.loc[:,'x1']
x2 = data.loc[:,'x2']
将x1和x2数据分布进行一个可视化
fig2 = plt.figure(figsize =(20,5))
plt.subplot(121)
plt.hist(x1,bins = 100) # 分成100个数据分隔,即有100条条状图, 绘制直方图
plt.title('x1 distribution') #x1 数据分布统计
plt.xlabel('x1')
plt.ylabel('counts')
plt.subplot(122)
plt.hist(x2,bins = 100) # 绘制直方图
plt.title('x2 distribution')
plt.xlabel('x2')
plt.ylabel('counts')
plt.show()
其中y轴为每个分隔范围x1或x2出现的次数。
计算x1、x2的均值(mean)和标准差(sigma)
#calculate the mean and sigma of x1 and x2
x1_mean = x1.mean()
x1_sigma = x1.std()
x2_mean = x2.mean()
x2_sigma = x2.std()
print(x1_mean, x1_sigma, x2_mean, x2_sigma)
#9.112225783931596 1.3559573758220915 9.997710507954398 1.30970711753864
计算高斯分布(即正态分布)概率密度函数
#calculate the gaussian distribution p(x)
from scipy.stats import norm
x1_range = np.linspace(0, 20, 300) # 范围是0到20,300个点均分
x1_normal = norm.pdf(x1_range, x1_mean, x1_sigma) # 计算高斯分布概率密度函数
x2_range = np.linspace(0, 20, 300)
x2_normal = norm.pdf(x2_range, x2_mean, x2_sigma)
可视化高斯分布概率密度函数
#visualize the p(x)
fig3 = plt.figure(figsize =(20,5))
plt.subplot(121)
plt.plot(x1_range, x1_normal)
plt.title('normal p(x1)')
plt.subplot(122)
plt.plot(x2_range, x2_normal)
plt.title('normal p(x2)')
plt.show()
至此,我们任务的第一部分就完成了,下面开始建立模型。
建立模型
协方差EllipticEnvelope:数据分布中存在异常值是常见的情况。许多算法都能处理异常值,EllipticEnvelope 是 Sklearn 内置的一个优秀示例。该算法在检测正态分布(高斯)特征中的异常值方面表现出色。
#establish the model and predict
from sklearn.covariance import EllipticEnvelope
ad_model = EllipticEnvelope()
ad_model.fit(data)
进行预测
#进行预测,看哪些点是异常的
y_predict = ad_model.predict(data)
print(pd.value_counts(y_predict)) # 1 是正常点,-1 是异常点
结果可视化
# Visualize the result
from matplotlib import pyplot as plt
fig4 = plt.figure(figsize = (20,10))
#原始数据点画出来
orginal_data = plt.scatter(data.loc[:,'x1'], data.loc[:,'x2'], marker = 'x')
#下面是异常点
anomaly_data = plt.scatter(data.loc[:,'x1'][y_predict == -1], data.loc[:,'x2'][y_predict == -1], marker = 'o',
facecolor = 'none', edgecolor = 'red', s = 150)
# y_predict==-1即是异常点; marker='o'将异常点用圆圈圈起来; facecolor='none' 不填充,即空心圆; edgecolor='red' 颜色为红色; s=150 圆圈的大小
plt.title('anomaly detection result')
plt.xlabel('x1')
plt.ylabel('x2')
plt.legend((orginal_data, anomaly_data),('original_data','anomaly_data'))
plt.show()
调小阈值,再做一次
#从上图可以看出,有些正常点也被判断成了异常点,说明在进行两个维度的高斯分布概率相乘时,阈值设置的太大了(默认是 0.1)
#下面将阈值调小一些,再做一次
ad_model = EllipticEnvelope(contamination = 0.02)
ad_model.fit(data)
#进行预测,看哪些点是异常的
y_predict = ad_model.predict(data)
print(pd.value_counts(y_predict)) # 1 是正常点,-1 是异常点
# Visualize the result
fig5 = plt.figure(figsize = (20,10))
#原始数据点画出来
orginal_data = plt.scatter(data.loc[:,'x1'], data.loc[:,'x2'], marker = 'x')
#下面是异常点
anomaly_data = plt.scatter(data.loc[:,'x1'][y_predict == -1], data.loc[:,'x2'][y_predict == -1], marker = 'o',
facecolor = 'none', edgecolor = 'red', s = 150)
plt.title('anomaly detection result')
plt.xlabel('x1')
plt.ylabel('x2')
plt.legend((orginal_data, anomaly_data),('original_data','anomaly_data'))
plt.show()
异常检测实战 summary
1、通过计算数据各维度对应的高斯分布概率密度函数,可用于寻找到数据中的异常点;
2、通过修改概率密度阈值 contamination,可调整异常点检测的灵敏度;
3、核心算法参考链接:https://scikit-learn.org/stable/modules/generated/sklearn.covariance.EllipticEnvelope.html?highlight=ellipticenvelope