异常值(outlier)是指一组测定值中与平均值的偏差超过两倍标准差的测定值,与平均值的偏差超过三倍标准差的测定值,称为高度异常的异常值。
现在老板给了我有个任务,说
的数据有几个异常值,搞它出来,顺便 做下预测
???我好像没有老板,全是吹逼,75000行,这怎么找?
思路
我先找出 固定间隔
含量的差值,就是这个数减去上面的数,画下图来看看是否在0的附近
import numpy as np
import matplotlib as mpl
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import BaggingRegressor
mpl.rcParams['font.sans-serif'] = ['simHei']
mpl.rcParams['axes.unicode_minus'] = False
data = pd.read_csv('C0911.csv', header=0) # C0911.csv, C0904.csv
x = data['H2O'].values
# 75000个太多了
width = 500
# 步长
delta = 10
# 设置阈值
eps = 0.15
N = len(x) # 75000多
p = []
# 存放不正常的数据
abnormal = []
# i = 0 ,10,20……
for i in np.arange(0, N-width, delta):
s = x[i:i+width]
p.append(np.ptp(s))
if np.ptp(s) > eps:
abnormal.append(list(range(i, i+width)))
abnormal = np.unique(abnormal)
plt.figure(facecolor='w')
plt.plot(p, lw=1)
plt.grid(b=True, ls=':', color='#404040')
plt.title('固定间隔$H_2O$含量的差值', fontsize=16)
plt.xlabel('时间', fontsize=15)
plt.xlabel('差值', fontsize=15)
plt.show()
print(abnormal)
abnormal.shape
# [ 3740 3741 3742 ... 68207 68208 68209]
# (6530,)
说明ptp()函数
>>> x = np.arange(4).reshape((2,2))
>>> x
array([[0, 1],
[2, 3]])
>>> np.ptp(x, axis=0)
array([2, 2])
>>> np.ptp(x, axis=1)
array([1, 1])
根据图中很容易看出数据的分布,上面的代码就是为了找出abnormal
采用的集成决策树的方法
plt.figure(figsize=(11, 5), facecolor='w')
plt.subplot(131)
plt.plot(x, 'r-', lw=1, label='原始数据')
plt.title('实际排放数据', fontsize=16)
plt.legend(loc='upper right')
plt.grid(b=True, ls=':', color='#404040')
plt.subplot(132)
t = np.arange(N)
plt.plot(t, x, 'r-', lw=1, label='原始数据')
plt.plot(abnormal, x[abnormal], 'go', markeredgecolor='g', ms=2, label='异常值')
plt.legend(loc='upper right')
# 异常校正(预测)
plt.subplot(133)
select = np.ones(N, dtype=np.bool)
select[abnormal] = False
t = np.arange(N)
# 决策树
dtr = DecisionTreeRegressor(criterion='mse', max_depth=10)
# 10个决策树
br = BaggingRegressor(dtr, n_estimators=10, max_samples=0.3)
br.fit(t[select].reshape(-1, 1), x[select])
y = br.predict(np.arange(N).reshape(-1, 1))
y[select] = x[select]
plt.plot(x, 'g--', lw=1, label='原始值') # 原始值
plt.plot(y, 'r-', lw=1, label='校正值') # 校正值
plt.legend(loc='upper right')
plt.title('异常值校正', fontsize=16)
plt.grid(b=True, ls=':', color='#404040')
plt.tight_layout(1.5, rect=(0, 0, 1, 0.95))
plt.suptitle('排污数据的异常值检测与校正', fontsize=18)
plt.show()
效果如图