總覽:
編號 |
方法 |
---|
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表示正常
|