总览:
编号 | 方法 |
---|
1 | 经验判断 |
2 | 3σ |
3 | dbscan |
4 | lof |
5 | isolation tree |
6 | one class svm |
一. 经验判断
X={x1,x2,...,xn}
IQR=0.75 分位数 - 0.25 分位数
outlier_min=0.25分位数-1.5IQR
outlier_max=0.75分位数+1.5IQR
判断标准:< outlier_min 或者 > outlier_max 则为异常值 ;
备注:非参数方法
二.3σ原则
若x~N(u,σ)
P(|x−μ|>3σ)≤0.003
三.dbscan
邻域:对于x_I 来说,若x_J 到x_i的距离小于c,则称x_j为x_i的邻域
核心对象:若x_i邻域的x_J的数量超过d个,则成x_i为核心对象
密度直达:x_I 为核心对象,若x_j在x_i的邻域内,则成x_j 到 x_j密度直达
密度可达:x_i → x_j → x_k , 其中 x_i → x_j 密度直达 x_j →x_k 密度直达,则 x_i → x_k 密度可达
密度相连:x_k 为核心样本, x_i,x_j均有x_k密度可达,那么x_i,x_j密度连

'''
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html
'''
from sklearn.cluster import DBSCAN
from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt
# 测试样本
iris=datasets.load_iris()
x=iris.data
y=iris.target
# 获取eps
def dist(x,y):
x=np.array(x)
y=np.array(y)
return np.sqrt(np.sum(np.square(x - y)))
k=4
k_dist=[]
for i in range(len(x)):
dist_i=[]
for j in range(len(y)):
dist_i.append(dist(x[i],x[j]))
dist_i.sort()
dist_i_k=dist_i[k]
k_dist.append(dist_i_k)
# k-dist 图
#plt.plot([ele for ele in range(len(k_dist))],k_dist)
#plt.show()
eps=np.percentile(np.array(k_dist),80)
clustering=DBSCAN(eps=eps,min_samples=4).fit(x)
y_hat=clustering.fit_predict(x)
print(y_hat) # -1为噪声点
|
四. lof (local outlier factor)
- 也是基于密度的思想,一个异常点的密度比上异常点周围点的平均密度小于1 或者 反过来 异常点周围样本点的平均密度比上样本点的密度大于1


第一步是要先找到距离p k近个的集合o
第二步 计算lrd(o) 以及 lrd(p)
from sklearn.datasets import load_iris
from sklearn.neighbors import LocalOutlierFactor
iris=load_iris()
x=iris.data
cls=LocalOutlierFactor(n_neighbors=20,algorithm='auto',contamination=0.1)
cls.fit(x)
res=cls.fit_predict(x)
print(res) # 1表示为正常值,-1表示为异常值
|
五.isolation tree
流程:
1.划分n份样本集
2.对于每份样本集构造一个itree,如何构造?
step1: 随机选择一个特征
step2:随机选择一个特征中的随机值,随机值>= min , 随机<=max
step3:根据随机值,进行样本划分
满足条件 : 深度到达一定条件 或者 节点只包含一个样本
3.计算每个点距离根节点的平均长度(平均的意思是对多颗itree的深度做的平均)
那么平均长度如何度量呢? 看论文:

BST: Binary Search Tree 二叉搜索树
H:harmonic number 调和级数,可以用ln + 欧拉系数进行估计,证明如下;

c(n) : 给定n,h(n)的平均
E(c(n)): 对于一系列itree的c(n)的平均
s(n,x):为异常得分
E 与 s(n,x)的关系

from sklearn.datasets import load_iris
from sklearn.ensemble import IsolationForest
''' 参数说明
contamination : 异常值比例
n_estimators: 树的数量
max_samples:每颗树,样本的比例0
max_features:每颗树,特征个数和比例
bootstrap: true表示有放回,false表示无返回
'''
iris=load_iris()
x=iris.data
cls=IsolationForest(contamination=0.1,n_estimators=30,max_features=3,max_samples=100)
cls.fit(x)
y=cls.predict(x)
print(y) # -1 表示异常值,1表示正常值 |
六.one class svm
from sklearn.svm import OneClassSVM
'''
kernel 根据经验判断数据可能是那种分布。‘linear’:线性;‘rbf’:高斯分布,默认的;
nu:异常数据百分比
'''
from sklearn.datasets import load_iris
iris=load_iris()
x=iris.data
cls=OneClassSVM(nu=0.1,kernel='rbf')
cls.fit(x)
y=cls.predict(x)
print(y) # -1表示异常,1表示正常 |